mov ebx, [esp+0] 的目的是什么?

逆向工程 拆卸 x86
2021-06-22 13:46:43

为了好玩,我正在拆解一个 SO 库,并且想知道以下过程的目的是什么:

sub_3699 proc near
mov     ebx, [esp+0]
retn
sub_3699 endp

它在整个库中广泛使用,具有非常令人困惑的模式(至少对我而言),如下所示:

push    ebp
mov     ebp, esp
push    esi
push    ebx
call    sub_3699        ; Here it is called
add     ebx, 1DD5Ch     ; And this magic number is something I'm trying to understand
...                     ; rest of caller body
pop     ebx
pop     esi
pop     ebp
retn

请注意在过程调用后1DD5Ch添加的幻数EBX似乎这个数字在所有调用中都是唯一的,但我不知道它的用途。EBX在调用者代码中,甚至register 本身似乎也不是读/写的。

任何的想法?

如果这很重要,这里是输出 readelf -s ...

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x14340
  Start of program headers:          52 (bytes into file)
  Start of section headers:          275660 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         5
  Size of section headers:           40 (bytes)
  Number of section headers:         25
  Section header string table index: 24

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .hash             HASH            000000d4 0000d4 00221c 04   A  2   0  4
  [ 2] .dynsym           DYNSYM          000022f0 0022f0 0047e0 10   A  3   1  4
  [ 3] .dynstr           STRTAB          00006ad0 006ad0 00825f 00   A  0   0  1
  [ 4] .gnu.version      VERSYM          0000ed30 00ed30 0008fc 02   A  2   0  2
  [ 5] .gnu.version_r    VERNEED         0000f62c 00f62c 000020 00   A  3   1  4
  [ 6] .rel.dyn          REL             0000f64c 00f64c 000eb8 08   A  2   0  4
  [ 7] .rel.plt          REL             00010504 010504 0014b0 08   A  2   9  4
  [ 8] .init             PROGBITS        000119b4 0119b4 00001c 00  AX  0   0  1
  [ 9] .plt              PROGBITS        000119d0 0119d0 002970 04  AX  0   0 16
  [10] .text             PROGBITS        00014340 014340 02b324 00  AX  0   0  4
  [11] .fini             PROGBITS        0003f664 03f664 000017 00  AX  0   0  1
  [12] .rodata           PROGBITS        0003f680 03f680 001fa0 00   A  0   0  8
  [13] .eh_frame_hdr     PROGBITS        00041620 041620 00002c 00   A  0   0  4
  [14] .eh_frame         PROGBITS        0004164c 04164c 0000f8 00   A  0   0  4
  [15] .ctors            PROGBITS        00042000 042000 000018 00  WA  0   0  4
  [16] .dtors            PROGBITS        00042018 042018 000018 00  WA  0   0  4
  [17] .jcr              PROGBITS        00042030 042030 000004 00  WA  0   0  4
  [18] .data.rel.ro      PROGBITS        00042038 042038 0006d8 00  WA  0   0  8
  [19] .dynamic          DYNAMIC         00042710 042710 0000d0 08  WA  3   0  4
  [20] .got              PROGBITS        000427e0 0427e0 0001b4 04  WA  0   0  4
  [21] .got.plt          PROGBITS        00042994 042994 000a64 04  WA  0   0  4
  [22] .data             PROGBITS        000433f8 0433f8 000010 00  WA  0   0  4
  [23] .bss              NOBITS          00043408 043408 000bb0 00  WA  0   0  8
  [24] .shstrtab         STRTAB          00000000 043408 0000c3 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  p (processor specific)

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x00000000 0x00000000 0x41744 0x41744 R E 0x1000
  LOAD           0x042000 0x00042000 0x00042000 0x01408 0x01fb8 RW  0x1000
  DYNAMIC        0x042710 0x00042710 0x00042710 0x000d0 0x000d0 RW  0x4
  GNU_EH_FRAME   0x041620 0x00041620 0x00041620 0x0002c 0x0002c R   0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x4

 Section to Segment mapping:
  Segment Sections...
   00     .hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame 
   01     .ctors .dtors .jcr .data.rel.ro .dynamic .got .got.plt .data .bss 
   02     .dynamic 
   03     .eh_frame_hdr 
   04     
1个回答

的目的sub_3699是返回调用该过程的指令之后的下一条指令的地址。call sub_3699将下一条指令的地址压入堆栈并跳转到 的第一条指令sub_3699

该指令获取堆栈顶部的值(不删除它)并将其写入ebx. 这种机制通常在生成位置无关代码时使用,以避免使用硬编码地址访问数据(尽管组合call $+5, pop reg更流行)。

因此,不是addr直接访问 some ,而是相对于下一条指令的地址来计算它。因此,您首先计算addr - address_of_next_instruction = addr - sub_3699() = 0x1DD5C(在您的情况下)并获得addr您必须简单地添加sub_3699()到该数字。在此添加之后,ebx包含addr.