通过-sectcreate __TEXT读取链接到可执行文件的数据(嵌入式plist) [英] Reading data (embedded plist) linked to executable through -sectcreate __TEXT

查看:157
本文介绍了通过-sectcreate __TEXT读取链接到可执行文件的数据(嵌入式plist)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am linking a executable with a plist using -sectcreate __TEXT linker flags. Reason for this is mainly to use the SMJobBless() method. But I need to read plist linked from another application. This is only because I need to install the same privileged application on a 10.5 system and I can’t use SMJobBless() on 10.5.

如何使用Objective-C阅读此链接的plist,以便将其复制到/Library/LaunchDaemons/我自己?

How do I read this linked plist using Objective-C so I can copy it to /Library/LaunchDaemons/ myself?

推荐答案

otool

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

otool

You can use otool(1) to dump the contents of the section containing the embedded plist:

otool -s __TEXT __info_plist /path/to/executable

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

and then pipe its output to xxd(1) in order to obtain the corresponding ASCII representation:

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

但是,工具仅在已安装Xcode的计算机中可用.

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

For the cases where a program needs to read its own embedded plist, NSBundle can be used:

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

Mach-O

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

Mach-O

For the cases where a program needs to read the embedded plist of an arbitrary file without resorting to otool, the program can parse the Mach-O information in the file and extract its embedded plist as follows:

#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文件;它不会报告错误.

Note that embeddedPlist() has some limitations: it expects the file to be a thin Mach-O file (i.e., it will crash with non-Mach-O files and it won’t work with fat files containing, for example, both i386 and x86_64 Mach-O data); it only works with x86_64 files; it doesn’t report errors.

我继续前进,并根据MIT许可证发布了 BVPlistExtractor .它可以检测文件确实是瘦Mach-O文件还是胖/通用文件,并且可以与i386和x86_64一起使用.

I went ahead and released BVPlistExtractor under the MIT licence. It detects whether the file is indeed a thin Mach-O file or a fat/universal file, and works with both i386 and x86_64.

这篇关于通过-sectcreate __TEXT读取链接到可执行文件的数据(嵌入式plist)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