DLL注入的8种姿势

 

目录

1、远程线程注入

2、APC注入

3、注册表注入

4、ComRes注入

5、劫持进程创建注入

6、输入法注入

7、消息钩子注入

8、依赖可信任进程注入

 

 

一、DLL注入——远程线程注入

https://blog.csdn.net/Cody_Ren/article/details/100041660

 

二、DLL注入——APC注入

APC注入的原理?

APC是一个简称,即“异步过程调用”。APC注入的原理是利用当线程被唤醒时,APC中的注册函数会被执行,并以此去执行我们的DLL加载代码,进而完成DLL注入的目的。在线程下一次被调度的时候,就会执行APC函数,APC有两种形式,由系统产生的APC称为内核模式APC,由应用程序产生的APC被称为用户模式APC。

其实现流程为:

    1)当EXE里某个线程执行到SleepEx()或者WaitForSingleObjectEx()时,系统就会产生一个软中断。
    2)当线程再次被唤醒时,此线程会首先执行APC队列中的被注册的函数。
    3)利用QueueUserAPC()这个API可以在软中断时向线程的APC队列插入一个函数指针,如果我们插入的是Loadlibrary()执行函数的话,就能达到注入DLL的目的。

使用方法:

1.利用快照枚举所有的线程

2.写入远程内存,写入的是Dll的路径

3.插入我们的DLL即可

 

C++实现

Step 1  编写测试程序,用来被注入

新建MFC工程,添加一个Button,修改ID如下,这个程序的作用就是调用上面的SleepEx.

《DLL注入的8种姿势》

双击Button进入添加代码,需要注意一下SleepEx中第二个参数为TRUE,当第二个参数为FALSE时,APC时不被执行的

《DLL注入的8种姿势》

(这个程序啥也不干,就是调用等待,注意第二个参数给TRUE,第二个参数决定了你的APC是否调用)

 

Step 2  编写DLL用作注入

直接生成一个简单的带有DllMain的入口的DLL即可.

《DLL注入的8种姿势》

 

Step 3  编写注入程序,即一个新的MFC程序用来攻击

添加一个按钮,为按钮添加如下代码(做法为:根据窗口找进程的TID和PID),修改ID为IDC_APCAttack,编译即可。

《DLL注入的8种姿势》

void CAPCInjectorDlg::OnBnClickedApcattack()
{
	// TODO: 在此添加控件通知处理程序代码
	//1.查找窗口
  HWND hWnd = ::FindWindow(NULL, TEXT("APCTest"));
  if (NULL == hWnd)
  {
    return;
  }
  /*2.获得进程的PID,当然通用的则是你把进程PID当做要注入的程序,这样不局限
  于窗口了.这里简单编写,进程PID可以快照遍历获取
  */
  DWORD dwPid = 0;
  DWORD dwTid = 0;
  dwTid = GetWindowThreadProcessId(hWnd, &dwPid);

  //3.打开进程
  HANDLE hProcess = NULL;
  hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
  if (NULL == hProcess)
  {
    return;
  }
  //4.成功了,申请远程内存
  void *lpAddr = NULL;
  lpAddr = VirtualAllocEx(hProcess, 0, 0x1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  if (NULL == lpAddr)
  {
    return;
  }
  //5.写入我们的DLL路径,这里我写入当前根目录下的路径
  char szBuf[] = "MyDll.dll";
  BOOL bRet = WriteProcessMemory(hProcess, lpAddr, szBuf, strlen(szBuf) + 1, NULL);
  if (!bRet)
  {
    return;
  }
  //6.根据线程Tid,打开线程句柄
  HANDLE hThread = NULL;
  hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, dwTid);
  if (NULL == hThread)
  {
    return;
  }
  //7.给APC队列中插入回调函数
  QueueUserAPC((PAPCFUNC)LoadLibraryA, hThread, (ULONG_PTR)lpAddr);

  CloseHandle(hThread);
  CloseHandle(hProcess);
}

