用Radare2模拟shellcode运行
Posted 蚁景科技
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用Radare2模拟shellcode运行相关的知识,希望对你有一定的参考价值。
当我们在编写汇编时,可能有的时候你需要看看编译器中到底发生了什么。如果你正在排除shellcode出现的问题,你那么更需要耐心地、慎重地运行指令。
本文将探讨如何在x86_64的Ubuntu系统上模拟32位ARM shellcode。由于大多数笔记本电脑和工作站还没有运行ARM,我们这里需要一种其他方法在系统上执行非原生的指令。另外,原始的shellcode二进制文件并不是可执行文件格式,并不能被大多数工具所运行,所以我们需要一种其他的方法来执行这些文件。
在这里我们使用的是Radare2, Radare2是一个控制台驱动的框架,集成了一套简便易用的二进制分析工具。你可以把这些工具编写成脚本,或者使用交互式的命令行界面。要在Ubuntu上设置这个,我们只需要几个简单的命令。
mkdir ~/github
cd ~/github
git clone https://github.com/radareorg/radare2.git
cd radare2
sys/install.sh
如果你已经安装了radare2,请确保你目前运行的是最新版本。这个工具一直在积极维护并定期进行更新。另外,在2022年6月的版本之前有一些错误,使得此次试验可能无法更好的完成。
cd ~/github/radare2
git pull
sys/install.sh
r2 -V
为了复制我们将在本文中使用的shellcode二进制文件,你可以在bash提示符下运行以下内容:
nemo@hammerhead:~$ echo -n -e \'\\x01\\x30\\x8f\\xe2\\x13\\xff\\x2f\\xe1\\x78\\x46\\x0c\\x30\\xc0\\x46\\x01\\x90\\x49\\x1a\\x92\\x1a\\x0b\\x27\\x01\\xdf\\x2f\\x62\\x69\\x6e\\x2f\\x73\\x68\\x00\' > shellcode-696.bin
nemo@hammerhead:~$ md5sum shellcode-696.bin
42ba1c77446594cac3508b940926575d shellcode-696.bin
ESIL简介
可评估字符串中间语言(ESIL)是radare2使用的一种从硬件中抽象出来的指令,可以在不考虑底层硬件的情况下,来 "执行" 机器指令。这对于在仿真环境中执行非本地的汇编指令是非常理想的。
为了使用ESIL来执行我们的shellcode,我们需要做以下工作:
-
加载我们的shellcode二进制文件
-
配置radare2,使其知道如何正确解释我们的shellcode二进制文件
-
初始化ESIL
-
根据需要设置寄存器
-
通过我们的汇编指令来验证其功能
【----帮助网安学习,以下所有学习资料免费领!加vx:yj009991,备注 “博客园” 获取!】
① 网安学习成长路径思维导图
② 60+网安经典常用工具包
③ 100+SRC漏洞分析报告
④ 150+网安攻防实战技术电子书
⑤ 最权威CISSP 认证考试指南+题库
⑥ 超1800页CTF实战技巧手册
⑦ 最新网安大厂面试题合集(含答案)
⑧ APP客户端安全检测指南(安卓+IOS)
用 ESIL 执行ARM shellcode
-
加载我们的shellcode二进制文件
当我们对shellcode二进制文件运行 "file"命令时,我们看到Linux不能确定其文件格式。同样地,radare2也不能确定它是什么。
nemo@hammerhead:~/labs/shellcode/asm$ file shellcode-696.bin
shellcode-696.bin: data
由于它只是一个二进制的文件,我们需要把它加载到radare2中后指定我们要看的是什么。在这里,我们修改了一些软件的分析设置,以便我们能够正确地分析我们的ARM文件:
nemo@hammerhead:~/labs/shellcode/asm$ r2 shellcode-696.bin
[0x00000000]> e anal.arch = arm
[0x00000000]> e asm.arch = arm
[0x00000000]> e asm.bits = 32
[0x00000000]> e anal.armthumb=true
-
配置radare2,使其知道如何正确运行我们的shellcode二进制文件
接下来我们要指定哪些指令是ARM,哪些是THUMB。我发现要做到这一点,就需要定义指令类型改变的函数。在这个特定的shellcode中,它会在ARM和THUMB指令之间进行切换。
[0x00000000]> af
[0x00000000]> pdf
┌ 8: fcn.00000000 ();
│ rg: 0 (vars 0, args 0)
│ bp: 0 (vars 0, args 0)
│ sp: 0 (vars 0, args 0)
│ 0x00000000 01308fe2 add r3, pc, 1
└ 0x00000004 13ff2fe1 bx r3
在这个radare2命令的片段中,我正在分析一个地址为0的函数。在这里并不存在一个真正的函数,但是我们这样做是为了让我们的"函数"可以指定为ARM或者THUMB。"pdf "命令只是打印了函数的反汇编指令,这其中包含了add和bx指令。
<p>[0x00000000]> s 8
[0x00000008]> af
[0x00000008]> pdf
┌ 24: fcn.00000008 (int32_t arg1, int32_t arg2);
│ ; arg int32_t arg1 @ r0
│ ; arg int32_t arg2 @ r1
│ 0x00000008 78460c30 andlo r4, ip, r8, ror r6
│ 0x0000000c c0460190 andls r4, r1, r0, asr 13 ; arg2
│ ┌─< 0x00000010 491a921a bne 0xfe48693c
│ │ 0x00000014 0b2701df svcle 0x1270b
│ │ 0x00000018 2f62696e cdpvs p2, 6, c6, c9, c15, 1
└ │ 0x0000001c 2f736800 rsbeq r7, r8, pc, lsr 6
[0x00000008]> afB 16</p>
从地址8开始的下一组指令是THUMB指令。"s 8 " 指令会在文件中寻找8个字节,并跳转到一个我们希望到达的地方,然后定义下一个 "函数"。用 "af "创建函数后,当我们试图用 "pdf "显示它时,它看起来有点古怪。这是因为工具仍然会将这些指令解释为ARM。
我们可以通过设置比特数为16来指定这个 "函数 " 是THUMB。也就是将asm.bits设置为16,不过只针对这个函数生效。在一个正常的ARM二进制文件中,radare2会尝试自动进行这种区分,但是由于我们只有这一串shellcode指令,我们仍然需要进行手动区分。
注意我们可以删掉前两条指令并使用全THUMB的shellcode。如果我们这样做,我们就可以在打开文件时设置 "e asm.bits=16",而不必再重新定义函数。只不过,如果需要的话,你可以区分这两种指令类型。
Radare2还有一个更方便的方法,就是用 "izz "命令显示二进制文件中的所有字符串。
> izz
[Strings]
nth paddr vaddr len size section type string
―――――――――――――――――――――――――――――――――――――――――――――――――――――――
0 0x00000008 0x00000008 4 5 ascii xF\\f0
1 0x00000018 0x00000018 7 8 ascii /bin/sh</p>
现在我们已经能够正确的加载我们的shellcode二进制文件了。
-
初始化ESIL
如前所述,radare2内置了很多命令,在命令前缀中加入"?" 可以列出所有相关的命令。"ae? " 命令将列出与ESIL和仿真相关的命令。
[0x00000000]> ae?
Usage: ae[idesr?] [arg] ESIL code emulation
| ae [expr] evaluate ESIL expression
| ae? show this help
| ae?? show ESIL help
| aea[f] [count] analyse n esil instructions accesses (regs, mem..)
| aeA[f] [count] analyse n bytes for their esil accesses (regs, mem..)
| aeb ([addr]) emulate block in current or given address
| aeC[arg0 arg1..] @ addr appcall in esil
| aec[?] continue until ^C
| aef [addr] emulate function
| aefa [addr] emulate function to find out args in given or current offset
| aeg [expr] esil data flow graph
| aegf [expr] [register] esil data flow graph filter
| aei[?] initialize ESIL VM state (aei- to deinitialize)
| aek[?] [query] perform sdb query on ESIL.info
| aeL list ESIL plugins
| aep[?] [addr] manage esil pin hooks (see “e cmd.esil.pin”)
| aepc [addr] change esil PC to this address
| aer[?] [..] handle ESIL registers like “ar” or “dr” does
| aes[?] perform emulated debugger step
| aets[?] esil Trace session
| aev [esil] visual esil debugger for the given expression or current instruction
| aex [hex] evaluate opcode expression
在这里,我们首先需要用 "aei "命令来初始化ESIL。之后,我们需要初始化一个堆栈。Radare2会自动选择一个堆栈的位置,不过这也可以使用"aeim "命令参数来指定地址 。
[0x00000008]> aei
[0x00000008]> aeim
-
根据需要设置寄存器
由于我们的shellcode指令是从0开始的,我们需要用 "aepc 0 "命令将我们的程序计数器(PC)设置为0。如果我们想在偏移量0以外的位置开始执行,我们可以用 "aepc <address>"来设置起始地址。
[0x00000008]> aepc 0
我们的shellcode中的一条指令("subs r1, r1, r1")会将r1设置为0.由于这个寄存器默认已经为0,让我们将它设置为0xffff,这样我们就可以看到当我们在shellcode中步进时所发生的变化。要做到这一点,我们需要使用 "aer "命令。
[0x00000008]> aer r1 = 0xffff
-
通过我们的设置来验证其功能
好了,现在我们已经设置好了。我们可以切换到可视化模式,进入到调试器面板。在可视模式下有多个选项(面板),所以我们需要敲两次 "p "来进入正确的面板。如果你想在任何时候退出可视化模式,只需按下escape键。你也可以按"?"来查看可用的命令列表。
[0x00000008]> V
(hit “p” twice to get to the debugger panel)
然后你会注意到靠近顶部有一组寄存器。它看起来会像这样:
通常在控制台输入的任何r2命令也可以在视觉模式下输入。例如,如果我们想打印偏移量为0x18的字符串,我们需要执行以下命令:
# Hit “:” while in visual mode.
> ps @0x18
/bin/sh
> # Hit enter on a blank line to return to visual mode.
现在,我们可以通过使用"s "键来执行汇编指令。当你在浏览时,你会注意到顶部的寄存器与堆栈数据会一起被更新(在第一张图片中从0x00178000开始)。你还会注意到,下一条要执行的指令(又称PC)的地址在汇编指令中被突出显示(第一幅图中的0x00000010)。
注意,上面的图片显示r1寄存器持有0x0000ffff。还注意到下一条指令将会被执行,即 "subs r1, r1, r1"。这条指令将会从自身减去r1,并将其存回r1,本质上是使其变为0。
再次按 "s "键,进入下一条指令。
现在一切都准备好了,可以通过 "svc 1 "指令通过守护进程调用了。我们现在正在进行 "execve "调用,所以我们应该在r7寄存器中设置0xb。r0中的第一个参数应该是一个指向我们要执行的二进制文件路径的指针。我们可以发现r0持有0x18。我们可以通过运行以下命令来验证它的指向:
# Hit “:” while at the “svc 1” instruction in visual mode.
> ps @r0
/bin/sh
>
现在我们没有向"/bin/sh "传递任何参数,也没有设置任何环境变量,因此我们可以发现r1和r2都被设置为0。
由于我们不是在ARM系统上运行,所以我们不能正确地使用守护进程调用("svc 1")指令。当你在测试更复杂的shellcode时,请牢记这一点。
总结
无论您是对自定义的shellcode进行故障排除,还是验证您所看到的静态内容,有时您只需要看看指令到底在做什么。Radare2允许您从一个未知的文件格式(如shellcode二进制文件或固件镜像)加载非本地汇编文件,并一步一步地执行指令。
更多网安技能的在线实操练习,请点击这里>>
radare2
介绍
r2是radare的第二版,目的是提供一组库和工具来处理二进制文件。Radare项目最初是一个取证工具,一个脚本命令行十六进制编辑器,可以打开磁盘文件,但后来添加了对分析二进制文件、分解代码、调试程序、附加到远程gdb服务器的支持,简单的来说它就是一个开源的(但也同样强大的)二进制分析工具,有些时候IDA用不了F5的时候就可以尝试用它来解决一些难题。
下载
https://github.com/radare/radare2 (下载源码,解压)
进入源码目录执行
sys/install.sh
1
常用命令
r2 filename 加载文件
aaa分析程序中所有函数,分析前 radare2 识别不了函数,分析后就可以正常打印函数代码了(pdf 打印函数代码),aa命令只分析主函数
加个问号可以查看帮助,这里我们直接用aaa就可以分析完程序了
afl显示主函数,有时候我们不需要分析整个二进制文件,或者有个函数 radare2没有识别出来我们可以 af 来分析该函数。
s function 跳转到想跳转的位置(function)
VV进入图形化模式(hjkl移动图像)使用 p/P 切换图形模式,空格切换文本图形模式,文本下可以用p切换模式,小写的vv用来粗略浏览函数信息
pdf查看函数汇编代码
pd x打印汇编信息x条
"wa xxx"修改汇编指令为xxx
px表示打印16进制数,默认从当前位置开始,参数控制打印的字节数
直接使用 r2 filename 进入程序。使用-d选项进入调试模式,输入!在调试的时候可以看到历史操作记录
pdc反汇编函数
afx查看调用函数
?可以查看帮助,这个工具非常强大,需要多实践学习
比较好的介绍教程:
https://xz.aliyun.com/t/1514
https://cloud.tencent.com/developer/article/1073910
https://github.com/radare/radare2(官方文档)
————————————————
版权声明:本文为CSDN博主「Thunder_J」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/CharlesGodX/article/details/84927524
以上是关于用Radare2模拟shellcode运行的主要内容,如果未能解决你的问题,请参考以下文章