您的位置:首页 > 其它

APC注入

2017-03-09 21:01 155 查看
Windows中的2种类型的APC:
用户模式  APC执行在用户模式下的线程的上下文中,必须得到线程的允许才能得到执行
同时用户APC还需要目标进程处在Alertable等待状态才能被成功的调度执行 在内核模式中
可以执行KeWaitForSingleObject.....,在用户模式下可以调用SleepEx..... 当用户APC
投递到线程中 调用上面函数 执行条件满足时去执行APC历程 执行完APC历程 继续执行线程
内核模式  分为普通内核APC和特殊内核APC 当APC投递到线程上 特殊的内核APC不需要
得到现车允许即可得到执行 普通内核APC需要特定环境才能得到执行 特殊内核APC甚至可以唤醒
阻塞的线程

APC执行优先级  特殊内核APC > 普通内核APC > 用户APC

每个线程都含有2个APC队列  用户模式APC队列 和 内核模式APC队列

APC注入的原理是利用当线程被唤醒时APC中的注册函数会被执行的机制,并以此去执行我们的DLL加载代码,进而完成DLL注入的目的,其具体流程如下:
1)当EXE里某个线程执行到SleepEx()或者WaitForSingleObjectEx()时,系统就会产生一个软中断。
2)当线程再次被唤醒时,此线程会首先执行APC队列中的被注册的函数。
3)利用QueueUserAPC()这个API可以在软中断时向线程的APC队列插入一个函数指针,如果我们插入的是Loadlibrary()执行函数的话,就能达到注入DLL的目的。

//打开远程进程
handle = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwProcessId);
if (handle)
{
//在远程进程申请空间
lpData = VirtualAllocEx(handle,
NULL,
1024,
MEM_COMMIT,
PAGE_EXECUTE_READWRITE);

if (lpData)
{
//在远程进程申请空间中写入待注入DLL的路径
bRet = WriteProcessMemory(handle,
lpData,
(LPVOID)sDllName,
1024,&dwRet);
}
//关闭句柄
CloseHandle(handle);
}

当我们准备好 用于注入DLL的LoadLibrary()函数后,接下来需要使用QueueUserAPC()函数将此函数插入到软中断线程的APC队列中。但是由于 QueueUserAPC()函数的第三个参数是线程ID,因此我们需要根据现有进程ID,并通过遍历对比得到线程ID,具体API如下表所示:
CreateToolhelp32Snapshot
创建线程快照
Thread32First
得到第一个线程快照
Thread32Next
循环下一个线程快照

THREADENTRY32 te = {0};
te.dwSize = sizeof(THREADENTRY32);
//得到线程快照
HANDLE handleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0);
if (INVALID_HANDLE_VALUE == handleSnap)
{
return FALSE;
}

BOOL bStat = FALSE;
//得到第一个线程
if (Thread32First(handleSnap,&te))
{
do
{
//进行进程ID对比
if (te.th32OwnerProcessID == dwProcessId)
{
//得到线程句柄
HANDLE handleThread = OpenThread(
THREAD_ALL_ACCESS,
FALSE,
te.th32ThreadID);

if (handleThread)
{
//向线程插入APC
dwRet = QueueUserAPC(
(PAPCFUNC)LoadLibrary,
handleThread,
(ULONG_PTR)lpData);
if (dwRet > 0)
{
bStat = TRUE;
}
//关闭句柄
CloseHandle(handleThread);
}
}
//循环下一个线程
} while (Thread32Next(handleSnap,&te));
}
CloseHandle(handleSnap);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: