APC(Asynchronous Procedure Call,异步过程调用)是在一个特定线程环境下被异步执行的函数,分为用户模式APC和内核模式APC。每个线程都有一个APC队列。在用户模式下,当线程调用SleepEx、WaitForSingleObjectEx等进入"Alterable WaitStatus"状态(可警告的等待状态)的时候,系统会遍历该进程的APC队列,然后按照先进先出的顺序来执行这些APC。
在用户模式下,微软提供了QueueUerAPC这个API来向一个线程插入APC。
声明如下:WINBASEAPIDWORDWINAPIQueueUserAPC( _In_ PAPCFUNC pfnAPC, _In_ HANDLE hThread, _In_ ULONG_PTR dwData );pfnAPC:指向一个APC函数hThread:将要插入APC的线程句柄dwData:APC函数的参数
先右键项目,点击属性->链接器->系统->子系统 选择窗口(/SUBSYSTEM:Windows)
然后将_tmain()函数改为WinMain()函数// LoadExe.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include#include using namespace std;typedef struct _UNICODE_STRING{ USHORT Length; USHORT MaximumLength; PWSTR Buffer;} UNICODE_STRING, *PUNICODE_STRING;typedef struct _INJECT_STRUCT { UINT_PTR LdrLoadDllAddress; //4 UNICODE_STRING DllFullPath; //4,4 HANDLE OutHandle;} INJECT_STRUCT, *PINJECT_STRUCT;int GrantDebugPrivileges();BOOL InjectByAPC(int ProcessID,int ThreadID,const char *szDllFullPath);UINT32 MakeShellCode(UINT8* ShellCodeData, PVOID Address);int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow){ int ProcessID = 0; int ThreadID = 0; if (__argc < 2) { return -1; } if (!strcmp(__argv[1], "Inject")) { GrantDebugPrivileges(); ProcessID = atoi(__argv[2]); ThreadID = atoi(__argv[3]); return InjectByAPC(ProcessID, ThreadID, __argv[4]); } return 0;}int GrantDebugPrivileges(){ HANDLE TokenHandle = NULL; TOKEN_PRIVILEGES PrivilegesToken; LUID v1; int iRet; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &TokenHandle)) { return 0; } if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &v1)) { CloseHandle(TokenHandle); return 0; } PrivilegesToken.PrivilegeCount = 1; PrivilegesToken.Privileges[0].Luid = v1; PrivilegesToken.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; iRet = AdjustTokenPrivileges(TokenHandle, FALSE, &PrivilegesToken, sizeof(PrivilegesToken), NULL, NULL); CloseHandle(TokenHandle); return iRet;}BOOL InjectByAPC(int ProcessID,int ThreadID,const char *szDllFullPath){ HANDLE ProcessHandle = NULL; HANDLE ThreadHandle = NULL; if (ProcessID <= 0 || ThreadID < 0) { return FALSE; } printf("Success\r\n"); ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessID); //打开系统所有进程 if (ProcessHandle == NULL) { return FALSE; } if (ThreadID > 0) { ThreadHandle = OpenThread(THREAD_ALL_ACCESS, FALSE, ThreadID);//打开所有线程 if (ThreadHandle == NULL) { CloseHandle(ProcessHandle); return FALSE; } } //注入都要在目标进程空间中申请内存 写入Dll的绝对路径 UINT32 DllPathLength = 0; DllPathLength = (UINT32)strlen(szDllFullPath); WCHAR* wzDllFullPath = (WCHAR*)calloc(1, (DllPathLength + 1) * sizeof(WCHAR)); //在LoadEx进程空间中 if (wzDllFullPath == NULL) { return FALSE; } for (int i=0;i