2017-10-27 6 views
0

私は、メモリマッピングmmapを使用して、基本的なnmを実装するプロジェクトに取り組んでいます。私は、コードを使用して、64ビットのバイナリを解析することができた:ユニバーサル/ファットバイナリファイルの解析

void  handle_64(char *ptr) 
{ 
    int      ncmds; 
    struct mach_header_64 *header; 
    struct load_command  *lc; 
    struct symtab_command *sym; 
    int      i; 

    i = 0; 
    header = (struct mach_header_64 *)ptr; 
    ncmds = header->ncmds; 
    lc = (void *)ptr + sizeof(*header); 
    while (i < ncmds) 
    { 
     if (lc->cmd == LC_SYMTAB) 
     { 
      sym = (struct symtab_command *)lc; 
      build_list (sym->nsyms, sym->symoff, sym->stroff, ptr); 
      break; 
     } 
     lc = (void *) lc + lc->cmdsize; 
     i++; 
    } 
} 

このlinkによれば、マッハ - Oおよび脂肪バイナリの唯一の違いは、その上fat_header構造体であるが、単に

とスキップ
lc = (void *)ptr + sizeof(struct fat_header) + sizeof(struct mach_header_64); 

私はload_command領域(segfault)に移動しません。 fat/universalバイナリのloadコマンドにアクセスするにはどうしたらいいですか?

私はMacOS High Sierraを実行している64ビットMacで作業しています。ありがとうございました。

答えて

1

あなたが持っている複数の問題:

  • あなたが呼び出し、「脂肪ヘッダ」へリンクしているブログがちょうどstruct fat_header以上のは何ですか。
  • はどこにもそれはマッハ-Oヘッダがとても太った直後にそれらを入れて、それが(通常はマッハ・O・セグメントは、ページ全体に整列させたいだけどこか後、脂肪ヘッダの後すぐに追従することが保証されていませんヘッダーが機能しない可能性もあります)。
  • 64ビットスライスがバイナリの最初のものになることは保証されていません。そのすべてを考慮すると

、あなたあなたが有用な結果を得ることのいずれかの希望をしたい場合は(とそれを無視しない)脂肪ヘッダを解析する必要が。次のように

さて、fat_headerが定義されている:第一に、私は通常、脂肪のバイナリを参照魔法の値はそう述べたコメントにもかかわらず、FAT_CIGAMはなくFAT_MAGIC

struct fat_header { 
    uint32_t magic;  /* FAT_MAGIC or FAT_MAGIC_64 */ 
    uint32_t nfat_arch; /* number of structs that follow */ 
}; 

ある

(ただし世話をする - これがあることを意味しますfatヘッダーの整数はリトルエンディアンではなくビッグエンディアンです!)。

struct fat_arch { 
    cpu_type_t cputype; /* cpu specifier (int) */ 
    cpu_subtype_t cpusubtype; /* machine specifier (int) */ 
    uint32_t offset;  /* file offset to this object file */ 
    uint32_t size;  /* size of this object file */ 
    uint32_t align;  /* alignment as a power of 2 */ 
}; 

これは「薄い」マッハ-Oヘッダがその負荷コマンドで行うのと同じように動作します:しかし、第二に、特定の構造体、すなわち、このヘッダに続くことを示しています。 fat_arch.offsetは、ファイルの先頭からのオフセットです。それに続いて、それが脂肪マッハ-Oのすべてのスライス印刷するには非常に簡単です:それはbufの長さを知らないと上記の関数は、不完全であることを

#include <stdio.h> 
#include <mach-o/fat.h> 

#define SWAP32(x) ((((x) & 0xff000000) >> 24) | (((x) & 0xff0000) >> 8) | (((x) & 0xff00) << 8) | (((x) & 0xff) << 24)) 

void print_fat_header(void *buf) 
{ 
    struct fat_header *hdr = buf; 
    if(hdr->magic != FAT_CIGAM) 
    { 
     fprintf(stderr, "bad magic: %08x\n", hdr->magic); 
     return; 
    } 
    struct fat_arch *archs = (struct fat_arch*)(hdr + 1); 
    uint32_t num = SWAP32(hdr->nfat_arch); 
    for(size_t i = 0; i < num; ++i) 
    { 
     const char *name = "unknown"; 
     switch(SWAP32(archs[i].cputype)) 
     { 
      case CPU_TYPE_I386:  name = "i386";  break; 
      case CPU_TYPE_X86_64: name = "x86_64"; break; 
      case CPU_TYPE_ARM:  name = "arm";  break; 
      case CPU_TYPE_ARM64: name = "arm64";  break; 
     } 
     uint32_t off = SWAP32(archs[i].offset); 
     uint32_t magic = *(uint32_t*)((uintptr_t)buf + off); 
     printf("%08x-%08x: %-8s (magic %8x)\n", off, off + SWAP32(archs[i].size), name, magic); 
    } 
} 

注ので、できないと任意のアクセスチェックしませんそれに対する記憶。深刻な実装では、与えられたバッファの外側を決して読み取らないようにする必要があります。あなたのコードがsegfaultedという事実は、十分なデータsanitisationをしていないことを示唆しています。