可执行文件中公共字符串的含义?
Meaning of a Common String In Executables?
在 Mach-O 64 位可执行文件和 ELF 64 位 LSB 可执行文件中似乎有一些看起来相似的长字母数字字符串以及其他非字母数字符号:
cat /bin/bash | grep -c "AWAVAUATSH"
有 181 个结果,
cat /usr/bin/gzip | grep -c "AWAVAUATSH"
有 9 个结果。
这些字符串是什么?
有趣的问题。由于我不知道答案,以下是我找出答案的步骤:
字符串出现在文件中的什么位置?
strings -otx /bin/gzip | grep AWAVAUATUSH
35e0 AWAVAUATUSH
69a0 AWAVAUATUSH
7920 AWAVAUATUSH
8900 AWAVAUATUSH
92a0 AWAVAUATUSH
在哪个部分?
readelf -WS /bin/gzip
There are 28 section headers, starting at offset 0x16860:
Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 0] NULL 0000000000000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 0000000000400238 000238 00001c 00 A 0 0 1
[ 2] .note.ABI-tag NOTE 0000000000400254 000254 000020 00 A 0 0 4
[ 3] .note.gnu.build-id NOTE 0000000000400274 000274 000024 00 A 0 0 4
[ 4] .gnu.hash GNU_HASH 0000000000400298 000298 000038 00 A 5 0 8
[ 5] .dynsym DYNSYM 00000000004002d0 0002d0 000870 18 A 6 1 8
[ 6] .dynstr STRTAB 0000000000400b40 000b40 000360 00 A 0 0 1
[ 7] .gnu.version VERSYM 0000000000400ea0 000ea0 0000b4 02 A 5 0 2
[ 8] .gnu.version_r VERNEED 0000000000400f58 000f58 000080 00 A 6 1 8
[ 9] .rela.dyn RELA 0000000000400fd8 000fd8 000090 18 A 5 0 8
[10] .rela.plt RELA 0000000000401068 001068 0007e0 18 A 5 12 8
[11] .init PROGBITS 0000000000401848 001848 00001a 00 AX 0 0 4
[12] .plt PROGBITS 0000000000401870 001870 000550 10 AX 0 0 16
[13] .text PROGBITS 0000000000401dc0 001dc0 00f1ba 00 AX 0 0 16
[14] .fini PROGBITS 0000000000410f7c 010f7c 000009 00 AX 0 0 4
... etc.
从上面的输出中,我们看到 AWAVAUATUSH
的所有实例都在 .text
部分(涵盖文件的 [0x1dc0, 0x10f7a)
偏移量。
因为这是 .text
,我们希望在那里找到可执行指令。我们感兴趣的地址是0x401dc0
(.text
地址)+0x35e0
(AWAVAUATUSH
在文件中的偏移量)-0x1dc0
([=18的偏移量) =] 在文件中)== 0x4035e0
.
首先,让我们检查一下上面的算法是否正确:
gdb -q /bin/gzip
(gdb) x/s 0x4035e0
0x4035e0: "AWAVAUATUSH34HdH3[=12=]4%("
是的,是的。接下来,那里的说明是什么?
(gdb) x/20i 0x4035e0
0x4035e0: push %r15
0x4035e2: push %r14
0x4035e4: push %r13
0x4035e6: push %r12
0x4035e8: push %rbp
0x4035e9: push %rbx
0x4035ea: sub [=13=]x48,%rsp
0x4035ee: mov %fs:0x28,%rax
0x4035f7: mov %rax,0x38(%rsp)
0x4035fc: xor %eax,%eax
0x4035fe: mov 0x213363(%rip),%rax # 0x616968
0x403605: mov %rdi,(%rsp)
0x403609: mov %rax,0x212cf0(%rip) # 0x616300
0x403610: cmpb [=13=]x7a,(%rax)
0x403613: je 0x403730
0x403619: mov [=13=]x616300,%ebx
0x40361e: mov (%rsp),%rdi
0x403622: callq 0x4019f0 <strlen@plt>
0x403627: cmp [=13=]x20,%eax
0x40362a: mov %rax,0x8(%rsp)
这些确实看起来像正常的可执行指令。 push %r15
的操作码是什么? This table表明0x41
,0x57
确实是push %r15
,而这些操作码只是恰好拼写AW
在ASCII
。类似地,push %r14
被编码为 0x41
、0x56
,这恰好拼写为 AV
。等等
P.S。我的 gzip 版本被完全剥离,这就是为什么 GDB 在上面的反汇编中没有显示任何符号。如果我改用非剥离版本,我会看到:
strings -o -tx gzip | grep AWAVAUATUSH | head -1
6be0 AWAVAUATUSH
readelf -WS gzip | grep text
[13] .text PROGBITS 0000000000401b00 001b00 00d102 00 AX 0 0 16
所以字符串还在.text
.
gdb -q ./gzip
(gdb) p/a 0x0000000000401b00 + 0x6be0 - 0x001b00
= 0x406be0 <inflate_dynamic>
(gdb) disas/r 0x406be0
Dump of assembler code for function inflate_dynamic:
0x0000000000406be0 <+0>: 41 57 push %r15
0x0000000000406be2 <+2>: 41 56 push %r14
0x0000000000406be4 <+4>: 41 55 push %r13
0x0000000000406be6 <+6>: 41 54 push %r12
0x0000000000406be8 <+8>: 55 push %rbp
0x0000000000406be9 <+9>: 53 push %rbx
0x0000000000406bea <+10>: 48 81 ec 38 05 00 00 sub [=15=]x538,%rsp
...
现在您可以清楚地看到 ASCII
0x4157415641554154...
操作码序列。
P.P.S。最初的问题询问 AWAVAUATSH
,它确实出现在我的 Mach-O bash
和 gzip
中,但没有出现在 Linux 中。相反,AWAVAUATUSH
没有出现在我的 Mach-O 二进制文件中。
答案是一样的。 AWAVAUATSH
序列与 AWAVAUATUSH
相同,但省略了 push %rbp
。
P.P.P.S 这里有一些其他 "fun" 相同性质的字符串:
strings /bin/bash | grep '^A.A.A.' | sort | uniq -c | sort -nr | head
44 AWAVAUATUSH
27 AVAUATUSH
16 AWAVAUA
15 AVAUATUH
14 AWAVAUI
14 AWAVAUATUH
12 AWAVAUATI
8 AWAVAUE1
8 AVAUATI
6 AWAVAUATU
在 Mach-O 64 位可执行文件和 ELF 64 位 LSB 可执行文件中似乎有一些看起来相似的长字母数字字符串以及其他非字母数字符号:
cat /bin/bash | grep -c "AWAVAUATSH"
有 181 个结果,
cat /usr/bin/gzip | grep -c "AWAVAUATSH"
有 9 个结果。
这些字符串是什么?
有趣的问题。由于我不知道答案,以下是我找出答案的步骤:
字符串出现在文件中的什么位置?
strings -otx /bin/gzip | grep AWAVAUATUSH
35e0 AWAVAUATUSH
69a0 AWAVAUATUSH
7920 AWAVAUATUSH
8900 AWAVAUATUSH
92a0 AWAVAUATUSH
在哪个部分?
readelf -WS /bin/gzip
There are 28 section headers, starting at offset 0x16860:
Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 0] NULL 0000000000000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 0000000000400238 000238 00001c 00 A 0 0 1
[ 2] .note.ABI-tag NOTE 0000000000400254 000254 000020 00 A 0 0 4
[ 3] .note.gnu.build-id NOTE 0000000000400274 000274 000024 00 A 0 0 4
[ 4] .gnu.hash GNU_HASH 0000000000400298 000298 000038 00 A 5 0 8
[ 5] .dynsym DYNSYM 00000000004002d0 0002d0 000870 18 A 6 1 8
[ 6] .dynstr STRTAB 0000000000400b40 000b40 000360 00 A 0 0 1
[ 7] .gnu.version VERSYM 0000000000400ea0 000ea0 0000b4 02 A 5 0 2
[ 8] .gnu.version_r VERNEED 0000000000400f58 000f58 000080 00 A 6 1 8
[ 9] .rela.dyn RELA 0000000000400fd8 000fd8 000090 18 A 5 0 8
[10] .rela.plt RELA 0000000000401068 001068 0007e0 18 A 5 12 8
[11] .init PROGBITS 0000000000401848 001848 00001a 00 AX 0 0 4
[12] .plt PROGBITS 0000000000401870 001870 000550 10 AX 0 0 16
[13] .text PROGBITS 0000000000401dc0 001dc0 00f1ba 00 AX 0 0 16
[14] .fini PROGBITS 0000000000410f7c 010f7c 000009 00 AX 0 0 4
... etc.
从上面的输出中,我们看到 AWAVAUATUSH
的所有实例都在 .text
部分(涵盖文件的 [0x1dc0, 0x10f7a)
偏移量。
因为这是 .text
,我们希望在那里找到可执行指令。我们感兴趣的地址是0x401dc0
(.text
地址)+0x35e0
(AWAVAUATUSH
在文件中的偏移量)-0x1dc0
([=18的偏移量) =] 在文件中)== 0x4035e0
.
首先,让我们检查一下上面的算法是否正确:
gdb -q /bin/gzip
(gdb) x/s 0x4035e0
0x4035e0: "AWAVAUATUSH34HdH3[=12=]4%("
是的,是的。接下来,那里的说明是什么?
(gdb) x/20i 0x4035e0
0x4035e0: push %r15
0x4035e2: push %r14
0x4035e4: push %r13
0x4035e6: push %r12
0x4035e8: push %rbp
0x4035e9: push %rbx
0x4035ea: sub [=13=]x48,%rsp
0x4035ee: mov %fs:0x28,%rax
0x4035f7: mov %rax,0x38(%rsp)
0x4035fc: xor %eax,%eax
0x4035fe: mov 0x213363(%rip),%rax # 0x616968
0x403605: mov %rdi,(%rsp)
0x403609: mov %rax,0x212cf0(%rip) # 0x616300
0x403610: cmpb [=13=]x7a,(%rax)
0x403613: je 0x403730
0x403619: mov [=13=]x616300,%ebx
0x40361e: mov (%rsp),%rdi
0x403622: callq 0x4019f0 <strlen@plt>
0x403627: cmp [=13=]x20,%eax
0x40362a: mov %rax,0x8(%rsp)
这些确实看起来像正常的可执行指令。 push %r15
的操作码是什么? This table表明0x41
,0x57
确实是push %r15
,而这些操作码只是恰好拼写AW
在ASCII
。类似地,push %r14
被编码为 0x41
、0x56
,这恰好拼写为 AV
。等等
P.S。我的 gzip 版本被完全剥离,这就是为什么 GDB 在上面的反汇编中没有显示任何符号。如果我改用非剥离版本,我会看到:
strings -o -tx gzip | grep AWAVAUATUSH | head -1
6be0 AWAVAUATUSH
readelf -WS gzip | grep text
[13] .text PROGBITS 0000000000401b00 001b00 00d102 00 AX 0 0 16
所以字符串还在.text
.
gdb -q ./gzip
(gdb) p/a 0x0000000000401b00 + 0x6be0 - 0x001b00
= 0x406be0 <inflate_dynamic>
(gdb) disas/r 0x406be0
Dump of assembler code for function inflate_dynamic:
0x0000000000406be0 <+0>: 41 57 push %r15
0x0000000000406be2 <+2>: 41 56 push %r14
0x0000000000406be4 <+4>: 41 55 push %r13
0x0000000000406be6 <+6>: 41 54 push %r12
0x0000000000406be8 <+8>: 55 push %rbp
0x0000000000406be9 <+9>: 53 push %rbx
0x0000000000406bea <+10>: 48 81 ec 38 05 00 00 sub [=15=]x538,%rsp
...
现在您可以清楚地看到 ASCII
0x4157415641554154...
操作码序列。
P.P.S。最初的问题询问 AWAVAUATSH
,它确实出现在我的 Mach-O bash
和 gzip
中,但没有出现在 Linux 中。相反,AWAVAUATUSH
没有出现在我的 Mach-O 二进制文件中。
答案是一样的。 AWAVAUATSH
序列与 AWAVAUATUSH
相同,但省略了 push %rbp
。
P.P.P.S 这里有一些其他 "fun" 相同性质的字符串:
strings /bin/bash | grep '^A.A.A.' | sort | uniq -c | sort -nr | head
44 AWAVAUATUSH
27 AVAUATUSH
16 AWAVAUA
15 AVAUATUH
14 AWAVAUI
14 AWAVAUATUH
12 AWAVAUATI
8 AWAVAUE1
8 AVAUATI
6 AWAVAUATU