恶意代码分析实战
恶意代码分析实战
静态分析
查看可执行文件/DLL文件编译时间:PETool查看PE文件头,找到_IMAGE_NT_HEADERS.FileHeader.TimeDateStamp。
当导入表存在WS2_32.dll,则有联网行为。ADVAPI32.dll中存在创建服务和提权API。ole32.dll可创建COM实例。
通用脱壳机linxerUnpacker可脱FSG壳。
判断PE文件为EXE还是DLL:PETools文件头->特征值,看DLL复选框是否勾选。
恶意代码检测Vmware原理:in(0xED)指令与魔术字符串“VMXH”进行检测。另一种遍历HKLM\SYSTEM\CurrentControlSet\Control\Device以查找vmware值。也有其他各种老六行为。
CreateToolhelp32Snapshot进程、线程拍摄快照。
动态分析
运行DLL:
1 | rundll32 *.dll,导出表函数名 |
用RegShot记录注册表操作。注册表创建服务路径:HKLM\SYSTEM\ControlSet001\Services\服务名,重要参数:ImagePath、DisplayName、Description
COM模型
导入表中含有OLE32.DLL和OLEAUT32.DLL,重要API:CoCreateInstance、OleInitialize、OleUninitialize。具体使用的对象需要确定riid和rclsid。riid需要上网查,rclsid可从这里找:KLM\SOFTWARE\Classes\CLSID\。
后门
DLL映射组合拳:CrreateFileA、CreateFileMappingA、MapViewOfFile,IsBadReadPtr判断映射内存区域权限。
1 | repne scasb ;等于strlen |
计划任务
NetScheduleJobAdd着重第二个Buffer参数。
资源区
msgina32.dll获取登录凭证。
sfc_os.dll为Windows文件保护机制模块。通过LoadLibraryA调用该模块后,所调用的函数为第二个参数lpProcName,其中编号为2号的函数没有公开(其实为禁用Windows文件保护机制函数)。
SMTP
属于TCP,“RCPT TO: <”指令为收件人。
添加注册表项在“HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs”时,能被所有加载user32.dll的程序加载。
用户态ROOTKIT-HOOK
准备时,先检测在哪个进程中运行GetCurrentThreadId,并提取。比较需要HOOK的进程,组合拳CreateToolhelp32Snapshot->Thread32First与Thread32Next遍历,找到后除自己进程其余SuspendThread,结束后再次遍历并ResumeThread。
模块载入:GetModuleHandleA、LoadLibraryA、GetProcAddress
核心方法,在原指令前增加无条件跳转jmp,结束后再返回原地址,前后VirtualProtect修改内存权限。
1 | mov edx,[ebp+lpAddress] |
另一种跳转方法:地址在eax中,再jmp eax。
键盘勾子
导入表有USER32.DLL中的GetAsyncKeyState和GetForegroundWindow。
UnmapViewOfFile后,任何对映射所作出的操作会被写入磁盘。
可能通过SetWindowsHookExA、UnhookWindowsHookEx的方式,前者第一个参数idHook为0x0Dh时代表键盘挂钩。
进程注入
留意的KERNEL32.DLL中的API:CreateRemoteThread、WriteProcessMemory、VirtualAllocEx
进程替换
进程创建及进程上下文修改:CreateProcessA、GetThreadContext、SetThreadContext。对内存空间修改:ReadProcessMemory、WriteProcessMemory。对资源操作:LoadResource、LockResource、SizeofResource。
当CreateProcessA的第6个参数dwCreationFlags为4时创建但不启动。
被替换的进程为CreateProcessA的第一个参数lpApplicationName
时间差反调试
原理:较多时间浪费在异常处理。
QueryPerformanceCounter、GetTickCount获取精确时间。
将eip赋予eax:
1 | call $+5 |
UPX手脱复盘
pushad以下控制流只向下跳,忽略回跳,找到一个大jmp,跳过去即为OEP。
importREC修复导出表,个人喜欢Scylla。
shellcode
推荐命令行工具scdbg,运行后可统计出所有Win32API调用记录及其参数。
工具PDFStreamDumper可自动找出相应shellcode及漏洞。
内核调试
随机数相关注册表操作:写HKLM\SOFTWARE\Microsoft\Cryptography\RNG\Seed。
CreateServiceA的第5个参数dwServiceType为1时表示加载到内核。StartServiceA启动,ControlService第2个参数dwControl为1时启动卸载程序。
Windbg:
1 | bp 00401080 #该地址设置断点 |
SSDT
系统服务描述表,用WinDBG
1 | dd KeServiceDescriptionTable #第二列为地址 第4列为大小 第5列为参数 |
ROOTKIT文件隐藏原理:获取枚举链该文件的前驱后继两个文件,将前驱连续两次加上FILE_BOTH_DIR_INFORMATION的偏移量NextEntryOffset实现目标文件的脱链。
卸载服务方法:
1 | sc query "服务名" |
进程隐藏
WinDBG启动,dd查看驱动服务信息后查看请求处理表:
1 | dd 820df7e0+0x038 L1c #+0x038代表MajorFunction |
发现请求处理表中大部分为0x804f454a,尝试获取该信息:
1 | ln 804f454a |
IopInvalidDeviceRequest表示该驱动对该信号的处理方式缺省,其余信号可查看wdm.h,重要的有启动0、终止2、控制0E。
IoGetCurrentProcess所需参数为_EPROCESS结构,该结构并未公开,尝试WinDBG获取:
1 | dt _eprocess |
与文件隐藏原理相同:脱链技术
双向链表为_EPROCESS的_LIST_ENTRY结构
x64之路
WinDBG导出寄存器值:
1 | da rcx |
是否在x64系统上以x32运行:IsWow64Process。
如果在IMAGE_NT_HEADERS->UNAGE_FILE_HEADER中设置了IMAGE_FILE_32BIT_MACHINE则确定了以32位编译的。