首页
社区
课程
招聘
[原创]DLL劫持-免杀
发表于: 2020-11-22 17:47 16929

[原创]DLL劫持-免杀

2020-11-22 17:47
16929

小白初试,大佬轻喷

举个简单的例子,一个程序A调用了d.dll中的某些函数.我现在修改d.dll的名字变成d-org.dll。然后我写再写一个d.dll的文件,将原本d.dll中的函数转发到d-org.dll上。实际上就是多了一个中间商

就和开了代理一样,我一样从本机连到网站,只是中间走了一个代理

既然走了代理,那我们就可以在这个“代理商”这里做点手脚。比如夹带私货等等

道理都懂,但是怎么转发dll函数

最朴素的思路是什么?那无疑是直接LoadLibray直接导入原来的dll,然后对
应的写一个相同的函数名,然后GetProcAddress导入对应函数名的函数

这样可以做到,但是很麻烦,而且低效率,一个更高效的做法是利用#program这条预编译命令

比如,我新的d.dll要转发d-org.dll中的一个msg的函数

在dll文件中添加一条

我是用vs2019写x64,release模式

要建3个项目,一个是可执行文件hello.exe(相当于a.exe),一个是dll-1.dll,一个是dll-2.dll

dll-2.dll是为了转发dll-1.dll中的函数

先写dll-1,写个简单的messagebox

记得在头文件framework.h中导出这个函数

然后写个调用这个dll的hello.exe

这个时候运行这个程序就回显示这个dll调用成功

然后来编写一个劫持的dll,也就是来转发函数的dll2

在导入我这个dll的时候我弹出一个劫持成功的弹窗

注意到预编译指令是

转发的dll名字是dll-1org,这是我决定把dll-1改名成dll-1org了,所以写死在dll-2中,毕竟等下要将dll-2改名成dll-1,这样程序才会调用我的dll

这时候不是在vs中跑,我把这个3个文件放到同目录的地方,然后运行hello.exe
劫持成功

表示我成功劫持了,思路也很简单

我不擅长写shellcode,就直接用msf生成shellcode
msf里的shell被各大安全厂家都看的很死的,直接生成exe秒杀,这里不直接生成exe,生成shellcode文件就可以了

继续用上面的例子来
dll-2就不弹窗了,在这个dll中导入shellcode

上面的函数就是读取shellcode,然后申请一块内存,再就执行函数,相当执行shellcode
我不做其他处理,没加上其他免杀操作,此时来执行这个程序
劫持成功2
可以看到,msf返回shell了,然儿火绒没有丝毫反应
火绒:你不讲武德

其实很简单,就是dll中申请内存,直接执行shellcode。
我尝试这个写法,程序中直接执行shellcode,会断了

DLL代理转发与维权

DLL劫持

 
-------              -------
-  -              -  -
-------              -------
   |                    |        ----------
  call     --->         |_____   -  new D -
   |                             ----------
-------              ---------        |
-  -              - D-org -  ______|
-------              ---------
-------              -------
-  -              -  -
-------              -------
   |                    |        ----------
  call     --->         |_____   -  new D -
   |                             ----------
-------              ---------        |
-  -              - D-org -  ______|
-------              ---------
 
 
#pragma comment(linker, "/EXPORT:<Function name>=<Dll name>.<Function name>")
#pragma comment(linker, "/EXPORT:<Function name>=<Dll name>.<Function name>")
 
#pragma comment(linker, "/EXPORT:msg=d-org.msg")
#pragma comment(linker, "/EXPORT:msg=d-org.msg")
 
 
 
#include "pch.h"
#include <Windows.h>
 
void msg() {
    MessageBox(0, L"dll-1 load succeed", 0, 0);
}
 
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
#include "pch.h"
#include <Windows.h>
 
void msg() {
    MessageBox(0, L"dll-1 load succeed", 0, 0);
}
 
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
#pragma once
 
#define WIN32_LEAN_AND_MEAN             // 从 Windows 头文件中排除极少使用的内容
// Windows 头文件
#include <windows.h>
 
extern "C" __declspec(dllexport) void msg(void);
 
void msg();
#pragma once
 
#define WIN32_LEAN_AND_MEAN             // 从 Windows 头文件中排除极少使用的内容
// Windows 头文件
#include <windows.h>
 
extern "C" __declspec(dllexport) void msg(void);
 
void msg();
#include <iostream>
#include <Windows.h>
 
int main() {
    typedef void(*DLLFUNC)(void);
    DLLFUNC GetDllfunc = NULL;
    HINSTANCE hinst = LoadLibrary(L"Dll-1.dll");
    if (hinst != NULL) {
        GetDllfunc = (DLLFUNC)GetProcAddress(hinst, "msg");
    }
    if (GetDllfunc != NULL) {
        (*GetDllfunc)();
    }
    return 0;
}
#include <iostream>
#include <Windows.h>
 
int main() {
    typedef void(*DLLFUNC)(void);
    DLLFUNC GetDllfunc = NULL;
    HINSTANCE hinst = LoadLibrary(L"Dll-1.dll");
    if (hinst != NULL) {
        GetDllfunc = (DLLFUNC)GetProcAddress(hinst, "msg");
    }
    if (GetDllfunc != NULL) {
        (*GetDllfunc)();
    }
    return 0;

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 1
支持
分享
最新回复 (8)
雪    币: 1556
活跃值: (310)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
2
火绒这个反应有点怪啊,按说不应该能pass
2020-11-23 08:51
0
雪    币: 3414
活跃值: (3003)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
学习了!
2020-11-23 09:33
0
雪    币: 1140
活跃值: (266)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
Mix_Channels
2020-11-23 16:00
0
雪    币: 6124
活跃值: (4656)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
5
本来,反劫持应该是应用自身应该做的工作,载入的任何dll使用绝对路径,同时嵌套依赖也使用绝对路径,保证代码不被劫持,杀毒对于劫持有时候灵有时候不灵。
2020-11-23 20:36
0
雪    币: 94
活跃值: (382)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
学习了
2020-11-24 06:43
0
雪    币: 25
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
7
学习了,感谢分享
2020-11-27 20:54
0
游客
登录 | 注册 方可回帖
返回
//