本文为看雪论坛优秀文章
看雪论坛作者ID:coneco
1
进程注入简介
2
Module Stomping
HANDLE hTargetHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_ALL_ACCESS | PROCESS_SUSPEND_RESUME, FALSE, targetPid);
//...
// Use OpenProcess + VirtualAllocEx + CreateRemoteThread(the traditional dll injection method)
injectLoadLibrary(hTargetHandle, legitimateDll);
//...
// Copy every malware dll's section into legitimate dll's corresponding sections within the target process address space.
for(section : malwareDll){
WriteProcessMemory(hTargetHandle, legitimateDllSection, section, section_size...);
if (has executable section)
BypassCFG();
}
RebuildImportTable();
RebuildRelocationTable();
callTLSCallback();
CreateRemoteThread(malwareDllEntryPoint);
先在目标进程加载一个合法DLL,以此隐藏恶意代码。
它用了SetProcessValidCallTargets,该方法可以bypass开启CFG的程序。
3
Process Hollowing
CreateProcess(“svchost.exe” , …, CREATE_SUSPENDED, …);
NtUnmapViewOfSection(…) and VirtualAllocEx(…);
For each section:
WriteProcessMemory(..., EVIL_EXE, …);
Relocate Image*;
Set base address in PEB*;
SetThreadContext(…);
ResumeThread(…);
Process Hollowing替换的模块是目标EXE程序
该方法使用NtUnmapViewOfSection将EXE程序解除映射
用ResumeThread来启动恶意程序的入口点
4
Process Doppelganging
Unmap目标进程的EXE模块(非常可疑),现代的安全检查一般都有Unmap检查。
如果不Unmap,而是直接覆写程序,那么覆写地址的页属性就不是共享的,也很可疑。
如果remap时的类型不是IMAGE,通过检查节的类型可判定是否可疑
如果remap时的类型是IMAGE,这时可疑的点就不多了。不过因为Process Hollowing用SetThreadContext修改了初始线程的执行入口点(ETHREAD.Win32StartAddress),那么我们可以检测其执行入口点是否是ETHREAD.Win32StartAddress。如果不是,那值得怀疑,并且我们可以检测其执行入口点对应的文件名,这样可进一步判定这段内存是否是可疑payload。
创建一个transaction(事务)
打开原程序句柄(通过CreateFileTransacted)
向原程序句柄写入恶意代码,根据此时的文件内容,创建一个section
rollback(回滚)之前的写操作
虽然回滚了文件的内容,但已生成的section映射的内容是修改后的,即内容是payload,解释可参考Process Herpaderping小节。
通过刚刚创建的section,创建进程(通过NtCreateProcessEx)
准备参数到目标进程(跨进程)
创建初始线程(NtCreateThreadEx),之后唤醒线程(NtResumeThread)
transact -> write -> map -> rollback -> execute
如果覆盖用的是非PE文件,NtCreateSection返回错误,提示无效的PE。
如果覆盖用的是PE文件,创建进程成功,不过我们在procExp中看到的是名叫System Idle Process,观察该进程信息,其提示“请求的操作是在不再活动的事务的上下文中进行的”。
5
Transacted Hollowing
采用Process Doppelganging的前半段,transact -> write -> map -> rollback
Remap恶意代码的section到目标进程
采用process hollowing的技巧,通过SetThreadContext和ResumeThread的执行恶意代码
关于该方法的描述细节,可参考:Process Doppelgänging meets Process Hollowing in Osiris dropper | Malwarebytes Labs
6
Process Ghosting
Process Doppelganging:通过事务API打开文件,修改文件(写入payload),创建section,再回滚修改的内容。
Process Ghosting:打开文件,设置删除标志,修改文件(写入payload),创建section,删除文件。这样进程运行时,反病毒软件打不开文件,因此无法做检测。
7
Ghostly Hollowing
8
Process Herpaderping
打开一个可读可写的文件
向文件写入payload(calc.exe),创建section
创建进程A(和Doppelganging一样,使用NtCreateProcessEx)
向同一个文件写入伪装的程序,比如lsass.exe
关闭并保存文件为output.exe(文件保存至磁盘,磁盘的内容是lsass.exe)
准备进程参数,创建线程(这时payload开始执行)
"C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\windbg.exe" ProcessHerpaderping.exe "E:\my_knowledge\Reverse\Tools\CFF_Explorer\CFF Explorer.exe" E:\tmp\cpp_test_ano.exe
wil::unique_handle sectionHandle;
auto status = NtCreateSection(§ionHandle,
SECTION_ALL_ACCESS,
nullptr,
nullptr,
PAGE_READONLY,
SEC_IMAGE,
targetHandle.get());
//windbg命令如下:
bp `ProcessHerpaderping!herpaderp.cpp:142`
lkd> !process 0 1 ProcessHerpaderping.exe
PROCESS ffffac0f0ede7080
...
lkd> .process /p ffffac0f0ede7080
Implicit process is now ffffac0f`0ede7080
lkd> !handle ac
...
00ac: Object: ffffac0f2281a300 GrantedAccess: 0012019f (Protected) (Audit) Entry: ffff818476fff2b0
Object: ffffac0f2281a300 Type: (ffffac0efc2d4d20) File
ObjectHeader: ffffac0f2281a2d0 (new version)
HandleCount: 1 PointerCount: 32655
Directory Object: 00000000 Name: \tmp\cpp_test_ano.exe {HarddiskVolume2}
lkd> dt nt!_FILE_OBJECT ffffac0f2281a300
...
+0x028 SectionObjectPointer : 0xffffac0f`066a6358 _SECTION_OBJECT_POINTERS
...
lkd> dx -id 0,0,ffffac0f0ede7080 -r1 ((ntkrnlmp!_SECTION_OBJECT_POINTERS *)0xffffac0f066a6358)
((ntkrnlmp!_SECTION_OBJECT_POINTERS *)0xffffac0f066a6358) : 0xffffac0f066a6358 [Type: _SECTION_OBJECT_POINTERS *]
[+0x000] DataSectionObject : 0xffffac0f0727b1d0 [Type: void *]
[+0x008] SharedCacheMap : 0xffffac0f07911dc0 [Type: void *]
[+0x010] ImageSectionObject : 0x0 [Type: void *]
lkd> dx -id 0,0,ffffac0f0ede7080 -r1 ((ntkrnlmp!_SECTION_OBJECT_POINTERS *)0xffffac0f066a6358)
((ntkrnlmp!_SECTION_OBJECT_POINTERS *)0xffffac0f066a6358) : 0xffffac0f066a6358 [Type: _SECTION_OBJECT_POINTERS *]
[+0x000] DataSectionObject : 0xffffac0f0727b1d0 [Type: void *]
[+0x008] SharedCacheMap : 0xffffac0f07911dc0 [Type: void *]
[+0x010] ImageSectionObject : 0xffffac0f0ebd3720 [Type: void *]
lkd> !process 0 1 cpp_test_ano.exe
PROCESS ffffac0f2b92f080
...
PROCESS ffffac0f1ccb6080(第二个是刚刚创建的进程)
...
lkd> dt nt!_EPROCESS sectionobject imagefilepointer ffffac0f1ccb6080
+0x3c0 SectionObject : 0xffff8184`7b06ecf0 Void
+0x448 ImageFilePointer : 0xffffac0f`159a2180 _FILE_OBJECT
lkd> dx -id 0,0,ffffac0f0ede7080 -r1 ((ntkrnlmp!_FILE_OBJECT *)0xffffac0f159a2180)
((ntkrnlmp!_FILE_OBJECT *)0xffffac0f159a2180) : 0xffffac0f159a2180 [Type: _FILE_OBJECT *]
[+0x028] SectionObjectPointer : 0xffffac0f066a6358 [Type: _SECTION_OBJECT_POINTERS *]
lkd> dx -r1 ((ntkrnlmp!_SECTION_OBJECT_POINTERS *)0xffffac0f066a6358)
((ntkrnlmp!_SECTION_OBJECT_POINTERS *)0xffffac0f066a6358) : 0xffffac0f066a6358 [Type: _SECTION_OBJECT_POINTERS *]
[+0x000] DataSectionObject : 0xffffac0f0727b1d0 [Type: void *]
[+0x008] SharedCacheMap : 0x0 [Type: void *]
[+0x010] ImageSectionObject : 0xffffac0f0ebd3720 [Type: void *]
9
Conclusion