该程序如何知道此字符串的确切存储位置?

Dra*_*mer 7 c assembly x86-64 memory-address

我已经用Radare2反汇编了一个C程序。在此程序内,有许多调用scanf类似于:

0x000011fe      488d4594       lea rax, [var_6ch]
0x00001202      4889c6         mov rsi, rax
0x00001205      488d3df35603.  lea rdi, [0x000368ff]       ; "%d" ; const char *format
0x0000120c      b800000000     mov eax, 0
0x00001211      e86afeffff     call sym.imp.__isoc99_scanf ; int scanf(const char *format)
0x00001216      8b4594         mov eax, dword [var_6ch]
0x00001219      83f801         cmp eax, 1                  ; rsi ; "ELF\x02\x01\x01"
0x0000121c      740a           je 0x1228
Run Code Online (Sandbox Code Playgroud)

这是从行传递给它scanf的字符串的地址。我假设是exectable文件中的位置,因为如果我以调试模式()重新启动Radare2,则将其替换为。"%d"lea rdi, [0x000368ff]0x000368ff"%d"r2 -d ./execlea rdi, [0x000368ff]lea rdi, [someMemoryAddress]

如果文件中lea rdi, [0x000368ff]有什么硬编码,那么在运行时指令如何更改为实际的存储器地址?

Mar*_*lli 9

Radare欺骗了您,您所看到的并不是真正的指示,它已为您简化了。

真正的指示是:

0x00001205    488d3df3560300    lea rdi, qword [rip + 0x356f3]
0x0000120c    b800000000        mov eax, 0
Run Code Online (Sandbox Code Playgroud)

这是典型的位置无关负载。要使用的字符串在offset处存储在二进制文件中0x000368ff,但是由于可执行文件与位置无关,因此需要在运行时计算实际地址。由于下一条指令位于offset处0x0000120c,因此您知道,无论二进制文件在内存中的何处加载,您想要的地址都将是rip + (0x000368ff - 0x0000120c)= rip + 0x356f3,这就是您在上面看到的。

在进行静态分析时,由于Radare不知道内存中二进制文件的基地址,因此它仅计算0x0000120c + 0x356f3= 0x000368ff。这使逆向工程更加容易,但是由于实际的指令是不同的,因此可能造成混乱。


例如,以下程序:

int main(void) {
    puts("Hello world!");
}
Run Code Online (Sandbox Code Playgroud)

编译后产生:

int main(void) {
    puts("Hello world!");
}
Run Code Online (Sandbox Code Playgroud)

所以rip + 0x99= 0x6bb + 0x99= 0x754,如果我们看一下0x754二进制文件中的offset hd

  6b4:   48 8d 3d 99 00 00 00    lea    rdi,[rip+0x99] 
  6bb:   e8 a0 fe ff ff          call   560 <puts@plt>
Run Code Online (Sandbox Code Playgroud)


fuz*_*fuz 7

完整说明是

48 8d 3d f3 56 03 00
Run Code Online (Sandbox Code Playgroud)

这条指令是字面上的

lea rdi, [rip + 0x000356f3]
Run Code Online (Sandbox Code Playgroud)

rip相对寻址模式。指令指针rip0x0000120c执行指令时具有该值,从而rdi接收所需的值0x000368ff

如果这不是真实地址,则您的程序可能是与位置无关的可执行文件(PIE),可能会被重定位。由于地址是使用相对相对寻址模式编码的,因此无论二进制文件加载在何处,都无需重定位且地址正确。