DLL注入技术之REG注入

DLL注入技术之REG注入
DLL注入技术指的是将一个DLL文件强行加载到EXE文件中,并成为EXE文件中的一部分,这样做的目的在于方便我们通过这个DLL读写EXE文件内存数据,(例如 HOOK EXE文件中的API),或以被注入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文件),这个紫菜鸡蛋汤可以是英伟达的UI加速的DLL文件,也可以是是病毒文件的DLL,这就要看使用者是怎么利用这个特性了。

设置完毕后,当我们启动一个EXE文件时(例如计算器),用调试器工具OllyDBG附加到计算器,调用OllyDBG菜单命令,“查看—可执行模块”,
此时我们已经可以看到DLL文件已经附加在EXE文件中了
我们可以利用这个特性来进行DLL的注入,接下来需要解决的就是关于注册表操作的Windows API了,如下所示:

RegOpenKeyEx 打开注册表键值
RegQueryValueEx 查询键值
RegSetValueEx 设置键值
RegCloseKey 关闭键值

主要代码如下:

  1. //打开键值
  2. nReg = RegOpenKeyEx(
  3. HKEY_LOCAL_MACHINE,
  4. m_szRegPath,
  5. 0,
  6. KEY_ALL_ACCESS,
  7. &hKey);
  8.  
  9. if(nReg != ERROR_SUCCESS)
  10. {
  11. return FALSE;
  12. }
  13.  
  14. //查询键值
  15. DWORD dwReadType;
  16. DWORD dwReadCount;
  17. TCHAR szReadBuff[1000] = {0};
  18. nReg = RegQueryValueEx(hKey,
  19. _T("AppInit_DLLs"),
  20. NULL,
  21. &dwReadType,
  22. (BYTE*)&szReadBuff,
  23. &dwReadCount);
  24.  
  25. if(nReg != ERROR_SUCCESS)
  26. {
  27. return FALSE;
  28. }
  29.  
  30. //是否dll名称已经在内容中
  31. tstring strCmpBuff;
  32. strCmpBuff = szReadBuff;
  33. if (!strCmpBuff.find(InjectFilePath))
  34. {
  35. return FALSE;
  36. }
  37.  
  38. //有字符串就加入空格
  39. if (0 != _tcscmp(szReadBuff,_T("")))
  40. {
  41. _tcscat_s(szReadBuff,_T(" "));
  42. }
  43.  
  44. _tcscat_s(szReadBuff,InjectFilePath);
  45.  
  46. //把dll路径设置到注册表中
  47. nReg = RegSetValueEx(hKey,
  48. _T("AppInit_DLLs"),
  49. 0,
  50. REG_SZ,
  51. (CONST BYTE*)szReadBuff,
  52. (_tcslen(szReadBuff)+1)*sizeof(TCHAR));

当我们完成了注册表的注入时,并不是希望所有程序都运行DLL里面的内容,这时我们就需要在DLL中过滤窗口名称,让指定窗口名称的EXE文件运行DLL里的线程。所需API如下表所示:

  1. CreateThread
  2. 创建线程
  3. Sleep
  4. 睡眠
  5. EnumWindows
  6. 遍历窗口
  7. GetWindowText
  8. 得到窗口名称
  9. GetCurrentProcessId
  10. 得到当前进程ID
  11. GetWindowThreadProcessId
  12. 由HWND获得进程ID

为了实现此功能,我们需要在注入的DLL中创建线程,并在线程中执行遍历窗口函数,我们需要先获取窗口名称,与我们想运行的EXE名称进行对比,并进行进程ID对比,因为不光只有一个EXE文件的运行实例,经过这些过滤后,我们就可以在指定的EXE文件中运行代码了。

主要代码如下:

  1. BOOL CALLBACK lpEnumFunc(HWND hwnd, LPARAM lParam)
  2. {
  3. TCHAR str[MAXBYTE] = {0};
  4. //得到窗口名称
  5. GetWindowText(hwnd,str,sizeof(str));
  6. //是否名称是计算器
  7. if(0 == _tcscmp(str,_T("计算器")))
  8. {
  9. //由于存在可能多个计算器,需要过滤线程ID
  10. //得到本身线程的ID
  11. DWORD dwCurrentProcessId = GetCurrentProcessId();
  12. DWORD dwFindCurrentProcessId = 0;
  13. //得到窗口线程ID
  14. GetWindowThreadProcessId(hwnd,&dwFindCurrentProcessId);
  15. //比较
  16. if (dwCurrentProcessId == dwFindCurrentProcessId)
  17. {
  18. *(PDWORD)lParam = 1;
  19. return FALSE;
  20. }
  21. }
  22. return TRUE;
  23. }
  24.  
  25. DWORD ThreadProc(CMfcRegInjectDllApp* pThis)
  26. { //切换mfc模块
  27. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  28. //等待1秒时间以便于让windows创建窗口
  29. Sleep(1000);
  30. DWORD dwFind = 0;
  31. //遍历窗口,过滤窗口名称
  32. EnumWindows(lpEnumFunc,(LPARAM)&dwFind);
  33.  
  34. if (!dwFind) return 0;
  35. //显示对话框
  36. if (!pThis->m_pUIDlg)
  37. {
  38. pThis->m_pUIDlg = new RegInjectMessageBox();
  39. pThis->m_pUIDlg->Create(IDD_DIALOG1);
  40. pThis->m_pUIDlg->ShowWindow(SW_SHOW);
  41. pThis->m_pUIDlg->RunModalLoop();
  42. }
  43.  
  44. return 0;
  45. }
  46.  
  47. BOOL CMfcRegInjectDllApp::InitInstance()
  48. {
  49. //CWinApp::InitInstance();
  50. DWORD dwThreadId;
  51. m_hThread = ::CreateThread(NULL, NULL,
  52. (LPTHREAD_START_ROUTINE)ThreadProc,
  53. this, NULL,&dwThreadId);
  54.  
  55. return TRUE;
  56. }

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

作者: xusir98
来源: 黑客反病毒 (http://bbs.hackav.com)

还没有评论,快来抢沙发!

发表评论

  • 😉
  • 😐
  • 😡
  • 😈
  • 😯
  • 😛
  • 😳
  • 😮
  • 😆
  • 💡
  • 😀
  • 👿
  • 😥
  • 😎
  • 😕