raw binary文件探秘

来源:互联网 发布:万网域名证书生成 编辑:程序博客网 时间:2024/05/30 23:04
Linux下的目标文件、动态库文件、可执行文件,其格式为elf格式。
elf文件是有结构的文件,其内部有丰富的信息,例如,可能包含了可执行文件的入口地址,各个节的起始地址,可重定位信息,还可能包含指令与代码行的对应关系(用于调试)。
内核则利用elf文件中的相关信息,加载运行可执行文件。
然而内核映像,u-boot映像这些特殊的文件,则是raw_binary文件。这当然有他的原因。
以u-boot为例,cpu通电后,就开始执行指令。而首先要执行的就是u-boot中的指令。然而cpu不具备解析elf文件的能力,他只知道执行指令。因此,只好给他一块纯粹的机器码让他跑。
因此,u-boot映像就做成了raw_binary文件。
raw_binary文件是没有任何结构的,其内容就是赤裸裸的代码与数据的组合体。
因此,不具备可解析性。


下面以一个简单的小例子,来看看raw_binary文件的面貌。

raw_binary.c是个简单的小程序,其内容如下:

char the_data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };char bss_data1[3], bss_data2[4];/* 为了初始化bss节,这里借助链接脚本中创建的两个符号,以得到bss节的地址区间 */extern char __bss_start[], __bss_end[];void init_bss_area();void my_test_func(){    /* 为了能以raw binary形式运行,程序自己实现对bss节的清零 */    init_bss_area();         the_data[1]++;        while (1)    {        asm volatile ("nop");    }}void init_bss_area(){    int i, len = __bss_end - __bss_start;    for (i=0; i<len; i++)        __bss_start[i] = 0;}

我们通过如下命令将上述代码编译成一个可执行文件。

[root@localhost raw_binary]# gcc -O2 -c raw_binary.c  -o  raw_binary.o[root@localhost raw_binary]# ld -T raw_binary.lds raw_binary.o  -o raw_binary.exe

注意,上述编译过程中,我们用到了一个链接脚本raw_binary.lds。其内容如下:

ENTRY(my_test_func)SECTIONS{    /* 这里设置代码段从2M开始 */    . = 0x200000;    .text :          {        *(.text)    }        /* 我们让数据段的虚拟地址空间开始于8字节对齐的地方 */    . = ALIGN(8);    .data :    {        *(.data)    }    __bss_start = .; /* 创建一个符号,以方便C代码得到bss起始地址 */    .bss :     {        *(.bss)    }    __bss_end = .; /* 创建一个符号,以方便C代码得到bss结束地址 */}

之所以这样做,是为了生成一个内容非常简单的可执行文件,以便于看清raw_binary文件的面貌。通过本方法生成的这个可执行程序与一般的可执行程序不大一样,他的入口是my_test_func,并且他不链接任何C库的东西。虽然他与别的程序不大一样,但从内核的角度或elf可执行文件的角度来看,并没有什么特殊的地方。因为他同样由多个section构成,同样完成了重定位,同样具有一个入口。 而站在这个角度上来看,一般的普通可执行程序也都是这样的。

另外,此程序为了在raw binary形式下也能运行,通过一些技巧自己初始化了bss段。

下面运行这个小程序,看看效果。由于没有链接C库,因此不方便打印信息。

只好通过ps简单看看他的存在。从命令输出可以看出,此程序是可以跑起来的。最后我们通过kill命令终止了此程序。

[root@localhost raw_binary]# ./raw_binary.exe &[1] 2205[root@localhost raw_binary]# ps -ef | grep -v grep | grep raw_binaryroot      2205  1605 98 23:14 pts/0    00:00:36 ./raw_binary.exe[root@localhost raw_binary]# kill -9 2205

下面我们将此可执行程序通过如下命令转换为raw_binary文件。

objcopy -O binary raw_binary.exe  raw_binary.rb

好了,看看转换得到的raw_binary.rb文件的内容吧:

b8 a7 00 20 00 31 d2 2d a0 00 20 00 85 c0 7e 0e c6 82 a0 00 20 00 00 83 c2 01 39 c2 75 f2 80 05 99 00 20 00 01 8d 76 00 90 eb fd 90 8d 74 26 00 ba a7 00 20 00 31 c0 81 ea a0 00 20 00 85 d2 7e 15 8d b4 26 00 00 00 00 c6 80 a0 00 20 00 00 83 c0 01 39 d0 75 f2 f3 c3 14 00 00 00 00 00 00 00 01 7a 52 00 01 7c 08 01 1b 0c 04 04 88 01 00 00 10 00 00 00 1c 00 00 00 88 ff ff ff 2b 00 00 00 00 00 00 00 10 00 00 00 30 00 00 00 a4 ff ff ff 28 00 00 00 00 00 00 00 01 02 03 04 05 06 07 08 

从上面的显示,很难看出raw binary文件的内容。不过我们通过以下objdump输出的raw_binary.exe的内容,就能看出端倪了:

raw_binary.bin文件的内容,就是.text、.eh_frame(是个没起作用的节)、.data这三个section的内容拼接到一块组成的。并且,其内容就是赤裸裸的节的内容,没有任何描述信息。

这三个节在elf文件中,处于一片连续的地址空间中。因此,如果可执行文件raw_binary.exe被加载执行,这三个节是位于一片连续的虚拟地址空间中的。

