通过异步过程调用(APC)注入DLL

转载 2015年11月20日 15:44:00

关于APC的介绍,可以参考MSDN对Asynchronous Procedure Calls的介绍(索引APCs),下面是简单翻译的一段文字。

APC(Asynchronous Procedure Calls,异步过程调用)是指在一个特定的线程环境中异步的执行代码。当一个APC被添加到一个线程的APC队列的时候,系统会产生一个软中断;当线程下一次被调度的时候APC函数将被执行。操作系统产生的APC称为内核模式APC,应用程序产生的APC称为用户模式APC。只有当线程处于可唤醒状态(alertable state),用户模式的APC才会被执行。

每一个线程都有自己的APC队列,应用程序可以通过调用QueueUserAPC来队列中插入APC。当一个用户模式的APC插入APC队列之后,与之关联的线程并不会立即执行APC函数,除非线程进入可唤醒状态。当线程调用SleepEx、SignalObjectAndWait、MsgWaitForMultipleObjectsEx、WaitForMultipleObjectsEx、WaitForSingleObjectEx这些函数的时候会进入可唤醒状态。如果在APC插入队列之前线程已经进入等待状态,那么APC函数将不会被执行,但APC会仍然存在于队列之中,所以APC函数将会在线程下一次进入可唤醒状态的时候被执行。

如果要通过QueueUserAPC来注入DLL模块,可以向指定进程的每一个线程(增加执行机会)都插入一个APC,然后把LoadLibrary作为APC函数的过程函数,把DLL路径字符串作为过程函数的参数。

示例代码:

#include <windows.h>
#include <TlHelp32.h>
#include <stdio.h>
#include <string.h>
 
#define CHECK_NULL_RET(bCondition) if (!bCondition) goto Exit0
 
BOOL EnableDebugPrivilege(void)
{
	HANDLE hToken; 
	TOKEN_PRIVILEGES tkp;
	BOOL bRet = FALSE;
 
	bRet = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
	CHECK_NULL_RET(bRet);
 
	bRet = LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tkp.Privileges[0].Luid);
	CHECK_NULL_RET(bRet);
	tkp.PrivilegeCount = 1;  
	tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 
 
	bRet = AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
	CHECK_NULL_RET(bRet);
	bRet = TRUE;
 
Exit0:
	CloseHandle(hToken);
	return bRet;
}
 
BOOL ApcInject(DWORD dwPid, CHAR *pszDllPath)
{
	HANDLE hProcess = NULL;
	BOOL bRet = FALSE;
	HANDLE hSnapshot = NULL;
	LPVOID lpDllName = NULL;
	DWORD dwResult = 0;
	THREADENTRY32 te32;
 
	bRet = EnableDebugPrivilege();
	CHECK_NULL_RET(bRet);
 
	hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
	CHECK_NULL_RET(bRet);
 
	lpDllName = VirtualAllocEx(hProcess, NULL, strlen(pszDllPath) + 1, 
		MEM_COMMIT, PAGE_READWRITE);
	CHECK_NULL_RET(lpDllName);
 
	bRet = WriteProcessMemory(hProcess, lpDllName, (LPVOID)pszDllPath, 
		strlen(pszDllPath) + 1, &dwResult);
 
	hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, dwPid);
	CHECK_NULL_RET((hSnapshot != INVALID_HANDLE_VALUE));
 
	te32.dwSize = sizeof(THREADENTRY32);
	bRet = Thread32First(hSnapshot, &te32);
	while (bRet)
	{
		if (te32.th32OwnerProcessID == dwPid)
		{
			HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID);
			if (hThread)
			{
				dwResult = QueueUserAPC((PAPCFUNC)LoadLibraryA, hThread, (ULONG_PTR)lpDllName);
				CloseHandle(hThread);
			}
		}
		te32.dwSize = sizeof(THREADENTRY32);
		bRet = Thread32Next(hSnapshot, &te32);
	}
 
Exit0:
	// VirtualFreeEx
	CloseHandle(hSnapshot);
	CloseHandle(hProcess);
 
	// Do NOT check this value
	return bRet;
}
 
int main(int argc, char **argv)
{
	if (argc != 3)
	{
		printf("Usage: %s PID DllPath\n", argv[0]);
		return 1;
	}
 
	ApcInject(atoi(argv[1]), argv[2]);
 
	return 0;
}



通过异步过程调用(APC)注入DLL

关于APC的介绍,可以参考MSDN对Asynchronous Procedure Calls的介绍(索引APCs),下面是简单翻译的一段文字。 APC(Asynchronous Procedur...
  • earbao
  • earbao
  • 2016年09月08日 11:49
  • 291

注入(2)--APC(Asynchronous Procedure Call)注入(异步过程调用)

APC(Asynchronous Procedure Call,异步过程调用)是在一个特定线程环境下被异步执行的函数,分为用户模式APC和内核模式APC。每个线程都有一个APC队列。在用户模式下,当线...

apc 异步过程调用无法抛到主线程的问题跟踪

引发:使用项目的ipc时发现不能向主线程抛apc消息,后编写测试代码经反复测试发现测试代码也无法发送:主线程:子线程:下面的内核调试记录对本次问题查找本无益处,但还是花费了大量时间,需要记录: 因为...
  • zamzll
  • zamzll
  • 2015年06月08日 09:05
  • 851

延迟过程调用/异步过程调用APC

延迟过程调用,即 DPC。 这是一种机制,当上层请求下来,由于过多的操作步骤,为了使系统性能更好,使用一个完成调用例程,告诉上层“我完成了”,这样就可以处理下面的请求了,而系统会把剩下得处理过程加...

异步过程调用(APC)——操作系统实现异步的原理

apc可以看成就是内核里的定时器,为了给自己一个在本函数返回后还能执行的一次机会,有很多操作是需要在函数返回后才能执行. 类似于析构函数但不完全是。 apc的最大特点就是在本函数返回后才执行,而且是在...

内核中通过给线程插apc注入dll

void ApcLoadDll(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2); void ApcLoadDll...

APC注入DLL(win7下有问题)

void APCKernelRoutine(PKAPC pKAPC, PKNORMAL_ROUTINE pUserAPC, PVOID pContext, PVOID p...
  • sgzwiz
  • sgzwiz
  • 2014年03月04日 01:00
  • 1877

DLL注入-APC注入

DLL注入-APC注入

Dll注入技术之APC注入

APC注入的原理是利用当线程被唤醒时APC中的注册函数会被执行的机制,并以此去执行我们的DLL加载代码,进而完成DLL注入的目的,其具体流程如下:    1)当EXE里某个线程执行到SleepEx()...

Dll注入技术之APC注入

APC注入的原理是利用当线程被唤醒时APC中的注册函数会被执行的机制,并以此去执行我们的DLL加载代码,进而完成DLL注入的目的,其具体流程如下:     1)当EXE里某个线程执行到SleepEx...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:通过异步过程调用(APC)注入DLL
举报原因:
原因补充:

(最多只允许输入30个字)