APP下载

电脑病毒分析详解一例

2019-06-22唐文昊李孟轩阮鉴杰陈红珍

视听 2019年5期
关键词:染毒字节区段

唐文昊 李孟轩 阮鉴杰 陈红珍

(广西广播电视技术中心桂林分中心)

一、引言

在拷贝文件的过程中,病毒通过U盘的自动运行,在短时间内感染了全盘的程序。影响了单位远程管理系统等一系列计算机软件的正常运行,给安全播出带来隐患。本着刨根究底的态度,笔者对染毒的程序样本“OEM设备IP配置.exe”进行了一次常规且详细的剖析。

二、分析准备

病毒分析需要在一个干净且可以撤销操作的环境中进行,虚拟机是很好的选择。在分析前建立还原点,以避免调试过程中的误操作使病毒生效,导致实验环境被破坏,影响分析过程和结果。笔者使用的分析工具有:虚拟机Vmware、动态调试器ollydbg、PE工具PE Explorer。本文中的十六进制数均以汇编语言的格式表示,以H结尾,表示Hex。

三、染毒程序的分析

(一)PE结构

图1 PE Explorer中显示的PE头部的部分信息

PE(Portable Executable)文件是Windows系统的程序文件,主要有可执行文件(exe)、动态链接库(dll)和驱动程序(sys)三种。操作系统为了组织程序中的代码和数据,定义了PE文件的区段结构。位于文件开头的PE头部可以得到整个程序的结构信息,给系统加载程序提供了依据。病毒感染程序的过程,是在不破坏PE结构的前提下,把自己附加到程序的新区段或者原代码段的空闲区域(文件中区段未满200H个字节时,剩下由0填充)。这里只需要关注PE头部的部分数据,图1是PE工具中显示的信息。

图1的PE头部信息对应Windows平台开发中winnt.h头文件定义的数据结构IMAGE_FILE_HEADER和IMAGE_OPTIONAL_HEADER32的前一部分。重点关注倒数第四行的入口点地址61B00H,表示程序被加载后将从这个地址开始执行。需要注意的是,为阅读方便,PE工具中显示的值是VA(虚拟地址),而文件中实际存储的值是RVA(相对虚拟地址),VA=RVA+映像基址。

图2 PE Explorer中显示的区段表

图3 染毒程序的入口点代码(感染代码的开头)

另一个重要的数据结构是区段表,包括了区段的位置信息。每一行代表一个区段,对应数据结构IMAGE_SECTION_HEADER。虚拟大小和虚拟地址指区段在内存中的位置。RAW数据大小和RAW数据入口指区段在文件中的位置。由此可以得到区段从磁盘文件映射到内存的对应关系。内存以页面(0x1000字节)对齐,磁盘以扇区(0x200字节)对齐,表中的数值也是它们的倍数。特征值则可以区别此区段包含的是代码或者数据,以及是否有读、写、执行等权限。

图2显示此程序共9个区段,图1中的第二行也有标识(PE工具翻译有误,应为区段数)。常见区段有代码段.text和数据段.data,以及导入表、导出表所在区段.idata和.edata。导入表非常重要,包含程序调用的系统函数或第三方动态链接库导出函数的名字和地址,会直接暴露程序的底层实现。导出表则标识了本程序可对外公开的函数。导出函数一般被用于共享(提供给多个程序调用),会被编译到dll文件,而exe文件很少会有导出函数。

图4 搜寻系统函数地址的部分代码

最后一个区段.rmnet是重点怀疑对象,这个名字不是链接器生成的默认区段名。实际上它就是病毒所在区段。正常的入口点会落在代码段.text内,靠近开头,一般是401xxxH,而染毒后的入口点却位于最后这个区段。此段的特征值E0000020H标识了:代码(第6位)、可执行(第30位)、可读(第31位)、可写(第32位)。代码段可写在正常情况下很少见,这意味着代码可能被加密了,一般是加壳软件或病毒才有具有的特征。

(二)感染代码——搜索函数地址

用调试器打开染毒的程序“OEM设备IP配置.exe”,来到入口点代码。

代码窗口的信息有:第一列是内存地址,第二列是代码的十六进制数值,对应第三列的汇编语句。图3中1处:ebp寄存器本来用于指向上一个栈帧的基址,回溯函数的调用关系,这里却用作重定位,寻址此区段的数据,还做了简单的变形,先减后加相近的数值。2、3处:从原程序的导入表中取得两个重要系统函数的地址:LoadLibraryA和GetProcAddress,均为kernel32.dll的导出函数,是获取其他函数的绝代双娇,也是Shellcode的常见操作。Shellcode指一段伪装成数据的代码,向有漏洞的程序进行远程注入,根据目标程序的内存、堆栈空间进行精密的调整,使程序执行的流程转移到自己身上。它的特点是无硬编码的寻址操作,必须对自身数据进行重定位。重定位使用call下一条指令将指令地址入栈,再弹出此地址用于相对寻址。为避免作为字符串被截断、出现’’字符,会使用代码中未出现的字节值进行简单的异或变换。感染代码使用了成熟的Shellcode技巧,增加了病毒的隐蔽性。

图5 搜索函数地址完成的结果

图6 正在解密中的数据(PE文件)

图7 解密的代码

图4中1处调用LoadLibraryA获得Kernel32.dll的基址。2、3处及后续多处调用GetProcAddress获得Kernel32.dll中各个函数的地址。把dll的基址和函数名作为参数传入GetProcAddress即可,以下是搜索结束后内存中的信息。其中第一列是内存地址,第二至第五列是十六进制数据(四个DWORD),第六列是数据的ascii码。

图5中1处包括kernel32.dll的基址(第一个DWORD7C800000H),后跟十一个搜索到的函数地址。2处是用于搜索的函数名和dll名。

(三)感染代码——解密病毒本体

函数准备完毕,进入主要流程:调用CreateMutexA创建名为“KyUffThOkYwRRtgPP”的互斥体,并检查GetLastError的返回值是否ERROR_ALREADY_EXISTS判断其是否存在。由后期分析得知病毒本体也会创建此互斥体,以此判断病毒本体是否已运行。接下来对一段数据进行解密,数据和代码分别如图6和图7所示。

图6中1处为已解密的明文,根据开头的DOS头特征“MZ”判断这可能是一个PE文件。

图7中1处edx为密钥长度13H。2处密钥(图8中1处)与密文逐字节异或得到明文。edx作为秘钥的索引,从最后第19字节23H逐步递减至第1字节4BH,再回到第19字节,是逆序的循环队列。bl保存由索引取出的密钥字节和异或的结果。edi指向要解密的密文字节,逐步递增。3处如果ecx不为0则减1并回跳。相当于循环ecx次,一共DC00H次,意味着密文长DC00H字节。以下是用C语言表示的解密过程:

图8 密钥和互斥体的名字

(四)感染代码——执行病毒本体

调用GetModuleFileNameA 得到本程序的完整路径名“C:vOEM设备IP配置.exe”,再将.exe替换为Srv.exe得到一个新的路径名“C:vOEM设备IP配置 Srv.exe”。依次调用 CreateFileA、WriteFile、CloseHandle用新路径名创建文件,并写入从61B573H开始的DC00H字节。这正是图7中解密后的数据,实为病毒本体。下图9为堆栈中WriteFile的参数,可以看到第二行的起始地址和第三行的长度。

程序调用CreateProcessA启动病毒本体,这里要让病毒启动失败,可以更改参数中的路径名或者病毒本体文件名。接下来进行一些收尾工作,释放句柄、dll等资源。

代码最后一行跳转到eax=4016FCH,位于代码段.text内,可以确定是原程序的入口点。

图9 调用WriteFile时堆栈中的参数

四、修复染毒程序

修复染毒程序需要三步:1.修改PE头部的入口点为原程序入口点;2.根据区段表的信息删除文件末尾的病毒区段.rmnet,并删除此表项,将PE头部中的区段数减一;3.修改PE头部的映像大小。步骤1的关键在于如何找到原程序入口点。在染毒代码的末尾,可以看到原入口点是由两个数相减算出来的(61B000H-219904H=4016FCH)。经过对多个染毒文件的对比,确定这两个数位于病毒区段的固定偏移320H和328H处,其中第一个数是固定的染毒程序的入口点(由图3中第七行代码写入)。

图10 感染代码的末尾

在修复之前必须精准匹配病毒特征:1.病毒区段名;2.病毒区段所占文件大小;3.图3中第五行代码固定的的立即数20016F32H。以下是计算原入口点的代码片段:

DWORDdwSections = pNTHeader->FileHeader.NumberOfSections;

PIMAGE_SECTION_HEADERpSectionHeader = IMAGE_FIRST_SECTION(pNTHeader);

PIMAGE_SECTION_HEADERpVirusSectionHeader =pSectionHeader + dwSections-1;

if (lstrcmpA((LPCSTR)(pVirusSectionHeader->Name), ".rmnet") != 0 || pVirusSectionHeader->SizeOfRawData != 0xe200)return-1;

PBYTEpVirus = (PBYTE)pFile +pVirusSectionHeader->PointerToRawData;

if (*(DWORD*)(pVirus + 0xb) != 0x20016f32)return-1;

DWORDdwOriEntryPoint = pVirusSectionHeader->VirtualAddress-*(DWORD*)(pVirus + 0x328);

pNTHeader->OptionalHeader.AddressOfEntryPoint = dwOriEntryPoint;

五、总结

计算机病毒的危害性是严重的,针对病毒的特点可利用逆向分析获取病毒的特征编写专杀工具,清除病毒,使计算机系统和软件恢复正常工作。

猜你喜欢

染毒字节区段
中老铁路双线区段送电成功
No.8 字节跳动将推出独立出口电商APP
大生产
香烟烟雾染毒改良方法的应用*
No.10 “字节跳动手机”要来了?
站内特殊区段电码化设计
站内轨道区段最小长度的探讨
基于MSP430的四旋翼飞行器的S-BUS通信协议的设计与实现
染毒的脐带
香烟烟雾染毒对雄性大鼠睾丸组织ATP酶活性的影响