在 C 中剖析二进制文件

Dissecting a binary file in C

我正在做作业,我需要剖析一个二进制文件,从 header 数据中检索源地址。我能够按照指示从文件中获取十六进制数据以写出,但我无法理解我正在查看的内容。这是我使用的打印输出代码。

FILE *ptr_myfile;
char buf[8];

ptr_myfile = fopen("packets.1","rb");
if (!ptr_myfile)
{
    printf("Unable to open file!");
    return 1;
}

size_t rb;
do {
    rb = fread(buf, 1, 8, ptr_myfile);
    if( rb ) {
        size_t i;
        for(i = 0; i < rb; ++i) {
                printf("%02x", (unsigned int)buf[i]);
        }
        printf("\n");
    }
 } while( rb );

这是输出的一小部分:

120000003c000000
4500003c195d0000
ffffff80011b60ffffff8115250b
4a7d156708004d56
0001000561626364
65666768696a6b6c
6d6e6f7071727374
7576776162636465
666768693c000000
4500003c00000000
ffffffff01ffffffb5ffffffbc4a7d1567
ffffff8115250b00005556
0001000561626364
65666768696a6b6c
6d6e6f7071727374
7576776162636465
666768693c000000
4500003c195d0000
ffffff8001775545ffffffcfffffffbe29
ffffff8115250108004d56
0001000561626364
65666768696a6b6c
6d6e6f7071727374
7576776162636465
666768693c000000
4500003c195f0000
......

所以我们使用这张图来帮助完成作业

我真的很难将二进制文件中的信息转换为我可以管理的有用的东西,并且搜索该网站并没有给我太多帮助。我只是需要一些帮助,让我朝着正确的方向前进。

好的,看起来你实际上是在根据图表反转 IP 数据包的一部分。此图基于 32 位字,每个位都显示为沿着水平标尺的小 'ticks',看起来在顶部。字节显示为顶部标尺上的大'ticks'。

所以,如果你要读取文件的第一个字节,low-order 半字节(low-order 四个字节)包含版本,高位半字节包含 32 的数字header 中的位词(假设我们可以将其解释为 IP header)。

所以,从你的图中,你可以看到源地址在第四个字中,所以要读取这个,你可以将文件指向这个点并读取四个字节。所以在 pseudo-code 你应该可以这样做:

    fp = fopen("the file name")
    fseek(fp, 12)                  // advance the file pointer 12 bytes
    fread(buf, 1, 4, fp)           // read in four bytes from the file.

现在你应该在 buf 中有了源地址。

好的,为了更具体一点,这是我从家庭网络捕获的一个数据包:

    0000   00 15 ff 2e 93 78 bc 5f f4 fc e0 b6 08 00 45 00  .....x._......E.
    0010   00 28 18 c7 40 00 80 06 00 00 c0 a8 01 05 5e 1f  .(..@.........^.
    0020   1d 9a fd d3 00 50 bd 72 7e e9 cf 19 6a 19 50 10  .....P.r~...j.P.
    0030   41 10 3d 81 00 00                                A.=...

前 14 个字节是 EthernetII header,前六个字节 (00 15 ff 2e 93 78) 是目标 MAC 地址,接下来的六个字节 (bc 5f f4 fc e0 b6) 是源地址MAC地址和新的两个字节(08 00)表示下一个header是IP类型。

接下来的二十个字节是IPheader(如图所示),这些字节是:

    0000   45 00 00 28 18 c7 40 00 80 06 00 00 c0 a8 01 05  E..(..@.........
    0010   5e 1f 1d 9a                                      ^...

所以要解释这个让我们看看 4 字节的单词。

第一个4字节的字(45 00 00 28),根据你的图是:

     first byte     : version & length, we have 0x45 meaning IPv4, and 5 4-byte words in length
     second byte    : Type of Service 0x00
     3rd & 4th bytes: total length 0x00 0x28 or 40 bytes.

第二个4字节的字(18 c7 40 00),根据你的图是:

     1st & 2nd bytes: identification 0x18 0xc7
     3rd & 4th bytes: flags (3-bits) & fragmentation offset (13-bits)
                      flags - 0x02  0x40 is 0100 0000 in binary, and taking the first three bits 010 gives us 0x02 for the flags.
                      offset - 0x00

第三个4字节字(80 06 00 00),根据你的图是:

     first byte     : TTL, 0x80 or 128 hops 
     second byte    : protocol 0x06 or TCP
     3rd & 4th bytes: 0x00 0x00 

第4个4字节字(c0 a8 01 05),按你的图是:

     1st to 4th bytes:  source address, in this case 192.168.1.5
                        notice that each byte corresponds to one of the octets in the IP address.

第5个4字节字(5e 1f 1d 9a),根据你的图是:

     1st to 4th bytes: destination address, in this case 94.31.29.154

一开始做这种类型的编程有点混乱,我建议手动进行几次配对(就像我上面做的那样)以掌握它。

最后一点,在这行代码 printf("%02x", (unsigned int)buf[i]); 中,我建议将其更改为 printf("%02x ", (unsigned char)buf[i]);。请记住,buf 数组中的每个元素代表从文件中读取的单个字节。

希望这对您有所帮助, T.