转载

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

0x00 引言

在上一篇之后,有个同学发来消息问笔者能不能直接注入exe,其实注入exe和注入dll并无太多的区别。既然有人想了解这方面知识,那笔者就把这部分内容拿出来作为第二篇分析一下。严格来讲,进程替换应该是一种病毒的隐藏方式。exe注入与进程替换有很多的相同之处,如果注入exe之后释放了原有进程,就可以理解为进程替换了。本篇将逆向分析一个实现替换自身进程的病毒,着重分析该病毒在实现进程替换的各种工作。

不知读者有没有听过“内核重载”的概念,其实注入一个exe与“内核重载”还是有很多相似的地方,从某种角度上来讲,“内核重载”也就是将内核exe在ring0中加载并运行起来。如果比较熟悉“内核重载”的原理,那接触这些这篇应该相对容易一些。本次选用的样本是最近比较火的勒索软件LOCKY病毒的一个变种,由于笔者并没有找到特别合适的注入exe样本,所以选取一个实现替换替换进程的样本作为例子进行分析,如果内容不能让你满意,还请见谅。最后,笔者忠心希望本系列能给读者一点启发和帮助,但由于笔者知识有限,才疏学浅,文中不当或错误之处还请各位读者包容和指正。

  • 分析工具:IDA,OD,CFF,PEiD等。
  • 分析环境:Win7 x86 Vmware
  • 样本地址:百度能搜到一堆,实在弄不到,再联系笔者吧。

0x01 样本概况

该病毒是近期出现的勒索病毒,其中有很多值得分析的地方,但本文不做其他分析,只将与进程替换相关的部分拿出来展示给大家。此外,样本的基本信息如下:

Name LOCKY.exe
Size 143.50 KB (146944 bytes)
MD5 0FED77B29961C0207BB4B7B033CA3FD4

为了让读者更顺利的进行分析和学习,笔者在2.1节逆向分析介绍了实现进程替换之前的各种反调试工作和准备工作,如果对这部分不感兴趣的读者,可以直接跳到2.2节。

0x03 详细分析

一、样本调试注意事项

调试样本时需要注意以下两点内容,其一是样本运行时需要一个参数:123,运行过程中会调用GetCommandLine()和wtoi()函数:

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

如上图所示,如果不能正确初始化eax,那么造成样本后续无法继续执行,对我们调试分析将会造成阻碍作用。

其二是样本会多次复制将要执行的代码,如果在调试过程中用到了INT 3断点,那么复制的代码将不可执行。具体如下图:

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

此时,相关的寄存器数值如下:

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

EDI的值为刚刚调用VirtualAlloc()申请到的内容地址,ESI为repmovsb指令所在函数的函数基址,ECX值DA9为相关函数的长度。复制完毕之后,会在接下来的函数retn_to_copyone中中修改函数返回地址,使之跳到刚刚完成复制的代码:

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

如果该段代码有INT3断点,那么复制的代码会包含CC指令。

当顺利通过以上提到的两点反调试工作之后,就可以正常调试样本了。样本首先从ntdll中获得RtlDecompressBuffer函数的地址:

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

进而,把处于样本不同位置的数据内容拼接复制起来:

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

拼接完毕之后,会对拼接之后的数据进行初步解码,最后调用RtlDecompressBuffer函数解压缩该部分数据:

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

解压完毕之后,可以得到一个完整的PE文件:

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

此时,可以把该PE文件从内存中dump出来,用CFF查看结果如下:

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

二、进程替换

在内存中的的这个PE文件,暂且命名为dump.exe文件,该文件相当于用ReadFile()获取而来,那么下面的工作就是用dump.exe替换当前进程。首先,调用VirtualProtect增加可写页属性,并将dump.exe的PE头内容复制到LOCKY.exe所在基址:

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

第二步,分段加载dump.exe的内容,在该样本中的实现如下:

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

简言之,即循环使用rep movsb指令复制内容。复制的目的地址是经过内存对齐的地址。通过PEiD可以查看dump.exe的段信息:

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

上图中,将偏移0x400即ESI值的.text段复制到内存偏移0x1000即EDI值的位置,复制大小为0x10E00即ECX值。

第三,会在sub_D062D函数中根据重定位表进行修复工作:

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

在该函数内部,最终的修复语句如下:

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

此时,正在修复偏移为0x2046的内存地址,其中EDI为加载基址,通过CFF查看dump.exe重定位表可以找到此项:

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

第四,在sub_D0467中修复导入表:

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

