APC是针对具体线程,由具体线程执行的,每个线程都有自己的APC队列。在系统调用、中断、或异常处理之后从内核返回用户空间途中或线程切换时会执行APC
只需要将加载Dll的代码放入线程APC队列中,就可以实现注入Dll
#include <Windows.h>
#include <stdio.h>
int main() {
printf("BeforeSleep\n");
// 第二个参数为True才可以注入
SleepEx(5000, TRUE);
printf("AfterSleep: HelloWorld!\n");
}
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include <Windows.h>
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
MessageBoxA(NULL, "Process Attach", "MsgboxDll", MB_OK);
break;
case DLL_THREAD_ATTACH:
MessageBoxA(NULL, "Thread Attach", "MsgboxDll", MB_OK);
break;
case DLL_THREAD_DETACH:
MessageBoxA(NULL, "Thread Detach", "MsgboxDll", MB_OK);
break;
case DLL_PROCESS_DETACH:
MessageBoxA(NULL, "Process Detach", "MsgboxDll", MB_OK);
break;
}
return TRUE;
}
#include <Windows.h>
#include <stdio.h>
#include <TlHelp32.h>
#include <string.h>
DWORD find_process_id(LPCWSTR ProcessName) {
HANDLE hProcessSnap;
PROCESSENTRY32 pe32;
// Take a snapshot of all processes in the system.
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
printf("Error Create ProcessSnap: %d\n", GetLastError());
exit(0);
}
pe32.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(hProcessSnap, &pe32))
{
CloseHandle(hProcessSnap); // clean the snapshot object
printf("Error Get first process: %d\n", GetLastError());
exit(0);
}
DWORD bRet = -1;
do
{
if (!wcscmp(ProcessName, pe32.szExeFile))
{
bRet = pe32.th32ProcessID;
break;
}
} while (Process32Next(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);
return bRet;
}
void inject_apc(DWORD tid,PVOID lpAddr) {
printf("[Inject] Open Thread %d\n", tid);
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, tid);
if (NULL == hThread) {
printf("Error Open Thread: %d\n", GetLastError());
return;
}
// 给APC队列中插入回调函数
printf("[Inject] Inject Apc %d\n",tid);
QueueUserAPC((PAPCFUNC)LoadLibraryA, hThread, (ULONG_PTR)lpAddr);
printf("[Inject] Inject over %d\n",tid);
}
DWORD get_and_inject(DWORD pid,PVOID lpAddr) {
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, pid);
DWORD tid = -1;
if (h != INVALID_HANDLE_VALUE) {
THREADENTRY32 te;
te.dwSize = sizeof(te);
if (Thread32First(h, &te)) {
do {
if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) +
sizeof(te.th32OwnerProcessID) && te.th32OwnerProcessID==pid) {
printf("Process 0x%04x Thread 0x%04x\n",
te.th32OwnerProcessID, te.th32ThreadID);
tid = te.th32ThreadID;
// 由于不知道哪个进程sleep,所以全部注入
inject_apc(tid, lpAddr);
}
te.dwSize = sizeof(te);
} while (Thread32Next(h, &te));
}
CloseHandle(h);
}
return tid;
}
void apc_inject(LPCWSTR pName, LPCSTR dllName) {
// 1.查找进程PID
DWORD dwPid = find_process_id(pName);
// 2.打开进程
HANDLE hProcess = NULL;
printf("[Inject] Open Process\n");
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
if (NULL == hProcess)
{
return;
}
// 3.成功了,申请远程内存
printf("[Inject] Alloc Memory\n");
void* lpAddr = NULL;
lpAddr = VirtualAllocEx(hProcess, 0, 0x1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (NULL == lpAddr)
{
return;
}
// 4.写入我们的DLL路径,这里我写入当前根目录下的路径
printf("[Inject] Write Process\n");
BOOL bRet = WriteProcessMemory(hProcess, lpAddr, dllName, strlen(dllName) + 1, NULL);
if (!bRet) {
return;
}
get_and_inject(dwPid, lpAddr);
}
int main() {
// 这里直接自动创建进程
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
WCHAR pName[100] = L"HelloSleep.exe";
// Start the child process.
if (!CreateProcess(NULL, // No module name (use command line)
pName, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi) // Pointer to PROCESS_INFORMATION structure
)
{
printf("CreateProcess failed (%d).\n", GetLastError());
return 0;
}
printf("Create Process Over\n");
apc_inject(pName, "MsgboxDll.dll");
return 0;
}
https://zhuanlan.zhihu.com/p/361357179
https://www.cnblogs.com/iBinary/p/7574055.html
https://stackoverflow.com/questions/1206878/enumerating-threads-in-windows