先知技术社区独家发表本文,如需要转载,请先联系先知技术社区授权;未经授权请勿转载。
先知技术社区投稿邮箱:[email protected]

前言

前文讲了一些 radare2 的特性相关的操作方法。本文以一个 crackme 来具体介绍下 radare2 的使用

程序的地址: 在这里

正文

首先使用 radare2 加载该程序。使用了 aaa 分析了程序中的所有函数。使用 iI 查看二进制文件的信息。可以看到是 32 位的。

使用 aaa分析完程序后,可以使用 afl 查看所有的函数。


直接跳到 main 函数看看逻辑

不习惯看文本模式的汇编的话,可以使用 VV 进入图形化模式

拿到个程序,我会首先看函数调用理解程序的大概流程。比如这里先调用了 printf 打印了一些提示信息,然后使用 scanf 获取我们的输入,分析 scanf的参数

|           0x080484cc      8d45fc         lea eax, [local_4h]
|           0x080484cf      89442404       mov dword [local_4h_2], eax
|           0x080484d3      c70424348604.  mov dword [esp], 0x8048634  ; [0x8048634:4]=0x6425
|           0x080484da      e851feffff     call sym.imp.scanf          ; int scanf(const char *format)

我们可以知道0x8048634 是我们的第一个参数, local_4h是我们的第二个参数。看看 0x8048634存放的是什么。

所以程序需要我们输入的是一个 整数,然后把它存在 local_4h里面了。那我们就可以把 local_4h 变量改下名字。这里改成 input

继续往下看发现 input 变量后来没有被处理直接传到了 test 函数。他的第二个参数是这样生成的

为了获得这个参数我们有很多方法,比如 我们可以直接静态分析,或者用 gdb 调试这都很容易得到结果。

这里正好试试 radare 的模拟执行功能。使用该功能我们需要先分析要模拟执行的代码对环境的依赖,比如寄存器的值,内存的值等,然后根据依赖关系修改内存和寄存器的值来满足代码运行的上下文。

在这里这段代码只对栈的内存进行了处理。那我们就先分配一块内存,然后用 esp 刚刚分配的内存。由于这里一开始没有对内存数据进行读取,所以我们直接使用分配的内存就好,不用对他进行处理。

首先我们跳到目标地址,然后使用 aei 或者 aeip 初始化虚拟机堆栈,然后使用 aer 查看寄存器状态。

然后分配一块内存作为栈内存,给程序模拟执行用。

0xff0000 分配了 0x40000 大小的内存。然后把 espebp 指到这块内存里面。

然后我们让模拟器运行到 0x0804850c 也就是调用 test 函数的位置处,查看他的参数,可以看到第二个参数的值就是 0x00052b24


最后我们进去 test 函数里面看看.


就是判断 参数一参数二 是否一致,所以这个 crackmekey 就是 0x00052b24 十进制数表示 338724.

成功

总结

radare2 的模拟执行功能是通过 esil 来实现的,粗略的试了一下感觉还是挺不错的感觉和 unicorn 有的一拼,不过radare2也是有 unicorn的插件的。

参考:

http://radare.org/r/talks.html

https://github.com/radare/radare2book

https://codeload.github.com/radareorg/r2con/

源链接

Hacking more

...