出于某种原因,我用 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
例如.text
段包含CPU指令,.data
全局变量,.bss
未初始化的全局变量(实际上是空的) ELF文件本身,但在程序执行时在主内存中创建),.plt
和.got
是跳转表,调试信息等。
顺便说一句。使用 hexdump 检查文件的二进制内容要方便得多:
hexdump -C bindata | less
您可以看到从偏移量 0x850(大约转储中的第 171 行)开始有很多零,您还可以在右侧看到 ASCII 表示。
让我们看看哪些部分对应于 0x850 和 0x1160 之间您感兴趣的 block (字段 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
...
根据specification (第 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;
这里不赘述太多细节,我认为这里重要的是这些 SECTION 条目的 st_name 和 st_size 都是零。两者都是 32 位数字,这意味着在这个特定部分中有很多零。
关于c - 有趣的可执行文件二进制转储,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22438057/