从入门开始:恶意代码的那些事(1)

介绍

▼恶意代码

任何以某种方式对用户、计算机或网络造成破坏的软件或代码,都可以被认为是恶意代码。

▼分类

感染型病毒 Virus
蠕虫 Worm
木马 Trojan
黑客工具 HackTool
间谍软件 Spyware
风险软件 Riskware
垃圾文件 Junk file
测试文件 Test file

反病毒引擎扫描

针对可疑文件进行扫描服务,主要通过检测样本程序关键行为、进程行为、文件行为、网络行为、注册表行为等等,判别文件行为是否为恶意代码程序。

▼行为分析

名称 网站
VirusTotal virustotal.com
Virscan virscan.org
火眼 fireeye.ijinshan.com
Jott virusscan.jotti.org

环境搭建

在开始分析恶意代码过程中难免需要动态分析, 你不知道你所分析的恶意代码程序会给你带来怎样的惊喜?所以我们需要建立一个安全环境,这里主要是通过“vmware 虚拟机”创建一个分析恶意代码的虚拟环境。

而恶意代码程序有时会依靠互联网连接,来进行自身更像、获取命令、接受控制以及运行其他功能。并且有的恶意代码会检测自身是否正在虚拟机中运行,并表现出不同行为来阻扰分析。这里暂时不考虑这些较为复杂的情况,仅仅介绍一下简单的分析恶意代码的虚拟环境搭建。

▼虚拟机创建

软件下载 http://dwz.cn/2o4vCU
教程链接 http://dwz.cn/2o1i5n

▼硬件设置

image001 image003

虚拟机设备中”USB 控制器”、 “网卡适配器”移除了,并且禁用了共享文件夹。主要是为了避免在分析带感染行为的恶意样本的时候,恶意样本向外感染传播。

▼优化配置

在安装好了操作系统和恶意代码分析工具,我们可以建立一个初始快照。这个初始化快照主要是作为你的干净状态的基础镜像。也就是说,在我们分析完恶意代码后,可以把分析环境恢复到基础镜像快照,便于再次恶意代码分析。为了能够更好的分析恶意代码,除了安装纯净的系统镜像文件之外,还可以将系统性能设置进行修改。

image005 image007

▼其他

虚拟机调试分析程序的时候,假如发现程序在虚拟机中运行会提示: “Soory, this application cannt rununder a Virtual Machine.“

解决方案

打开对应的虚拟机配置文件 .VMX 格式(如 Windows XP Professional.vmx),记事本编辑 在尾部加入以下代码。

image009

信息收集

▼哈希值

每一个恶意代码样本都一个唯一的哈希值。而在恶意代码分析中 MD5 校验最为常用。对可疑样本进行分析的过程中,通过”MD5 校验工具”计算可疑样本的 MD5、SHA1、CRC32 的值与已知的病毒样本 MD5、SHA1、CRC32进行匹配。如果匹配上则可以对样本标”黑”,没有匹配上则需要进一步对可疑样本分析,因为存在病毒程序再变种的可能。

image010

▼字符串

恶意代码样本程序中都会包含一些字符串, 我们可以通过提取程序中所包含的字符串对样本的行为做一个简单的分析。

Strings工具

一款能够提取程序所包含的字符串小工具。image012

例子

这里通过自己编写的一个弹窗小程序,我们通过“Strings.exe”提取这个小程序所包含的字符串信息,可以发现提取的字符串中包含了“MessageBoxW”API函数和编译程序的路径信息。

image014

▼外壳信息

有时候在提取分析恶意程序的字符串的时候,发现所提取的字符串都是些无意义的字符串,遇到这种情况很有可能是恶意程序被加壳或者代码混淆了,导致我们不能通过提取字符串获取到有价值的信息。

换句话说,当我们在对恶意程序提取字符串的时候,发现它的字符串很少时,它就很有可能是加壳或是代码混淆了。而加壳或者代码混淆后至少会包含“LoadLibrary”和“GetProcAddress”函数,这两个函数是用来加载和使用其他函数功能的。

函数名 作用
LoadLibrary 加载动态连接库
GetProcAddress 获取功能函数的地址

壳是什么

壳指的是可执行文件所具有的压缩、加密、保护作用的东西。

壳的类型

  1. 压缩壳:减小软件体积大小,加密保护不是重点。
  2. 加密壳:种类比较多,不同的壳侧重点不同,一些壳单纯保护程序,另一些壳提供额外的功能,如提供注册机制、使用次数、时间限制等。
