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

    1)当EXE里某个线程执行到SleepEx()或者WaitForSingleObjectEx()时,系统就会产生一个软中断。

    2)当线程再次被唤醒时,此线程会首先执行APC队列中的被注册的函数。

    3)利用QueueUserAPC()这个API可以在软中断时向线程的APC队列插入一个函数指针,如果我们插入的是Loadlibrary()执行函数的话,就能达到注入DLL的目的。



1.编写测试文件

    新建MFC工程,添加按钮控件,双击写代码如下所示:

  1. void CMfcTextApcInjectDlg::OnBnClickedSleepex()
  2. {
  3. // TODO: 在此添加控件通知处理程序代码
  4. SleepEx(5000,TRUE);
  5. }

这里我们需要注意一下SleepEx中第二个参数为TRUE,查下msdn,上面写到:

bAlertable [in] 

If this parameter is FALSE, the function does not return until the time-out period has elapsed. If an I/O completion callback occurs, the function does not return and the I/O completion function
is not executed. If an APC is queued tothe thread, the function does not return and the APC function is not executed.

大概意思是说当第二个参数为FALSE,APC是不被执行的,从此可以认为APC注入的使用条件还是有很大约束的。

.编写APC注入程序

    由于我们需要时使用LoadLibrary()函数完成注入,因此需要为其先准备好必要的参数,需要我们可以通过在远程进程中申请空间的方式写入LoadLibrary()函数所需要的参数(也就是DLL的路径)。关键代码如下所示:

  1. //打开远程进程
  2. handle = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwProcessId);
  3. if (handle)
  4. {
  5. //在远程进程申请空间
  6. lpData = VirtualAllocEx(handle,
  7. NULL,
  8. 1024,
  9. MEM_COMMIT,
  10. PAGE_EXECUTE_READWRITE);
  11. if (lpData)
  12. {
  13. //在远程进程申请空间中写入待注入DLL的路径
  14. bRet = WriteProcessMemory(handle,
  15. lpData,
  16. (LPVOID)sDllName,
  17. 1024,&dwRet);
  18. }
  19. //关闭句柄
  20. CloseHandle(handle);
  21. }

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

CreateToolhelp32Snapshot   创建线程快照  
Thread32First   得到第一个线程快照  
Thread32Next   循环下一个线程快照  

关键代码如下所示:

  1. THREADENTRY32 te = {0};
  2. te.dwSize = sizeof(THREADENTRY32);
  3. //得到线程快照
  4. HANDLE handleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0);
  5. if (INVALID_HANDLE_VALUE == handleSnap)
  6. {
  7. return FALSE;
  8. }
  9. BOOL bStat = FALSE;
  10. //得到第一个线程
  11. if (Thread32First(handleSnap,&te))
  12. {
  13. do
  14. {
  15. //进行进程ID对比
  16. if (te.th32OwnerProcessID == dwProcessId)
  17. {
  18. //得到线程句柄
  19. HANDLE handleThread = OpenThread(
  20. THREAD_ALL_ACCESS,
  21. FALSE,
  22. te.th32ThreadID);
  23. if (handleThread)
  24. {
  25. //向线程插入APC
  26. dwRet = QueueUserAPC(
  27. (PAPCFUNC)LoadLibrary,
  28. handleThread,
  29. (ULONG_PTR)lpData);
  30. if (dwRet > 0)
  31. {
  32. bStat = TRUE;
  33. }
  34. //关闭句柄
  35. CloseHandle(handleThread);
  36. }
  37. }
  38. //循环下一个线程
  39. } while (Thread32Next(handleSnap,&te));
  40. }
  41. CloseHandle(handleSnap);

3.MFC工程设置和提升权限

    经过以上两步的操作,我们已经准备好APC注入的关键代码,现在我们需要将自己的程序提升权限以方便注入操作(另,动态MFC库编译有可能造成注入失败)。主要代码如下:

  1. int CApcInjectDll::EnablePrivilege(bool isStart)
  2. {
  3. //1. 得到令牌句柄
  4. HANDLE  hToken = NULL;      //令牌句柄
  5. if (!::OpenProcessToken( GetCurrentProcess(),
  6. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_READ,
  7. &hToken))
  8. {
  9. return FALSE;
  10. }
  11. //2. 得到特权值
  12. LUID    luid = {0};         //特权值
  13. if (!::LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
  14. {
  15. return FALSE;
  16. }
  17. //3. 提升令牌句柄权限
  18. TOKEN_PRIVILEGES tp = {0};  //令牌新权限
  19. tp.PrivilegeCount = 1;
  20. tp.Privileges[0].Luid = luid;
  21. tp.Privileges[0].Attributes = isStart ? SE_PRIVILEGE_ENABLED : 0;
  22. if (!::AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL))
  23. {
  24. return FALSE;
  25. }
  26. //4. 关闭令牌句柄
  27. ::CloseHandle(hToken);
  28. return 0;
  29. }

4.测试注入效果

    点击待注入的EXE进行SleepEx,这时EXE的窗口是不可以移动的,因为只有一个线程,处于SleepEx的挂起状态,然后进行注入,我们此时会发现处于挂起状态的进程窗口突然可以移动了,这是因为进程在挂起状态等待时,如果有APC队列就会退出等待并执行APC队列中的函数,然后程序继续运行。

APC注入因为受目标进程使用API的条件而受限,并且处于等待的线程被注入后会立即返回,也有可能造成线程的运行错误,所以应用起来不是很通用

