恶意代码分析-第十五章-对抗反汇编

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_37809075/article/details/82496022

目录

笔记

实验

Lab15-1

Lab15-2

Lab15-3


笔记

反汇编技术:分为线性反汇编器和面向代码流的反汇编器,对于同一段字节集合。有时候反汇编出来的代码并不相同。

                     对抗反汇编技术是基于反汇编算法的天生漏洞而产生的

线性反汇编:用已经反汇编的指令大小来决定下一个要反汇编的字节,而不考虑代码流的控制指令。

                     而且PE的代码段还有一些数据。不能有效区分代码和数据

面向代码流的反汇编:检查每一条指令,然后建立一个需要反汇编的地址列表

对抗反汇编技术:利用反汇编器选择算法和假设算法的漏洞

                           相同目标的跳转指令:连续两个条件跳转指向一同一个目的地址,比如jz和jnz的结合,实际就是jmp

                                                               jz

                                                               jnz

                                                               call(数据)

                                                               当遇到jnz时会反汇编这个指令的false分支,与true分支产生冲突

                                                              (显示16进制字节Options->>General->>Number of Opcode Bytes)

                           固定条件的跳转指令:跳转条件总是相同的一条指令,比如xor eax ,eax然后jz。实际就是jmp

                                                                xor eax ,eax

                                                                jz

                                                               jmp (数据)

                                                               当遇到jz时会反汇编这个指令的false分支,与true分支产生冲突

                           无效的反汇编指令:EB FF C0 48

                                                           字节FF同时作为两条实际运行指令的一部分

import idaapi

idaapi.CompileLine('static n_key() {RunPythonStatement("nopIt()");}')

AddHotkey("Alt-N","n_key")

def nopIt():
    start = ScreenEA()
    end = NextHead(start)
    for ea in range(start,end):
        PatchByte(ea,0x90)
    Jump(end)
    Refresh()

IDApython对指令进行NOP

混淆控制流图

                       函数指针问题:使用函数指针可以大大降低反汇编器自动推导出程序流的信息量

                                                mov [ebp+var_4],offset sub_4011C0

                                                call   [ebp+var_4]     可以检测出来,一个函数偏移量加载到堆栈中,可以探测到函数的初始化引用

                                                call   [ebp+var_4]     检测不出来,函数的原型信息丢失

                        IDA中添加代码的交叉引用:AddCodeXref函数,fl_CF-->普通call     fl_JF-->跳转

                                                                      AddCodeXref(交叉引用来源的位置,交叉引用指向的位置,流的类型)

                        滥用返回指针:retn指令等同于jmp指令加pop指令。

                                                 不能显示代码中任何要跳转的交叉引用目标,另一个显著的结果是反汇编器会提前结束这个函数

                        滥用结构化异常处理:SEH链是一个函数列表,设计的目的是处理线程中的异常(访问无效内存区域,除0操作)。列表中的每个函数有两种选择,一种自己处理异常,另一种把异常传递到列表的下一个函数。

                                                            为了查找这个SEH链,操作系统先检查FS段寄存器(包含一个段选择子)-----》得到线程环境块(TEB)-----》TEB的第一个数据结构是线程信息块TIB。--------》TIB中的第一个元素就是SEH链的指针。

                                                            mov eax,(offset loc_40106B+1)

                                                            add  eax,14h

                                                            push eax

                                                            push large dword ptr fs:0

                                                            mov  large dword ptr fs:0,esp

                                                            xor    ecx,ecx

                                                            div    ecx

eax+14h,构造401080函数指针,通过div ecx的异常操作(除0)。调用了401080的异常代码

栈帧问题:

 

实验

Lab15-1

在main位置,可以看到有红底的部分和交叉引用的部分都是红色的,说明这里是错误的。其中call BB4C55A0这显然不是一个合法地址。这里利用了插入流氓E8来人反汇编器汇编出了call的指令。代码采用了“固定条件的跳转指令”来对抗反汇编技术。

 先把401010地方转化为数据

再把401011地方转化为代码。紧跟着这段代码的指令没有对齐,那么为了对齐指令,从0x00401014开始,遇到的所有db指令都按下键盘上的“c”键,转换成代码,直至一条指令紧挨着另一条指令,它们中间没有数据字节

然后选中main函数的所有代码,按下键盘的P键。让IDA将这部分的代码变成一个函数,这样就可以使用图形的模式来分析这段代码了

Lab15-2

test esp,esp。对于一个正常的程序,ESP寄存器的值一定是非0的 

 转化

第二处xor eax,eax

第三处,把401215的地方NOP掉

可以看到,这里的jz和jnz都跳转到同一个地方。那么我们这里依旧要采用之前的方法来将0x0040126D位置处的语句进行转换:

因为这里出现的jz跳转是向上进行的(之前的都是向下跳转)。分析跳转的目的地,它会跳到mov语句中间。

这里所出现的对抗反汇编技术与之前的有些不同,因为这里出现的jz跳转是向上进行的(之前的都是向下跳转)。分析跳转的目的地,它会跳到mov语句中间。

这里出现了一处名为sub_401386的函数调用。双击进入这个call来分析一下,可以发现程序在栈上创建了一个字符串:http://www.practicalmalwareanalysis.com/bamboo.html。并且程序还调用InternetOpenUrlA来试图访问这个网站

InternetOpen函数的第一个参数就是User-Agent字符串,这里它被保存在了edx中。而edx的内容是取决于szAgent的。

调用了gethostname来填充szAgent,也就是使用本地计算机的名称来填充szAgent。

Lab15-3

Imports窗口中调用了CreateToolhelp32Snapshot这个API函数,用于给当前的进程拍一个快照,接下来又使用了Process32First以及Process32Next来不断地列举当前的进程。还有URLDownloadToFile和WinExec

0x400000赋值给eax,然后将eax与0x148C进行或运算。结果其实就是0x40148C,保存在eax中。之后将这个值保存进ebp+4的地址位置。这个地址是返回地址,那么这段程序的目的就是要将返回地址覆盖为``0x0040148C。这样一来,当main函数执行完后,就会跳转到0x0040148C的位置继续执行。

修改这里的对抗反汇编 

这里利用对抗反汇编技术是SEH链,因为它上面的五行语句创建了一个异常处理例程,并且在0x004014AC的位置触发了一个除零异常(因为经过对ecx自身的异或运算,会使它的值变为0,接下来用它作为除数)。而异常处理的地址是4014C0

4014C0

把这里的数据转化为code ,目的是从异常处理链中摘除异常处理的例程,并从栈中删除了记录。

并修正代码

可以发现这里调用了URLDownloadToFileA这个函数。这个函数的第二和第三个参数分别是URL和文件名。,这两个参数都作为了sub_401534的参数,所以可以推测,sub_401534就是用于解密的函数

sub_401534

待解密的字符与0x0FF进行异或运算

第三处对抗反汇编位置

猜你喜欢

转载自blog.csdn.net/m0_37809075/article/details/82496022