Frame 1 too long (-16711680 bytes) error in Wireshark - c

I have been using Cooja in Instant Contiki v2.7. I have added the global and pcap header in the write_to_serial() function in tunslip6.c . Later these packets are sent to the named pipe /tmp/myfifo (which will be the interface for wireshark). And then to display it in wireshark. But when the wireshark is opened (wireshark -k -i /tmp/myfifo), it gives the prompt " Frame 1 too long (-16711680 bytes) "
Below is the code snippet of write_to_serial().
if(verbose>2) {
if (timestamp) stamptime();
printf("Packet from TUN of length %d - write SLIP\n", len);
if (verbose>4) {
#if WIRESHARK_IMPORT_FORMAT
printf("0000");
for(i = 0; i < len; i++) {
printf(" %02x",p[i]);
}
mkfifo(myfifo,0777);
fd=open(myfifo,O_WRONLY);
//add global header only once and packet header
if(gb==0) //gb globally declared ; int gb=0
{
header.magic = 0xa1b2c3d4;
header.version_major = 2;
header.version_minor = 4;
header.thiszone =0;
header.sigfigs = 0;
header.snaplen = 65535;
header.linktype = 113;
bufg[0]=header.magic ;
bufg[1]=header.version_major ;
bufg[2]=header.version_minor ;
bufg[3]=header.thiszone ;
bufg[4]=header.sigfigs ;
bufg[5]=header.snaplen ;
bufg[6]=header.linktype;
// pcap packet header
gettimeofday(&time,0);
pcap_header.ts.tv_sec = time.tv_sec;
pcap_header.ts.tv_usec = time.tv_usec;
pcap_header.caplen = len;
pcap_header.len = len;
bufp[0]=pcap_header.ts.tv_sec ;
bufp[1]=pcap_header.ts.tv_usec ;
bufp[2]=pcap_header.caplen ;
bufp[3]=pcap_header.len ;
if (((write(fd,bufg,7))&&(write(fd,bufp,4))&&(write(fd,p,len)))< 0)
fputs("write() of bytes failed!\n", stderr);
else
printf("\nSuccessfully wrote bytes ");
gb++;
}
else if(gb>0)
{
gettimeofday(&time,0);
pcap_header.ts.tv_sec = time.tv_sec;
pcap_header.ts.tv_usec = time.tv_usec;
pcap_header.caplen = len;
pcap_header.len = len;
bufp[0]=pcap_header.ts.tv_sec ;
bufp[1]=pcap_header.ts.tv_usec ;
bufp[2]=pcap_header.caplen ;
bufp[3]=pcap_header.len ;
if (((write(fd,bufp,4))&&(write(fd,p,len)))< 0)
fputs("write() of bytes failed!\n", stderr);
else
printf("Successfully wrote bytes\n");
}
#endif
The value printed by the pointer p is
Packet from TUN of length 48 - write SLIP
0000 60 00 00 00 00 08 3a ff fe 80 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ff 02 00 00 00 00 00 00 00 00 00 00 00 00 00 02 85 00 7d 36 00 00 00 00
And the fifo is dumped with the values:
0000000 a1b2c3d4 92000002 60567aeb 00000000
0000020 feff3a08 00000080 00000000 00000000
0000040 ff010000 00000002 00000000 00000000
0000060 85020000 00367d00 93000000 60567aeb
0000100 00000000 feff3a08 00000080 00000000
0000120 00000000 ff010000 00000002 00000000
0000140 00000000 85020000 00367d00 97000000
0000160 60567aeb 00000000 feff3a08 00000080
0000200 00000000 00000000 ff010000 00000002
0000220 00000000 00000000 85020000 00367d00
What should be done inorder to rectify this error?

Based on the binary dump, "a1b2c3d4" means that it's big endianness. But the frame length of ff010000 doesn't make sense. I guess you meant to use little endianess, which starts with "d4c3b2a1". Good luck.

It is because the values assigned are in the array which was previously declared as unsigned long. The exact values got changed when this was done. Instead, I wrote the values directly from the structure to the pipe and also added the ethernet header between the pcap header and the ip header.
This is how it looks after editing the code
fd=open(myfifo,O_WRONLY);
if (fd == -1)
{
// Could not open the port.
perror(" Unable to open named pipe");
}
else
printf("\nPipe open : Successsful\n");
eth.h_dest[ETH_ALEN]=(unsigned char){0x00 ,0x00 ,0x00 ,0x00,0x00 ,0x00};
eth.h_source[ETH_ALEN]=(unsigned char){0x00 ,0x00 ,0x00 ,0x00,0x00 ,0x00};
eth.h_proto=0xDD86;
//add global header only once and packet header
if(gb==0)
{
header.magic = 0xa1b2c3d4;
header.version_major = 2;
header.version_minor = 4;
header.thiszone =0;
header.sigfigs = 0;
header.snaplen = 65535;
header.linktype = 1;
// pcap packet header
gettimeofday(&time,0);
pcap_header.ts.tv_sec = time.tv_sec;
pcap_header.ts.tv_usec = time.tv_usec;
pcap_header.caplen = len;
pcap_header.len = len;
if (write(fd,&header,sizeof(header))< 0)
fputs("write() of bytes failed!\n", stderr);
else
printf("\nSuccessfully wrote global_header ");
if (write(fd,&pcap_header,sizeof(pcap_header))< 0)
fputs("write() of bytes failed!\n", stderr);
else
printf("\nSuccessfully wrote pcap header");
if (write(fd,&eth,14)< 0)
fputs("write() of eth bytes failed!\n", stderr);
else
printf("\nSuccessfully wrote ethernet header ");
if (write(fd,p,len)< 0)
fputs("write() of ip bytes failed!\n", stderr);
else
printf("\nSuccessfully wrote ipheader\n ");
gb++;
}
else if(gb>0)
{
gettimeofday(&time,0);
pcap_header.ts.tv_sec = time.tv_sec;
pcap_header.ts.tv_usec = time.tv_usec;
pcap_header.caplen = len;
pcap_header.len = len;
if (write(fd,&pcap_header,sizeof(pcap_header))< 0)
fputs("write() of bytes failed!\n", stderr);
else
printf("\nSuccessfully wrote pcap header");
if (write(fd,&eth,14)< 0)
fputs("write() of eth bytes failed!\n", stderr);
else
printf("\nSuccessfully wrote ethernet header ");
if (write(fd,p,len)< 0)
fputs("write() of ip bytes failed!\n", stderr);
else
printf("\nSuccessfully wrote ipheader\n ");}
And later the packets sent to the pipe is:
0000000 a1b2c3d4 00040002 00000000 00000000
0000020 0000ffff 00000001 56808fb9 000ed0b2
0000040 00000030 00000030 41880000 3600bf8e
0000060 4188b77c 0060dd86 08000000 80feff3a
0000100 00000000 00000000 00000000 02ff0100
0000120 00000000 00000000 00000000 00850200
0000140 0000367d 8fbd0000 ad725680 0030000e
0000160 00300000 00000000 bf8e4188 b77c3600
0000200 dd864188 00000060 ff3a0800 000080fe
0000220 00000000 00000000 01000000 000002ff
0000240 00000000 00000000 02000000 367d0085
0000260 00000000 56808fc1 000eccfe 00000030
0000300 00000030 41880000 3600bf8e 4188b77c
0000320 0060dd86 08000000 80feff3a 00000000
0000340 00000000 00000000 02ff0100 00000000
0000360 00000000 00000000 00850200 0000367d

Related

TCP socket connect function ignoring my entirely valid SYN+ACK packets,is there anything aweful about that I can't stop this, send SYN after SYN+ACK

I have verified in wireshark that my TCP handshake SYN+ACK packet after receiving SYN packet is getting ignored
This is wireshark main view that shows within time wireshark read my SYN+ACK packet for RTT. but my linux socket api function connect acting dummy and send SYN again, Wht I need to do in this case I am attaching my wireshark packet times plus actual communication packets, I need someone with knowledge of this and C to answer this very much thanks
This is recorded time in wireshark when packets in attempted handshake are read
This is received packet in my program code
SYN
0000 45 00 00 3c fa ed 40 00 40 06 aa 5a c0 a8 0a 14
0010 c0 a8 0a 0f bc be 00 50 f8 08 9d 5b 00 00 00 00
0020 a0 02 fa f0 bb 0f 00 00 02 04 05 b4 04 02 08 0a
0030 9a 68 0f b0 00 00 00 00 01 03 03 07
ACK SYN with valid checksums, sequence number and acknowledgement number
0000 45 00 00 28 00 64 40 00 40 06 a4 f8 c0 a8 0a 0f
0010 c0 a8 0a 14 00 50 bc be 00 00 00 03 f8 08 9d 5c
0020 50 12 fa f0 cc f6 00 00
And this is my linux connect function complete dummy behavior by sending SYN again
0000 45 00 00 3c fa ee 40 00 40 06 aa 59 c0 a8 0a 14
0010 c0 a8 0a 0f bc be 00 50 f8 08 9d 5b 00 00 00 00
0020 a0 02 fa f0 b7 1b 00 00 02 04 05 b4 04 02 08 0a
0030 9a 68 13 a4 00 00 00 00 01 03 03 07
Can anyone please tell me how to handle this, since I am clueless on this, Is there any command that I can use to make my connect function TCP Handshake handling more attentive to my SYN+ACK packet and finally done with responding only ACK instead of playing plain stupid to send SYN again
As #LuisColorado mentioned to ask how am I generating the packet so the answer is this is how
this is my receiver thread that also transmit response TCP packets like SYN+ACK
void * receiver(void *data)
{
//struct sockaddr_in cliaddr = {0};
int recvlen = -1;
int writelen = -1;
//socklen_t clilen = sizeof(cliaddr);
while (!_do_exit)
{
//recvlen = rrecvfrom(_udp_fd, buf, sizeof(buf), 0, (struct sockaddr*)&cliaddr, &clilen);
char buf[VPN_MAX_MTU] = {0};
char buf_1[VPN_MAX_MTU] = {0};
memset(buf,0,VPN_MAX_MTU);
memset(buf_1,0,VPN_MAX_MTU);
memset(buf,0,VPN_MAX_MTU);
memset(buf_1,0,VPN_MAX_MTU);
char *str_source=malloc(18);
char *str_dest=malloc(18);
memset(str_source,0,18);
memset(str_dest,0,18);
recvlen=read(_tun_fd,buf,VPN_MAX_MTU);
if(recvlen>0)
{
//BUFFER received here
struct iphdr *iph=(struct iphdr *)buf;
struct iphdr *ip=(struct iphdr *)buf_1;
int y=0;
for(int b=0;b<(sizeof(struct iphdr)+sizeof(struct tcphdr));b++)
{
if(y==20)
{
y=0;
//printf("\n");
}
//printf("%x ",buf[b]<<24);
y++;
}
// tcph->check=(tcp_chksum(iph,tcph));
//iph->check = csum(iph, sizeof(*iph));
char str_src[18]={0};
char str_dest_t[18]={0};
//printf("IN %s %s\n",get_ip_str_1(iph->saddr,str_src),get_ip_str_1(iph->daddr,str_dest_t));
memcpy(&ip->daddr,&iph->saddr,sizeof(uint32_t));
memcpy(&ip->saddr,&iph->daddr,sizeof(uint32_t));
//printf("OUT %s %s\n",get_ip_str_1(ip->saddr,str_src),get_ip_str_1(ip->daddr,str_dest_t));
//Create ip
//DOUBLE CHECK FOR BYTE ORDER
//ip->tot_len=iph->tot_len;
populate_ip_some(iph,ip);
ip->tos=0;
ip->tos=iph->tos;
ip->ihl = 5;
ip->version = 4;
ip->tot_len = htons(sizeof(struct iphdr) + sizeof(struct tcphdr));
ip->protocol = 6;
ip->check=0;
//DOUBLE CHECK FOR BYTE ORDER
ip->id=htons(100);
ip->check = htons(csum(ip, sizeof(*ip)));
//printf("before %d \n",htons(iph->check));
iph->check=0;
//printf("middle %d\n",iph->check);
//DOUBLE CHECK FOR BYTE ORDER
iph->check = htons(csum(iph, sizeof(*iph)));
int i=iph->ihl*4;
struct tcphdr *tcph=(struct tcphdr *)(buf+i);
//printf("tcp before %x\n",htons(tcph->check));
tcph->check=0;
printf("TCP START\n");
tcph->check=(tcp_chksum(iph,tcph));
printf("TCP END\n");
//printf("tcp after %d\n",(tcph->check));
//printf("i == %d\n",i);
//POSSIBLY PRINT IPH for fun
//for(int a=0;a<recvlen;a++)
//printf("%x\n",buf[a]);
//GET ihl SEND -- tcp
int j=(ip->ihl*4);
//printf("j == %d\n",j);
int x=0;
//SEEK filling
struct tcphdr *tcp=(struct tcphdr *)(buf_1+20);
//populate_tcp_some(tcph,tcp);//Do LOOK AT THIS FUNCTION TO [SEE/CORRECT IT] >:)
if(tcph->syn==1)
{
printf("WHAT THE HELL THEN WHY\n");
printf("syn\n");
populate_tcp_some(tcph,tcp);
tcp->seq=htonl(1);
// tcp->ack_seq=1;
tcp->syn=1;
tcp->ack=1;
tcp->res1=0;
tcp->res1=0;
tcp->urg=0;
tcp->psh=0;
tcp->fin=0;
tcp->doff=5;
tcp->source=htons(80);
int xx=ntohl(tcph->seq)+1;
printf("\n\nfwdfwdfwd FAWAD %x\n\n",xx);
tcp->ack_seq=htonl(xx);
// printf("received tcp syn = %d\n",tcph->syn);
}
else
{
populate_tcp_some(tcph,tcp);
tcp->syn=0;
tcp->ack=1;
tcp->seq=htonl(1);
tcp->res1=0;
tcp->res1=0;
tcp->urg=0;
tcp->psh=0;
tcp->fin=0;
tcp->doff=5;
tcp->ack_seq=htonl(ntohs(tcph->seq)+1);
// printf("sending tcp syn = %d ack = %d\n",tcp->syn,tcp->ack);
}
printf("syn=%d | ack = %d | fin = %d | %d seq = %d ack_seq = %d | urg = %d | doff = %d | psh = %d rst = %d | rst2 = %d\n",tcp->syn,tcp->ack,tcp->fin,tcp->seq,tcp->ack_seq,tcp->urg,tcp->doff,tcp->psh,tcp->res1,tcp->res2);
//populate_tcp_some(tcph,tcp);
tcp->dest=tcph->source;
tcp->window=htons(40);//tcph->window;
//tcp->ack_seq=tcph->seq;
//printf("%d %d SOURCE PORT \n",ntohs(tcph->source),ntohs(tcp->dest));
tcp->source=htons(80);
printf("%d %d PORTS \n",ntohs(tcp->source),ntohs(tcp->dest));
tcp->check=0;
//TCP CHECKSUM ABOUT TRIPPLE WOW
tcp->check=htons(tcp_chksum(ip,tcp));
//printf("tcpH = %d | tcp = %d\n",tcph->check,htons(tcp->check));
//IF needed make payload data
//WRITE
if (recvlen > 0)
{
writelen = write(_tun_fd, buf_1, sizeof(struct iphdr)+sizeof(struct tcphdr));
//debug("SR:%04d\n", recvlen);
//debug("TW:%04d\n", writelen);
if (writelen < 0)
{
//debug("%s: rwrite() %s [%d]\n", _progname, strerror(errno), errno);
//break;//NO NEED
}
}
else if (recvlen < 0)
{
//debug("%s: rrecvfrom() %s\n", _progname, strerror(errno));
//break;//NO NEED
}
else if (recvlen == 0)
{
//why
}
//FINALLY THEN SEND || DO WIRE SHARK
}
// ...:)__ :) __:) ___:)___ (: __(:__ (;...
}
debug("** Receiver ending.\n");
pthread_exit(NULL);
}

ptrace doesnt show the same as objdump

I am writing a C program thats shows instructions using ptrace. This is the code:
#include<stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <string.h>
void run_target()
{
ptrace(PTRACE_TRACEME, 0, 0, 0);
execl("./test", "test", NULL);
}
void debugger(pid_t pid)
{
int status;
wait(&status);
while(WIFSTOPPED(status))
{
struct user_regs_struct regs;
ptrace(PTRACE_GETREGS, pid, 0, &regs);
long instruction = ptrace(PTRACE_PEEKTEXT, pid, regs.rip, 0);
ptrace(PTRACE_SINGLESTEP, pid, 0, 0);
//EDITED SO IT PRINTS ONLY LINES I WANT
if(((regs.rip >> (8*5)) & 0xFF) != 0x7f) //i noticed all the junk lines that shouldnt be there, their regs.rip began with 7f
printf("%llx %16lx\n", regs.rip, instruction);
wait(&status);
}
}
int main()
{
pid_t pid;
pid = fork();
if(pid == 0)
{
run_target();
}
else
{
debugger(pid);
}
return 0;
}
But the output looks like this
...
7f3bf1487308 8348da7426fa8348
7f3bf148730c d47408fa8348da74
7f3bf148730e 8d48d47408fa8348
7f3bf1487312 16ad50d8d48d474
7f3bf14872e8 18c0834810508b48
7f3bf14872ec 48f2014c18c08348
7f3bf14872f0 8948c33948f2014c
7f3bf14872f3 860f118948c33948
7f3bf14872f6 fff670860f118948
7f3bf14872f9 508bfffff670860f
And the objdump -d looks like this:
000000000000064a <main>:
64a: 55 push %rbp
64b: 48 89 e5 mov %rsp,%rbp
64e: 48 8d 3d af 00 00 00 lea 0xaf(%rip),%rdi # 704 <_IO_stdin_used+0x4>
655: b8 00 00 00 00 mov $0x0,%eax
65a: e8 c1 fe ff ff callq 520 <printf#plt>
65f: 48 8d 3d a5 00 00 00 lea 0xa5(%rip),%rdi # 70b <_IO_stdin_used+0xb>
666: b8 00 00 00 00 mov $0x0,%eax
66b: e8 b0 fe ff ff callq 520 <printf#plt>
670: b8 00 00 00 00 mov $0x0,%eax
675: 5d pop %rbp
676: c3 retq
677: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1)
67e: 00 00
And running ./program | grep "64e" for example shows this
7f46f3bb64e2 89483e8b48f90148
7f46f3bb64e5 8b483989483e8b48
7f46f3bb64e8 48087e8b48398948
7f46f3bb64eb 48c70148087e8b48
7f46f3bb64ef 4808798948c70148
7f46f3bb7318 f64ee8ef894c9174
7f46f3bb731a f64ee8ef894c
7f46f3bb731d 4887eb0000f64ee8
7f46f3800b70 4864e889481f8948
7f46f3800b73 2504334864e88948
55dfb208464e b8000000af3d8d48
7f46f38564e2 89440af883481476
7f46f38f2a11 4334864e8458b48
7f46f380505a e264e8ff894c0874
with this one actually being correct:
55dfb208464e b8000000af3d8d48
So is there something im missing in objdump or is there something missing in my code that it shows more of the rip than it should?
EDIT: added whole code
EDIT: edited the printf, now it prints the lines its supposed to, but it still adds random hex to the beginning
what it should be
64a: 55
what it is
56160a60a64a 9f3d8d48e5894855
I understand why the instruction isnt the same, that is NOT my problem, my problem is why the regs.rip isnt 64a, but is 64a. And the random hex at the start is different everytime i rerun the program.
Your program works, you just have to look at the right place in the right order in your result.
Having that test definition :
#include <stdio.h>
int main()
{
puts("hello");
puts("world");
return 0;
}
objdump -d test produces among other things :
0000000000400526 <main>:
400526: 55 push %rbp
400527: 48 89 e5 mov %rsp,%rbp
40052a: bf d4 05 40 00 mov $0x4005d4,%edi
40052f: e8 cc fe ff ff callq 400400 <puts#plt>
400534: bf da 05 40 00 mov $0x4005da,%edi
400539: e8 c2 fe ff ff callq 400400 <puts#plt>
40053e: b8 00 00 00 00 mov $0x0,%eax
400543: 5d pop %rbp
400544: c3 retq
400545: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
40054c: 00 00 00
40054f: 90 nop
if I run your program among the result I found the code with the same addresses of objdump and the same instructions codes, so the init section etc then main (from the line 81208 !) :
400526 4005d4bfe5894855
400527 4005d4bfe58948
40052a fecce8004005d4bf
40052f 5dabffffffecce8
400400 6800200c1225ff
400406 ffe0e90000000068
40040b a25ffffffffe0e9
4003f0 25ff00200c1235ff
4003f6 1f0f00200c1425ff
...
I run on an Intel i7, the instruction bytes have to be read in the reverse order than shown by objdump, for instance the first instruction is 55, then 48 89 e5 then bf d4 05 40 00 then e8 cc fe ff ff etc.
Of course in your case it is like you do 'step' rather than 'next' in a debugger, so on a callq to puts you enter in puts, while objdump disassemble. There are 60084 lines after the address 40052f before to reach address 400534, so 60084 instructions are necessary to do puts("hello"); !
Of course it is possible to print only from the beginning of main, for instance with a lazy way using objdump :
void debugger(pid_t pid)
{
FILE * fp = popen("objdump -d ./test | grep \"<main>:\"", "r");
if (fp == NULL) {
puts("cannot get main address");
}
else {
char line[256];
if (fgets(line, sizeof(line), fp) == NULL) {
puts("no address !");
pclose(fp);
}
else {
unsigned long long main_addr;
pclose(fp);
errno = 0;
main_addr = strtoull(line, NULL, 16);
if (errno != 0)
puts("invalid address");
else {
int found = 0;
int status;
while(wait(&status), WIFSTOPPED(status))
{
struct user_regs_struct regs;
ptrace(PTRACE_GETREGS, pid, 0, &regs);
if (found |= (regs.rip == main_addr)) {
long instruction = ptrace(PTRACE_PEEKTEXT, pid, regs.rip, 0);
printf("%llx %16lx\n", regs.rip, instruction);
}
ptrace(PTRACE_SINGLESTEP, pid, 0, 0);
}
}
}
}
}
[edit from your remark]
ptrace does not know if you want to read a data or instructions, if you want to separate each instructions as objdump you have to know the code of each and the corresponding length, else you can use the difference of addresses from one to the next even that does not work in case of call/jmp/conditional jmp/return :
void debugger(pid_t pid)
{
FILE * fp = popen("objdump -d ./test | grep \"<main>:\"", "r");
if (fp == NULL) {
puts("cannot get main address");
}
else {
char line[256];
if (fgets(line, sizeof(line), fp) == NULL) {
puts("no address !");
pclose(fp);
}
else {
unsigned long long main_addr;
pclose(fp);
errno = 0;
main_addr = strtoull(line, NULL, 16);
if (errno != 0)
puts("invalid address");
else {
int found = 0;
int status;
unsigned long prev_instr;
long long prev_addr = -1;
while(wait(&status), WIFSTOPPED(status))
{
struct user_regs_struct regs;
ptrace(PTRACE_GETREGS, pid, 0, &regs);
if (found |= (regs.rip == main_addr)) {
unsigned long instruction =
(unsigned long) ptrace(PTRACE_PEEKTEXT, pid, regs.rip, 0);
if (prev_addr != -1) {
/* longest instruction has 15 bytes on x86 */
int len = ((regs.rip > prev_addr) && ((regs.rip - prev_addr) <= 15))
? regs.rip - prev_addr : 100;
printf("%llx ", prev_addr);
while (prev_instr && len--) {
printf("%02x ", (unsigned) (prev_instr & 0xff));
prev_instr /= 256;
}
if (len > 15)
puts(" (?)");
else
putchar('\n');
}
prev_instr = instruction;
prev_addr = regs.rip;
}
ptrace(PTRACE_SINGLESTEP, pid, 0, 0);
}
}
}
}
}
now the output is :
400526 55
400527 48 89 e5
40052a bf d4 05 40 00
40052f e8 cc fe ff ff bf da 05 (?)
400400 ff 25 12 0c 20 00
400406 68 00 00 00 00
40040b e9 e0 ff ff ff ff 25 0a (?)
4003f0 ff 35 12 0c 20 00
4003f6 ff 25 14 0c 20 00 0f 1f (?)
7fe20cc1fe10 53
7fe20cc1fe11 48 89 e3
7fe20cc1fe14 48 83 e4 c0
7fe20cc1fe18 48 2b 25 31 df 20 00
7fe20cc1fe1f 48 89 04 24
7fe20cc1fe23 48 89 4c 24 08
...
to do more you have to know the code and length of each instruction call/jmp/conditional jmp/return.Note a code operation can be on 1 or 2 bytes.

Can't get data (payload) from sk_buff

I try to create a module for encrypt network packets but when try get data from sk_buff and print it in Hexa not get a correct packet.
I use this method to print data in Hexa :
void pkt_hex_dump(struct sk_buff *skb)
{
size_t len;
int rowsize = 16;
int i, l, linelen, remaining;
int li = 0;
uint8_t *data, ch;
printk("Packet hex dump:\n");
data = (uint8_t *) skb_mac_header(skb);
if (skb_is_nonlinear(skb)) {
len = skb->data_len;
} else {
len = skb->len;
}
remaining = len;
for (i = 0; i < len; i += rowsize) {
printk("%06d\t", li);
linelen = min(remaining, rowsize);
remaining -= rowsize;
for (l = 0; l < linelen; l++) {
ch = data[l];
//data[l] = '1';
printk(KERN_CONT "%02X ", (uint32_t) ch);
}
data += linelen;
li += 10;
printk(KERN_CONT "\n");
}
}
I used this sample to create a chat application.
And output when I send hello world message from client to server is :
[ 3981.963124] Packet hex dump:
[ 3981.963125] 000000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00
[ 3981.963128] 000010 00 34 6A 1F 40 00 40 06 D1 A2 7F 00 01 01 7F 00
[ 3981.963130] 000020 00 01 07 E4 BD 36 A2 52 E9 62 6D 40 3D FE 80 10
[ 3981.963133] 000030 02 00 FF 28
And I try to follow this solution but can't get any output.
My hook function
static unsigned int hfunc( void *priv, struct sk_buff *skb, const struct nf_hook_state *state){
struct iphdr *iph; /* IPv4 header */
struct tcphdr *tcph; /* TCP header */
uint16_t sport;
uint16_t dport;
struct ethhdr *ether = eth_hdr(skb);
iph = ip_hdr(skb); /* get IP header */
tcph = tcp_hdr(skb); /* get TCP header */
sport = ntohs(tcph->source);
dport = ntohs(tcph->dest);
/* Watch only port of interest */
if (dport == PTCP_WATCH_PORT || sport == PTCP_WATCH_PORT){
printk(KERN_INFO "UDP packet is received: {'sport': %d; 'dport': %d}\n", sport, dport);
printk("Source: %x:%x:%x:%x:%x:%x\n", ether->h_source[0], ether->h_source[1], ether->h_source[2], ether->h_source[3], ether->h_source[4], ether->h_source[5]);
printk("Destination: %x:%x:%x:%x:%x:%x\n", ether->h_dest[0], ether->h_dest[1], ether->h_dest[2], ether->h_dest[3], ether->h_dest[4], ether->h_dest[5]);
printk("Protocol: %d\n", ether->h_proto);
pkt_hex_dump(skb);
}
return NF_ACCEPT;
}

Why do I receive a Netlink ERRORMSG when using nl_recvmsgs?

I am trying to use nl_recvmsgs as a blocking function to receive Netlink messages from a kernel module.
In my example the client sends a message to the kernel and then it calls nl_recvmsgs_report()(is equal to nl_recvmsgs). Then the kernel module sends a return message. That message is successful received by the client.
Now I want the client to listen for more messages in the future and call nl_recvmsgs_report() again. The kernel did not sent any second message. But somehow an ERRORMSG is received by the client. This leads to a SEGFAULT at the client because he tries to parse the message not as an ERRORMSG.
If I check if the message type is 2 , and skip the message parsing, a third call of nl_recvmsgs_report() blocks perfectly fine.
Does someone know why the client receives this ERRORMSG?
Have a look at my github branch. Just call make, sudo insmod nlk.ko, ./nlclient I copied only the relevant parts here.
client code
nlclient.c main() sending and receiving part:
// setup netlink socket
sk = nl_socket_alloc();
nl_socket_disable_seq_check(sk); // disable sequence number check
genl_connect(sk);
int id = genl_ctrl_resolve(sk, DEMO_FAMILY_NAME);
struct nl_msg * msg;
// create a messgae
msg = nlmsg_alloc();
genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, id, 0, // hdrlen
0, // flags
DEMO_CMD, // numeric command identifier
DEMO_VERSION // interface version
);
nla_put_string(msg, DEMO_ATTR1_STRING, "hola");
nla_put_u16(msg, DEMO_ATTR2_UINT16, 0xf1);
// send it
nl_send_auto(sk, msg);
// handle reply
struct nl_cb * cb = NULL;
cb = nl_cb_alloc(NL_CB_CUSTOM);
//nl_cb_set_all(cb, NL_CB_DEBUG, NULL, NULL);
nl_cb_set_all(cb, NL_CB_CUSTOM, cb_handler, &cbarg);
nl_cb_err(cb, NL_CB_DEBUG, NULL, NULL);
int nrecv = nl_recvmsgs_report(sk, cb);
printf("cbarg %d nrecv %d\n", cbarg, nrecv);
printf("First test if it blocks here for incoming messages:\n");
nrecv = nl_recvmsgs_report(sk, cb);
printf("cbarg %d nrecv %d\n", cbarg, nrecv);
printf("Second test if it blocks here for incoming messages:\n");
nrecv = nl_recvmsgs_report(sk, cb);
printf("cbarg %d nrecv %d\n", cbarg, nrecv);
nlclient.c cb_handler() parsing the header and message
struct nlmsghdr * hdr = nlmsg_hdr(msg);
struct genlmsghdr * gnlh = nlmsg_data(hdr);
nl_msg_dump(msg, stderr);
if (hdr->nlmsg_type == 2) {
printf("hdr->nlmsg_type is ERROR. Skipping message parsing!\n");
} else {
int valid =
genlmsg_validate(hdr, 0, DEMO_ATTR_MAX, demo_gnl_policy);
printf("valid %d %s\n", valid, valid ? "ERROR" : "OK");
// one way
struct nlattr * attrs[DEMO_ATTR_MAX + 1];
if (genlmsg_parse(hdr, 0, attrs, DEMO_ATTR_MAX, demo_gnl_policy) < 0)
{
printf("genlsmg_parse ERROR\n");
}
else
{
printf("genlsmg_parse OK\n");
printf("attr1 %s\n", nla_get_string(attrs[DEMO_ATTR1_STRING]));
printf("attr2 %x\n", nla_get_u16(attrs[DEMO_ATTR2_UINT16]));
struct attr_custom * cp = (struct attr_custom *) nla_data(attrs[DEMO_ATTR3_CUSTOM]);
printf("attr3 %d %ld %f %lf\n", cp->a, cp->b, cp->c,cp->d);
}
}
// another way
printf("gnlh->cmd %d\n", gnlh->cmd); //--- DEMO_CMD_ECHO
int remaining = genlmsg_attrlen(gnlh, 0);
struct nlattr * attr = genlmsg_attrdata(gnlh, 0);
while (nla_ok(attr, remaining))
{
printf("remaining %d\n", remaining);
printf("attr # %p\n", attr); // nla_get_string(attr)
attr = nla_next(attr, &remaining);
}
kernel code
nlkernel.c demo_cmd() sending to client part:
/* send message back */
/* allocate some memory, since the size is not yet known use NLMSG_GOODSIZE */
skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
if (skb == NULL) {
goto out;
}
/* create the message */
msg_head =
genlmsg_put(skb, 0, info->snd_seq + 1, &demo_gnl_family, 0,
DEMO_CMD);
if (msg_head == NULL) {
rc = -ENOMEM;
goto out;
}
rc |= nla_put_string(skb, DEMO_ATTR1_STRING,"world");
rc |= nla_put_u16(skb, DEMO_ATTR2_UINT16, 0x1f);
cp.a = 1;
cp.b = 2;
cp.c = 3.0;
cp.d = 4.0;
rc |= nla_put(skb, DEMO_ATTR3_CUSTOM, sizeof(struct attr_custom), &cp);
if (rc != 0) {
goto out;
}
/* finalize the message */
genlmsg_end(skb, msg_head);
/* send the message back */
rc = genlmsg_unicast(&init_net, skb, info->snd_portid);
if (rc != 0) {
goto out;
}
return 0;
output
nlclient console output
./nlclient
-------------------------- BEGIN NETLINK MESSAGE ---------------------------
[NETLINK HEADER] 16 octets
.nlmsg_len = 76
.type = 27 <0x1b>
.flags = 0 <>
.seq = 1458476257
.port = 0
[GENERIC NETLINK HEADER] 4 octets
.cmd = 1
.version = 1
.unused = 0
[PAYLOAD] 56 octets
0a 00 01 00 77 6f 72 6c 64 00 00 00 06 00 02 00 ....world.......
1f 00 00 00 24 00 03 00 01 00 00 00 ff ff ff ff ....$...........
02 00 00 00 00 00 00 00 00 00 40 40 04 88 ff ff ..........##....
00 00 00 00 00 00 10 40 .......#
--------------------------- END NETLINK MESSAGE ---------------------------
valid 0 OK
genlsmg_parse OK
attr1 world
attr2 1f
attr3 1 2 3.000000 4.000000
gnlh->cmd 1
remaining 56
attr # 0x10df344
remaining 44
attr # 0x10df350
remaining 36
attr # 0x10df358
cbarg 123 nrecv 1
First test if it blocks here for incoming messages:
-------------------------- BEGIN NETLINK MESSAGE ---------------------------
[NETLINK HEADER] 16 octets
.nlmsg_len = 36
.type = 2 <ERROR>
.flags = 0 <>
.seq = 1458476256
.port = -1061151077
[ERRORMSG] 20 octets
.error = 0 "Success"
[ORIGINAL MESSAGE] 16 octets
.nlmsg_len = 16
.type = 27 <0x1b>
.flags = 5 <REQUEST,ACK>
.seq = 1458476256
.port = -1061151077
--------------------------- END NETLINK MESSAGE ---------------------------
hdr->nlmsg_type is ERROR. Skipping message parsing!
gnlh->cmd 0
cbarg 123 nrecv 1
Second test if it blocks here for incoming messages:
KERNEL syslog
kernel: [ 4694.318428] got demo_cmd
kernel: [ 4694.318430] attr1: hola
kernel: [ 4694.318431] attr2: f1
Sorry for taking so long.
The output is somewhat misleading. That's not an error message; it's an automatic ACK. Netlink defines ACKs to be "error" messages with error code 0.
(Zero is typical jargon for success in the C language.)
Since you're crafting an answer, you probably don't need ACKs anyway. You can stop your client from requesting ACKs by adding a call to nl_socket_disable_auto_ack().
I'd hack it close to sequence check disabling because it's kind of similar:
sk = nl_socket_alloc();
nl_socket_disable_seq_check(sk);
nl_socket_disable_auto_ack(sk);
genl_connect(sk);

