恶意代码分析实战 隐蔽的恶意代码启动 lab12-1 12-2 12-3 12-4 进程注入、进程替换、hook procmon监控os api调用不行 数据分析还是要sysmon
一、常用的隐藏技术
- 启动器
- 进程注入
- 进程替换
- Hook注入
- Detours
- APC注入
二、Lab12-1 - 创建远程线程
(winxp有效,win7我没有运行成功,why?)
1.行为分析
执行之后的效果是每隔一段时间会弹窗。
查看process momitor。可以发现psapi.dll被createFileMapping进内存,可能是修改了CreateFileMapping.
我++,没有监控到createremotethread!procmon只能监控到dll加载。如下图:
只是到线程创建和退出、dll加载!但是是不是用该dll创建远程线程,它提供的信息就不充分了!
在process explorer里也可以看到类似的:
使用火绒剑监控更好!
针对恶意代码分析实战 lab 12-1的创建远程线程注入方式,我监控了下:
火绒剑报出的关键日志如下:
11:34:38:656, explorer.exe, 2744:2156, 0, THRD_resume, C:\Documents and Settings\Administrator\桌面\Chapter_12L\Lab12-01.exe, target_pid:1984 target_tid:3068 , 0x00000000 [操作成功完成。 ], 11:34:38:734, Lab12-01.exe, 1984:3068, 1984, PROC_writevm, C:\WINDOWS\explorer.exe, target_pid:2744 base:0x01750000 bytes_written:0x00000104 datalen:0x00000104 data:'43 3A 5C 44 6F 63 75 6D 65 6E 74 73 20 61 6E 64 ' , 0x00000000 [操作成功完成。 ], 11:34:38:734, Lab12-01.exe, 1984:3068, 1984, THRD_remote, C:\WINDOWS\explorer.exe, target_pid:2744 target_tid:3064 access:0x001F03FF suspended:true start_vaddr:0x7C801D7B thread_param:0xB0B5FD64 , 0x00000000 [操作成功完成。 ], 11:34:38:734, Lab12-01.exe, 1984:3068, 1984, THRD_resume, C:\WINDOWS\explorer.exe, target_pid:2744 target_tid:3064 , 0x00000000 [操作成功完成。 ],
看来的确是可以监控进程注入!比procmon和procexp都方便!
这几个都是进程注入的常用api监控!
2.Lab12-1.exe
反汇编看下:
可以看到是在做进程注入!都是典型的os api!
注入到explorer.exe里是
其他都是边角细节了,如下:
主要流程分析
1.初始化:通过LoadLibrary和GetProcAddress来获得EnumProcessModules、GetModuleBaseNameA、EnumProcesses函数地址。并拼接得到Lab12-01.dll的绝对地址
2.通过上面EnumProcesses、EnumProcessModules和GetModuleBaseName寻找explorer.exe的pid
3.通过openProcess、VirtualAllocEx和WriteProcessMemory向explorer,exe写入Lab12-01.dll的地址
4.CreateRemoteThread指定explorer.exe调用LoadLibrary,参数为吸入的Lab12-01.dll地址
3.Lab12-01.dll
字符串里面找到前面弹窗里面的字符串"Press OK to reboot"和“Practical Malware Analysis %d”
DLLMain
通过CreateThread调用sub_10001030函数
sub_10001030函数每60秒调用一次StartAddress
StartAddress函数创建一个弹窗
反编译看起来更快:
4.用到的数据结构和函数
获得PID数组
使用方法
https://docs.microsoft.com/en-us/windows/win32/psapi/enumerating-all-processes
BOOL EnumProcesses(
DWORD *lpidProcess,//指向保存pid的数组
DWORD cb,//数组大小
LPDWORD lpcbNeeded//指向返回pid的数量
);
获得现有PID的句柄
HANDLE OpenProcess(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
DWORD dwProcessId
);
枚举进程模块信息
BOOL EnumProcessModules(
HANDLE hProcess,
HMODULE *lphModule,
DWORD cb,
LPDWORD lpcbNeeded
);
获得模块的名字
DWORD GetModuleBaseNameA(
HANDLE hProcess,
HMODULE hModule,
LPSTR lpBaseName,
DWORD nSize
);
为某个进程申请空间(flAllocationType都有什么用呢)
LPVOID VirtualAllocEx(
HANDLE hProcess,
LPVOID lpAddress,
SIZE_T dwSize,
DWORD flAllocationType,
DWORD flProtect
);
向某个进程的某个地址写入内容
BOOL WriteProcessMemory(
HANDLE hProcess,
LPVOID lpBaseAddress,
LPCVOID lpBuffer,
SIZE_T nSize,
SIZE_T *lpNumberOfBytesWritten
);
在另一个进程启动一个线程
HANDLE CreateRemoteThread(
HANDLE hProcess,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,//线程地址
LPVOID lpParameter,//参数
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
创建一个线程执行虚拟地址的函数
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
__drv_aliasesMem LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
5. 远程线程注入流程
1.EnumProcesses得到所有进程PID。遍历PID,EnumProcessModules和GetModuleBaseName得到进程文件名
2.OpenProcess打开目标进程
3.VirtualAllocEx在目标进程开辟一块空间用于写入hack.dll
4.WriteProcessMemory向目标进程写入hack.dll的绝对路径
5.CreateRemoteThread指定线程地址为LoadLibraryA,参数为前面开辟的地址
三、Lab12-2 - 进程替换、Lab12-3
1.行为分析
整体功能:进程替换svchost,做键盘记录器,替换的shellcode是xor加密的资源文件,因此解密的话需要使用xor。
比较下dll加载:
正常的svchost:
恶意的:
貌似都没有看到本质的差别,都是正常的dll。
没有对注册表进行修改
先关注进程线程操作,发现程序还启动了一个svchost.exe进程
接下来关注一下文件操作,有没有对svchost.exe进行修改或者注入。确实有一些操作但是不能确定
当前目录生成了practicalmalwareanalysis.log,保存了击键信息。猜测是击键记录器。
2.Lab12-02.exe
1.拼接字符串得到svchost.exe的系统目录
2.获取资源并解密
资源类型为UNICODE,名字为LOCALIZATION。大量的0x41,猜测是与0x41异或的。动态调试下断点保存资源。
使用winhex,进行解密:
然后就正常了:
反编译下看看,可以看出是一个键盘记录器:
3.比较加载内存中的文件标志‘MZ’和‘PE’是否正确
4.以挂起的方式(CREATE_SUSPENDED)创建c:\WINDOWS\system32\svchost.exe。接下来应该要进程替换了。
5.新创建被挂起的进程EBX寄存器总是包含一个指向进程环境块(PEB)的数据结构,+8表示StackLimit
6.NtUnmapViewOfSection卸载原本进程的stack
7.循环将所有的节拷贝到目标进程中
8.设置CONTEXT->eax=addressOfEntryPoint
9.ResumeThread恢复进程运行,此时运行的svchost.exe实际为资源文件的PE
3.资源文件分析
字符串有一个文件名,还有一些键盘操作
设置挂钩0x0d为WH_KEYBOARD_LL
fn函数为保存击键信息并将消息传递
4.用到的一些函数和结构体
返回指向资源信息的块
HRSRC FindResourceA(
HMODULE hModule,
LPCSTR lpName,//资源名字
LPCSTR lpType//资源类型
);
得到和资源联系的句柄
HGLOBAL LoadResource(
HMODULE hModule,
HRSRC hResInfo
);
返回资源的第一个字节地址
LPVOID LockResource(
HGLOBAL hResData
);
创建进程
BOOL CreateProcessA(
LPCSTR lpApplicationName,
LPSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCSTR lpCurrentDirectory,
LPSTARTUPINFOA lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
);
创建进程的信息结构体
typedef struct _PROCESS_INFORMATION {
HANDLE hProcess;//进程句柄
HANDLE hThread;//线程句柄
DWORD dwProcessId;//PID
DWORD dwThreadId;//TID
} PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION;
获得线程信息
BOOL GetThreadContext(
HANDLE hThread,
LPCONTEXT lpContext//比较复杂的结构体包含当前线程的所有寄存器信息
);
读取进程数据
BOOL ReadProcessMemory(
HANDLE hProcess,//进程句柄
LPCVOID lpBaseAddress,//要读的地址
LPVOID lpBuffer,//保存内容地址
SIZE_T nSize,//大小
SIZE_T *lpNumberOfBytesRead
);
写进程数据
BOOL WriteProcessMemory(
HANDLE hProcess,
LPVOID lpBaseAddress,
LPCVOID lpBuffer,
SIZE_T nSize,
SIZE_T *lpNumberOfBytesWritten
);
unmaps进程一块内存
NTSYSAPI NTSTATUS ZwUnmapViewOfSection(
HANDLE ProcessHandle,
PVOID BaseAddress
);
找到ClassName的窗体
HWND FindWindowA(
LPCSTR lpClassName,
LPCSTR lpWindowName//如果为0,表示搜索所有
);
HHOOK SetWindowsHookExA(
int idHook,
HOOKPROC lpfn,
HINSTANCE hmod,
DWORD dwThreadId
);
5.进程替换流程
1.用挂起的方式执行进程
2.ZwUnmapViewOfSection释放指向的内存,解除内存映射
3.VirtualAlloc为恶意代码分配新的内存
4.循环将恶意代码的每个段写入受害者进程的内存空间
5.恢复受害者进程的环境,SetThreadContext函数
6.ResumeThread函数恢复执行。
lab12-3:
就是利用setwindowhook进行键盘记录!比12-2还简单,就是12-2解密出来的exe。
Lab12-4
1.行为分析
整体功能:winlogon里去createremotethread,进行注入,注入代码主要是从url去下载更新恶意文件。
开启了新进程
2.Lab12-04.exe
1.找到winlogon.exe的PID
2.提升进程权限
这个提权比较有意思,反汇编看下:
3.创建远程线程执行,sfc_os.dll的2号导出函数(负责Windows文件保护机制,2号为SfcTerminateWatcherThread函数禁用文件保护机制)
4.将wupdmgr.exe移动到%Temp%目录
注入后效果:
我们导出该dll看下2号函数是什么鬼?
我++,啥也没有!
看来是msdn的内部函数,而不开放。不行,必须IDA搞下:
不太容易看懂!我们看下原版:
The fourth argument is the address for the remote thread to begin execution. In this case, it points to the undocumented function sfc_os.SfcTerminateWatcherThread, which will disable Windows File Protection, allowing system files to be modified.
The remote thread was set to execute beginning at a function in sfc_os.dll
, referenced by the ordinal "2" during the call to GetProcAddress.
Viewing sfc_os.dll
through Dependency Walker doesn't give a name for the ordinal, only an offset.
However, viewing sfc_os.dll
through IDA shows that the ordinal references the function SfcTerminateWatcherThread
, which disables Windows File Protection.
==》GG,我的IDA没有!
5.释放资源到wupdmgr.exe
6.最后运行wupdmgr.exe
3.BIN101.bin
1.运行原版wupdmgrd.exe
2.下载http://www.practicalmalwareanalysis.com/updater.exe
3.运行updater.exe
总结
最近也分析了一个实际的病毒样本imnet蠕虫病毒。虽然是8年前的病毒了,但是也用到了很多病毒技术,而且加壳之后分析起来也挺麻烦的。