x86-64 CALL 操作码 + 反汇编

逆向工程 部件 二元分析 缓冲区溢出 外壳代码
2021-07-03 11:28:42

在 64 位系统上处理基本的缓冲区溢出并将一些基本的 shellcode 放在一起。主程序调用 puts@plt。当我在 gdb 中反汇编 main 时,操作码显示为:

e8 6b fe ff ff    0x555555554580 <puts@plt>

我查看了调用指令集参考,它说它与下一条指令的相对位移。下一条指令是:

0x0000555555554715 b8 00 00 00 00 mov eax, 0x0

“6b fe ff ff”如何从“0x555555554715”中移出以获得 puts@plt 地址?

我正在将我的 shellcode 放到堆栈上,是否可以从那里调用 puts@plt 作为下一条指令的位移?或者我只需要为系统调用设置寄存器?

1个回答

相对地址可以从当前指令的末尾或下一条指令的开始向前或向后

E8 00 00 00 00将呼叫到下一个立即指令
向前可以 E8(00 00 00 00 .... 7F FF FF FF)
向后可以 E8(FF FF FF FF 80 .... 00 00 00)

所以你直接在这里0xfffffe6b 即== -0x195

负数设置了符号位(第 31 位)

0 & 0x80000000 == 0x80000000  will be False 
and
0xffffffff & 0x80000000 == 0x80000000  will be True

C:\>python -c "print((0xffffffff&0x80000000)==0x80000000);print((0x0&0x80000000)==0x80000000)"
True
False

所以我们可以找出负数和正数 负数 向后跳跃 正数 向前跳跃

正 1 是 0 + 1
正 2 是 0 + 2 等等......

负 1 是 0x10000000 - 1
负 2 是 0x10000000 - 2 等等......

>>> for i in range (1,20,1):
...     print (  "-%02d    ==    %x    +%02d    ==    %x" %  (i,( 0x10000000-i) ,i,( 0 + i )) )
...
-01    ==    fffffff    +01    ==    1
-02    ==    ffffffe    +02    ==    2
-03    ==    ffffffd    +03    ==    3
-04    ==    ffffffc    +04    ==    4
-05    ==    ffffffb    +05    ==    5
-06    ==    ffffffa    +06    ==    6
-07    ==    ffffff9    +07    ==    7
-08    ==    ffffff8    +08    ==    8
-09    ==    ffffff7    +09    ==    9
-10    ==    ffffff6    +10    ==    a
-11    ==    ffffff5    +11    ==    b
-12    ==    ffffff4    +12    ==    c
-13    ==    ffffff3    +13    ==    d
-14    ==    ffffff2    +14    ==    e
-15    ==    ffffff1    +15    ==    f
-16    ==    ffffff0    +16    ==    10
-17    ==    fffffef    +17    ==    11
-18    ==    fffffee    +18    ==    12
-19    ==    fffffed    +19    ==    13

所以我从 0x100000000 中减去 0xffffffe6b

C:\>python -c "print hex(0xfffffe6b - 0x100000000)"
-0x195L

C:\>python -c "print hex(0x0000555555554715 + (-0x195))"
0x555555554580L

在radare2中演示

[0x00000000]> w \xe8\x00\x00\x00\x00 ; pd 1
            0x00000000      e800000000     call 5
[0x00000000]> w \xe8\x01\x00\x00\x00 ; pd 1
            0x00000000      e801000000     call 6
[0x00000000]> w \xe8\x02\x00\x00\x00 ; pd 1
            0x00000000      e802000000     call 7
[0x00000000]> w \xe8\x08\x00\x00\x00 ; pd 1
            0x00000000      e808000000     call 0xd
[0x00000000]> w \xe8\xff\xff\xff\xff ; pd 1
            0x00000000      e8ffffffff     call 4
[0x00000000]> w \xe8\xfe\xff\xff\xff ; pd 1
            0x00000000      e8feffffff     call 3
[0x00000000]> w \xe8\x6b\xff\xff\xff ; pd 1
            0x00000000      e86bffffff     call 0xffffff70
[0x00000000]> w \xe8\x6b\xfe\xff\xff ; pd 1
            0x00000000      e86bfeffff     call 0xfffffe70
[0x00000000]>

模拟实际调用操作码

opening a random elf file 
:\>radare2 elfie

getting the address of sym.puts
[0x08048150]> ?v sym.puts
0x8048de0

calculating relative address for force writing a call to sym.puts
[0x08048150]> ?v sym.puts + 0x195 - 0x5
0x8048f70

seeking to target address
[0x08048150]> s sym.puts + 0x195 - 0x5

setting cache = true for writing to memory (radare2 opens in read only mode)
[0x08048f70]> e io.cache = true

checking the present disassembly
[0x08048f70]> pd 1
        `=< 0x08048f70      ebd7           jmp 0x8048f49
patching a call to sym.puts in place 

[0x08048f70]> w \xe8\x6b\xfe\xff\xff

checking disassembly again 

[0x08048f70]> pd 1
            0x08048f70      e86bfeffff     call sym.puts