我想找到如何识别仅对GDB中共享库的调用。在已剥离的二进制文件上,我找不到动态符号表: >
$> objdump -tT crackme-01

crackme-01:     file format elf32-i386

objdump: crackme-01: not a dynamic object
SYMBOL TABLE:
no symbols

DYNAMIC SYMBOL TABLE:
no symbols


我的问题是如何从strcmp隐藏符号表,但在执行过程中仍可使用它?

#1 楼

实际上,他们可能使用了ElfKicker软件包中的sstrip软件。根据sstrip文件:sstrip是一个小型实用程序,可删除ELF文件末尾不属于程序内存映像的内容。 br />
大多数ELF可执行文件都是用程序头表和
节头表构建的。但是,顺序
只需要前者即可使OS加载,链接和执行程序。 sstrip尝试提取
ELF头,程序头表及其内容,
将其他所有内容保留在位存储桶中。在要保存的部分之后,它只能删除文件末尾出现的部分。但是,
几乎总是包括节头表,以及一些
其他不涉及程序加载和执行的节。

应该注意,大多数程序用于ELF文件的文件
依赖于节头表作为文件内容的索引。因此,当使用不带节头文件的可执行文件时,诸如gdb和objdump之类的实用程序通常会具有有限的功能。其他实用程序可能会拒绝使用它们。


实际上,README从可执行文件中删除了所有节信息,并使可执行文件仍然可用。
但是让我们看到不同的层次是我们可以达到的剥离。

不剥离

让我们考虑一个程序(类似于问题中所看的那个)没有剥离全部。

$> 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


sstrip剥离


$> 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 ./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的符号都已删除,地址保留为静态地址。这是strip过程序言的示例,首先是所有符号:

 0x8048390 <_start>:    xor    %ebp,%ebp
 0x8048392 <_start+2>:  pop    %esi
 0x8048393 <_start+3>:  mov    %esp,%ecx
 0x8048395 <_start+5>:  and    
0x8048390:  xor    %ebp,%ebp
0x8048392:  pop    %esi
0x8048393:  mov    %esp,%ecx
0x8048395:  and    
0x8048390:  xor    %ebp,%ebp
0x8048392:  pop    %esi
0x8048393:  mov    %esp,%ecx
0x8048395:  and    
$> 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     
xfffffff0,%esp 0x8048398: push %eax 0x8048399: push %esp 0x804839a: push %edx 0x804839b: push
$> 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
x80485e0 0x80483a0: push q4312078qx8048570 0x80483a5: push %ecx 0x80483a6: push %esi 0x80483a7: push q4312078qx8048490 0x80483ac: call 0x8048380 0x80483b1: hlt
xfffffff0,%esp 0x8048398: push %eax 0x8048399: push %esp 0x804839a: push %edx 0x804839b: push q4312078qx80485e0 0x80483a0: push q4312078qx8048570 0x80483a5: push %ecx 0x80483a6: push %esi 0x80483a7: push q4312078qx8048490 0x80483ac: call 0x8048380 <__libc_start_main@plt> 0x80483b1: hlt
xfffffff0,%esp 0x8048398 <_start+8>: push %eax 0x8048399 <_start+9>: push %esp 0x804839a <_start+10>: push %edx 0x804839b <_start+11>: push q4312078qx80485e0 0x80483a0 <_start+16>: push q4312078qx8048570 0x80483a5 <_start+21>: push %ecx 0x80483a6 <_start+22>: push %esi 0x80483a7 <_start+23>: push q4312078qx8048490 0x80483ac <_start+28>: call 0x8048380 <__libc_start_main@plt> 0x80483b1 <_start+33>: hlt


,然后sstrip ep:

q4312078q

最后是sstrip版本:

q4312078q

令人惊讶的是,可执行文件仍然起作用。让我们比较一下_startstrip之后剩下的ELF标头(如建议的Igor)。首先,在sstrip之后:

q4312078q

然后是strip所经历的版本: >如您所见,这些部分的名称也已删除(如README文件中所述)。已尝试)。

评论


我不认为sstrip会删除动态符号。

–伊戈尔·斯科钦斯基♦
2014年8月8日17:48

最后一个甚至运行吗?您可以对其进行readelf -l吗?

–伊戈尔·斯科钦斯基♦
2014年8月8日19:41

实际上,我从未花时间研究它在内部的工作方式。但是,当然值得去挖掘它。

–恐怖
2014年8月8日19:56



好的,因此它确实保留了带有符号的DYNAMIC条目。但是看来objdump太傻了(哈哈),无法处理这个问题。

–伊戈尔·斯科钦斯基♦
2014年8月8日20:06

很抱歉与您@perror矛盾,但不会删除动态符号。删除了节表,并且objdump和readelf依靠节在二进制文件中找到它们的方式(如果是,则通过libbfd)。但是这些段绝对不是必需的,并且动态链接程序(通常是ld.so之类的东西)实际上并未使用它们。 readelf -d将显示一个SYMTAB条目,该条目指向符号表,可以与DYNAMIC条目STRTAB,JMPREL和RELA一起合理地解释。

–塞利利比
2014年12月8日在16:17

#2 楼

因此,看起来您的可执行文件毕竟确实使用共享对象。我会运用自己的精神力量,并冒险猜测它已经被UPX之类的东西压缩了。 。

然而,生成的可执行文件在OS上看起来像是静态的。但是,运行时,解压程序存根将段和标头解压缩到内存中,并在原始程序需要的情况下加载动态解释器。 。因此,在运行时,该文件确实使用了动态符号(通过解释器)。尽管这不会影响其可运行性,但确实破坏了许多工具,包括objdumpreadelf。您可能需要尝试使用我们的扩展文件转储器(EFD)工具,即使已经删除了节表,该工具也可以打印动态符号表。尝试运行readelf。 (我首先尝试过readelf -D -s <file.elf>,但没有用。)

#3 楼

区别如下:

符号表包含其代码在二进制本身中的函数的符号。

上面列出的第二段代码显示了函数名称代码在共享库的二进制文件之外。