有趣的可执行文件的二进制转储

出于某种原因,我在C中创建了简单的程序来输出给定输入的二进制表示:

int main() { char c; while(read(0,&c,1) > 0) { unsigned char cmp = 128; while(cmp) { if(c & cmp) write(1,"1",1); else write(1,"0",1); cmp >>= 1; } } return 0; } 

编译后:

 $ gcc bindump.c -o bindump 

我做了简单的测试来检查程序是否能够打印二进制文件:

 $ cat bindump | ./bindump | fold -b100 | nl 

输出如下: http : //pastebin.com/u7SasKDJ

我怀疑输出看起来像随机系列的1和0。 但是,输出部分似乎更有趣。 例如,看看第171行和第357行之间的输出。我想知道为什么与可执行文件的其他部分相比有很多零

我的架构是:

 $ lscpu Architecture: i686 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian CPU(s): 4 On-line CPU(s) list: 0-3 Thread(s) per core: 2 Core(s) per socket: 2 Socket(s): 1 Vendor ID: GenuineIntel CPU family: 6 Model: 28 Stepping: 10 CPU MHz: 1000.000 BogoMIPS: 3325.21 Virtualization: VT-x L1d cache: 24K L1i cache: 32K L2 cache: 512K 

当您将程序编译为Linux(以及许多其他unix系统)上的可执行文件时,它将以ELF格式编写。 ELF格式有许多部分,您可以使用readelf或objdump检查:

 readelf -a bindump | less 

例如,section .text包含CPU指令, .data全局变量, .bss未初始化的全局变量(它在ELF文件本身实际上是空的,但是在执行程序时在主内存中创建) .plt.got这是跳转表,调试信息等。

顺便说一句。 使用hexdump检查文件的二进制内容要方便得多:

 hexdump -C bindata | less 

在那里你可以看到从偏移量0x850开始(转储中大约​​第171行)有很多零,你也可以在右边看到ASCII表示。

让我们看看哪些部分对应于您感兴趣的块在0x850和0x1160之间(字段Off – 文件中的偏移量在这里很重要):

 > readelf -a bindata ... Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al ... [28] .shstrtab STRTAB 00000000 00074c 000106 00 0 0 1 [29] .symtab SYMTAB 00000000 000d2c 000440 10 30 45 4 ... 

您可以使用-x检查单个部分的内容:

 > readelf -x .symtab bindump | less 0x00000000 00000000 00000000 00000000 00000000 ................ 0x00000010 00000000 34810408 00000000 03000100 ....4........... 0x00000020 00000000 48810408 00000000 03000200 ....H........... 0x00000030 00000000 68810408 00000000 03000300 ....h........... 0x00000040 00000000 8c810408 00000000 03000400 ................ 0x00000050 00000000 b8810408 00000000 03000500 ................ 0x00000060 00000000 d8810408 00000000 03000600 ................ 

你会看到有很多零。 该部分由定义符号的18字节值(= -x输出中的一行)组成。 从readelf -a你可以看到它有68个条目,其中前27个(不包括第一个)是SECTION类型:

 Symbol table '.symtab' contains 68 entries: Num: Value Size Type Bind Vis Ndx Name 0: 00000000 0 NOTYPE LOCAL DEFAULT UND 1: 08048134 0 SECTION LOCAL DEFAULT 1 2: 08048148 0 SECTION LOCAL DEFAULT 2 3: 08048168 0 SECTION LOCAL DEFAULT 3 4: 0804818c 0 SECTION LOCAL DEFAULT 4 ... 

根据规范 (第1-18页),每个条目具有以下格式:

 typedef struct { Elf32_Word st_name; Elf32_Addr st_value; Elf32_Word st_size; unsigned char st_info; unsigned char st_other; Elf32_Half st_shndx; } Elf32_Sym; 

在这里没有详细说明,我认为这里重要的是st_name和st_size都是这些SECTION条目的零。 两者都是32位数字,这意味着在这个特定部分中有很多零。

这不是一个真正的编程问题,但是……

二进制文件通常由不同的部分组成:代码,数据,调试信息等。由于这些部分的内容因类型而异,我几乎希望它们看起来不同。

即符号表由二进制中的地址偏移组成。 如果我正确读取了你的lspci ,你就是32位系统。 这意味着每个偏移量有四个字节,并且给定程序的大小,在大多数情况下,这些字节中的两个将为零。 还有更多像这样的效果。

你没有strip你的程序,这意味着二进制文件中仍然存在大量信息(符号表等)。 尝试剥离二进制文件并再次查看它。

    Interesting Posts