发布时间:2023-08-05 15:30
当你的才华
还撑不起你的野心时
那你就应该静下心来学习
由于 输入表中只包含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
-
#include
-
-
-
-
// 导出函数
-
#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
我不需要自由,只想背着她的梦
一步步向前走,她给的永远不重
深度网络架构的设计技巧(二)之BoT:Bottleneck Transformers for Visual Recognition
Unity UGUI RawImage RenderTexture完美解决方案
ES2018 最新 理解Javascript中的执行上下文和执行栈
Java Agent 踩坑之 appendToSystemClassLoaderSearch 问题
RuntimeError: one of the variables needed for gradient computation has been modified by an...
【第25天】给定一个长度为 n 的数组,统计每个数出现的次数 | 计数哈希