远程线程注入(一)编写动态链接库

来源:互联网 发布:梁朝伟张曼玉 知乎 编辑:程序博客网 时间:2024/06/06 00:16

想写个远程线程注入的东西......

问了下栋哥终于把机理给搞明白了。

参考的书本是《Windows API 开发详解 ---函数、接口、编程实例》和《windows核心编程》

首先我们从编写一个dll开始。

为了统一起见,下面的代码中所有函数全部使用宽字符版本。

首先把代码给贴出来:

[cpp] view plain copy
 print?
  1. /****************************** 
  2. * msg.c动态链接库 
  3. *******************************/  
  4. #include <Windows.h>  
  5. #include <Psapi.h>  
  6.   
  7. #pragma comment(lib, "Psapi.lib")  
  8.   
  9. __declspec(dllexportDWORD ExportExample(LPSTR sMsg, DWORD dwCode);  
  10.   
  11. //dll main  
  12. BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)  
  13. {  
  14.     switch (fdwReason)  
  15.     {  
  16.     case DLL_PROCESS_ATTACH:  
  17.         {  
  18.             TCHAR lpMainMoudleName[MAX_PATH];  
  19.             TCHAR lpMessage[MAX_PATH + 64];  
  20.             //获取PID和主模块名,将弹出消息框  
  21.             DWORD dwPID = GetCurrentProcessId();  
  22.             GetModuleBaseName(GetCurrentProcess(), NULL, lpMainMoudleName, MAX_PATH);  
  23.             wsprintf(lpMessage, L"process name: %s, PID: %u ", lpMainMoudleName, dwPID);  
  24.             MessageBox(NULL, lpMessage, L"msg.dll", MB_OK);  
  25.             break;  
  26.         }  
  27.     case DLL_THREAD_ATTACH:  
  28.         break;  
  29.     case DLL_PROCESS_DETACH:  
  30.         break;  
  31.     case DLL_THREAD_DETACH:  
  32.         break;  
  33.     }  
  34.     return TRUE;  
  35. }  
  36.   
  37. //导出函数,显示消息  
  38. DWORD ExportExample(LPWSTR szMsg, DWORD dwCode)  
  39. {  
  40.     LPVOID lpShowOut = HeapAlloc(GetProcessHeap(), NULL, lstrlen(szMsg) + 100);  
  41.     wsprintf((LPWSTR)lpShowOut, L"%s,%d", szMsg, dwCode);  
  42.     MessageBox(NULL, (LPWSTR)lpShowOut, L"由导出函数弹出的消息! ", MB_OK);  
  43.     HeapFree(GetProcessHeap(), NULL, lpShowOut);  
  44.     return 0;  
  45. }  
然后我们来分析一下代码:

[cpp] view plain copy
 print?
  1. __declspec(dllexportDWORD ExportExample(LPSTR sMsg, DWORD dwCode);  
这是个导出函数的声明,声明了这个函数是从dll中导出的函数。


接下来是dll的主函数入口。跟main 和WinMain 差不多。它是DllMain

[cpp] view plain copy
 print?
  1. BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)  


dwnReason可以是下面四个值:

[cpp] view plain copy
 print?
  1. switch (fdwReason)  
  2. {  
  3. case DLL_PROCESS_ATTACH:  
  4.     break;  
  5. case DLL_THREAD_ATTACH:  
  6.     break;  
  7. case DLL_PROCESS_DETACH:  
  8.     break;  
  9. case DLL_THREAD_DETACH:  
  10.     break;  
  11. }  
通俗的理解,分别是附加进程,附加线程,分离进程,分离线程的意思。

具体的理解,大家可以查看《windows核心编程》,下面的博客也分别摘录了核心编程里面的东西:

http://blog.csdn.NET/ithzhang/article/details/7051558

本例子中的代码是这样的,在DLL_PROCESS_ATTACH的时候执行下面的代码:

[cpp] view plain copy
 print?
  1. case DLL_PROCESS_ATTACH:  
  2.     {  
  3.         TCHAR lpMainMoudleName[MAX_PATH];  
  4.         TCHAR lpMessage[MAX_PATH + 64];  
  5.         //获取PID和主模块名,将弹出消息框  
  6.         DWORD dwPID = GetCurrentProcessId();  
  7.         GetModuleBaseName(GetCurrentProcess(), NULL, lpMainMoudleName, MAX_PATH);  
  8.         wsprintf(lpMessage, L"process name: %s, PID: %u ", lpMainMoudleName, dwPID);  
  9.         MessageBox(NULL, lpMessage, L"msg.dll", MB_OK);  
  10.         break;  
  11.     }  
代码很简单,获得进程ID并且用对话框的方式显示出来。

接下来我们看看导出函数:

[cpp] view plain copy
 print?
  1. //导出函数,显示消息  
  2. DWORD ExportExample(LPWSTR szMsg, DWORD dwCode)  
  3. {  
  4.     LPVOID lpShowOut = HeapAlloc(GetProcessHeap(), NULL, lstrlen(szMsg) + 100);  
  5.     wsprintf((LPWSTR)lpShowOut, L"%s,%d", szMsg, dwCode);  
  6.     MessageBox(NULL, (LPWSTR)lpShowOut, L"由导出函数弹出的消息! ", MB_OK);  
  7.     HeapFree(GetProcessHeap(), NULL, lpShowOut);  
  8.     return 0;  
  9. }  
导出函数也很简单,就是弹出一个对话框。这个没什么好说的。

加载了动态链接库之后我们就可以直接使用这个dll中的接口函数了。dll的方便性就体现在这里了。^_^



然后我们简单的重新写个代码测试一下这个dll的正确性:

[cpp] view plain copy
 print?
  1. #include <stdio.h>  
  2. #include <windows.h>  
  3.   
  4. typedef DWORD (*MY_EXPORT_PROC)(LPWSTRDWORD);  
  5.   
  6. void main(void)  
  7. {  
  8.     HINSTANCE hinstLib;  
  9.     MY_EXPORT_PROC lpProcAdd;  
  10.     BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;  
  11.     //获得DLL模块句柄  
  12.     hinstLib = LoadLibrary(TEXT("msg.dll"));  
  13.     //是否加载成功  
  14.     if (NULL != hinstLib)  
  15.     {  
  16.         //获得指定导出函数的地址  
  17.         lpProcAdd = (MY_EXPORT_PROC)GetProcAddress(hinstLib, "ExportExample");  
  18.   
  19.         //判断是否成功  
  20.         if (NULL != lpProcAdd)  
  21.         {  
  22.             fRunTimeLinkSuccess = TRUE;  
  23.             (lpProcAdd) (TEXT("hello"), 123);  
  24.         }  
  25.         //释放dll  
  26.         fFreeResult = FreeLibrary(hinstLib);  
  27.     }  
  28.   
  29.     if (!fRunTimeLinkSuccess)  
  30.         printf("error; %u\n", GetLastError());  
  31. }  
这里使用的一种比较麻烦的方法。跟#pragma comment(“xxx.lib”, lib)有点不一样的地方。

#pragma comment(“xxx.lib”, lib)这种方式会在程序的可执行文件中创建导入表,并在程序加载时进行函数的链接。

使用这种方法的话,有没有lib文件的必要了。因为他在LoadLibrary之后直接获得了导出函数的地址

[cpp] view plain copy
 print?
  1. //获得指定导出函数的地址  
  2.   lpProcAdd = (MY_EXPORT_PROC)GetProcAddress(hinstLib, "ExportExample");  

然后我们测试一下,发现成功弹出了dll中的两个对话框~~~!!

OK,第一步我们先到这里了,接下来就是伟大的远程线程注入了,哈哈。


转自:http://blog.csdn.net/gaoxin1076/article/details/8112767

0 0