Ring3 APC注入

系统产生一个软中断,当线程再次被唤醒时,此线程会首先执行APC队列中的被注册的函数,利用QueueUserAPC()这个API,并以此去执行我们的DLL加载代码,进而完成DLL注入的目的,

1.根据进程名称得进程ID
2.枚举该进程中的线程
3.将自己的函数插入到每个线程的APC队列中


1 // APCInject(Ring3).cpp : 定义控制台应用程序的入口点。
  2 //
  3
  4 #include "stdafx.h"
  5 #include <windows.h>
  6 #include <TlHelp32.h>
  7 #include <ntstatus.h>
  8 #include <vector>
  9 #include <iostream>
 10
 11 using namespace std;
 12 /*
 13 Win7下成功 Win10不一定成功(编译对应的位数,管理员身份运行)
 14 Win7要将倒着插入!!
 15 要将DLL拷到.cpp的文件夹中
 16 尽量选择线程多的exe
 17
 18 另外没有提供删除APC队列中函数的方法,所以不能反复注入。
 19 */
 20
 21
 22 WCHAR    __DllFullPath[MAX_PATH] = { 0 };
 23 PVOID    __DllFullPathBufferData = NULL;
 24 UINT_PTR __LoadLibraryWAddress = 0;
 25
 26
 27 //typedef void(*pfnSub_110)();
 28
 29
 30 BOOL GetProcessIDByProcessImageName(IN PWCHAR ProcessImageName, OUT PUINT32 ProcessID);
 31 BOOL GetThreadIDByProcessID(IN UINT32 ProcessID, OUT vector<UINT32>& ThreadIDVector);
 32 BOOL InjectDllByApc(IN UINT32 ProcessID, OUT UINT32 ThreadID);
 33 BOOL DebugPrivilege(WCHAR * DebugName, BOOL bEnable);
 34
 35 int main()
 36 {
 37     if (DebugPrivilege(SE_DEBUG_NAME, TRUE)==FALSE)
 38     {
 39         printf("DebugPrivilege Error\r\n");
 40     }
 41
 42     GetCurrentDirectory(MAX_PATH, __DllFullPath);
 43
 44     wcscat(__DllFullPath, L"\\Dll.dll");
 45
 46
 47     UINT ProcessID = 0;
 48
 49     if (GetProcessIDByProcessImageName(
 50         L"taskmgr.exe", &ProcessID) == FALSE)
 51     {
 52
 53
 54         return 0;
 55     }
 56
 57     vector<UINT32> ThreadIDVector;
 58
 59     if (GetThreadIDByProcessID(ProcessID, ThreadIDVector) == FALSE)
 60     {
 61         return 0;
 62     }
 63
 64     size_t ThreadCount = ThreadIDVector.size();
 65     //每一个线程
 66     /*
 67     win7下得倒着注入
 68     */
 69     for (INT_PTR i = ThreadCount - 1; i >= 0; i--)
 70     {
 71         UINT32 ThreadID = ThreadIDVector[i];
 72         InjectDllByApc(ProcessID, ThreadID);
 73     }
 74
 75
 76     printf("Input Any Key to Exit\r\n");
 77     getchar();
 78     getchar();
 79
 80     return 0;
 81 }
 82
 83
 84 BOOL InjectDllByApc(IN UINT32 ProcessID, OUT UINT32 ThreadID)
 85 {
 86     HANDLE  ThreadHandle = NULL;
 87     HANDLE    ProcessHandle = OpenProcess(
 88         PROCESS_ALL_ACCESS, FALSE, ProcessID);
 89
 90     SIZE_T  DllFullPathLength = ((wcslen(__DllFullPath) + 1));
 91
 92     SIZE_T        ReturnLength = 0;
 93     BOOL        IsOk = FALSE;
 94
 95     // 申请一次内存
 96     if (__DllFullPathBufferData == NULL)
 97     {
 98         __DllFullPathBufferData =
 99             VirtualAllocEx(
100                 ProcessHandle,
101                 NULL,
102                 DllFullPathLength * 2,
103                 MEM_COMMIT | MEM_RESERVE,
104                 PAGE_EXECUTE_READWRITE
105             );
106
107         if (__DllFullPathBufferData == NULL)
108         {
109             CloseHandle(ProcessHandle);
110             ProcessHandle = NULL;
111             return FALSE;
112         }
113
114         IsOk = WriteProcessMemory(
115             ProcessHandle,
116             __DllFullPathBufferData,
117             __DllFullPath,
118             DllFullPathLength * 2,
119             &ReturnLength
120         );
121
122         if (IsOk == FALSE)
123         {
124
125             VirtualFree(__DllFullPathBufferData,
126                 DllFullPathLength * 2, MEM_RELEASE);
127
128             CloseHandle(ProcessHandle);
129             ProcessHandle = NULL;
130             return FALSE;
131         }
132     }
133
134     __LoadLibraryWAddress =
135         (UINT_PTR)GetProcAddress(
136             GetModuleHandle(L"Kernel32.dll"),
137             "LoadLibraryW"
138         );
139
140     if (__LoadLibraryWAddress == NULL)
141     {
142         VirtualFree(
143             __DllFullPathBufferData,
144             DllFullPathLength * 2, MEM_RELEASE);
145         CloseHandle(ProcessHandle);
146         ProcessHandle = NULL;
147         return FALSE;
148     }
149
150     __try
151     {
152         ThreadHandle = OpenThread(THREAD_ALL_ACCESS, FALSE, ThreadID);
153         DWORD v1 = QueueUserAPC(
154             (PAPCFUNC)__LoadLibraryWAddress,
155             ThreadHandle,
156             (UINT_PTR)__DllFullPathBufferData
157         );   //LoadLibraryWAddress("DllFullPathBufferData")
158         if (v1 == 0)
159         {
160             printf("FAIL %d\r\n", GetLastError());
161         }
162         else if (v1 != 0)
163         {
164             printf("Success\r\n");
165         }
166     }
167
168     __except (EXCEPTION_CONTINUE_EXECUTION)
169     {
170
171     }
172
173     CloseHandle(ProcessHandle);
174     CloseHandle(ThreadHandle);
175
176
177
178
179     return TRUE;
180 }
181
182
183 BOOL GetThreadIDByProcessID(IN UINT32 ProcessID, OUT vector<UINT32>& ThreadIDVector)
184 {
185     HANDLE            ThreadSnapshotHandle = NULL;
186     THREADENTRY32    ThreadEntry32 = { 0 };
187
188     ThreadEntry32.dwSize = sizeof(THREADENTRY32);
189
190     ThreadSnapshotHandle = CreateToolhelp32Snapshot(
191         TH32CS_SNAPTHREAD, 0);
192     if (ThreadSnapshotHandle == INVALID_HANDLE_VALUE)
193     {
194         return FALSE;
195     }
196
197     BOOL IsOk = Thread32First(
198         ThreadSnapshotHandle, &ThreadEntry32);
199
200     if (IsOk)
201     {
202         do
203         {
204             if (
205                 ThreadEntry32.th32OwnerProcessID
206                 == ProcessID)
207             {
208                 ThreadIDVector.emplace_back(
209                     ThreadEntry32.th32ThreadID);        // 把该进程的所有线程id压入模板
210             }
211         } while (Thread32Next(
212             ThreadSnapshotHandle, &ThreadEntry32)
213             );
214
215     }
216
217
218
219
220
221     CloseHandle(ThreadSnapshotHandle);
222     ThreadSnapshotHandle = NULL;
223
224
225     return TRUE;
226 }
227
228 BOOL GetProcessIDByProcessImageName(IN PWCHAR ProcessImageName, OUT PUINT32 ProcessID)
229 {
230     HANDLE ProcessSnapshotHandle = NULL;
231     ProcessSnapshotHandle =
232         CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
233
234     if (ProcessSnapshotHandle == INVALID_HANDLE_VALUE)
235     {
236         return FALSE;
237     }
238
239     PROCESSENTRY32 ProcessEntry32 = { 0 };
240     ProcessEntry32.dwSize = sizeof(PROCESSENTRY32);
241
242     BOOL IsOk = Process32First(
243         ProcessSnapshotHandle,
244         &ProcessEntry32
245     );
246
247     if (IsOk)
248     {
249         do
250         {
251             if (
252                 lstrcmpi(ProcessEntry32.szExeFile,
253                     ProcessImageName)==0
254                 )
255             {
256                 *ProcessID = ProcessEntry32.th32ProcessID;
257                 break;
258             }
259         } while (Process32Next(
260             ProcessSnapshotHandle,
261             &ProcessEntry32
262         )
263             );
264     }
265
266     if (*ProcessID==0)
267     {
268         printf("Get ProcessID FAIL! 请打开任务管理器.\r\n");
269         return FALSE;
270     }
271
272     CloseHandle(ProcessSnapshotHandle);
273     ProcessSnapshotHandle = NULL;
274
275
276
277     return TRUE;
278 }
279
280
281
282
283
284
285
286
287 BOOL DebugPrivilege(WCHAR * DebugName, BOOL bEnable)
288 {
289     BOOL              bRet = TRUE;
290     HANDLE            TokenHandle;
291     TOKEN_PRIVILEGES  TokenPrivileges;
292
293     //进程 Token 令牌
294     if (!OpenProcessToken(GetCurrentProcess(),
295         TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &TokenHandle))
296     {
297         bRet = FALSE;
298         return bRet;
299     }
300     TokenPrivileges.PrivilegeCount = 1;
301     TokenPrivileges.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0;
302
303     LookupPrivilegeValue(NULL, DebugName, &TokenPrivileges.Privileges[0].Luid);
304     AdjustTokenPrivileges(TokenHandle, FALSE, &TokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
305     if (GetLastError() != ERROR_SUCCESS)
306     {
307         bRet = FALSE;
308     }
309
310     CloseHandle(TokenHandle);
311     return bRet;
312
313 }
时间: 2024-08-11 09:55:30

Ring3 APC注入的相关文章

QueryUserAPC Ring3下 APC注入

DLL.dll可以自己建,实测在win7 X86 X64, win10 X64下可用 #pragma once /****************************************************************************************************/ /*Ring3下 APC注入提权 TLHelp32枚举线程 vector*/ /***************************************************

Windows x86/ x64 Ring3层注入Dll总结

0x01.前言 提到Dll的注入,立马能够想到的方法就有很多,比如利用远程线程.Apc等等,这里我对Ring3层的Dll注入学习做一个总结吧. 我把注入的方法分成六类,分别是:1.创建新线程.2.设置线程上下背景文,修改寄存器.3.插入Apc队列.4.修改注册表.5.挂钩窗口消息.6.远程手动实现LoadLibrary. 那么下面就开始学习之旅吧! 0x02.预备工作 在涉及到注入的程序中,提升程序的权限自然是必不可少的,这里我提供了两个封装的函数,都可以用于提权.第一个是通过权限令牌来调整权限

[转载]Dll注入技术之APC注入

转自:黑客反病毒 APC注入的原理是利用当线程被唤醒时APC中的注册函数会被执行的机制,并以此去执行我们的DLL加载代码,进而完成DLL注入的目的,其具体流程如下:     1)当EXE里某个线程执行到SleepEx()或者WaitForSingleObjectEx()时,系统就会产生一个软中断.     2)当线程再次被唤醒时,此线程会首先执行APC队列中的被注册的函数.     3)利用QueueUserAPC()这个API可以在软中断时向线程的APC队列插入一个函数指针,如果我们插入的是L

注入理解之APC注入

近期学习做了一个各种注入的MFC程序,把一些心得和体会每天分享一些 APC(Asynchronous procedure call)异步程序调用,在NT中,有两种类型的APCs:用户模式和内核模式.用户APCs运行在用户模式下目标线程当前上下文中,并且需要从目标线程得到许可来运行.特别是,用户模式的APCs需要目标线程处在alertable等待状态才能被成功的调度执行.通过调用下面任意一个函数,都可以让线程进入这种状态.这些函数是:KeWaitForSingleObject, KeWaitFor

APC注入APCInject(DLL)

APC注入的原理是利用当线程被唤醒时APC中的注册函数会被执行的机制,并以此去执行我们的DLL加载代码,进而完成DLL注入的目的,其具体流程如下:1)当EXE里某个线程执行到SleepEx()或者WaitForSingleObjectEx()时,系统就会产生一个软中断(或者是Messagebox弹窗的时候不点OK的时候也能注入).2)当线程再次被唤醒时,此线程会首先执行APC队列中的被注册的函数.3)利用QueueUserAPC()这个API可以在软中断时向线程的APC队列插入一个函数指针,如果

APC注入(Ring3)

首先简单介绍一下APC队列和Alertable. 看看MSDN上的一段介绍(https://msdn.microsoft.com/en-us/library/ms810047.aspx): The system delivers most user-mode APCs when a thread unwinds from kernel mode back to user mode after an alertable wait. User-mode APCs do not interrupt u

APC注入(Ring3层)

/* 步骤: 1.提权(GrantDebugPrivileges) (1)获得令牌token,OpenThreadToken(),OpenProcessToken () WINADVAPI BOOL WINAPI OpenThreadToken( _In_ HANDLE ThreadHandle, _In_ DWORD DesiredAccess, _In_ BOOL OpenAsSelf, _Outptr_ PHANDLE TokenHandle ); OpenAsSelf参数 [in]  t

Windows 注入

平常用的最多的dll注入技术就是远程线程,刚刚逛看雪,看到有人写的面试的时候被问到的问题,其中就有dll注入的方法,我突然想到我开始面试的时候也被问了dll注入的方法,当时也是就只知道一个远程线程,答的也不好,然后就想把一些注入技术写个总结.接下来讲的注入技术,有ring3层的lld的远程线程和apc注入,还有ring0的apc注入,此外还有更为隐蔽的代码注入. 先写最广泛的,也是相对简单的注入方式,远程线程. 一 ring3 dll的远程线程 我写的涉及到x86和x64的注入,因为x64的系统

注入DLL之主线程方式

目前对于APC注入方式依然还没有了解内幕, QueueUserAPC((PAPCFUNC)LoadLibraryA, hThread, (ULONG_PTR)param); 但看其调用方式可以猜出一二.,基本也是插入到线程再装载DLL. 以前在黑客防线里看到过主线程注入方式装载DLL,研究了一下,发现很像是手工实现了QueueUserApc的功能...不过这种比直接调用API更自由灵活. 另不知怎么回事,WIN7下与黑客防线所载文章实例中的细节有些出入. 首先黑客防线里的找主线程的方式有些绕,他