在其内部,分别调用LoadLibraryA和GetProcAddress获取函数地址,并用mov命令完成初始化IAT功能。

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

此时,正在修复WININET.dll的InternetSetOptionA函数,同样可以通过CFF查看到:

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

从HexView中可以看到函数名,用CFF观察导入表可以找到此项。

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

第五,调用VirtualProtect函数去掉可写属性,并循环调用VirtualProtect函数给dump.exe的各个段赋予不同的页属性。

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

第六,在函数sub_D06AC中查找kernel32.dll模块:

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

该函数查找kernel32.dll基址的方法是通过遍历InMemoryOrderModuleList链表实现的,该链表_PEB_LDR_DATA结构的一项,具体内容如下:

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

首先通过FS寄存器获取PEB基址,然后获取获取_PEB_LDR_DATA,进而获取InMemoryOrderModuleList并开始遍历,并调用sub_D0775判断是否为kernel32.dll模块:

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

如果查找到了,则退出该函数,否则获取下一个模块。 此后,会在栈上构造一些数据并以该数据为参数调用GetEnvironmentVariable函数:

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

在笔者的测试机中,并没有该环境变量,GetEnvironmentVariable函数的返回值为0。

第七,遍历调用栈,查找返回地址在kernel32.dll模块内的函数,在第六步已获得kernel32.dll的模块基址。函数sub_D0D25中会遍历函数的调用栈:

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

其遍历方法如下:

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

图中,EDX为遍历函数的返回地址,如果返回地址在kernel32.dll模块的范围内,则退出遍历;否则,令EAX取外层函数的EBP值,继续遍历。

第八,以jmp eax的形式调用RtlZeroMemory,返回地址为dump.exe的入口地址。其中,EBP和ESP是根据第七步获得的EDX值设置的。

逆向浅析各种病毒的注入方式之二-----exe注入与进程替换

当RtlZeroMemory执行完毕之后,便回到dump.exe的入口地址,执行dump.exe的代码。到此,可以理解为进程替换完毕,原进程已经被清除,新进程即将被执行。

0x03 正向分析进程替换

如果对以上逆向分析内容无法很清楚的理解,那么本节将给出一个正向分析的例子,该例子源自于 [email protected]

的loadEXE.cpp,有兴趣的读者可以自行下载。在该cpp中 [email protected]

将进程替换的步骤分为5点:

  1. 以挂起模式调动创建原始进程
  2. 取消原始进程镜像的映射
  3. 在原始进程的进程空间中申请内存空间
  4. 将新进程的镜像载入申请内存
  5. 设置入口地址并恢复挂起的线程

需要指出的是,恢复挂起线程后,系统会自动初始化导入表并根据重定位表进行相关的修复工作,而在上一节0x02中逆向分析的病毒样本是需要自己完成这部分工作的。此外,在oadEXE.cpp中明显以calc.exe为原始进程,所以在文中第33行应是calc.exe的进程空间,而不是svchost.exe的进程空间。

借鉴《恶意代码分析实战》一书中的内容,上述5步操作的伪代码大致如下:

#!cpp CreateProcess(...,”calc.exe”,...,CREATE_SUSPENDED,...); ZwUnmapViewOfSection(...); VirtualAllocEx(...,ImageBase,SizeOfImage,...); for ( i = 0; i < NumberOfSections; i++) {   WriteProcessMemory(...,section,...); } SetThreadContext(); ... ResumeThread(); 

0x04 exe注入

综合之前所述的内容,并结合本系列第一篇来看,注入exe也并非很麻烦的事。大体上,只需针对第一篇提到的注入DLL方法做出小部分修改,即可完成exe的注入工作。第一篇中注入DLL时,需要用到的初始化导入表和根据重定位表进行修复的PIC代码,只要将这部分代码做出相应的修改即可运用于注入exe的初始化修复工作。

此外,本文分析的样本实现了自身进程的替换,虽然要比上一节0x04中介绍的替换其他进程复杂一些,但也很有参考价值。

0x05 总结

本文以病毒LOCKY.exe某个变种为样本,着重介绍了其完成自身替换的方法,并结合《恶意代码分析实战》和 [email protected]

方法。其实,该样本的后续行为中,还有很多值得进行深入分析的地方,比如说其加密算法等等。不过,受限于篇幅问题,这里就不深入探讨了。本次分析就到此为止,若读者有什么不明白的地方,可以私信于我,咱们共同探讨。

原文  http://drops.wooyun.org/tips/17351
正文到此结束
Loading...