压缩壳 加密壳 虚拟机保护软件
ASPacK ASProtect VMProtect
UPX Themida
PECompact Armadillo
NsPack EXECrypto

查壳工具

名称 下载地址
PEID http://dwz.cn/2o6sAS
ProtectionID http://dwz.cn/2o6u7E
Detect it Easy http://dwz.cn/2o6Hmk
ExEinfo PE http://dwz.cn/2o6NPm

例子

这里主要通过PEID对程序进行查壳,发现程序所加的壳为UPX。它是一款应用程序专用压缩、解压缩软件,支持 EXE、COM、DLL、SYS、OCX 等多种文件格式的压缩。UPX 加壳后程序的区块名称被修改为UPX0、UPX1、RSRC。

image016 image018

脱壳

一些恶意代码程序里有一段专门负责保护软件不被修改或反编译的程序。它们一般都是先于程序运行,拿到控制权,然后完成它们保护恶意代码程序、加大分析难度的任务。为了进一步分析的恶意代码程序我们需要去掉恶意代码程序所加的壳,脱壳的方式主要有手工脱壳和自动脱壳。

手工脱壳

手工脱壳的常用方法:

  1. 单步跟踪法
  2. ESP 定律
  3. 两次断点法
  4. 一步到达 OEP
  5. 最后一次异常法
  6. 模拟跟踪法
  7. “SFX”法
  8. 出口标志法

自动脱壳

关于自动脱壳其实网上也有很多公开的自动化脱壳程序和脱壳脚本。

image020

image022

软件名称 下载链接
UPX 静态脱壳机 http://dwz.cn/2obbaF
ASPACK2.12 脱壳工具 http://dwz.cn/2obcnr
北斗脱壳机 http://dwz.cn/2obfhY
PECompact 脱壳机 http://dwz.cn/2obDvh

例子

这里通过利用UPX脱壳脚本对一个被加了UPX壳的程序进行脱壳, 将程序载入OD中通过插件中的ODbgScript导入脱壳脚本。

▼API 函数

假设我们知道一个恶意代码程序导入了URLDownloadtoFile函数,我们便可以初步判断该程序会从网上下载一些内容到本地,那么该程序就很可能是下载者。而在分析恶意代码程序的时候,我们可以利用 Dependency Walker工具获取可执行程序的动态链接函数。

常见的动态链接库文件

Kernel32.dll 包含核心系统功能,如访问和操作内存、文件和硬件
Advapi32.dll 这个DLL提供对核心Windows组件的访问,比如服务管理器和注册表
User32.dll 这个DLL中包含了所有用户界面组件,如按钮、滚动条以及控制和响应用户操作的组件
Gdi32.dll 这个DLL中包含了图形显示和操作的函数
Wsock32.dll 联网DLL,访问其中任意个DLL的程序非常可能连接网络,或者执行网络相关任务
Ws2_32.dll 如上
Wininet.dll 这个DLL包含了更好层次的网络函数,实现了如FTP、HTTP、NTP等协议

Kernel32.dll

CreateDirectoryw 创建一个新目录
CreateFileW 打开或创建以下对象,并返回可访问的句柄:控制台,通信资源,目录(只读打开),磁盘驱动器,文件,邮槽,管道
CreateThread 在主线程的基础上创建一个新线程
DeleteFileW 删除指定文件
ExitProcess 终止一个进程
FindClose 关闭一个搜索句柄
FindFirstFileW 根据文件名查找文件,利用在历遍指定目录的所有文件
FindNextFileW 根据文件名查找文件,利用在历遍指定目录的所有文件
GetCommandLineW 获得指向当前命令行缓冲区的一个指针
GetCurrentProcess 获取当前进程的一个伪句柄
GetCurrentThread 获取当前线程句柄
GetFileSize 获得该文件的大小
GetModuleHandleW 获取一个应用程序或动态链接库的模块句柄
GetProcessHeap 返回调用进程的默认堆句柄
GetShortPathNameW 获取指定路径的短路径形式
HeapAlloc 指定的堆上分配内存,并且分配后的内存不可移动
HeapFree 释放堆内存
IsDebuggerPresent 确定调用进程是否由用户模式的调试器调试
MapViewOffile 负责把文件数据映射到进程的地址空间
ReadFile 从文件中读出数据
SetFilePointer 说明在一个文件中设置当前的读取位置
WriteFile 将数据写入文件

