raw binary文件探秘
来源:互联网 发布:万网域名证书生成 编辑:程序博客网 时间:2024/05/30 23:04
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]#
- raw binary文件探秘
- Linux下如何反汇编arm raw binary文件
- RAW文件的读取
- RAW文件读写
- RAW文件的读取
- raw文件的使用
- RAW文件读写
- POST提交RAW文件
- 读取raw文件
- 获取raw文件路径
- raw 文件读取
- 读取raw下的文件
- 使用raw文件模拟硬盘
- 使用OpenCV打开RAW文件
- 医学RAW文件的读取
- assets和raw文件路径
- 获取Raw和assets文件
- 读取raw中.properties文件
- 进制转换
- 读书笔记《Effective C++》条款03:尽可能使用const
- myeclipse的problem报错,工程出现了一个感叹号
- easyui datagrid combobox多选第一个时最前面会多加“,”逗号
- leetcode 13. Roman to Integer
- raw binary文件探秘
- webstrom注册方法 不用下载插件
- 试探用法
- 5.文件操作 --- 系统调用
- 【C语言】(windows.h)MessageBox函数
- 湖大程序设计题5
- Android 实现拨打电话
- Uva11059—最大乘积
- 手持端车牌识别app技术