由于raw_binary文件,是按节的地址由低至高,将3个节的内容拼接到一块的,因此在raw_binary文件中,三个节的内容在文件中也是连续的。

同理,如果在cpu刚启动时,将此raw binary文件的内容拷贝到内存的0x200000物理地址处,那么三个节的内容将位于一片连续的物理地址区间中。

然后如果再跳转到0x200000处执行,那么这个raw binary映像就能跑起来了。

并且程序对变量的访问也将是正常的,因为从objdump输出可以看出,重定位是成功的。
因为the_data的地址是0x200038,而my_test_func函数的指令addb   $0x1,0x200039

正是在执行“the_data[1]++;”。

bss初始化代码也是正确的,他正是在对 0x2000a0~0x2000a7地址区间的内存做清零操作。

[root@localhost raw_binary]# objdump -D raw_binary.exe raw_binary.exe:     file format elf32-i386Disassembly of section .text:00200000 <my_test_func>:  200000:       b8 a7 00 20 00          mov    $0x2000a7,%eax  200005:       31 d2                   xor    %edx,%edx  200007:       2d a0 00 20 00          sub    $0x2000a0,%eax  20000c:       85 c0                   test   %eax,%eax  20000e:       7e 0e                   jle    20001e <my_test_func+0x1e>  200010:       c6 82 a0 00 20 00 00    movb   $0x0,0x2000a0(%edx)  200017:       83 c2 01                add    $0x1,%edx  20001a:       39 c2                   cmp    %eax,%edx  20001c:       75 f2                   jne    200010 <my_test_func+0x10>  20001e:       80 05 99 00 20 00 01    addb   $0x1,0x200099  200025:       8d 76 00                lea    0x0(%esi),%esi  200028:       90                      nop  200029:       eb fd                   jmp    200028 <my_test_func+0x28>  20002b:       90                      nop  20002c:       8d 74 26 00             lea    0x0(%esi,%eiz,1),%esi00200030 <init_bss_area>:  200030:       ba a7 00 20 00          mov    $0x2000a7,%edx  200035:       31 c0                   xor    %eax,%eax  200037:       81 ea a0 00 20 00       sub    $0x2000a0,%edx  20003d:       85 d2                   test   %edx,%edx  20003f:       7e 15                   jle    200056 <init_bss_area+0x26>  200041:       8d b4 26 00 00 00 00    lea    0x0(%esi,%eiz,1),%esi  200048:       c6 80 a0 00 20 00 00    movb   $0x0,0x2000a0(%eax)  20004f:       83 c0 01                add    $0x1,%eax  200052:       39 d0                   cmp    %edx,%eax  200054:       75 f2                   jne    200048 <init_bss_area+0x18>  200056:       f3 c3                   repz ret Disassembly of section .eh_frame:00200058 <.eh_frame>:  200058:       14 00                   adc    $0x0,%al  20005a:       00 00                   add    %al,(%eax)  20005c:       00 00                   add    %al,(%eax)  20005e:       00 00                   add    %al,(%eax)  200060:       01 7a 52                add    %edi,0x52(%edx)  200063:       00 01                   add    %al,(%ecx)  200065:       7c 08                   jl     20006f <init_bss_area+0x3f>  200067:       01 1b                   add    %ebx,(%ebx)  200069:       0c 04                   or     $0x4,%al  20006b:       04 88                   add    $0x88,%al  20006d:       01 00                   add    %eax,(%eax)  20006f:       00 10                   add    %dl,(%eax)  200071:       00 00                   add    %al,(%eax)  200073:       00 1c 00                add    %bl,(%eax,%eax,1)  200076:       00 00                   add    %al,(%eax)  200078:       88 ff                   mov    %bh,%bh  20007a:       ff                      (bad)    20007b:       ff 2b                   ljmp   *(%ebx)  20007d:       00 00                   add    %al,(%eax)  20007f:       00 00                   add    %al,(%eax)  200081:       00 00                   add    %al,(%eax)  200083:       00 10                   add    %dl,(%eax)  200085:       00 00                   add    %al,(%eax)  200087:       00 30                   add    %dh,(%eax)  200089:       00 00                   add    %al,(%eax)  20008b:       00 a4 ff ff ff 28 00    add    %ah,0x28ffff(%edi,%edi,8)  200092:       00 00                   add    %al,(%eax)  200094:       00 00                   add    %al,(%eax)        ...Disassembly of section .data:00200098 <the_data>:  200098:       01 02                   add    %eax,(%edx)  20009a:       03                      .byte 0x3  20009b:       04 05                   add    $0x5,%al  20009d:       06                      push   %es  20009e:       07                      pop    %es  20009f:       08                      .byte 0x8Disassembly of section .bss:002000a0 <bss_data2>:  2000a0:       00 00                   add    %al,(%eax)        ...002000a4 <bss_data1>:  2000a4:       00 00                   add    %al,(%eax)        ...Disassembly of section .comment:00000000 <.comment>:   0:   47                      inc    %edi   1:   43                      inc    %ebx   2:   43                      inc    %ebx   3:   3a 20                   cmp    (%eax),%ah   5:   28 47 4e                sub    %al,0x4e(%edi)   8:   55                      push   %ebp   9:   29 20                   sub    %esp,(%eax)   b:   34 2e                   xor    $0x2e,%al   d:   38 2e                   cmp    %ch,(%esi)   f:   32 00                   xor    (%eax),%al[root@localhost raw_binary]# 


0 0
原创粉丝点击