2011-10-15 20 views
12

के माध्यम से निष्पादन योग्य से जुड़े डेटा (एम्बेडेड प्लेस्ट) को पढ़ना मैं -sectcreate __TEXT लिंकर झंडे का उपयोग करके एक प्लेस्ट के साथ निष्पादन योग्य को जोड़ रहा हूं। इसके लिए मुख्य रूप से SMJobBless() विधि का उपयोग करना है। लेकिन मुझे किसी अन्य एप्लिकेशन से जुड़े प्लिस्ट को पढ़ने की जरूरत है। यह केवल इसलिए है क्योंकि मुझे 10.5 सिस्टम पर एक ही विशेषाधिकार प्राप्त एप्लिकेशन इंस्टॉल करने की आवश्यकता है और मैं 10.5 पर SMJobBless() का उपयोग नहीं कर सकता।निष्पादन योग्य __TEXT

मैं उद्देश्य-सी का उपयोग करके इस लिंक किए गए प्लेस्ट को कैसे पढ़ूं ताकि मैं इसे/लाइब्रेरी/लॉन्चडेमन्स/स्वयं में कॉपी कर सकूं?

+1

यदि आपने अद्यतन उत्तर नहीं देखा है, तो मैंने [BVPlistExtractor] (https://github.com/bavarious/BVPlistExtractor) जारी किया है। –

+0

@ बेवकूफ धन्यवाद! BVPlistExtractor सही है। – ETroll

उत्तर

18

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 दोनों के साथ काम करती है।

+0

क्या होता है जब आप निष्पादन योग्य फ़ाइल के लिए एनएसबंडल बनाते हैं (जैसा कि आपके स्वयं के निष्पादन योग्य के लिए मुख्य "बंडल" प्राप्त करने के विपरीत है)? –

+0

@ पीटर '+ [एनएसबंडल बंडल के साथ ...:] स्टैंडअलोन निष्पादन योग्य फ़ाइलों के लिए 'रिटर्न' शून्य '। –

+0

मैंने एक्सएक्सडी को पाइप करते समय -X विकल्प जोड़ने के लिए अपनी पोस्ट अपडेट की है क्योंकि हेडर को हटाए बिना आपको दूषित डेटा मिलेगा जिसे आप तुरंत नोटिस नहीं कर सकते हैं (यानी '') –

12

इसके लिए कोरफाउंडेशन फ़ंक्शन है: CFBundleCopyInfoDictionaryForURL()। प्रलेखन से:

एक निर्देशिका यूआरएल के लिए, यह CFBundleCopyInfoDictionaryInDirectory के बराबर है। एक अनबंडल एप्लिकेशन का प्रतिनिधित्व करने वाले एक सादे फ़ाइल यूआरएल के लिए, यह फ़ंक्शन फ़ाइल के ((मैक-ओ फ़ाइल के लिए) या plst संसाधन से (__TEXT, __info_plist) अनुभाग से या किसी भी जानकारी शब्दकोश को पढ़ने का प्रयास करेगा।

यह मैक ओएस एक्स v10.2 और बाद में उपलब्ध है।आप कोको में उपयोग करते हैं आप (बशर्ते आप बंडल के लिए एक (NSURL*)url है) कर सकते हैं:

NSDictionary* infoPlist = [ (NSDictionary*) CFBundleCopyInfoDictionaryForURL((CFURLRef) url) autorelease]; 
+0

अफसोस की बात है, यह 10.11.5 पर मेरे लिए काम नहीं करता है। ऊपर एम्बेडेड फ़ाइल() फ़ंक्शन किया (unmodified) – kainjow

3

एक बहुत सरल दृष्टिकोण:

#include <mach-o/getsect.h> 

unsigned long *len; 
char *data = getsectdata("__TEXT", "__info_plist"); 

आदमी getsectdata। विभिन्न टुकड़ों (वर्तमान निष्पादन योग्य, मनमाने ढंग से निष्पादन योग्य, ढांचे, आदि) तक पहुंचने के कई उदाहरण हैं।

+0

'getsectdata()' हाल ही में सिस्टम पर ठीक से काम नहीं कर रहा है या जाहिर है, जाहिर है, यह एएसएलआर या कुछ के लिए जिम्मेदार नहीं है। [यह सवाल] (http: // st ackoverflow.com/q/28978788/291280) 'getsectiondata()' का उपयोग करता है, जो उसके लिए खाता है। – Isaac

संबंधित मुद्दे