编译二进制文件以链接OSX

Sat*_*pal 8 macos dylib binary-data ld

我正在尝试将二进制文件编译为MACH_O对象文件,以便将其链接到dylib.dylib是用c/c ++编写的.

在linux上使用以下命令:ld -r -b binary -o foo.o foo.bin

我在OSX上尝试了各种选项,但无济于事:

ld -r foo.bin -o foo.o
gives:
ld: warning: -arch not specified
ld: warning: ignoring file foo.bin, file was built for unsupported file format which is not the architecture being linked (x86_64)
Run Code Online (Sandbox Code Playgroud)

创建一个空的.o文件

ld -arch x86_64 -r foo.bin -o foo.o 
ld: warning: ignoring file foo.bin, file was built for unsupported file format which is not the architecture being linked (x86_64)
Run Code Online (Sandbox Code Playgroud)

再次创建空的.o文件.用nm检查文件给出:nm foo.o nm:没有名称列表

二进制文件实际上是将下载到外部设备的固件.

谢谢你的期待

Llo*_*eki 9

这是与Linux链接器命令最接近的转换,用于使用OSX链接器执行二进制嵌入:

touch stub.c
gcc -o stub.o -c stub.c
ld -r -o foo.o -sectcreate binary foo_bin foo.bin stub.o
Run Code Online (Sandbox Code Playgroud)

foo.bin将存储在对象的段binary,节foo_bin(两个名称都是任意的,但选择模仿Linux上的ELF的GNU ld)中foo.o.

stub是必要的,因为ld拒绝只创建自定义细分/部分.如果直接链接到真实的代码对象,则不需要它.

要从该部分获取数据,请使用getsectbyname(struct in defined in mach-o/loader.h):

#include <mach-o/getsect.h>
const struct section_64 *sect = getsectbyname("binary", "foo_bin");
char *buffer = calloc(1, sect->size+1);
memcpy(buffer, sect->addr, sect->size); // whatever
Run Code Online (Sandbox Code Playgroud)

或getsectdata:

#include <mach-o/getsect.h>
size_t size;
char *data = getsectdata("binary", "foo_bin", &size);
char *buffer = calloc(1, size+1);
memcpy(buffer, data, size); // whatever
Run Code Online (Sandbox Code Playgroud)

(我用它来存储文本数据,因此通过calloc将大小+ 1加上blob复制归零进行字符串化)

警告:自10.7以来,ASLR变得越来越强大并且getsect*功能混乱,导致了段错误.set disable-aslr off之前在GDB中run在调试条件下重现EXC_BAD_ACCESS(SIGSEGV).人们不得不跳过过度的箍来找到真正的地址并让它重新开始工作.

一个简单的解决方法是获取偏移量和大小,打开二进制文件并直接从磁盘读取数据.这是一个工作示例:

// main.c, build with gcc -o main main.c foo.o
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <mach-o/getsect.h>

int main() {
    // finding the filename of the running binary is left as an exercise to the reader
    char *filename = "main";

    const struct section_64 *sect = getsectbyname("binary", "foo_bin");
    if (sect == NULL) {
        exit(1);
    }

    char *buffer = calloc(1, sect->size+1);
    int fd = open(filename, O_RDONLY);
    if (fd < 0) {
        exit(1);
    }
    lseek(fd, sect->offset, SEEK_SET);
    if (read(fd, buffer, sect->size) != sect->size) {
        close(fd);
        exit(1);
    }

    printf("%s", buffer);
}
Run Code Online (Sandbox Code Playgroud)

  • 看起来有一些更新的`getsection*` 版本的`getsect*` 函数可以使用并且不受ASLR 问题的影响。比必须读取原始二进制文件要好一些。 (2认同)