首页
社区
课程
招聘
[原创]Dll hijack 的另一种编程实现方式及工具
发表于: 2019-3-17 21:42 8849

[原创]Dll hijack 的另一种编程实现方式及工具

2019-3-17 21:42
8849

AheadLib: 215K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6k6L8$3&6K6L8g2)9J5c8V1q4Z5k6h3q4V1e0r3W2T1i4K6u0o6 27bK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6K6N6s2u0A6N6X3g2^5K9Y4g2F1i4K6u0r3b7h3S2W2j5h3c8x3K9h3u0Q4x3X3c8^5z5o6k6Q4x3X3c8^5y4U0b7`.

AddExport: https://bbs.pediy.com/thread-154269.htm

技术上就是:动态加载函数和函数转发。


AheadLib 是动态加载函数; AddExport 是函数转发,不过呢是修改编译后 dll 的方式。

函数转发没见源代码实现方式。于是,就做了这个工具,技术上基于函数转发 ,产生 C 源代码,可修改性高,操作灵活。

编译函数转发 ,完全依赖于 MSVC linker。其它编译器的 linker 不支持函数转发。


举例来说:

主程序 test_dll.c


依赖的 dll 源文件 name_mangling.c

关于Dll hijack,早就有人研究过了:

AheadLib: 215K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6k6L8$3&6K6L8g2)9J5c8V1q4Z5k6h3q4V1e0r3W2T1i4K6u0o6 27bK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6K6N6s2u0A6N6X3g2^5K9Y4g2F1i4K6u0r3b7h3S2W2j5h3c8x3K9h3u0Q4x3X3c8^5z5o6k6Q4x3X3c8^5y4U0b7`.

AddExport: https://bbs.pediy.com/thread-154269.htm

技术上就是:动态加载函数和函数转发。


AheadLib 是动态加载函数; AddExport 是函数转发,不过呢是修改编译后 dll 的方式。

函数转发没见源代码实现方式。于是,就做了这个工具,技术上基于函数转发 ,产生 C 源代码,可修改性高,操作灵活。

编译函数转发 ,完全依赖于 MSVC linker。其它编译器的 linker 不支持函数转发。


举例来说:

主程序 test_dll.c

#include <stdlib.h>
#include <stdio.h>

int __cdecl    _e (int x);
int __cdecl    f (int x);
int __stdcall  g (int x);
int __fastcall h (int x);

int main(int argc, char **argv)
{
    printf("%d\n", _e(1));
    printf("%d\n", f(2));
    printf("%d\n", g(3));
    printf("%d\n", h(4));
    return 0;
}


依赖的 dll 源文件 name_mangling.c

#include <stdlib.h>

__declspec(dllexport) int __cdecl    _e (int x) { return x; }
__declspec(dllexport) int __cdecl    f (int x) { return x; }
__declspec(dllexport) int __stdcall  g (int x) { return x; }
__declspec(dllexport) int __fastcall h (int x) { return x; }

编译后,产生可运行的 test_dll. exe 和 name_mangling.dll。

使用工具,可根据 name_mangling.dll 产生 name_mangling~.c
// Created by hijackdll-helper
/* There should be dll hijacking possible first! */
/* cl.exe /Os /GD /LD /Fe */
/* 5e5K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6W2L8W2)9J5k6i4N6A6K9$3W2H3k6h3c8A6j5g2)9J5k6h3!0J5k6#2)9J5c8Y4N6A6K9$3W2Q4x3V1k6z5j5h3#2W2i4K6g2X3L8h3q4F1k6$3I4A6L8X3N6Q4x3U0k6F1j5Y4y4H3i4K6y4n7i4K6u0m8i4K6u0r3

#include <windows.h>

/*  Don't forward to itself!
    "C:\Windows\System32\version" is acceptable ;p
*/
#define HIJACKED_DLL_NAME "name_mangling_"    //<--- modify