将上面三步编译生成的文件放到同一个目录中,打开APCInject.exe和APCInjector.exe然后先点一下Button1挂起程序,然后点击注入,弹出MessageBox说明成功。

《DLL注入的8种姿势》

下图为网友的程序,源码是相同的。

《DLL注入的8种姿势》

通过PChunter或者Process Explorer可发现成功注入

《DLL注入的8种姿势》

 

三、DLL注入——注册表注入

什么是DLL注入技术?

将一个DLL文件强行加载到EXE文件中,并成为EXE文件中的一部分,这样做的目的在于方便我们通过这个DLL读写EXE文件内存数据,或以被注入EXE的身份去执行一些操作。
 

什么是REG注入?

利用在Windows系统中,当REG中的以下键值中存在有DLL文件路径时,会跟随EXE文件的启动加载这个DLL文件路径中的DLL文件。当如果遇到有多个DLL文件时,需要用逗号或者空格隔开多个DLL文件的路径。

注册表项:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLL

REG注入就是Windows 系统在给EXE文件加载DLL文件的过程中,多加载了一个比如说AppInit_DLL中的DLL文件,这个DLL文件可以是合法的,也可以是病毒文件的DLL,这就要看使用者是怎么利用这个特性了。

《DLL注入的8种姿势》

换个说法理解一下:

在系统中每一个进程加载User32.dll时,会收到DLL_PROCESS_ATTACH通知,当User32.dll对其进行处理时,会取得注册表键值HKEY_LOCAL_MACHINE\Software\Microsoft\windowsNT\CurrentVresion\Windows\AppInit_Dlls,并调用LoadLibrary来载入这个字符串中指定的每个DLL。被调用的DLL会在系统调用它们的DllMain函数,并将参数fdwReason的值设为DLL_PROCESS_ATTACH时,对自己进行初始化。所以我们在这个键值中添加我们的Dll路径,即可实现注入。

再换个说法理解一下:

注册表中默认提供了AppInit_Dlls与LoadAppInit_Dlls两个注册表项

在注册表编辑器中,将要注入的DLL路径字符串写入AppInit_Dlls项目,然后把LoadAppInit_Dlls项目值设置为1,重启后,指定DLL会注入所有运行进程。

工作原理:User32.dll被加载到进程是,会读取AppInit_DLLs注册表项,若有值,则调用LoadLibrary()API加载用户DLL,所以,严格的说,想应DLL并不会被加载到所有进程,而只是加载user32.dll的进程,Windows Xp忽略LoadAppInit.DLLs项。
 

注入流程:

打开注册表键值如下:
HKEY_LOCAL_MACHINE\SoftWare\MicroSoft\Windows NT\CurrentVersion\Windows\

1. 在上面的注册表项中操作 AppInit_DLLs 键值,在该键值中添加自己的DLL的全路径加dll名,多个DLL以逗号或者空格分开(因此在文件名中应该尽量不要存在空格),该键值只有第一个dll文件名可以包含路径,后面的都不能包含,因此我们最好将dll放在系统路径    下,这样就可以不用包含路径也能被加载了。

2. 在该注册表项中添加键值 LoadAppInit_DLLs ,类型为 DWORD,并将其值置为 1 。

总结

REG注入操作简单易懂,甚至不用写程序都可以完成注入操作,但是正是由于他的简单性,每个EXE都被注入,效率低,程序的扩展性差。
 

四、DLL注入——ComRes注入

原理?

ComRes注入的原理是利用Windows系统中C:\WINDOWS\system32目录下的ComRes.dll这个文件,当待注入EXE如果使用CoCreateInstance()这个API时,COM服务器会加载ComRes.dll到EXE中,利用这个加载过程,我们可以将ComRes.dll替换掉,并在伪造的ComRes.dll,然后利用LoadLibrary()将事先准备好的DLL加载到目标EXE中。

 

注意事项:

