恶意代码分析实战第6章 识别汇编中的C代码结构_恶意代码分析实战第6章 识别汇编中的C代码结构试读-查字典图书网
查字典图书网
当前位置: 查字典 > 图书网 > 编程 > 恶意代码分析实战 > 第6章 识别汇编中的C代码结构

恶意代码分析实战——第6章 识别汇编中的C代码结构

在第4章中,我们讨论了x86体系结构以及它最常用的指令。但是成功的逆向工程师并不会单独评估每一条指令,除非到他们必须这么做的时候。这个过程实在是太乏味了,并且整个被反汇编程序中的指令数目可以达到上千甚至上百万。作为一名恶意代码分析师,你必须能通过技巧,来获得一个高层次的代码功能视图,这个技巧就是以组为单位来分析指令,只在需要时再将精力集中在单条指令上。这个技巧的使用需要时间积累。 作为开始,让我们先考虑一个恶意代码作者是如何开发代码的,从而确定该如何分组指令。恶意代码典型情况下都是采用高级语言开发的,大多数时候是C语言。一个代码结构是一段代码的抽象层,它定义了一个功能属性,而不是它的实现细节。代码结构的例子包括循环、if语句、链接表、switch语句,等等。程序可以被划分为单独的结构,当它们组合到一起时,才能实现程序的总体功能。 本章将通过讨论超过十种不同的C代码结构,领你入门。尽管本章的目的是帮助读者学习逆向分析,但我们还是会检查每一种代码结构的汇编语言代码,你作为恶意代码分析师的目标是将恶意代码程序反汇编后,再恢复到高级语言结构从反汇编恢复到高级结构。而对于从高级语言结构到反汇编这个反方向的学习通常更简单,因为计算机程序员习惯阅读和理解高级语言源代码。 本章将精力集中在较常见的和有难度的结构上,比如循环和条件语句。当你构建了这些基础以后,你将学习如何快速地形成代码功能的高级视图。 除了讨论结构的区别外,我们也会验证编译器之间的区别,因为编译器版本和设置能影响一个特定结构在反汇编代码中的表现。我们会评估使用不同的编译器编译switch语句和函数调用的两种不同方式。本章将在C代码结构上进行更深层次的挖掘,所以总体而言,你理解的C和编程越多,你从中学到的东西就会越多。想在C语言上获得帮助,看一看由Brian Kernighan和Dennis Ritchie写的The C Programming Language(Prentice-Hall,1988)。多数恶意代码由C语言编写,尽管有时用Delphi和C++编写。C语言是一个与汇编有着紧密关系的简单语言,所以它是新手恶意代码分析师开始的最合理的地方。 阅读本章时,记住你的目标是理解一个程序的总体功能,而不是分析每一条指令。时刻记住这一点,不要在细节上陷入困境。将精力集中在程序整体上是如何工作的,而不是它们是如何做每一件特定事情的。 6.1 全局与局部变量 全局变量可以被一个程序中的任意函数访问和使用。局部变量只能在它被定义的函数中访问。在C中全局和局部变量的声明方式是相似的,但是在汇编中看起来完全不同。 下面是全局变量和局部变量的两个C语言代码例子。全局变量的例子见代码清单6-1,在函数外面定义了x和y变量。局部变量的例子见代码清单6-2,这两个变量在函数中被定义。 代码清单6-1 有两个全局变量的简单程序例子 代码清单6-2 有两个局部变量的简单程序例子 在这两个C代码例子中,全局和局部变量的差别并不大,而且在这个例子中程序结果是一样的。但在反汇编代码中,如代码清单6-3和6-4中显示的,差别却很大。全局变量通过内存地址引用,而局部变量通过栈地址引用。 在代码清单6-3中,全局变量x通过dword_40CF60来标记,一个在0x40CF60处的内存位置。注意在 处,eax的值被赋给dword_40CF60,所以x的值被修改了。所有后续使用这个变量的函数都会受影响。 代码清单6-3 代码清单6-1中的全局变量例子的汇编代码 在代码清单6-4和6-5中,局部变量x位于栈上一个相对ebp的常量偏移处。在代码清单6-4中,内存位置[ebp-4]在整个函数中被一致地用来引用局部变量x。这告诉我们ebp-4是一个基于栈的局部变量,它只在被定义的那个函数中被引用。 代码清单6-4 代码清单6-2中局部变量例子的汇编代码(未经标记) 在代码清单6-5中,x已经被IDA Pro反汇编器用假名var_4漂亮地标记了。正如我们在第5章中讨论的,假名可以被重命名为反映它们功能的有意义的名字。将这个局部变量命名为var_4而不是-4简化了你的分析,因为一旦你重命名var_4为x,你就不需要贯穿整个函数中在你的头脑里跟踪偏移-4了。 代码清单6-5 代码清单6-2中显示的局部变量例子的汇编代码(经过标记) 6.2 反汇编算术操作 许多不同类型的算术操作可以用C编程来执行,我们在这节将展示这些操作的反汇编。 代码清单6-6显示了两个变量和一些算术操作的C代码。其中,两个是- -和++操作,它们分别被用来自减1和自增1。%操作在两个变量之间执行取模操作,这个操作是取得执行一次个除法之后的余数。 代码清单6-6 两个变量和一些算术操作的C代码 代码清单6-7显示了代码清单6-6中C语言代码的汇编,它们可以被翻译回C语言。 代码清单6-7 代码清单6-6中算术操作例子的汇编代码 在这个例子中,a和b是局部变量,因为它们被通过栈来引用。IDA Pro已经标记了a为var_4,将b标记为var_8。首先,var_4和var_8分别被初始化为0和1。a被移动到eax中 ,然后0x0b被加给eax,从而a增加了11,b然后被a减 。(编译器决定使用sub和add指令 和 ,而不是inc和dec指令。) 最后5条汇编指令实现了取模。当执行div或idiv指令时 ,你是在用edx:eax除操作数并将结果保存到eax中,余数保存到edx中。这就是为什么edx被移动到var_8中的原因 。 6.3 识别if语句 程序员使用if语句来实现基于特定条件改变程序的执行。if语句在C代码和反汇编汇编代码中很常见。我们将在本节中检验基本的和嵌套的if语句。你的目标应该是学习如何识别不同类型的if语句。 代码清单6-8显示了一个简单C的if语句,这段代码对应的汇编代码在代码清单6-9中显示。注意在 处的条件跳转jnz。对于一个if语句必定有一个条件跳转,但不是所有条件跳转都对应if语句。 代码清单6-8 if语句例子的C代码 代码清单6-9 代码清单6-8中if语句例子的汇编代码 如你在代码清单6-9中看到的,代码清单6-8中在if语句内部的代码在被执行之前必须做一个决定。这个决定对应于 处显示的条件跳转(jnz)。要跳转的决定是基于一个比较(cmp)语句来做的,这个比较语句检查在 处var_4是否等于var_8(var_4和var_8对应我们源代码中的x和y)。如果这两个值不相等,这个跳转就会发生,并且这段代码打印“x is not equal to y.”;否则,代码继续执行并打印“x equals y.”。 同时也注意跳过在 处else段的代码跳转(jmp)。你识别出这两个代码路径中只有一条会被执行,这是识别if语句的关键点。

展开全文

推荐文章

猜你喜欢

附近的人在看

推荐阅读

拓展阅读

《恶意代码分析实战》其他试读目录

• 第0章 恶意代码分析技术入门
• 第6章 识别汇编中的C代码结构 [当前]
• 第19章 shellcode分析