事实上,他们可能使用了ElfKickersstrip
包中的软件。根据文件:sstrip
README
sstrip 是一个小型实用程序,用于删除 ELF 文件末尾不属于程序内存映像的内容。
大多数 ELF 可执行文件都使用程序头表和节头表构建。然而,只有前者是操作系统加载、链接和执行程序所必需的。sstrip 尝试提取 ELF 头、程序头表及其内容,将其他所有内容留在位桶中。它只能删除文件最后出现的部分,在要保存的部分之后。然而,这几乎总是包括节头表,以及一些不涉及程序加载和执行的其他节。
应该注意的是,大多数使用 ELF 文件的程序都依赖于节头表作为文件内容的索引。因此,当使用没有节头表的可执行文件时,诸如 gdb 和 objdump 之类的实用程序通常具有有限的功能。其他一些公用事业公司可能根本拒绝与他们合作。
事实上,sstrip
从可执行文件中删除所有节信息并保持可执行文件仍然可用。
但是让我们看看我们可以达到的不同级别是条带。
无剥离
让我们考虑一个没有剥离全部的程序(类似于问题中看到的那个程序)。
$> objdump -tT ./crackme
./crackme: file format elf32-i386
SYMBOL TABLE:
08048134 l d .interp 00000000 .interp
08048148 l d .note.ABI-tag 00000000 .note.ABI-tag
08048168 l d .note.gnu.build-id 00000000 .note.gnu.build-id
0804818c l d .gnu.hash 00000000 .gnu.hash
080481ac l d .dynsym 00000000 .dynsym
0804822c l d .dynstr 00000000 .dynstr
...
080497dc g .bss 00000000 _end
08048390 g F .text 00000000 _start
080485f8 g O .rodata 00000004 _fp_hw
080497d8 g .bss 00000000 __bss_start
08048490 g F .text 00000000 main
00000000 w *UND* 00000000 _Jv_RegisterClasses
080497d8 g O .data 00000000 .hidden __TMC_END__
00000000 w *UND* 00000000 _ITM_registerTMCloneTable
080482f4 g F .init 00000000 _init
DYNAMIC SYMBOL TABLE:
00000000 DF *UND* 00000000 GLIBC_2.0 strcmp
00000000 DF *UND* 00000000 GLIBC_2.0 read
00000000 DF *UND* 00000000 GLIBC_2.0 printf
00000000 DF *UND* 00000000 GLIBC_2.0 system
00000000 w D *UND* 00000000 __gmon_start__
00000000 DF *UND* 00000000 GLIBC_2.0 __libc_start_main
080485fc g DO .rodata 00000004 Base _IO_stdin_used
剥离与 strip
$> strip ./crackme-striped
$> objdump -tT ./crackme-striped
./crackme-striped: file format elf32-i386
SYMBOL TABLE:
no symbols
DYNAMIC SYMBOL TABLE:
00000000 DF *UND* 00000000 GLIBC_2.0 strcmp
00000000 DF *UND* 00000000 GLIBC_2.0 read
00000000 DF *UND* 00000000 GLIBC_2.0 printf
00000000 DF *UND* 00000000 GLIBC_2.0 system
00000000 w D *UND* 00000000 __gmon_start__
00000000 DF *UND* 00000000 GLIBC_2.0 __libc_start_main
080485fc g DO .rodata 00000004 Base _IO_stdin_used
如您所见,strip
应用时动态符号仍然存在。其余的只是干净地移除。
剥离与 sstrip
最后,让我们看看使用sstrip
.
$> sstrip ./crackme-sstriped
$> objdump -tT ./crackme-sstriped
./crackme-sstriped: file format elf32-i386
objdump: ./crackme-sstriped: not a dynamic object
SYMBOL TABLE:
no symbols
DYNAMIC SYMBOL TABLE:
no symbols
如您所见,所有符号,包括动态符号都已被删除。事实上,所有指向 PLT 的符号都被移除,地址被保留为静态地址。这是_start
程序序言的示例,首先是所有符号:
0x8048390 <_start>: xor %ebp,%ebp
0x8048392 <_start+2>: pop %esi
0x8048393 <_start+3>: mov %esp,%ecx
0x8048395 <_start+5>: and $0xfffffff0,%esp
0x8048398 <_start+8>: push %eax
0x8048399 <_start+9>: push %esp
0x804839a <_start+10>: push %edx
0x804839b <_start+11>: push $0x80485e0
0x80483a0 <_start+16>: push $0x8048570
0x80483a5 <_start+21>: push %ecx
0x80483a6 <_start+22>: push %esi
0x80483a7 <_start+23>: push $0x8048490
0x80483ac <_start+28>: call 0x8048380 <__libc_start_main@plt>
0x80483b1 <_start+33>: hlt
然后,strip
ep:
0x8048390: xor %ebp,%ebp
0x8048392: pop %esi
0x8048393: mov %esp,%ecx
0x8048395: and $0xfffffff0,%esp
0x8048398: push %eax
0x8048399: push %esp
0x804839a: push %edx
0x804839b: push $0x80485e0
0x80483a0: push $0x8048570
0x80483a5: push %ecx
0x80483a6: push %esi
0x80483a7: push $0x8048490
0x80483ac: call 0x8048380 <__libc_start_main@plt>
0x80483b1: hlt
最后,sstrip
版本:
0x8048390: xor %ebp,%ebp
0x8048392: pop %esi
0x8048393: mov %esp,%ecx
0x8048395: and $0xfffffff0,%esp
0x8048398: push %eax
0x8048399: push %esp
0x804839a: push %edx
0x804839b: push $0x80485e0
0x80483a0: push $0x8048570
0x80483a5: push %ecx
0x80483a6: push %esi
0x80483a7: push $0x8048490
0x80483ac: call 0x8048380
0x80483b1: hlt
令人惊讶的是,可执行文件仍然可以运行。让我们比较一下strip
和之后留下的 ELF 标头sstrip
(如 Igor 建议的那样)。首先,经过一个strip
:
$> readelf -l crackme-striped
Elf file type is EXEC (Executable file)
Entry point 0x8048390
There are 8 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x00100 0x00100 RWE 0x4
INTERP 0x000134 0x08048134 0x08048134 0x00013 0x00013 RWE 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD 0x000000 0x08048000 0x08048000 0x006b4 0x006b4 RWE 0x1000
LOAD 0x0006b4 0x080496b4 0x080496b4 0x00124 0x00128 RWE 0x1000
DYNAMIC 0x0006c0 0x080496c0 0x080496c0 0x000e8 0x000e8 RWE 0x4
NOTE 0x000148 0x08048148 0x08048148 0x00044 0x00044 RWE 0x4
GNU_EH_FRAME 0x000600 0x08048600 0x08048600 0x00024 0x00024 RWE 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x10
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss
04 .dynamic
05 .note.ABI-tag .note.gnu.build-id
06 .eh_frame_hdr
07
然后是通过的版本sstrip
:
$> readelf -l ./crackme-sstriped
Elf file type is EXEC (Executable file)
Entry point 0x8048390
There are 8 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x00100 0x00100 RWE 0x4
INTERP 0x000134 0x08048134 0x08048134 0x00013 0x00013 RWE 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD 0x000000 0x08048000 0x08048000 0x006b4 0x006b4 RWE 0x1000
LOAD 0x0006b4 0x080496b4 0x080496b4 0x00124 0x00128 RWE 0x1000
DYNAMIC 0x0006c0 0x080496c0 0x080496c0 0x000e8 0x000e8 RWE 0x4
NOTE 0x000148 0x08048148 0x08048148 0x00044 0x00044 RWE 0x4
GNU_EH_FRAME 0x000600 0x08048600 0x08048600 0x00024 0x00024 RWE 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x10
如您所见,部分的名称也已被删除(如 README 文件中所述)。
请注意,应用sstrip
经过upx
渲染的可执行文件使最终的可执行文件无法使用(我尝试过)。