由于直接拷贝comres.dll文件到C:\WINDOWS\system32目录下会引起winows的文件系统保护机制,所以首先需要将C:\WINDOWS\system32\dllcache下的文件替换掉,然后再将其C:\WINDOWS\system32文件替换为我们伪造的文件。

ComRes注入只需伪造与替换就可以完成,编程要求不高,方便使用,但是由于加载了ComRes.dll后,再想替换ComRes.dll文件就不可能了,因此想反复测试ComRes.dll文件就比较麻烦。

 

五、DLL注入——劫持进程创建注入

劫持进程创建注入原理是利用Windows系统中的CreateProcess()这个API创建一个进程,并且将第六个参数设置为CREATE_SUSPENDED,进而创建一个挂起状态的进程,利用这个进程状态进行远程线程注入DLL,然后用ResumeThread()函数回复进程。

劫持进程创建注入其实就是远程线程注入的前期加强版,他可以在进程启动前进行注入,由于进程的线程没有启动,这样就可以躲过待注入进程的检测,提高注入的成功率。

 

六、DLL注入——输入法注入

输入法注入原理?

输入法注入的原理是利用Windows系统中在切换输入法需要输入字符时,系统就会把这个输入法需要的IME文件装在到当前进程中,而由于这个IME文件本质上只是个存放在C:\WINDOWS\system32目录下的特殊的DLL文件,因此我们可以利用这个特性,在IME文件中使用LoadLibrary()函数待注入的DLL文件。

如果想进行输入法注入,需要以下几步:

1、编写IME文件

输入法的IME文件其实就是个显式导出19个特殊函数的DLL文件。

《DLL注入的8种姿势》

如果想编写输入法程序,那么这19个导出函数都需要仔细的研究,但是对于只想实现注入的我们,现在只需要对ImeInquire()有比较深的认识就可以了,ImeInquire()是启动并初始化当前Ime输入法函数。

2、编写装载输入法程序

装载输入法的基本逻辑就是将他们编写的输入法设置为默认输入法,这样只要系统中所有进程都会默认加载他们的恶意输入法程序。黑客们首先需要得到系统当前的默认的输入法,以便恢复时使用。然后需要将IME文件拷贝到C:\WINDOWS\system32目录下,最后将装载成功之后的输入法设置成为默认的输入法。

3、编写卸载输入法

当新建进程不再需要注入时,就需要卸载输入法。卸载输入法时需要先判定系统当前的输入法不是其原有的默认输入法,确认无误之后将系统的默认输入法恢复后,再将恶意输入法卸载即可。

注意:

输入法注入的实现需要对输入法IME文件的生成有所了解,API使用较多,所以实现起来比较困难,单系统存在多个输入法,被注入进程很难判断当前是可信赖输入法还是用于注入的恶意输入法,所以难以阻止,大大提高了注入的几率。

 

七、DLL注入——消息钩子注入

消息钩子注入原理是利用Windows系统中的SetWindowsHookEx()这个API,他可以拦截目标进程的消息到指定的DLL中的导出函数,利用这个特性,我们可以将DLL注入到指定的进程中。

《DLL注入的8种姿势》

 

注意:

消息钩子注入只需要对SetWindowsHookEx()和DLL导出函数有深刻的认识就可以很容编写,所以代码简单,比较容易实现。

 

八、DLL注入——依赖可信进程注入

原理?

依赖可信进程注入原理是利用Windows系统中Services.exe这个权限较高的进程,首先先将a.dll远线程注入到Service.exe中,再利用a.dll将b.dll远线程注入的待注入进程中。

 

具体过程:

《DLL注入的8种姿势》

这里有一个小技巧,当注入到Services.exe里的DLL时,想在做完事情以后悄无声息地将自己释放掉,在Windows中可以利用API函数FreeLibraryAndExitThread(),他可以将自己卸载掉并且退出线程。

 

 

 

 

 

    原文作者:dajiiii
    原文地址: https://blog.csdn.net/Cody_Ren/article/details/100053434
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