<返回更多

PC端恶意代码的混淆与加壳对抗

2022-12-26  今日头条  Th0r安全
加入收藏

前言

之前的实验部分,也出现过加壳对抗,文中也说了几种工具脱壳和手动脱壳的方法,但是之前主要还是针对功能点的分析。从这里开始,主要涉及到的就是逆向对抗了。

Lab15:花指令

花指令是企图隐藏掉不想被逆向工程的代码块(或其它功能)的一种方法,在真实代码中插入一些垃圾代码的同时还保证原有程序的正确执行,而程序无法很好地反编译, 难以理解程序内容,达到混淆视听的效果。

__asm { }内联嵌入__emit 0e8h;

当出现这样的语句时,ida会把E8当作call,然后后面的部分当作调用函数,导致出现混淆。

所以此时一般可以用xor配合跳转语句,保证程序的正常运行。

除此之外,也可以加入0E9h等混淆IDA.

call $+5

add [esp],5

retn

当内联嵌入这样的语句时,会混淆IDA的流程图,这个语句最后的效果相当于一个jmp,等于没有。

Lab15-1

放入IDA中查看。


 

可以看到这里有一个永假跳转。

这边因为字符开头是E8,会让反编译误认为是Call,这时候把它先转为数据,然后把E8排除,就出现了原来的代码了。


 


 

接着可以看到下面还有好几处地方一样


 

用之前的方法修复

可以看到先是判断了参数的个数


 

之后第一个参数和p比,第二个参数和d比,第三个参数和q比,进行对比,最后可以得出当参数是pdq的时候成功。


 

Lab15-2

放到IDA中查看。


 

可以看到第一个出现返汇编的地方。

将40115E这一行,先变成data,然后把115F变成code,最后E9转为nop.


 


 


 

之后来到第二处


 

进行相似的修补。


 

继续一样的修补。


 

这里面的修补都差不多,最后的结果图


 

接着分析修复好后的程序。


 

先获取了主机名,然后这里经过+1和替换变成了agent头。


 

这里可以看到访问的网站


 

从网站中取出Bamboo::和::之间的内容,作为下载的网址


 

下载并运行。


 

Lab15-3

放到IDA中查看。

看到了异常处


 

修复


 

继续修复。


 


 

继续修复


 

修补后


 

分析修补后的网站

看到传入url函数的进行了异或


 

写个idc脚本进行解密


 

之后下载运行。


 

Lab16:反调试

进程运行时,位置fs:[30h]指向PEB的基地址。为了实现反调试技术,恶意代码通过这个位置的BeingDebugged标志检测,这个标志标识进程是否正在被调试

Reserved4数组中一个未公开的位置叫做ProcessHeap,它被设置为加载器为进程分配的第一个堆的位置。ProcessHeap位于PEB结构的0x18处。第一个堆头部有一个属性字段,它告诉内核这个堆是否在调试器中创建。这些属性叫做ForceFlags和Flags

windows XP系统中,ForceFlags属性位于堆头部偏移量0x10处;但是在Windows7系统中,对于32位应用程序来说它位于偏移量0x44处

由于调试器中启动进程与正常模式下启动进程有些不同,所以它们创建内存堆的方式也不同。系统使用PEB结构偏移量0x68处的一个未公开设置,来决定如何创建堆结构。如果这个位置的值为0x70,我们就知道进程正在调试器中

系统痕迹检测

HKEY_LOCAL_macHINESOFTWAREMicrosoftWindows NTCurrentVersionAeDebug

该注册表项指定当应用程序发生错误时,触发哪一个调试器。默认情况下,它被设置为Dr.Watson.如果该注册表的键值被修改为OllyDbg,则恶意代码可能确定它正在被调试

1

扫描代码的断点

call $+5

pop edi

sub edi,5

mov ecx,400h

mov eax,0CCh

repne scasb

jz DebuggerDeteced

对抗这种反调试技术的方法是使用硬件断点而不是使用软件断点

时钟检测

被调试时,进程的运行速度大大降低,例如,单步调试大幅度降低恶意代码的运行速度,所以时钟检测是恶意代码探测调试器存在的最常用方式之一。

记录执行一段操作前后的时间戳,然后比较这两个时间戳,如果存在滞后,则可以认为存在调试器

Lab16-1

放入IDA中查看,这个跟lab9的一个样本是一样的,除了增加反调试。


 

可以看到先是检查了BeingDebugged是否为0

之后检查processheap的forceflag是否为0


 

再检查NTGlobalFlag是否为70h


 

如果检测到任何一个有反调试的行为就删除自身。


 


 

对于这几个反调试方法都可以使用填充0的方法进行绕过

dump ds:[fs:[30] +0x18] + 0x10

dump fs:[30]

dump fs:[30]+0x68


 


 

也可以手动修改寄存器的值,让其跳转产生改变。


 

剩下的功能点前面都分析过了,就不继续分析了。

Lab16-2

这里用PEView查看


 

放入IDA中查看。


 