User32.dll

BeginDeferWindowPos 该函数为一个多窗口位置结构分配内存并且返回该结构的句柄
CallNextHookEx 将钩子信息传递到当前钩子链中的下一个子程,一个钩子程序可以调用这个函数之前或之后处理钩子信息
CreateDialogParamw 根据对话框模板资源创建一个无模式的对话框
CreateWindowsExw 创建窗口
DefWindowProcW 该函数调用缺省的窗口过程来为应用程序没有处理的任何窗口消息提供缺省的处理。
DialogBoxParamW 根据对话框模板资源创建一个模态的对话框
EndDialog 清除一个模态对话框,并使系统中止对对话框的任何处理
GetMessageW 从调用线程的消息队列里取得一个消息并将其放于指定的结构
GetSystemMetrics 用于得到被定义的系统数据或者系统配置信息
GetWindowLongW 该函数获得指定窗口的有关信息,函数也获得在额外窗口内存中指定偏移位地址的32位度整型值
GetWindowsRect 该函数返回指定窗口的边框矩形的尺寸
GetWindowsTextW 该函数将指定窗口的标题条文本(如果存在)拷贝到一个缓存区内
InvalidateRect 该函数向指定的窗体更新区域添加一个矩形,然后窗口客户区域的这一部分将被重新绘制
IsDlgButtonChecked 该函数可以确定某个按钮控件是否有选中标志,或者三态按钮控制是否为灰色的、选中的、或两者都不是
IsWindowEnabled 该函数用于判断指定的窗口是否允许接受键盘或鼠标输入
LoadCursorW 该函数从一个与应用事例相关的可执行文件(EXE文件)中载入指定的光标资源
LoadIconW LoadIcon函数从与hInstance模块相关联的可执行文件中装入lpIconName指定的图标资源,仅当图标资源还没有被装入时该函数才执行装入操作,否则只获取装入的资源句柄
LoadMenuW 该函数从与应用程序实例相联系的可执行文件(.EXE)中加载指定的菜单资源
MapVirtualKeyw 该函数将一虚拟键码翻译(映射)成一扫描码或一字符值,或者将一扫描码翻译成一虚拟键码
MapWindwosPoints 函数功能该函数把相对于一个窗口的坐标空间的一组点映射成相对于另一窗口的坐标空间的一组点
MessageBoxW MessageBox显示一个模态对话框,其中包含一个系统图标、 一组按钮和一个简短的特定于应用程序消息,如状态或错误的信息
RegisterHotKey 该函数定义一个系统范围的热键
RegisterClassExw 该函数为随后在调用Createwindow函数和CreatewindowEx函数中使用的窗口注册一个窗口类
SendMessageA 将指定的消息发送到一个或多个窗口
SetClipboardData 把指定数据按照指定格式放入剪切板中
SetDlgItemTextW 该函数设置对话框中控件的文本和标题
SetWindowTextW 改变指定窗口的标题栏的文本内容
SetWindowsHooExw 钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。
ShowWindow 该函数设置指定窗口的显示状态
ToUnicodeEx 作用是将给定的虚拟键码字符串
TeackPopupMenu 该函数在指定位置显示快捷菜单,并跟踪菜单项的选择
TrackPopupMenuEx 该函数在指定位置显示快捷菜单,并跟踪菜单项的选择。快捷菜单可出现在屏幕上的任何位置
TranslateMessage 用于将虚拟键消息转换为字符消息
UnhookWindowsHookEx 要删除的钩子的句柄
UnregisterClassW 该函数注销一个窗口类
UnregisterHotKey hWnd与被释放的热键相关的窗口句柄

shell32.dll

CommandLineToArgvW 函数获得命令行参数
SHChangeNotify 通知系统 应用程序已经完成某个事件。如果应用程序执行的动作会影响到外壳就应该使用这个函数
ShGetFolderPathW 获取文件夹的CSIDL路径
ShellExecuteExW 指定应用程序执行某个操作
ShellExecuteW 运行一个外部程序(或者是打开一个已注册的文件、打开一个目录、打印一个文件等等),并对外部程序有一定的控制

Advapi32.dll

RegCloseKey 释放指定注册键的句柄
RegDeleteValueW 删除值
RegOpenCurrentUser 打开当前用户
RegOpenKeyExw 打开一个指定的注册表键
RegQueryValueExw 取得指定项或子项的默认值
RegSetValueExW 该函数将在注册表项下设置指定值的数据和类型

