otool
आप (1) एम्बेडेड plist युक्त खंड की सामग्री को डंप करने के लिए otool उपयोग कर सकते हैं:
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];
मच-ओ
मामलों के लिए जहां एक कार्यक्रम की जरूरत है otool का उपयोग किए बिना एक मनमानी फ़ाइल के एम्बेडेड प्लेस्ट को पढ़ें, प्रोग्राम फ़ाइल में मैच-ओ जानकारी को पार्स कर सकता है और इसके एम्बेडेड प्लिस्ट को निम्नानुसार निकाला जा सकता है:
#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()
कुछ सीमाएँ हैं वसा फाइलों के साथ काम करें, उदाहरण के लिए, i386 और x86_64 मैक-ओ डेटा दोनों); यह केवल x86_64 फ़ाइलों के साथ काम करता है; यह त्रुटियों की रिपोर्ट नहीं करता है।
मैं आगे बढ़ गया और एमआईटी लाइसेंस के तहत BVPlistExtractor जारी किया। यह पता लगाता है कि फ़ाइल वास्तव में एक पतली मैच-ओ फ़ाइल या एक वसा/सार्वभौमिक फ़ाइल है, और i386 और x86_64 दोनों के साथ काम करती है।
यदि आपने अद्यतन उत्तर नहीं देखा है, तो मैंने [BVPlistExtractor] (https://github.com/bavarious/BVPlistExtractor) जारी किया है। –
@ बेवकूफ धन्यवाद! BVPlistExtractor सही है। – ETroll