arg_4与1比较,说明只在程序刚开始的时候有用。


 

查看有无OllyDbg.

BeingDebugged,之后通过检查这个值,进行调试判断。


 

之后发现通过OutDebugStringA检测调试器


 

这里针对PEB,还是之前的方法

针对tls,把exit换成nop


 

针对OutputDebugStringA,也是用nop填充add.


 

但是不知道为啥我这里的密码得到是bzrr,书上是byrr.


 

Lab16-3

运行,会直接退出。跟之前分析过的一个样本是一样的


 

用od动态调试,我这边直接就出了最后的答案。

找到比较名字的地方。


 

但还是跟着步骤走一遍,找到4011E0


 

进入查看,可以看到QueryPerformanceCounter,通过两次时间差,判断有无调试。

通过设置2来作为有调试的标准,因此这里设置为nop


 

查看其中的异常处理


 

因为前面的xor语句,这里ecx被设置为0,所以这里会产生异常。


 

接着看下面,这里通过GetTickCount,对时间进行判断。


 

这里的401000也是异常处理。


 

继续往下看,可以看到rdstc,也是通过异常处理。


 

Lab17:反虚拟化

当镜像安装了vmware Tools,进程中就会出现VMwareService.exe、VMwareTray.exe和VMware.exe

通过搜索注册表中安装的服务

或者.NET stat | findstr Vmware

“航天课堂”第一课内容非常精彩。接下来我们会以更简单明了的方式向小朋友讲解相关知识。敬请期待第二节航天课堂。

以00:0C:29开始的MAC地址与VMware相对应

Red Pill反虚拟机技术

通过运行sidt指令获取IDTR寄存器的值。虚拟机监视器必须重新定位Guest系统的IDTR,来避免与host系统的IDTR冲突。因为在虚拟机中运行sidt指令时,虚拟机监视器不会得到通知,所以会返回虚拟机的IDTR,Red Pill通过测试这种差异来探测VMware的使用

查询I/O通信端口

VMware使用虚拟化I/O端口完成宿主系统与虚拟机之间的通信,以便支持诸如复制和粘贴功能。这个端口可以被查询

这种技术成功的关键在于x86体系结构中的in指令,它从一个源操作数指定的端口复制数据到目的操作数指导的内存地址

str指令用来从任务寄存器中检索段选择子,段选择子指向当前运行任务的任务状态段(TSS)

恶意代码编写者可以利用str指令探测虚拟机的存在,因为这条指令返回的值,在虚拟机系统与宿主系统可能不同(这种技术对于多处理器的硬件无效)

Lab17-1

这里先写一个idc脚本,在程序中搜索相关反虚拟的指令,然后输出对应的地址。


 

这里可以看到有三个地址,三个地方存在反虚拟的指令401121,4011b5,401204


 

先去401121,可以看到是sldt


 

之后对sldt之后值进行了一个比较,应对方法,nop掉


 

再去4011b5,可以看到这里是sidt.


 

这里是对结果的一个检测,也可以通过nop的方式解决。


 

接下来是str.


 

之后是检测,也是nop


 

Lab17-2

这次只关注反虚拟化的操作。


 

这里用之前写好的idc脚本,找到了一个地址。


 

可以看到是in


 


 

这里也可以用nop处理

Lab17-3

放入ida中查看。


 

用之前的idc脚本查找


 

可以查到一个地址


 

是I/O查找


 

这里看一下交叉引用


 

这里可以用Olldydbg将test该为xor


 


 


 


 

这里查看strings


 

查看交叉引用


 

然后到这里


 

再查看交叉引用,

看到是SYSTEMCurrentControlSetControlDevicesClasses传入。


 

可以得知这里是查询与vmware对比,探测虚拟化

利用之前的test修改为xor即可

Lab18:脱壳

前面提到过几个手动脱壳的方法,这里再来深入一下。

脱壳存根指向了以下三步操作

将原始程序脱壳到内存中

解析原始可执行文件的所有导入函数

将可执行程序转移到原始的程序入口点(OEP)

单步跟踪法

宗旨:向上的跳转不让实现,向下的跳转实现,当发现大跨度跳转时,即会到OEP

ESP定律法

遵循堆栈平衡原理,在壳对程序进行操作加密或者压缩时,会把程序的OEP压入栈中,当壳执行完成后,进行解密或者解压缩,会把真正的OEP从栈中弹出

2次内存镜像法

在壳进行解密或解压缩时,最后释放的是资源区段:.rsrc,这个区段被释放完全后,说明整个程序已经被全部解密

Lab18-1

放入od,直接Ollydump插件即可,然后修复即可


 

Lab18-2

放入od,也是插件即可


 

Lab18-3

放入od,设置硬件断点,利用ESP定律


 


 


 


 

Lab18-4

放入od,设置硬件断点,利用ESP定律


 

这里单步调试到OEP


 


 

Lab18-5

跟之前一样,放入od,设置硬件断点,利用ESP定律


 

声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍相关推荐
更多资讯 >>>