Windows Ring3层注入——“QueueUserAPC” APC注入(四)

APC概念

正常情况下,线程自己不主动调用ExitThread函数,或者一个进程内的其他线程不调用TerminateThread函数来终止线程的话,线程本身的行为是不会改变的。
那如果想改变一个线程的行为可以给他提供一个函数,让它自己去调用,这个函数就是APC(Asyncroneus Procedure Call),即异步过程调用。

APC(Asynchronous Procedure Call 异步过程调用)是一种与常用的和简单的同步对象不同的一种同步机制。它是一种软中断机制。

  • APC有两种形式:
    - 用户模式APC:由应用程序产生,APC函数地址位于用户空间,在用户空间执行。
    - 内核模式APC:由系统产生,APC函数地址位于内核空间,在内核空间执行.

举一个例子理解一下APC的实际作用:假设一个线程在执行过程中,发出一个I/O请求,然后设备驱动执行线程传过来的I/O请求,但发出I/O请求的线程会继续执行下去,但是当线程走不下去的时候(必须得到I/O请求的的返回结果),线程需要获得返回结果才能继续进行,然后设备驱动执行完的I/O请求结果是通过插入APC队列来告诉线程的。但是设备驱动如何知道线程索要的结果怎么返还给他?因为在线程刚开始发送I/O请求时,线程就已经告诉设备驱动执行后的结果放到APC队列中就可以。

更多详细的APC解释可以去:https://blog.csdn.net/youyou519/article/details/82355009

APC重点解释

  • 每个线程都会有一个APC队列
  • 当一个线程从等待状态中苏醒(线程调用SlleepEx、SignalObjectAndWait、MsgWaitForMultiple、ObjectsEx、WaitForMultipleObjectsEx、WaitForSingleObjectEx函数时会进入可唤醒状态),进入"Alterable WaitStatus" 状态的时候,系统遍历该线程的APC队列,然后按照FIFO的顺序来执行APC。
  • 在用户模式下,我们可以像创建远程线程一样,使用QueueUserAPC把APC过程添加到目标线程的APC队列中,等这个线程恢复执行时,就会执行我们插入的APC过程了。

APC调用回调函数的条件

  • 1、首先必须是多线程的条件。
  • 2、多线程的条件下执行了上述的需要调用的函数(SlleepEx、SignalObjectAndWait、MsgWaitForMultiple、ObjectsEx、WaitForMultipleObjectsEx、WaitForSingleObjectEx等)进入**“Alterable Wait Status”**状态。

APC注入函数原型及原理

QueueUserAPC函数原型:

DWORD WINAPI QueueUserAPC(
  PAPCFUNC pfnAPC,     //APC的函数地址
  HANDLE hThread,      //线程的句柄
  ULONG_PTR dwData     //APC函数的参数
);

因为QueueUserAPC是Windows提供的允许我们自己把回调函数插入APC队列,并且函数的hThread参数可以跨进程,也就是说可以是电脑的任何一个线程,所以这样可以使我们轻而易举在其他的进程的线程中插入一段我们的函数。

APC函数原型如下:

VOID CALLBACK APCProc(
  ULONG_PTR dwParam
);//可以对比一下LoadLibrary函数原型

APC注入步骤

  • 1、多线程程序执行上面所提到的等待函数之后,产生一个中断。
  • 2、通过函数QueueUserAPC在队列中加入一个回调函数。
  • 3、插入回调函数时,把回调函数地址改为LoadLibrary,我们使用VirtualAllocEx申请内存插入函数,并且写入内存。
  • 4、当所被中断的程序被唤醒的时候,线程会优先执行APC队列中的回调函数。

注:为了增加调用机会,应向所有线程插入APC

APC注入代码示例

///APCInject.h

//以Suspend打开目标进程 与上一章函数相同
BOOL OpenTargetProcess(LPCWSTR ProcName , STARTUPINFO  &st , PROCESS_INFORMATION &pi );
//在目标进程地址空间中分配待加载的DLL路径空间  与上一章函数相同
BOOL TagetAlloc(HANDLE	 hTargetProcess,	LPVOID &lpAddr);
//把待加载的DLL路径写入目标进程空间  与上一章函数相同
BOOL WriteDLLToTarget(HANDLE hTargetProcess ,	LPVOID lpAddr , LPCWSTR lpBuffer);

