使用 GCC/MinGW 创建代理 DLL

Posted

技术标签:

【中文标题】使用 GCC/MinGW 创建代理 DLL【英文标题】:Create a proxy DLL with GCC/MinGW 【发布时间】:2015-05-08 22:32:49 【问题描述】:

使用 Visual C++ 编译器,可以创建一个 DLL 文件,该文件可以模仿另一个 DLL 文件并将所有函数调用重定向到原始 DLL。 Here是一篇带工具的文章,可以自动生成Visual C++代码。

生成的函数存根工作(经过测试),如下所示:

extern "C" __declspec(naked) void __stdcall __E__0__()

    __asm
    
        jmp p[0]; // p[0] = GetProcAddress(hL,"AcceptEx");
    

现在我想用 MinGW/GCC 而不是 MSVC 做同样的事情。

__declspec(naked) 在 i386 上不受 GCC 支持,所以我们需要另一种方式。 正如here 建议的那样,我可以通过在全局范围内编写汇编代码来覆盖函数。这是我的代码应该可以解决问题:

__asm__
(
    "jmp *%0"
    : /* empty output list */
    : "r" (pointer_to_original_function) /* p[0] in the example above */
);

我的 sn-p 使用GCC's extended ASM。但不幸的是,这只允许在函数内部,而不是在全局范围内!

那么...我该怎么做呢?我的下一个方法是在没有扩展 ASM 的情况下尝试它,但是我如何在汇编中获取指针地址呢?

这里我试图从一个全局变量中获取它,但它在 repace_this_stub() 处出现段错误:

#include <stdio.h>

void try_to_jump_to_me()

    printf("you made the jump\n");


void* target_pointer = try_to_jump_to_me;

__asm__ (
    "replace_this_stub:"
    "jmp target_pointer"
);
void replace_this_stub();


int main(int argc, char** argv)
   
    printf("starting in main. \n");

    replace_this_stub();

    printf("back in main?\n");


【问题讨论】:

大概指针在某个全局变量中……所以就用它的名字吧。 我不太擅长组装,你能给我一个示例代码吗?我猜 __asm__("jmp global_variable");行不通——如果可能的话,我也想使用某种数组,因为通常有很多函数 【参考方案1】:

如果指针在一个全局变量中,你可以直接使用它的名字。请务必应用任何名称修饰。还将您的代码放在适用的代码部分并为其命名。示例代码:

#include <stdio.h>

void* p = printf;

asm(
    ".section .text\n\t"
    "proxy: jmp *p\n\t"
    ".previous\n\t");
extern void proxy();
int main()

    proxy("Hello world!\n");
    return 0;

如果要使用数组,只需添加适当的位移即可。扩展示例:

#include <stdio.h>
#include <string.h>

void* p[] =  printf, strcpy ;
#define str(x) #x
#define PROXY(name, index) asm( \
    ".section .text\n\t" \
    str(proxy_##name) ": jmp *p + " str(index) " * 4\n\t" \
    ".previous\n\t"); \
    extern void proxy_##name()

PROXY(printf, 0);
PROXY(strcpy, 1);

int main()

    char buf[128];
    proxy_strcpy(buf, "Hello world!\n");
    proxy_printf(buf);
    return 0;

【讨论】:

太棒了!我研究了几个小时,你真的为我节省了很多时间!我会给你一个赞成票,但我还没有足够的声望。 另外,在 x86_64 上编译进行测试时,需要在流水线中将 4 替换为 8,因为那里的指针大小是原来的两倍。有用! :)

以上是关于使用 GCC/MinGW 创建代理 DLL的主要内容,如果未能解决你的问题,请参考以下文章

GCC/MingW 在不同版本上编译

MinGW - GCC 6.1.0

gcc MinGW 上的 InterlockedOr8

gcc+mingw 下的 C++ segfault 但不是 gcc+linux

通过 DLL 代理重定向损坏的函数

GCC (MingW-w64) 找不到基础构造函数 (!?)