IDA PRO 02 - 静态逆向分析基础02

​之前我们的例子还没有分析完成,由于 算法分析部分会单独成一个系列,所以就不继续了,该系列的核心还是在于IDA的使用。

本篇再介绍一些其他的IDA使用技巧,有些技巧在特定的地方会很好用。

数据转换

我们在文本视图里面,经常会看到这样的东西:

有没有好奇过,这个 db 是什么意思呢?

byte / char / uint8 / int8 -> db 1个字节

word / short / uint16 / int16 -> dw 2个字节

dword / int / uint ... -> dd 4个字节 (32位指针)

qword / int64 ... -> dq 8个字节 (64位指针)

大部分情况下,整数以小端序存储在内存,比如 0xA1B2C3D4 存储到内存的顺序为 D4 C3 B2 A1。

我们看上图中的字符串,它们其实储存的方式也是一个一个的字节,只不过 ida 帮我们显示的漂亮了,可以算一下两个字符串之间的地址距离。

我们在字符串那一行,按一下 D 键,效果如下:

可以看到,每个字符都拆成了一个一个的字节,每个字节都是其 ASCII 码。

我们继续按 D,可以将该处的字节解释为 双字节/四字节/八字节/单字节 等,这个在动态调试的时候用处很大,因为对于C这种可以一个指针大天下的语言来说,你不动态调一下,根本不知道那个变量里面放的是什么东西,所以掌握D键非常的重要。

花指令处理

ctf-wiki.org/reverse/obf...

花指令(junk code)是一种专门用来迷惑反编译器的指令片段,这些指令片段不会影响程序的原有功能,但会使得反汇编器的结果出现偏差,从而使破解者分析失败。比较经典的花指令技巧有利用 jmpcallret 指令改变执行流,从而使得反汇编器解析出与运行时不相符的错误代码。

一般情况下,我们正常写程序是不会出现花指令的,但是有心人就不一样了,比如,我们可以在 C 代码里面写汇编:

ini 复制代码
//源码
#include<stdio.h>
#include<windows.h>

int main(int argc, char* argv[])
{

 int a = MessageBox(NULL,"Hello","main",MB_OK);
 int b,c,d,e;
   //这部分为花指令部分
 __asm{_emit 0xe8}
   //花指令结束
 b=1;
 c=2;
 d=3;
 e=4;
 return 0;
}

对于这样的程序,就会出现花指令。

当然,这么小儿科的花指令是难不倒IDA,但是总有人能写出骗过IDA的花指令。因为反汇编也是使用的算法来实现的,算法不可能做到完美。

我们看一个例子:

红色的部分,IDA 提示分析失败了,我们空格键切到文本模式看看:

发现code指令里面存在这种奇怪的指令,jz与jnz构成了一个绝对跳转,也就是无论 zf flag 的值是啥,都会跳转到 loc_405AF6。同时观察到,没有别的线条指向这些指令的中间位置,也就是说中间的指令不会被用到,我们可以将这些指令替换成 nop 指令。

首先,要将花指令中间的指令解释成数据:

对这些指令按下U键:

然后,再将整段花指令替换成 nop 指令:

比较让我疑惑的是,为啥不直接替换成 nop 指令呢?我尝试了几次,直接替换反汇编会报错。等后面学习栈修复了之后,再回来思考这个问题吧,现在猜想是ida本身自己有一个分析过程,直接替换是打乱了它的分析步骤???

注意要多选中一条指令,因为 Fill with NOPs 选项是不会替换选中的最后一条指令的。替换完成的效果如下:

继续往下看,还有很多这种指令,我们按照上面的方法全部替换掉。替换完成后,我们需要让ida来重新分析这个函数,先对这个函数取消定义,找到这个函数的头,按快捷键U或者右键

效果如下:

ida将这块函数暂时解释成一个一个的 byte,我们再按 C 键,将这块内容解释为代码:

往下看下整个函数是否都解释完成了,如果没有,会有一些数据指令,在未解释的地方继续按 C 键,强制解释就行,如下图:

整个横线下面的就是没有解释的部分,我们再这里按下 C 键,继续解释就行。

全部弄完后,我们再按tab键将这个函数反汇编一下,IDA会提示:

如果没有出现这个提示,大概率是fill nops 搞错了,再重新来一次吧。弹这个窗是因为我们还需要为这块代码创建一个函数,按 P 键,或者右键选择创建函数:

创建完成后,再按tab键,就能看到反汇编代码了:

网上也有很多介绍如何去掉花指令的文章,可以自行搜索然后学习。特别是一些脚本的编写与使用,比人力要方便的多。

函数调用图

这里一个to,一个 from,还是很容易理解反的。to 的意思是谁调用了我。From 的意思是我调用了谁。

先看下 to 的效果:

由于 start 函数,已经是最上头的函数了,所以没人调用它。

看下 From 的效果:

这就非常恐怖了,但是我们可以放大了看:

可以看到 start 调用了3个方法。在你没啥思路的时候,这个图也许会有奇效。

常数搜索

菜单 [Search] → [Immediate Value],弹出一个窗,勾选"Find all occurrences":

什么时候会需要搜索常数呢?一般是在你找到了某个特征的时候,比如我想看有系统调用的地方,那么我们可以搜索,0x81,为啥是这个值呢?可以去看 x86 汇编相关知识。

搜索到的结果,我们只看 text 部分即可,代码都是放在 text 段的。点一个进去看看是不是系统调用:

发现,确实是的。

指令文本搜索

菜单 [Search] → [Text],弹出一个窗,勾选"Find all occurrences":

比如,我们可以使用 异或 的指令来搜索加密算法。

可以搜索 SVC 指令,这个相当于 x86 里面的 0x81 指令。

字节序列搜索

搜索满足匹配 HEX 串的序列。

菜单 [Search] → [Sequence of bytes],弹出一个窗,勾选"Find all occurrences":

这个的用处就自行发散吧,主要是基于自身对逆向目标的了解程度。

IDA 的 patch

直接修改数据:数据窗口 F2,这种方法不推荐,

插件修改数据:LazyIDA,修改位置,右键,[Paste Data],修改大段数据。

修改汇编代码:Keypatch(得保持指令字节不变,不然so格式就乱了)。

注意,修改完成之后,需要将修改应用到文件:菜单项 [Edit] → [Patch program] → [Apply Patches to ...]。

如果 apply 了多次,想撤回修改是不可能的(每次 patch 都是基于上一次 apply 的结果),所以每次 patch 完得自己存一个备份文件。

LazyIDA 数据提取

这个就是一个插件的功能,右键看一下就明白了。

点击后,会在窗口输出:

ini 复制代码
[+] Dump 0x4B8389 - 0x4B8395 (13 bytes) :
[0x55, 0x54, 0x50, 0x55, 0x54, 0x5F, 0x43, 0x48, 0x41, 0x52, 0x53, 0x45, 0x54]

还是非常好用的。

BinDiff

有需要再单独开。贴个网址:www.zynamics.com/bindiff.htm...

相关推荐
虾球xz6 分钟前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇11 分钟前
HTML常用表格与标签
前端·html
疯狂的沙粒15 分钟前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员30 分钟前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐32 分钟前
前端图像处理(一)
前端
程序猿阿伟40 分钟前
《智能指针频繁创建销毁:程序性能的“隐形杀手”》
java·开发语言·前端
疯狂的沙粒42 分钟前
对 TypeScript 中函数如何更好的理解及使用?与 JavaScript 函数有哪些区别?
前端·javascript·typescript
瑞雨溪1 小时前
AJAX的基本使用
前端·javascript·ajax
力透键背1 小时前
display: none和visibility: hidden的区别
开发语言·前端·javascript
程楠楠&M1 小时前
node.js第三方Express 框架
前端·javascript·node.js·express