gpt4 book ai didi

objective-c - 通过 -sectcreate __TEXT 读取链接到可执行文件的数据(嵌入式 plist)

转载 作者:太空狗 更新时间:2023-10-30 03:14:04 25 4
gpt4 key购买 nike

我正在使用 -sectcreate __TEXT 链接器标志将可执行文件与 plist 链接起来。这样做的原因主要是使用了 SMJobBless() 方法。但我需要阅读从另一个应用程序链接的 plist。这只是因为我需要在 10.5 系统上安装相同的特权应用程序,而我不能在 10.5 上使用 SMJobBless()。

我如何使用 Objective-C 读取这个链接的 plist,以便我自己可以将它复制到/Library/LaunchDaemons/?

最佳答案

工具

您可以使用 otool(1) 转储包含嵌入式 plist 的部分的内容:

otool -s __TEXT __info_plist /path/to/executable

然后将其输出通过管道传递给 xxd(1) 以获得相应的 ASCII 表示形式:

otool -X -s __TEXT __info_plist /path/to/executable | xxd -r

然而,otool is only available in machines where Xcode has been installed .

NSBundle

对于程序需要读取自己嵌入的plist的情况,可以使用NSBundle:

id someValue = [[NSBundle mainBundle] objectForInfoDictionaryKey:someKey];

马赫-O

对于程序需要读取任意文件的嵌入式plist而不借助otool的情况,程序可以解析文件中的Mach-O信息并提取其嵌入式plist,如下所示:

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <mach-o/loader.h>
#include <sys/mman.h>
#include <sys/stat.h>
#import <Foundation/Foundation.h>

id embeddedPlist(NSURL *executableURL) {
id plist = nil;
int fd;
struct stat stat_buf;
size_t size;

char *addr = NULL;
char *start_addr = NULL;
struct mach_header_64 *mh = NULL;
struct load_command *lc = NULL;
struct segment_command_64 *sc = NULL;
struct section_64 *sect = NULL;

// Open the file and get its size
fd = open([[executableURL path] UTF8String], O_RDONLY);
if (fd == -1) goto END_FUNCTION;
if (fstat(fd, &stat_buf) == -1) goto END_FILE;
size = stat_buf.st_size;

// Map the file to memory
addr = start_addr = mmap(0, size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
if (addr == MAP_FAILED) goto END_FILE;

// The first bytes are the Mach-O header
mh = (struct mach_header_64 *)addr;

// Load commands follow the header
addr += sizeof(struct mach_header_64);

for (int icmd = 0; icmd < mh->ncmds; icmd++) {
lc = (struct load_command *)addr;

if (lc->cmd != LC_SEGMENT_64) {
addr += lc->cmdsize;
continue;
}

if (lc->cmdsize == 0) continue;

// It's a 64-bit segment
sc = (struct segment_command_64 *)addr;

if (strcmp("__TEXT", sc->segname) != 0 || sc->nsects == 0) {
addr += lc->cmdsize;
continue;
}

// It's the __TEXT segment and it has at least one section
// Section data follows segment data
addr += sizeof(struct segment_command_64);
for (int isect = 0; isect < sc->nsects; isect++) {
sect = (struct section_64 *)addr;
addr += sizeof(struct section_64);

if (strcmp("__info_plist", sect->sectname) != 0) continue;

// It's the __TEXT __info_plist section
NSData *data = [NSData dataWithBytes:(start_addr + sect->offset)
length:sect->size];
plist = [NSPropertyListSerialization propertyListWithData:data
options:NSPropertyListImmutable
format:NULL
error:NULL];
goto END_MMAP;
}
}

END_MMAP:
munmap(addr, size);

END_FILE:
close(fd);

END_FUNCTION:
return plist;
}

和:

NSURL *url = [NSURL fileURLWithPath:@"/path/to/some/file"];
id plist = embeddedPlist(url);
if ([plist isKindOfClass:[NSDictionary class]]) {
NSDictionary *info = plist;
id someValue = [info objectForKey:someKey];
}

请注意 embeddedPlist() 有一些限制:它希望文件是一个薄的 Mach-O 文件(即,它会与非 Mach-O 文件一起崩溃并且无法工作包含例如 i386 和 x86_64 Mach-O 数据的胖文件);它只适用于 x86_64 文件;它不会报告错误。

我继续发布了 BVPlistExtractor根据麻省理工学院的许可。它检测文件是否确实是瘦 Mach-O 文件或胖/通用文件,并适用于 i386 和 x86_64。

关于objective-c - 通过 -sectcreate __TEXT 读取链接到可执行文件的数据(嵌入式 plist),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7780789/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com