欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

路由器漏洞复现终极奥义——基于MIPS的shellcode编写

来源:本站整理 作者:佚名 时间:2018-08-04 TAG: 我要投稿

前言
今天我们来聊聊如何在MIPS架构中编写shellcode。在前面的两篇文章中,我们分别介绍了基于MIPS的缓冲区溢出实践,以及进一步的如何利用学到的溢出知识复现与验证路由器的漏洞。但是在上文的路由器漏洞利用的例子里面,我们需要有一个前置条件,即含有漏洞的程序必须导入了系统的库函数,我们才能方便的验证,然而这个条件并不是时刻有效的。因此,在本文中,我们介绍路由器漏洞复现的终极奥义——基于MIPS的shellcode编写。有了shellcode,如果目标程序能够被溢出,那么我们就可以执行任意的程序。所以说是终极奥义。简单来说,shellcode就是一段向进程植入的一段用于获取shell的代码,(shell即交互式命令程序)。现如今,shellcode从广义上来讲,已经统一指在缓冲区溢出攻击中植入进程的代码。因此,shellcode现在所具备的功能不仅包括获取shell,还包括弹出消息框、开启端口和执行命令等。
在本文中,我将介绍
基于MIPS的常用shellcode;
快速提取shellcode的二进制指令的工具-shell_extractor.py;
开发的shellcode如何在自己的实验程序应用。
其中,shellcode二进制指令快速提取工具是我自己开发的。我随便搜索了一下,没有发现类似的能够满足我需求的工具,所以就自己开发了一个工具,已经开源在shell_extractor),欢迎大家使用。如果大家有更好的工具,欢迎评论。^_^
 
0. 鸟瞰shellcode
首先,我们先从一个比较直观的角度来了解一下,一个shellcode它在缓冲区溢出攻击的过程所扮演的角色和所处的位置。如图所示一个常见的MIPS堆栈分配情况

Shellcode最常见的用法,就是把可以执行的命令覆盖到堆栈里面,通过修改RA跳转到堆栈的起始位置的方式,达到在堆栈里面执行自己想要的命令的方式。因此shellcode实际上就是一段可执行的汇编指令。讲到这里,那么问题来了,怎么编写这段汇编指令呢?
有两种思路,第一种:从网上搜索一些shellcode的汇编,编译之后反编译,获取二进制指令。这种方法也可以,也是比较常见的做法。还有一种,需要稍微花一点功夫:即用c语言先写一个系统命令调用,编译,然后用IDA反编译,直接把对应的汇编指令提取出来。不过,在提取对应的汇编指令的时候,需要对存储的参数的位置,以及对于寄存器的处理进行重新的调整。
比如,我们编写一个execve的调用程序。execve是shellcode常用的程序之一,它的目的是让已经嵌入的应用程序执行另外一个程序,比如/bin/sh。Linux 中对该系统调用的定义如下:
int execve(const char *path, char *const argv[], char *const envp[]);
那么我一个常见的c语言调用execve的代码可以是这样的:
#include
int main()
{
    char *program = "/bin/ls";
    char *arg = "-l";
    char *args[3];
    args[0] = program;
    args[1] = arg;
    args[2] = 0;
    execve(program, args, 0);
}
编译下,看看IDA反编译出来是什么样的

会发现,参数program和arg的是需要重新处理的,比如就跟着放在这段shellcode程序的后面(之后介绍的手动编写shellcode就会写到这种处理方式)execve在跳转之后,会发现,最终是通过syscall完成的系统调用。

总结来说,这二种方法适合初学者一步一步对应着c源代码和汇编程序,学习汇编程序的shellcode编写。但是直接提取的话,会发现冗余的指令过多。在覆盖堆栈的时候,占用的空间越少,漏洞利用的成功率会越高。因此,本文还是着重第一种方式,即从成熟的处理好的shellcode中学习。感兴趣的读者也可以进一步优化上述代码,让它的体积尽可能小,这对于打基础是非常好的。
前面我们提到,最终execve是通过syscall这个命令实现的系统调用,因此,基于MIPS的shellcode编写,大部分都是基于syscall这个命令的。
syscall函数的参数形式为 syscall($v0, $a0, $a1…); 其中$v0用于保存需要执行的系统调用的调用号,并且按照对应的函数调用规则放置参数。比如调用exit的汇编代码例子。
li $a0, 0
li $v0, 4001
syscall
其中指令li (x,y)的意思是将立即数y放置到寄存器x中。系统调用好可以在linux系统里找到,比如在/usr/include/mips-linux-gnu/asm/unistd.h里面。本文中,我们围绕两个系统命令来展开,并且深入介绍一个完整shellcode开发以及漏洞的流程。即write, execve指令。Write就是输出字符串到指定流的系统调用。我们可以找到write的调用号是4004, 而execve是4011.
总体来说,基于MIPS的shellcode开发以及漏洞的流程分为以下的步骤(其他平台的shellcode开发也类似):
1.    编写shellcode的汇编代码,从网上寻找,或者自己编写。
2.    编译,反编译之后,提取shellcode的二进制代码。
3.    在c中测试提取的二进制代码。
4.    构造payload进行测试。
 
1. Shellcode的汇编代码构造
首先第一步,shellcode的编写。一个典型的调用write的c代码为:
Int main()
{
char *pstr = “ABCn”;
write(1, pstr, 5);
}
写成shellcode就为write.S
.section .text
.globl __start
.set noreorder
__start:
addiu $sp,$sp,-32        # 抬高堆栈,用来放置参数

[1] [2] [3]  下一页

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载