Dll注入技术之APC注入的更多相关文章

  1. Dll注入技术之ComRes注入

    DLL注入技术之ComRes注入 ComRes注入的原理是利用Windows 系统中C:\WINDOWS\system32目录下的ComRes.dll这个文件,当待注入EXE如果使用CoCreateI ...

  2. Dll注入技术之输入法注入

    DLL注入技术之输入法注入 输入法注入原理是利用Windows系统中在切换输入法需要输入字符时,系统就会把这个输入法需要的ime文件装载到当前进程中,而由于这个Ime文件本质上只是个存放在C:\WIN ...

  3. 注入理解之APC注入

    近期学习做了一个各种注入的MFC程序,把一些心得和体会每天分享一些 APC(Asynchronous procedure call)异步程序调用,在NT中,有两种类型的APCs:用户模式和内核模式.用 ...

  4. DLL注入技术(输入法注入)

    输入法注入原理 IME输入法实际就是一个dll文件(后缀为ime),此dll文件需要导出必要的接口供系统加载输入法时调用.我们可以在此ime文件的DllMain函数的入口通过调用LoadLibrary ...

  5. 注入技术--LSP劫持注入

    1.原理 简单来说,LSP就是一个dll程序. 应用程序通过winsock2进行网络通信时,会调用ws2_32.dll的导出函数,如connect,accept等. 而后端通过LSP实现这些函数的底层 ...

  6. Dll注入技术之注册表注入

    DLL注入技术之REG注入 DLL注入技术指的是将一个DLL文件强行加载到EXE文件中,并成为EXE文件中的一部分,这样做的目的在于方便我们通过这个DLL读写EXE文件内存数据,(例如 HOOK EX ...

  7. 分析恶意驱动(进程启动apc注入dll)

    一.前言  用IDA也有好些时间了,以前就只会用F5功能玩无壳无保护的裸驱动,感觉太坑了,这两天就开始看网上大牛的逆向. 今天记录一下sudami曾经逆向过的fuck.sys.第一遍自己走的时候漏掉了 ...

  8. HOOK -- DLL的远程注入技术详解(1)

    DLL的远程注入技术是目前Win32病毒广泛使用的一种技术.使用这种技术的病毒体通常位于一个DLL中,在系统启动的时候,一个EXE程序会将这个DLL加载至某些系统进程(如Explorer.exe)中运 ...

  9. Dll注入:Ring3 层 APC注入

    APC,即Asynchronous procedure call,异步程序调用APC注入的原理是:在一个进程中,当一个执行到SleepEx()或者WaitForSingleObjectEx()时,系统 ...

随机推荐

  1. 6374. 【NOIP2019模拟2019.10.04】结界[生与死的境界]

    题目 题目大意 给你一个数列,每次可以选择任意两个相邻的数\(x\)和\(y\),将其删去,并在原来位置插入\(x+2y\). 每次询问一个区间,对这个区间进行上述操作.求最后剩下的数最大是多少. 答 ...

  2. vue 多选框 checkbox 父到子传值

    vue多选功能, 修改时选中的状态不能从当前组件中得到,从父组件中传过来. 这里 新增和修改封装了一个组件,在点击确定按钮后,会发送新增或修改请求,重新渲染页面.但是在点击[新增]/ [修改]按钮时, ...

  3. git——commit成功后,GitHub方格不变绿

    一通百度该设置的都设置了,还是不好使 发现有提示一栏 pull request的东西  在网上查貌似是因为两个分支内容不同 提示是否合并,还查到了不变绿可能的原因. Contributions未被Gi ...

  4. PHP FILTER_SANITIZE_NUMBER_INT 过滤器

    定义和用法 FILTER_SANITIZE_NUMBER_INT 过滤器删除数字中所有非法的字符. 该过滤器允许所有数字以及 . + - Name: "number_int" ID ...

  5. NOIP模拟测试17

    T1:入阵曲 题目大意:给定一个N*M的矩形,问一共有多少个子矩形,使得矩形内所有书的和为k的倍数. 60%:N,M<=80 枚举矩形的左上角和右下角,用二维前缀和求出数字之和. 时间复杂度$O ...

  6. 【mac】配置sublime开发C

    1.sublime text3,Tools/Build System/New Build system创建一个新配置文件. {"cmd": ["gcc", &q ...

  7. Centos7 安装 telnet 服务

    准备写一个 django-webtelnet(运维管理系统集成后管理网络设备),但是手边没有现成的网络设备资源可以测试,那就研究下 Centos7 下安装 telnet-server 吧. 安装 yu ...

  8. jeecg随笔-3.X的生成后配置

    生成后按以上步骤进行配置即可.

  9. 安卓apk反编译、修改、重新打包、签名全过程

    首先明确,反编译别人apk是一件不厚道的事情.代码是程序员辛苦工作的成果,想通过这种手段不劳而获,是不对的.这也说明,代码混淆是非常重要的.本文抱着学习的态度,研究在一些特殊的情况下如果有需要,该怎么 ...

  10. 2019牛客多校第三场F-Planting Trees(单调队列)

    Planting Trees 题目传送门 解题思路 枚举每一个下边界,再枚举其对应的所有上边界,求出其对应区间内的最大最小值,当下边界一样的时候,其最大最小值可以随着上边界减小逐步更新.然后将这些最大 ...