例子

再次用自己编写的一个弹窗小程序,我们通过“Dependency Walker”工具获取可执行程序的动态链接函数。发现在“USER32.DLL”中有“MessageBoxW”API 函数,也就是说程序执行会调用“MessageBoxW”这个API函数。

image024

▼PE 文件格式

我们所分析的恶意代码程序都是些Windows可执行文件、对象代码和DLL,它们的格式都为可移植执行文件格式,也就是我们常说的PE文件格式。而在PE结构中又包含了很多Windows操作系统加载器管理可执行代码所必要的信息。

PE 文件结构 DOS 文件头
PE 文件头
区块表
区块
调试信息

关于PE文件结构的文章网上都有很多,这里就不再冗余。对PE结构感兴趣的同学可以看一看《Windows PE权威指南》,这本书主要讲的是 Windows PE文件格式的原理及其编程技术,书中的实例也涵括了 PE 文件格式在加密与解密、软件汉化、逆向工程、反病毒等安全领域的应用。

文件名 下载地址
Windows PE 权威指南 http://dwz.cn/2o9QTQ

PE 文件格式示意图

由于图片较大,可能在阅读上会造成一定的不便。这里将 PE 文件格式示意图的图片地址也贴出来,感兴趣的同学可以自己下载下来看。

image026

文件名 下载地址
PE 文件格式示意图 http://dwz.cn/2oonTN

区块信息

PE文件头中有更多我们需要获取的信息,PE文件格式包括一个PE文件头,随后跟着一系列的分节。文件头中包含了有关文件本身的元数据。而头部之后是文件的一些实际部分,每个分节都包含了有用的信息。

常见的节
.text 包含了CPU执行指令。所有其他节存储数据和支持性的消息。一般来说,这是唯一可以执行的节,也是唯一包含代码的节
.rdata 包含导入与导出函数信息,与Dependency Walker和PEview工具所获得信息时相同的。这个节中还可以存储程序所用使用的只读数据。有些文件还会包含.idata和.edata节,来储存导入导出的信息
.data 包含了程序的全局数据,可以从程序的任何地方访问到
.rsrc 包含有可执行文件所用的资源,而这些内容并不是可执行的,比如图标、图片、菜单项和字符串等。
.reloc 包含来重定位文件的信息

有时候区块的名称会被篡改,而导致区块的名称被篡改最有可能的原因就是程序加壳了。换句话说,当我们在分析恶意代码程序的过程中发现程序区块的名称存在异样,那么程序就很有可能是被加壳了。

例子

这里列出了一些加壳程序的区块信息,没有列出来的大家可以通过在网上下载加壳程序自己进行加壳操作,再通过前面介绍的查壳工具来观察区块信息。

image028

UPX

image030

ASProtect

image032

ASPack

image034

Themida

编译信息

“IMAGE_NT_HEADERS”中的映像文件头(IMAGE_FILE_HEADER)中“Time Date Stamp”可以获取可执行文件是什么时候编译的。

image036

当然这里的编译时间仅仅是静态分析过程提供参考的信息,毕竟编译时间是可以恶意篡改的。就比如 Delphi程序都是采用统一的编译时间,都是1992年6月19日。

image038

image040

入口信息

在”IMAGE_OPTIONAL_HEADER”中第七个成员“AddressOfEntryPoint“,它持有OEP的RVA。

image042

我们用过二进制编辑器中,我们通过手动查找”IMAGE_OPTIONAL_HEADER”中第七个成员 AddressOfEntryPoint,发现是正确的。

image044

资源信息

资源区块包含有可执行文件所用的资源, 而这些内容并不是可执行的, 比如图标、 图片、 菜单项和字符串等。Resource Hacker 工具主要用来浏览.rsrc 节,我们可以通过这个工具看到字符串、图标和菜单,而现实的菜单项和程序所使用的是一致的。

image046

总体来说”Resource Hacker”这款工具使用起来还是挺简单的,所以这里就不详细解释了,至于怎么利用”Resource Hacker”工具这款工具就因人而异了。

▼总结

这次主要介绍初级的静态文件分析方法,通过简单的分析可以初步获取恶意代码程序的静态文件特征。如果有什么欠妥的地方,欢迎交流。感恩!

【via@xi2omin9】本文系投稿文章,未经授权请勿转载!