Dll注入技术之APC注入
APC注入的原理是利用当线程被唤醒时APC中的注册函数会被执行的机制,并以此去执行我们的DLL加载代码,进而完成DLL注入的目的,其具体流程如下:
1)当EXE里某个线程执行到SleepEx()或者WaitForSingleObjectEx()时,系统就会产生一个软中断。
2)当线程再次被唤醒时,此线程会首先执行APC队列中的被注册的函数。
3)利用QueueUserAPC()这个API可以在软中断时向线程的APC队列插入一个函数指针,如果我们插入的是Loadlibrary()执行函数的话,就能达到注入DLL的目的。
1.编写测试文件
新建MFC工程,添加按钮控件,双击写代码如下所示:
- void CMfcTextApcInjectDlg::OnBnClickedSleepex()
- {
- // TODO: 在此添加控件通知处理程序代码
- SleepEx(5000,TRUE);
- }
这里我们需要注意一下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的路径)。关键代码如下所示:
- //打开远程进程
- 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);
3.MFC工程设置和提升权限
经过以上两步的操作,我们已经准备好APC注入的关键代码,现在我们需要将自己的程序提升权限以方便注入操作(另,动态MFC库编译有可能造成注入失败)。主要代码如下:
- int CApcInjectDll::EnablePrivilege(bool isStart)
- {
- //1. 得到令牌句柄
- HANDLE hToken = NULL; //令牌句柄
- if (!::OpenProcessToken( GetCurrentProcess(),
- TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_READ,
- &hToken))
- {
- return FALSE;
- }
- //2. 得到特权值
- LUID luid = {0}; //特权值
- if (!::LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
- {
- return FALSE;
- }
- //3. 提升令牌句柄权限
- TOKEN_PRIVILEGES tp = {0}; //令牌新权限
- tp.PrivilegeCount = 1;
- tp.Privileges[0].Luid = luid;
- tp.Privileges[0].Attributes = isStart ? SE_PRIVILEGE_ENABLED : 0;
- if (!::AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL))
- {
- return FALSE;
- }
- //4. 关闭令牌句柄
- ::CloseHandle(hToken);
- return 0;
- }
4.测试注入效果
点击待注入的EXE进行SleepEx,这时EXE的窗口是不可以移动的,因为只有一个线程,处于SleepEx的挂起状态,然后进行注入,我们此时会发现处于挂起状态的进程窗口突然可以移动了,这是因为进程在挂起状态等待时,如果有APC队列就会退出等待并执行APC队列中的函数,然后程序继续运行。
APC注入因为受目标进程使用API的条件而受限,并且处于等待的线程被注入后会立即返回,也有可能造成线程的运行错误,所以应用起来不是很通用
Dll注入技术之APC注入的更多相关文章
- Dll注入技术之ComRes注入
DLL注入技术之ComRes注入 ComRes注入的原理是利用Windows 系统中C:\WINDOWS\system32目录下的ComRes.dll这个文件,当待注入EXE如果使用CoCreateI ...
- Dll注入技术之输入法注入
DLL注入技术之输入法注入 输入法注入原理是利用Windows系统中在切换输入法需要输入字符时,系统就会把这个输入法需要的ime文件装载到当前进程中,而由于这个Ime文件本质上只是个存放在C:\WIN ...
- 注入理解之APC注入
近期学习做了一个各种注入的MFC程序,把一些心得和体会每天分享一些 APC(Asynchronous procedure call)异步程序调用,在NT中,有两种类型的APCs:用户模式和内核模式.用 ...
- DLL注入技术(输入法注入)
输入法注入原理 IME输入法实际就是一个dll文件(后缀为ime),此dll文件需要导出必要的接口供系统加载输入法时调用.我们可以在此ime文件的DllMain函数的入口通过调用LoadLibrary ...
- 注入技术--LSP劫持注入
1.原理 简单来说,LSP就是一个dll程序. 应用程序通过winsock2进行网络通信时,会调用ws2_32.dll的导出函数,如connect,accept等. 而后端通过LSP实现这些函数的底层 ...
- Dll注入技术之注册表注入
DLL注入技术之REG注入 DLL注入技术指的是将一个DLL文件强行加载到EXE文件中,并成为EXE文件中的一部分,这样做的目的在于方便我们通过这个DLL读写EXE文件内存数据,(例如 HOOK EX ...
- 分析恶意驱动(进程启动apc注入dll)
一.前言 用IDA也有好些时间了,以前就只会用F5功能玩无壳无保护的裸驱动,感觉太坑了,这两天就开始看网上大牛的逆向. 今天记录一下sudami曾经逆向过的fuck.sys.第一遍自己走的时候漏掉了 ...
- HOOK -- DLL的远程注入技术详解(1)
DLL的远程注入技术是目前Win32病毒广泛使用的一种技术.使用这种技术的病毒体通常位于一个DLL中,在系统启动的时候,一个EXE程序会将这个DLL加载至某些系统进程(如Explorer.exe)中运 ...
- Dll注入:Ring3 层 APC注入
APC,即Asynchronous procedure call,异步程序调用APC注入的原理是:在一个进程中,当一个执行到SleepEx()或者WaitForSingleObjectEx()时,系统 ...
随机推荐
- Shiro学习(8)拦截器机制
8.1 拦截器介绍 Shiro使用了与Servlet一样的Filter接口进行扩展:所以如果对Filter不熟悉可以参考<Servlet3.1规范>http://www.iteye.com ...
- WdatePicker.js的使用方法 帮助文档 (日历控件)
WdatePicker配置和功能 一.配置 日期范围限制 静态限制 注意:日期格式必须与 realDateFmt 和 realTimeFmt 一致 你可以给通过配置minDate(最小日期),maxD ...
- (转)openfire插件开发(一)
转:http://blog.csdn.net/lovexieyuan520/article/details/37774909 1. 在上一篇博文中,我介绍了Openfire3.9.3源代码导入ecli ...
- linux python3 venv 虚拟环境报错 [-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 2.
解决办法: 先创建没有pip的虚拟环境,然后启动虚拟环境后,再安装pip 办法一: 亲测失败了... python3 -m venv --without-pip py36env 办法二 sudo ap ...
- Sql生成 Insert 语句
declare @TableName sysname select @TableName = 'T_OOSOrder' declare @result varchar(max) = 'INSERT I ...
- PHP面试 PHP基础知识 六(正则表达式)
正则表达式 正则表达式的作用 分割.查找.匹配.替换字符串 分隔符:正斜线(/).hash符号(#).以及取反符号(~) 通用原子:\d(代表十进制的0-9).\D (取反除了0-9).\w(数字 ...
- 戏说 .NET GDI+系列学习教程(三、Graphics类的应用_打印收银小票)
#region 打印 /// <summary> /// 打印字符串内容 /// </summary> /// <returns></returns> ...
- 【Stanford Machine Learning Open Course】学习笔记目录
这里是斯坦福大学机器学习网络课程的学习笔记. 课程地址是:https://class.coursera.org/ml-2012-002/lecture/index 课程资料百度网盘分享链接:https ...
- Apache Solr远程命令执行复现
环境 /vulhub/solr/CVE-2019-0193/ 创建一个集合 docker-compose exec solr bash bin/solr create_core -c test -d ...
- CF#538 C - Trailing Loves (or L'oeufs?) /// 分解质因数
题目大意: 求n!在b进制下末尾有多少个0 https://blog.csdn.net/qq_40679299/article/details/81167283 一个数在十进制下末尾0的个数取决于10 ...