/* gcc does't support this. */
#pragma comment(linker, "/EXPORT:__e="HIJACKED_DLL_NAME"._e,@1")
#pragma comment(linker, "/EXPORT:_g@4="HIJACKED_DLL_NAME"._g@4,@2")
#pragma comment(linker, "/EXPORT:f="HIJACKED_DLL_NAME".f,@3")
#pragma comment(linker, "/EXPORT:h="HIJACKED_DLL_NAME".h,@4")


// Add your implementations here, and comment the forwarders <---

extern int sideload();    //<---

/*  Less dependencies: _DllMainCRTStartup
    More functions: DllMain
    Take care of the core libs yourself: msvcrt, kernel32, ntdll, user32 */
BOOL WINAPI _DllMainCRTStartup(HMODULE hModule, DWORD dwReason, PVOID pvReserved)
{
	switch (dwReason) {
	case DLL_PROCESS_ATTACH:
		sideload();    //<---
		break;
    /*
	case DLL_PROCESS_DETACH:
        break;
	case DLL_THREAD_ATTACH:
        break;
	case DLL_THREAD_DETACH:
        break;
    */
	}
	return TRUE;
}

旁路 sideload.c
#include <windows.h>

__declspec(dllexport) void sideload (void)
{
    MessageBox (0, "test", "From DLL", MB_ICONINFORMATION);
}

编译后,产生 name_mangling~.dll 和 sideload.dll 。 把原来的 name_mangling.dll 重命名为 name_mangling_.dll,name_mangling~.dll 重命名为 name_mangling.dll,放在一起即可验证劫持。可以使用 depends 查看。

最后,要说的是利用方式,可以有两种: 1,自己实现要修改的函数;2,从 dll 入口(旁路)加载额外的代码(当然把代码写进来也行,不过分离到其它 dll 更易于维护)。 生成的 c 文件中 “<---”标明了主要操作点。

开源地址:b65K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6D9K9h3k6W2L8X3A6G2K9h3&6W2M7W2)9J5c8X3S2A6K9X3q4U0K9$3c8D9L8q4)9#2k6X3S2W2L8s2m8W2M7R3`.`.

#include <stdlib.h>
#include <stdio.h>

int __cdecl    _e (int x);
int __cdecl    f (int x);
int __stdcall  g (int x);
int __fastcall h (int x);

int main(int argc, char **argv)
{
    printf("%d\n", _e(1));
    printf("%d\n", f(2));
    printf("%d\n", g(3));
    printf("%d\n", h(4));
    return 0;
}
#include <stdlib.h>

__declspec(dllexport) int __cdecl    _e (int x) { return x; }
__declspec(dllexport) int __cdecl    f (int x) { return x; }
__declspec(dllexport) int __stdcall  g (int x) { return x; }
__declspec(dllexport) int __fastcall h (int x) { return x; }

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2019-3-18 09:35 被walkier编辑 ,原因: 补一下附件。之前明明选了附件的~
上传的附件:
收藏
免费 2
支持
分享
最新回复 (3)
雪    币: 3549
活跃值: (951)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
2
试一下
2019-3-19 11:47
0
雪    币: 190
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
我做了一个类似的软件,用的delphi. 也是动态载入dll转发函数
f00K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2&6k6$3g2Q4x3X3g2E0k6g2)9J5c8Y4m8#2j5X3I4A6j5#2)9J5c8X3q4V1k6r3!0F1M7#2)9J5c8Y4W2S2K9$3g2T1L8r3!0Y4i4K6u0r3k6r3g2@1j5h3W2D9i4K6u0r3M7$3S2G2N6#2)9J5c8X3W2V1i4K6u0r3x3U0y4Q4x3X3g2Z5N6r3#2D9
有GUI,有源代码,有编译器,直接生成dll文件.(在资源文件里,执行时会自动解压的%tmp%目录)


补充:
编译器用的是DELPHI XE2.

发布后就发现一些bug,比如劫持的DLL导出函数带'_'下划线的会报错.一直没修改.
最后于 2019-3-19 17:49 被yake-job编辑 ,原因:
2019-3-19 17:47
0
雪    币: 314
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
感谢分享
2019-3-22 10:30
0
游客
登录 | 注册 方可回帖
返回