微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

有没有办法创建一个具有正确偏移量的剥离二进制文件?

如何解决有没有办法创建一个具有正确偏移量的剥离二进制文件?

我正在尝试将程序集文件转换为 C++,以用作另一个库的小型且易于插入的“蹦床”加载程序。它在运行时被注入到另一个程序中,然后加载一个库,在其中运行一个函数,然后释放它。这只是为了避免需要多次对 WriteProccessMemory 进行冗长的调用,并在需要时允许进行某些运行时检查。

最初,我用汇编编写代码,因为它让我可以高度控制文件的结构。我最终得到了一个 ~128 字节的文件,结构如下:

<Relocation Header> // Table of function pointers filled in by the loading code
<Code>
<Static Data>

头的大小/结构在编译时是已知的,也允许计算入口点,因此加载它所需的代码很少。

问题是在我的汇编器 (NASM) 和编译器 (GCC) 之间共享头文件的结构非常困难,因此需要重写。

我想出了这一系列的命令来编译/链接 C++ 代码

g++ -c -O3 -fpic Loader.cpp

g++ -O3 -shared -nostdlib Loader.o

运行 objcopy -O binary -j .text a.exe 然后给出一个只有大约 95 字节大小的二进制文件(我在程序集版本中手动插入了一些填充,以便在调试“节”的位置时清楚)。

只有一个问题(至少对于这个问题),变量偏移量没有被重新定位(显然)。查看二进制文件,我可以看到类似 mov rcx,QWORD PTR [rip+0x4fc9] 的行。显然,这在 95 字节文件中无效。有没有办法(最好使用 GCC 或 Binutils 中的程序)我可以获得具有正确偏移量的剥离二进制文件解决方案不必是像 objcopy 这样的后期处理,它可以在构建过程的任何部分发生。

我真的很想避免文件中出现任何不需要的信息,这不一定是有害的,但这意味着超轻量级。该文件不需要可以直接运行(入口点不必为 0)。

还要明确一点,我不是要求对所有指针进行简单的加法/减法,GCC 生成的地址分布在内存中,它们应该与代码背道而驰。

解决方法

虽然不完整并且需要一些更改,但我想我现在已经想出了一个有效的解决方案。

我像以前一样编译,但使用稍微不同的命令链接:g++ -T lnkscrpt.txt -O3 -nostdlib Loader.o-shared 只是让链接器抱怨缺少 DllMain)。

lnkscrpt.txt 是一个 ld 链接描述文件 (https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_5.html#SEC5),如下所示:

SECTIONS
{
    . = 0x00;
    .bss : { *(.bss) }
    .text : { *(.text) }
    .data : { *(.rdata) *(.data) }
    /DISCARD/ : {*(*)}
}

这会保留我想要的顺序并丢弃任何其他默认部分。

最后我运行 objcopy -O binary -j .* --set-section-flags .bss=alloc,load,contents a.exe 将其余部分复制到平面二进制文件中。 --set-section-flags 选项只是确保二进制文件包含为 .bss 部分分配的空间。

这会生成一个 128 字节的二进制文件,其布局方式与我的自定义程序集版本完全相同,使用正确的偏移量,并且不包含任何不需要的数据。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。