Producing an erroneous WAV file

I have some code that captures audio using the PortAudio library, and then tries to package it into the WAV codec. I then attempt to convert that file to a FLAC file codec, but it keeps telling me it's not a valid .wav file.
wav.h:
#include <stdint.h>
#include <string.h>
/**
* #struct WaveHeader
* #brief A basic WAVE header
*/
typedef struct
{
char RIFF_marker[4];
uint32_t file_size;
char filetype_header[4];
char format_marker[4];
uint32_t data_header_length;
uint16_t format_type;
uint16_t number_of_channels;
uint32_t sample_rate;
uint32_t bytes_per_second;
uint16_t bytes_per_frame;
uint16_t bits_per_sample;
} WaveHeader;
WaveHeader *genericWAVHeader(uint32_t sample_rate, uint16_t bit_depth, uint16_t channels);
WaveHeader *retrieveWAVHeader(const void *ptr);
int writeWAVHeader(FILE* fd, WaveHeader *hdr);
int recordWAV(const char *fileName, WaveHeader *hdr, uint32_t duration);
capture.c:
#include <stdio.h>
#include <stdlib.h>
#include <portaudio.h>
#include <unistd.h>
#include <math.h>
#include "wav.h"
typedef struct
{
int frameIndex; /* Index into sample array. */
int maxFrameIndex;
char* recordedSamples;
} PAData;
WaveHeader *genericWAVHeader(uint32_t sample_rate, uint16_t bit_depth, uint16_t channels)
{
WaveHeader *hdr = malloc(sizeof(*hdr));
if (!hdr) return NULL;
memcpy(&hdr->RIFF_marker, "RIFF", 4);
memcpy(&hdr->filetype_header, "WAVE", 4);
memcpy(&hdr->format_marker, "fmt ", 4);
hdr->data_header_length = 16;
hdr->format_type = 1;
hdr->number_of_channels = channels;
hdr->sample_rate = sample_rate;
hdr->bytes_per_second = sample_rate * channels * bit_depth / 8;
hdr->bytes_per_frame = channels * bit_depth / 8;
hdr->bits_per_sample = bit_depth;
return hdr;
}
int writeWAVHeader(FILE* fd, WaveHeader *hdr)
{
if (!hdr) return -1;
fwrite(&hdr->RIFF_marker, sizeof(*hdr->RIFF_marker), sizeof(&hdr->RIFF_marker), fd);
fwrite(&hdr->file_size, sizeof(hdr->file_size), sizeof(&hdr->file_size), fd);
fwrite(&hdr->filetype_header, sizeof(*hdr->filetype_header), sizeof(&hdr->filetype_header), fd);
fwrite(&hdr->format_marker, sizeof(*hdr->format_marker), sizeof(&hdr->format_marker), fd);
fwrite(&hdr->data_header_length, sizeof(hdr->data_header_length), sizeof(&hdr->data_header_length), fd);
fwrite(&hdr->format_type, sizeof(hdr->format_type), sizeof(&hdr->format_type), fd);
fwrite(&hdr->number_of_channels, sizeof(hdr->number_of_channels), sizeof(&hdr->number_of_channels), fd);
fwrite(&hdr->sample_rate, sizeof(hdr->sample_rate), sizeof(&hdr->sample_rate), fd);
fwrite(&hdr->bytes_per_second, sizeof(hdr->bytes_per_second), sizeof(&hdr->bytes_per_second), fd);
fwrite(&hdr->bytes_per_frame, sizeof(hdr->bytes_per_frame), sizeof(&hdr->bytes_per_frame), fd);
fwrite(&hdr->bits_per_sample, sizeof(hdr->bits_per_sample), sizeof(&hdr->bits_per_sample), fd);
fwrite("data", 1, sizeof("data") - 1, fd);
uint32_t data_size = hdr->file_size - 36;
fwrite(&data_size, sizeof(data_size), sizeof(&data_size), fd);
return 0;
}
static int recordCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void *userData)
{
PAData *data = (PAData*) userData;
const char *rptr = (const char*) inputBuffer;
char *wptr = &data->recordedSamples[data->frameIndex * 2 /*channels*/];
long framesToCalc;
int finished;
unsigned long framesLeft = data->maxFrameIndex - data->frameIndex;
(void) outputBuffer; /* Prevent unused variable warnings. */
(void) timeInfo;
(void) statusFlags;
(void) userData;
if(framesLeft < framesPerBuffer)
{
framesToCalc = framesLeft;
finished = paComplete;
}
else
{
framesToCalc = framesPerBuffer;
finished = paContinue;
}
if(!inputBuffer)
{
for(long i = 0; i < framesToCalc; i++)
{
*wptr++ = 0; /* left */
*wptr++ = 0; /* right */
}
}
else
{
for(long i = 0; i < framesToCalc; i++)
{
*wptr++ = *rptr++; /* left */
*wptr++ = *rptr++; /* right */
}
}
data->frameIndex += framesToCalc;
return finished;
}
int recordWAV(const char *fileName, WaveHeader *hdr, uint32_t duration)
{
PaStreamParameters inputParameters;
PaStream* stream;
PaError err = paNoError;
PAData data;
int totalFrames;
int numSamples;
int numBytes;
char max, val;
double average;
printf("%d", hdr->bytes_per_second);
data.maxFrameIndex = totalFrames = duration * hdr->sample_rate; /* Record for a few seconds. */
data.frameIndex = 0;
numSamples = totalFrames * hdr->number_of_channels;
numBytes = numSamples;
data.recordedSamples = malloc(numBytes);
if(!data.recordedSamples)
{
printf("Could not allocate record array.\n");
goto done;
}
for(int i = 0; i < numSamples; i++) data.recordedSamples[i] = 0;
if((err = Pa_Initialize())) goto done;
inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
if (inputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default input device.\n");
goto done;
}
inputParameters.channelCount = 2; /* stereo input */
inputParameters.sampleFormat = 1;
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
inputParameters.hostApiSpecificStreamInfo = NULL;
/* Record some audio. -------------------------------------------- */
err = Pa_OpenStream(&stream, &inputParameters, NULL, hdr->sample_rate, paFramesPerBufferUnspecified, paClipOff, recordCallback, &data);
if(err) goto done;
if((err = Pa_StartStream(stream))) goto done;
puts("Now recording!! Please speak into the microphone.");
while((err = Pa_IsStreamActive(stream)) == 1)
{
Pa_Sleep(1000);
printf("index = %d\n", data.frameIndex);
}
if( err < 0 ) goto done;
err = Pa_CloseStream(stream);
if(err) goto done;
/* Measure maximum peak amplitude. */
max = 0;
average = 0.0;
for(int i = 0; i < numSamples; i++)
{
val = data.recordedSamples[i];
val = abs(val);
if( val > max )
{
max = val;
}
average += val;
}
average /= (double)numSamples;
{
FILE* fid = fopen(fileName, "wb");
if(!fid) printf("Could not open file.");
else
{
writeWAVHeader(fid, hdr);
fwrite(data.recordedSamples, hdr->number_of_channels, totalFrames, fid);
fclose(fid);
}
}
done:
Pa_Terminate();
if(data.recordedSamples) /* Sure it is NULL or valid. */
free(data.recordedSamples);
if(err)
{
fprintf(stderr, "An error occured while using the portaudio stream\n");
fprintf(stderr, "Error number: %d\n", err);
fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err));
err = 1; /* Always return 0 or 1, but no other return codes. */
}
return err;
}
Some tests I ran on the file:
$ xxd -g1 test.wav | head
0000000: 52 49 46 46 00 00 00 30 00 00 00 30 57 41 56 45 RIFF...0...0WAVE
0000010: 66 6d 74 20 10 00 00 00 01 00 02 00 e0 ab 00 00 fmt ............
0000020: 80 af 02 00 04 00 10 00 57 41 56 45 66 6d 74 20 ........WAVEfmt
0000030: 66 6d 74 20 10 00 00 00 10 00 00 00 01 00 02 00 fmt ............
0000040: e0 ab 00 00 80 af 02 00 04 00 10 00 00 00 00 80 ................
0000050: 37 3d 04 10 00 00 03 00 01 00 02 00 e0 ab 00 00 7=..............
0000060: 80 af 02 00 04 00 10 00 02 00 e0 ab 00 00 80 af ................
0000070: 02 00 04 00 10 00 00 00 e0 ab 00 00 80 af 02 00 ................
0000080: 04 00 10 00 00 00 00 80 37 3d 04 10 00 00 03 00 ........7=......
0000090: 00 00 00 00 00 00 00 00 80 af 02 00 04 00 10 00 ................
$ file test.wav
test.wav: RIFF (little-endian) data
$ stat -f %s test.wav
stat: %s: bad format
I'm not quite sure where I am going wrong. Am I not writing out the data correctly?
I don't know about the rest of it, but your fwrites should be like this:
fwrite( hdr->RIFF_marker, sizeof(hdr->RIFF_marker), 1, fd);
fwrite(&hdr->file_size, sizeof(hdr->file_size), 1, fd);
fwrite( hdr->filetype_header, sizeof(hdr->filetype_header), 1, fd);
fwrite( hdr->format_marker, sizeof(hdr->format_marker), 1, fd);
fwrite(&hdr->data_header_length, sizeof(hdr->data_header_length), 1, fd);
fwrite(&hdr->format_type, sizeof(hdr->format_type), 1, fd);
fwrite(&hdr->number_of_channels, sizeof(hdr->number_of_channels), 1, fd);
fwrite(&hdr->sample_rate, sizeof(hdr->sample_rate), 1, fd);
fwrite(&hdr->bytes_per_second, sizeof(hdr->bytes_per_second), 1, fd);
fwrite(&hdr->bytes_per_frame, sizeof(hdr->bytes_per_frame), 1, fd);
fwrite(&hdr->bits_per_sample, sizeof(hdr->bits_per_sample), 1, fd);
fwrite("data", 4, 1, fd);

Resources