///main函数
void main()
{
	PROCESS_INFORMATION stProcessInfo;                   // 存储进程信息的PROCESS_INFORMATION 结构体
	::memset(&stProcessInfo, 0 ,sizeof(stProcessInfo));  //分配结构体内存

	STARTUPINFO stStartUpInfo;                                    //进程的主窗体显示信息的STARTUPINFO结构体 
	::memset(&stStartUpInfo, 0 ,sizeof(stStartUpInfo)); //分配结构体内存
	stStartUpInfo.cb = sizeof(stStartUpInfo);

	LPCWSTR ProcName;                //目标进程地址名
	LPVOID    lpAddr;                     //目标进程申请内存空间的指针
	LPCWSTR lpBuffer;                   //要注入的DLL在磁盘中的地址
	LPVOID    pnfStartAddr ;          //LoadLibrary地址

	ProcName = L"D:\\Program Files (x86)\\Notepad++\\notepad++.exe";
	if(	OpenTargetProcess(ProcName , stStartUpInfo , stProcessInfo ) == FALSE )
	{
		MessageBox(L"注入失败",L"提示",MB_OK);
		return;
	}

	HANDLE hTargetProcess= stProcessInfo.hProcess;	    //目标进程的句柄
	if( TagetAlloc(hTargetProcess , lpAddr) == FALSE )
	{
		MessageBox(L"注入失败",L"提示",MB_OK);
		return;
	}

	lpBuffer= TEXT("C:\\Users\\10178\\Desktop\\InjectDllFile.dll");
	if(WriteDLLToTarget(hTargetProcess, lpAddr , lpBuffer)== FALSE )
	{
		MessageBox(L"注入失败",L"提示",MB_OK);
		return;
	}

	HANDLE	 hTargetThread = stProcessInfo.hThread;       //目标线程的句柄
	//获取LoadLibrary地址
	pnfStartAddr = (LPVOID)GetProcAddress(GetModuleHandle (TEXT ("Kernel32")) , "LoadLibraryW");

	if(!QueueUserAPC((PAPCFUNC)pnfStartAddr , hTargetThread , (ULONG_PTR)lpAddr))
	{
		MessageBox(L"注入失败",L"提示",MB_OK);
		return;
	}

	//恢复注入的目标线程挂起状态
	 ResumeThread(hTargetThread);

}

APC注入优缺点

优点:

比较隐蔽,代码简单,理解过程简单。如果能够加载驱动,就可以在驱动中向目标进程中的线程插入APC,并直接修改线程对象的某些域,使得该线程满足调用APC的条件了(这样做的成功率几乎可以达到100%)。

缺点:

实现的条件苛刻,能利用的机会并不多。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Windows APC(Asynchronous Procedure Call)注入是一种常见的注入技术,它利用了 Windows 操作系统中的异步过程调用机制来实现注入。具体原理如下: 1. 创建目标进程 首先,攻击者需要创建一个目标进程,该进程将作为注入目标。一般情况下,攻击者会选择一个易受攻击的进程,例如 Windows Explorer。 2. 分配内存空间 攻击者需要在目标进程中分配一块内存空间,用于存放要注入的代码。可以使用 VirtualAllocEx 等函数来实现。 3. 编写注入代码 接下来,攻击者需要编写注入代码,并将其写入到之前分配的内存空间中。注入代码通常是一个 DLL 文件,其中包含了攻击者想要执行的恶意代码。同时,在注入代码中还需要将恶意代码的入口点指向一个 APC 回调函数。 4. 调用 QueueUserAPC 函数 接下来,攻击者需要在目标进程中的某个线程上调用 QueueUserAPC 函数,并将之前分配的内存空间中的 APC 回调函数作为参数。这样,当目标进程的线程下一次进入 Alertable 状态时,它将执行注入代码中的 APC 回调函数。 5. 触发注入 最后,攻击者需要触发目标进程中的线程进入 Alertable 状态。可以使用 Sleep、WaitForSingleObject 等函数来实现。 总之,APC 注入技术是一种高级的注入技术,攻击者可以通过它将恶意代码注入到目标进程中,并在其中执行。然而,这种技术也有一定的局限性,例如无法注入到特权级较高的进程中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值