病毒分析
病毒分析
1. 情报收集
1.1 文件观察
1.1.1 文件类型
使用PE studio,CFF Explorer等PE解析工具观察程序的基本信息,如入口点,文件类型,HASH值。
1.1.2 文件的节
各个节区,是否存在可疑的节区?节区的权限是否正常?节区的文件大小和内存大小是否异常(如果某个节内存占用过大,可能就是后续释放恶意代码的位置)?判断节区的熵值,过高则可能存在加密。
1.1.3 文件的导入表
存在非常明显的API组合,VirtualProtect, ShellExecuteEx, VirtualAllocEx, MapViewOfFile等。如果导入的函数和DLL过少则程序可能在后续动态加载DLL和API,或使用自己实现的GetModuleHandle,GetProcAddress等。
1.2 程序行为观察
1.2.1 明显行为观察
多次运行程序,观察现象,记录。比如启动项是否被篡改,Temp文件夹是否被添加了可疑文件?如果观测到程序创建文件之后又删除文件使用文件夹高级选项防止进程删除痕迹。
1.2.2 进程生命周期
使用Process Explorer或System Informer观察进程创建了什么进程?启动ProcMon,之后运行进程,记录程序所有的操作,查看进程树,查看进程的生命周期。过滤分析行为日志,打开或创建了什么文件?查询或修改写入了哪些注册表的键值?启动了哪些进程?详细记录。
1.2.3 API追踪
追踪程序使用的所有API,如果有明显的API组合则需要留意并记录参数和调用栈。
1.3 信息整理
记录所有有价值的信息以及病毒释放的所有文件,进行初步猜测,尝试定位病毒。
2. 静态分析
2.1 明文提取
使用floss之类的工具提取程序的字符串,以及使用 stack 这类的参数,尝试从栈中解密出明文,特别是一些文件名,域名,IP地址等。如果在IDA这类工具发现了关键的明文信息,直接反引用去定位相关代码。很可能直接定位到恶意代码附近。
2.2 反编译
如果程序的编译信息没有清除干净,那么反编译工具可能直接会显示出程序的开发环境的一些信息。如果通过API定位或字符串定位到的函数非常复杂,并且控制流图具有明显的特征,比如辐射状,可能使用了控制流平坦化混淆。如果掺杂了大量的无效指令或等价指令,如xchg eax, eax等,也可以确定是被混淆过的。
如果没有找到任何有用的明文信息或者API组合,大概是存在加壳混淆。
3. 调试分析
3.1 反调试对抗
3.1.1 常见反调试API
使用 ScyllaHide 插件,"NtGlobalFlag"、"Heap Flags" 和 "PEB",这些是绕过基础反调试的核心。隐藏对应API。
NtQuerySystemInformation NtQueryInformationProcess等API可以直接查询是否存在调试器。程序也可能使用syscall指令来直接调用这些api,在程序代码中搜寻相关的指令进行判断。
3.1.2 断点
如果打上软件断点导致了程序异常行为,则很可能程序检测到了API部分的代码被调试器或者EDR修改了,程序检测到了自己正在被分析,拒绝执行。使用硬件断点可以规避此类检测。
如果断点还是没有触发,查看进程的内存是否存在原始DLL的一份拷贝,程序使用自己拷贝的一份DLL,而不是系统加载好的。
3.1.3 异常
如果程序主动触发了大量的异常,如果调试器没有正确处理这些异常(被调试程序触发异常,调试器会首先接管),程序就可以检测到当前程序正在被调试。需要将异常直接交给被调试的程序。
3.2 简单壳的脱壳
在 VirtualAlloc, VirtualProtect 等内存操作相关的API上添加断点,查看程序是否向可疑的地址写入数据,或者更改内存为可执行。留意所有可执行的内存。如果程序在可疑的内存区域启动了新线程,则很可能是恶意代码被释放的地方。使用Scylla等工具将内存dump出来。
3.3 恶意代码定位
如果确定VirtualProtect执行可疑的操作或者新线程执行的代码处于可以的内存区域,则很可能是关键恶意代码的附近。通过调用栈来回到恶意代码区域,通过dump内存,使用反编译工具和其他静态分析工具对解密出的恶意代码重新进行分析,尝试提取明文信息,反编译程序分析程序的恶意行为和手法。
4. 信息整理
收集所有的信息以及证据,进行合理的推测,结合新得到的信息和新的推测重新对程序进行分析。
