1 /* ldid - (Mach-O) Link-Loader Identity Editor 
   2  * Copyright (C) 2007-2015  Jay Freeman (saurik) 
   5 /* GNU Affero General Public License, Version 3 {{{ */ 
   7  * This program is free software: you can redistribute it and/or modify 
   8  * it under the terms of the GNU Affero General Public License as published by 
   9  * the Free Software Foundation, either version 3 of the License, or 
  10  * (at your option) any later version. 
  12  * This program is distributed in the hope that it will be useful, 
  13  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
  14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  15  * GNU Affero General Public License for more details. 
  17  * You should have received a copy of the GNU Affero General Public License 
  18  * along with this program.  If not, see <http://www.gnu.org/licenses/>. 
  40 #include <openssl/sha.h> 
  42 #include <plist/plist.h> 
  44 #define _assert___(line) \ 
  46 #define _assert__(line) \ 
  49     throw __FILE__ "(" _assert__(__LINE__) "): _assert(" e ")" 
  51 #define _assert(expr) \ 
  53         fprintf(stderr, "%s(%u): _assert(%s); errno=%u\n", __FILE__, __LINE__, #expr, errno); \ 
  57 #define _syscall(expr) ({ \ 
  58     __typeof__(expr) _value; \ 
  59     do if ((long) (_value = (expr)) != -1) \ 
  61     else switch (errno) { \ 
  71     fprintf(stderr, "_trace(%s:%u): %s\n", __FILE__, __LINE__, __FUNCTION__) 
  77     __attribute__((packed)) 
  79 template <typename Type_
> 
  81     typedef typename 
Type_::const_iterator Result
; 
  84 #define _foreach(item, list) \ 
  85     for (bool _stop(true); _stop; ) \ 
  86         for (const __typeof__(list) &_list = (list); _stop; _stop = false) \ 
  87             for (Iterator_<__typeof__(list)>::Result _item = _list.begin(); _item != _list.end(); ++_item) \ 
  88                 for (bool _suck(true); _suck; _suck = false) \ 
  89                     for (const __typeof__(*_item) &item = *_item; _suck; _suck = false) 
  96 #define FAT_MAGIC 0xcafebabe 
  97 #define FAT_CIGAM 0xbebafeca 
 117 #define MH_MAGIC 0xfeedface 
 118 #define MH_CIGAM 0xcefaedfe 
 120 #define MH_MAGIC_64 0xfeedfacf 
 121 #define MH_CIGAM_64 0xcffaedfe 
 123 #define MH_DYLDLINK   0x4 
 125 #define MH_OBJECT     0x1 
 126 #define MH_EXECUTE    0x2 
 128 #define MH_BUNDLE     0x8 
 129 #define MH_DYLIB_STUB 0x9 
 131 struct load_command 
{ 
 136 #define LC_REQ_DYLD           uint32_t(0x80000000) 
 138 #define LC_SEGMENT            uint32_t(0x01) 
 139 #define LC_SYMTAB             uint32_t(0x02) 
 140 #define LC_DYSYMTAB           uint32_t(0x0b) 
 141 #define LC_LOAD_DYLIB         uint32_t(0x0c) 
 142 #define LC_ID_DYLIB           uint32_t(0x0d) 
 143 #define LC_SEGMENT_64         uint32_t(0x19) 
 144 #define LC_UUID               uint32_t(0x1b) 
 145 #define LC_CODE_SIGNATURE     uint32_t(0x1d) 
 146 #define LC_SEGMENT_SPLIT_INFO uint32_t(0x1e) 
 147 #define LC_REEXPORT_DYLIB     uint32_t(0x1f | LC_REQ_DYLD) 
 148 #define LC_ENCRYPTION_INFO    uint32_t(0x21) 
 149 #define LC_DYLD_INFO          uint32_t(0x22) 
 150 #define LC_DYLD_INFO_ONLY     uint32_t(0x22 | LC_REQ_DYLD) 
 151 #define LC_ENCRYPTION_INFO_64 uint32_t(0x2c) 
 156     uint32_t current_version
; 
 157     uint32_t compatibility_version
; 
 160 struct dylib_command 
{ 
 166 struct uuid_command 
{ 
 172 struct symtab_command 
{ 
 181 struct dyld_info_command 
{ 
 185     uint32_t rebase_size
; 
 188     uint32_t weak_bind_off
; 
 189     uint32_t weak_bind_size
; 
 190     uint32_t lazy_bind_off
; 
 191     uint32_t lazy_bind_size
; 
 193     uint32_t export_size
; 
 196 struct dysymtab_command 
{ 
 209     uint32_t extrefsymoff
; 
 210     uint32_t nextrefsyms
; 
 211     uint32_t indirectsymoff
; 
 212     uint32_t nindirectsyms
; 
 219 struct dylib_table_of_contents 
{ 
 220     uint32_t symbol_index
; 
 221     uint32_t module_index
; 
 224 struct dylib_module 
{ 
 225     uint32_t module_name
; 
 234     uint32_t iinit_iterm
; 
 235     uint32_t ninit_nterm
; 
 236     uint32_t objc_module_info_addr
; 
 237     uint32_t objc_module_info_size
; 
 240 struct dylib_reference 
{ 
 245 struct relocation_info 
{ 
 247     uint32_t r_symbolnum
:24; 
 266 struct segment_command 
{ 
 280 struct segment_command_64 
{ 
 322 struct linkedit_data_command 
{ 
 329 struct encryption_info_command 
{ 
 337 #define BIND_OPCODE_MASK                             0xf0 
 338 #define BIND_IMMEDIATE_MASK                          0x0f 
 339 #define BIND_OPCODE_DONE                             0x00 
 340 #define BIND_OPCODE_SET_DYLIB_ORDINAL_IMM            0x10 
 341 #define BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB           0x20 
 342 #define BIND_OPCODE_SET_DYLIB_SPECIAL_IMM            0x30 
 343 #define BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM    0x40 
 344 #define BIND_OPCODE_SET_TYPE_IMM                     0x50 
 345 #define BIND_OPCODE_SET_ADDEND_SLEB                  0x60 
 346 #define BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB      0x70 
 347 #define BIND_OPCODE_ADD_ADDR_ULEB                    0x80 
 348 #define BIND_OPCODE_DO_BIND                          0x90 
 349 #define BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB            0xa0 
 350 #define BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED      0xb0 
 351 #define BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB 0xc0 
 353 inline void get(std::streambuf 
&stream
, void *data
, size_t size
) { 
 354     _assert(stream
.sgetn(static_cast<char *>(data
), size
) == size
); 
 357 inline void put(std::streambuf 
&stream
, const void *data
, size_t size
) { 
 358     _assert(stream
.sputn(static_cast<const char *>(data
), size
) == size
); 
 361 inline void pad(std::streambuf 
&stream
, size_t size
) { 
 363     memset(padding
, 0, size
); 
 364     put(stream
, padding
, size
); 
 367 template <typename Type_
> 
 368 Type_ 
Align(Type_ value
, size_t align
) { 
 375 uint16_t Swap_(uint16_t value
) { 
 377         ((value 
>>  8) & 0x00ff) | 
 378         ((value 
<<  8) & 0xff00); 
 381 uint32_t Swap_(uint32_t value
) { 
 382     value 
= ((value 
>>  8) & 0x00ff00ff) | 
 383             ((value 
<<  8) & 0xff00ff00); 
 384     value 
= ((value 
>> 16) & 0x0000ffff) | 
 385             ((value 
<< 16) & 0xffff0000); 
 389 uint64_t Swap_(uint64_t value
) { 
 390     value 
= (value 
& 0x00000000ffffffff) << 32 | (value 
& 0xffffffff00000000) >> 32; 
 391     value 
= (value 
& 0x0000ffff0000ffff) << 16 | (value 
& 0xffff0000ffff0000) >> 16; 
 392     value 
= (value 
& 0x00ff00ff00ff00ff) << 8  | (value 
& 0xff00ff00ff00ff00) >> 8; 
 396 int16_t Swap_(int16_t value
) { 
 397     return Swap_(static_cast<uint16_t>(value
)); 
 400 int32_t Swap_(int32_t value
) { 
 401     return Swap_(static_cast<uint32_t>(value
)); 
 404 int64_t Swap_(int64_t value
) { 
 405     return Swap_(static_cast<uint64_t>(value
)); 
 410 uint16_t Swap(uint16_t value
) { 
 411     return little_ 
? Swap_(value
) : value
; 
 414 uint32_t Swap(uint32_t value
) { 
 415     return little_ 
? Swap_(value
) : value
; 
 418 uint64_t Swap(uint64_t value
) { 
 419     return little_ 
? Swap_(value
) : value
; 
 422 int16_t Swap(int16_t value
) { 
 423     return Swap(static_cast<uint16_t>(value
)); 
 426 int32_t Swap(int32_t value
) { 
 427     return Swap(static_cast<uint32_t>(value
)); 
 430 int64_t Swap(int64_t value
) { 
 431     return Swap(static_cast<uint64_t>(value
)); 
 434 template <typename Target_
> 
 447     Swapped(bool swapped
) : 
 452     template <typename Type_
> 
 453     Type_ 
Swap(Type_ value
) const { 
 454         return swapped_ 
? Swap_(value
) : value
; 
 466     Data(void *base
, size_t size
) : 
 472     void *GetBase() const { 
 476     size_t GetSize() const { 
 487     struct mach_header 
*mach_header_
; 
 488     struct load_command 
*load_command_
; 
 491     MachHeader(void *base
, size_t size
) : 
 494         mach_header_ 
= (mach_header 
*) base
; 
 496         switch (Swap(mach_header_
->magic
)) { 
 498                 swapped_ 
= !swapped_
; 
 504                 swapped_ 
= !swapped_
; 
 513         void *post 
= mach_header_ 
+ 1; 
 515             post 
= (uint32_t *) post 
+ 1; 
 516         load_command_ 
= (struct load_command 
*) post
; 
 519             Swap(mach_header_
->filetype
) == MH_EXECUTE 
|| 
 520             Swap(mach_header_
->filetype
) == MH_DYLIB 
|| 
 521             Swap(mach_header_
->filetype
) == MH_BUNDLE
 
 525     bool Bits64() const { 
 529     struct mach_header 
*operator ->() const { 
 533     operator struct mach_header 
*() const { 
 537     uint32_t GetCPUType() const { 
 538         return Swap(mach_header_
->cputype
); 
 541     uint32_t GetCPUSubtype() const { 
 542         return Swap(mach_header_
->cpusubtype
) & 0xff; 
 545     struct load_command 
*GetLoadCommand() const { 
 546         return load_command_
; 
 549     std::vector
<struct load_command 
*> GetLoadCommands() const { 
 550         std::vector
<struct load_command 
*> load_commands
; 
 552         struct load_command 
*load_command 
= load_command_
; 
 553         for (uint32_t cmd 
= 0; cmd 
!= Swap(mach_header_
->ncmds
); ++cmd
) { 
 554             load_commands
.push_back(load_command
); 
 555             load_command 
= (struct load_command 
*) ((uint8_t *) load_command 
+ Swap(load_command
->cmdsize
)); 
 558         return load_commands
; 
 561     std::vector
<segment_command 
*> GetSegments(const char *segment_name
) const { 
 562         std::vector
<struct segment_command 
*> segment_commands
; 
 564         _foreach (load_command
, GetLoadCommands()) { 
 565             if (Swap(load_command
->cmd
) == LC_SEGMENT
) { 
 566                 segment_command 
*segment_command 
= reinterpret_cast<struct segment_command 
*>(load_command
); 
 567                 if (strncmp(segment_command
->segname
, segment_name
, 16) == 0) 
 568                     segment_commands
.push_back(segment_command
); 
 572         return segment_commands
; 
 575     std::vector
<segment_command_64 
*> GetSegments64(const char *segment_name
) const { 
 576         std::vector
<struct segment_command_64 
*> segment_commands
; 
 578         _foreach (load_command
, GetLoadCommands()) { 
 579             if (Swap(load_command
->cmd
) == LC_SEGMENT_64
) { 
 580                 segment_command_64 
*segment_command 
= reinterpret_cast<struct segment_command_64 
*>(load_command
); 
 581                 if (strncmp(segment_command
->segname
, segment_name
, 16) == 0) 
 582                     segment_commands
.push_back(segment_command
); 
 586         return segment_commands
; 
 589     std::vector
<section 
*> GetSections(const char *segment_name
, const char *section_name
) const { 
 590         std::vector
<section 
*> sections
; 
 592         _foreach (segment
, GetSegments(segment_name
)) { 
 593             section 
*section 
= (struct section 
*) (segment 
+ 1); 
 596             for (sect 
= 0; sect 
!= Swap(segment
->nsects
); ++sect
) { 
 597                 if (strncmp(section
->sectname
, section_name
, 16) == 0) 
 598                     sections
.push_back(section
); 
 606     template <typename Target_
> 
 607     Pointer
<Target_
> GetPointer(uint32_t address
, const char *segment_name 
= NULL
) const { 
 608         load_command 
*load_command 
= (struct load_command 
*) (mach_header_ 
+ 1); 
 611         for (cmd 
= 0; cmd 
!= Swap(mach_header_
->ncmds
); ++cmd
) { 
 612             if (Swap(load_command
->cmd
) == LC_SEGMENT
) { 
 613                 segment_command 
*segment_command 
= (struct segment_command 
*) load_command
; 
 614                 if (segment_name 
!= NULL 
&& strncmp(segment_command
->segname
, segment_name
, 16) != 0) 
 617                 section 
*sections 
= (struct section 
*) (segment_command 
+ 1); 
 620                 for (sect 
= 0; sect 
!= Swap(segment_command
->nsects
); ++sect
) { 
 621                     section 
*section 
= §ions
[sect
]; 
 622                     //printf("%s %u %p %p %u\n", segment_command->segname, sect, address, section->addr, section->size); 
 623                     if (address 
>= Swap(section
->addr
) && address 
< Swap(section
->addr
) + Swap(section
->size
)) { 
 624                         //printf("0x%.8x %s\n", address, segment_command->segname); 
 625                         return Pointer
<Target_
>(this, reinterpret_cast<Target_ 
*>(address 
- Swap(section
->addr
) + Swap(section
->offset
) + (char *) mach_header_
)); 
 631             load_command 
= (struct load_command 
*) ((char *) load_command 
+ Swap(load_command
->cmdsize
)); 
 634         return Pointer
<Target_
>(this); 
 637     template <typename Target_
> 
 638     Pointer
<Target_
> GetOffset(uint32_t offset
) { 
 639         return Pointer
<Target_
>(this, reinterpret_cast<Target_ 
*>(offset 
+ (uint8_t *) mach_header_
)); 
 643 class FatMachHeader 
: 
 650     FatMachHeader(void *base
, size_t size
, fat_arch 
*fat_arch
) : 
 651         MachHeader(base
, size
), 
 656     fat_arch 
*GetFatArch() const { 
 665     fat_header 
*fat_header_
; 
 666     std::vector
<FatMachHeader
> mach_headers_
; 
 669     FatHeader(void *base
, size_t size
) : 
 672         fat_header_ 
= reinterpret_cast<struct fat_header 
*>(base
); 
 674         if (Swap(fat_header_
->magic
) == FAT_CIGAM
) { 
 675             swapped_ 
= !swapped_
; 
 677         } else if (Swap(fat_header_
->magic
) != FAT_MAGIC
) { 
 679             mach_headers_
.push_back(FatMachHeader(base
, size
, NULL
)); 
 681             size_t fat_narch 
= Swap(fat_header_
->nfat_arch
); 
 682             fat_arch 
*fat_arch 
= reinterpret_cast<struct fat_arch 
*>(fat_header_ 
+ 1); 
 684             for (arch 
= 0; arch 
!= fat_narch
; ++arch
) { 
 685                 uint32_t arch_offset 
= Swap(fat_arch
->offset
); 
 686                 uint32_t arch_size 
= Swap(fat_arch
->size
); 
 687                 mach_headers_
.push_back(FatMachHeader((uint8_t *) base 
+ arch_offset
, arch_size
, fat_arch
)); 
 693     std::vector
<FatMachHeader
> &GetMachHeaders() { 
 694         return mach_headers_
; 
 698         return fat_header_ 
!= NULL
; 
 701     struct fat_header 
*operator ->() const { 
 705     operator struct fat_header 
*() const { 
 710 template <typename Target_
> 
 713     const MachHeader 
*framework_
; 
 714     const Target_ 
*pointer_
; 
 717     Pointer(const MachHeader 
*framework 
= NULL
, const Target_ 
*pointer 
= NULL
) : 
 718         framework_(framework
), 
 723     operator const Target_ 
*() const { 
 727     const Target_ 
*operator ->() const { 
 731     Pointer
<Target_
> &operator ++() { 
 736     template <typename Value_
> 
 737     Value_ 
Swap(Value_ value
) { 
 738         return framework_
->Swap(value
); 
 742 #define CSMAGIC_REQUIREMENT            uint32_t(0xfade0c00) 
 743 #define CSMAGIC_REQUIREMENTS           uint32_t(0xfade0c01) 
 744 #define CSMAGIC_CODEDIRECTORY          uint32_t(0xfade0c02) 
 745 #define CSMAGIC_EMBEDDED_SIGNATURE     uint32_t(0xfade0cc0) 
 746 #define CSMAGIC_EMBEDDED_SIGNATURE_OLD uint32_t(0xfade0b02) 
 747 #define CSMAGIC_EMBEDDED_ENTITLEMENTS  uint32_t(0xfade7171) 
 748 #define CSMAGIC_DETACHED_SIGNATURE     uint32_t(0xfade0cc1) 
 749 #define CSMAGIC_BLOBWRAPPER            uint32_t(0xfade0b01) 
 751 #define CSSLOT_CODEDIRECTORY uint32_t(0x00000) 
 752 #define CSSLOT_INFOSLOT      uint32_t(0x00001) 
 753 #define CSSLOT_REQUIREMENTS  uint32_t(0x00002) 
 754 #define CSSLOT_RESOURCEDIR   uint32_t(0x00003) 
 755 #define CSSLOT_APPLICATION   uint32_t(0x00004) 
 756 #define CSSLOT_ENTITLEMENTS  uint32_t(0x00005) 
 758 #define CSSLOT_SIGNATURESLOT uint32_t(0x10000) 
 760 #define CS_HASHTYPE_SHA1 1 
 775     struct BlobIndex index
[]; 
 778 struct CodeDirectory 
{ 
 782     uint32_t identOffset
; 
 783     uint32_t nSpecialSlots
; 
 793 extern "C" uint32_t hash(uint8_t *k
, uint32_t length
, uint32_t initval
); 
 795 void sha1(uint8_t *hash
, const void *data
, size_t size
) { 
 796     SHA1(static_cast<const uint8_t *>(data
), size
, hash
); 
 799 struct CodesignAllocation 
{ 
 800     FatMachHeader mach_header_
; 
 807     CodesignAllocation(FatMachHeader mach_header
, size_t offset
, size_t size
, size_t limit
, size_t alloc
, size_t align
) : 
 808         mach_header_(mach_header
), 
 830             _syscall(close(file_
)); 
 833     void open(const char *path
, int flags
) { 
 834         _assert(file_ 
== -1); 
 835         _syscall(file_ 
= ::open(path
, flags
)); 
 852         _syscall(munmap(data_
, size_
)); 
 864     Map(const char *path
, int oflag
, int pflag
, int mflag
) : 
 867         open(path
, oflag
, pflag
, mflag
); 
 870     Map(const char *path
, bool edit
) : 
 880     void open(const char *path
, int oflag
, int pflag
, int mflag
) { 
 883         file_
.open(path
, oflag
); 
 884         int file(file_
.file()); 
 887         _syscall(fstat(file
, &stat
)); 
 888         size_ 
= stat
.st_size
; 
 890         _syscall(data_ 
= mmap(NULL
, size_
, pflag
, mflag
, file
, 0)); 
 893     void open(const char *path
, bool edit
) { 
 895             open(path
, O_RDWR
, PROT_READ 
| PROT_WRITE
, MAP_SHARED
); 
 897             open(path
, O_RDONLY
, PROT_READ
, MAP_PRIVATE
); 
 904     size_t size() const { 
 908     operator std::string() const { 
 909         return std::string(static_cast<char *>(data_
), size_
); 
 913 // I wish Apple cared about providing quality toolchains :/ 
 915 template <typename Function_
> 
 918 template <typename Type_
, typename
... Args_
> 
 919 class Functor
<Type_ (Args_
...)> { 
 921     virtual Type_ 
operator ()(Args_
... args
) const = 0; 
 924 template <typename Function_
> 
 927 template <typename Value_
, typename Type_
, typename
... Args_
> 
 928 class FunctorImpl
<Type_ (Value_::*)(Args_
...) const> : 
 929     public Functor
<Type_ (Args_
...)> 
 932     const Value_ 
*value_
; 
 940     FunctorImpl(const Value_ 
&value
) : 
 945     virtual Type_ 
operator ()(Args_
... args
) const { 
 946         return (*value_
)(args
...); 
 950 template <typename Function_
> 
 951 FunctorImpl
<decltype(&Function_::operator())> fun(const Function_ 
&value
) { 
 955 void resign(void *idata
, size_t isize
, std::streambuf 
&output
, const Functor
<size_t (size_t)> &allocate
, const Functor
<size_t (std::streambuf 
&output
, size_t, const std::string 
&, const char *)> &save
) { 
 956     FatHeader 
source(idata
, isize
); 
 960         offset 
+= sizeof(fat_header
) + sizeof(fat_arch
) * source
.Swap(source
->nfat_arch
); 
 962     std::vector
<CodesignAllocation
> allocations
; 
 963     _foreach (mach_header
, source
.GetMachHeaders()) { 
 964         struct linkedit_data_command 
*signature(NULL
); 
 965         struct symtab_command 
*symtab(NULL
); 
 967         _foreach (load_command
, mach_header
.GetLoadCommands()) { 
 968             uint32_t cmd(mach_header
.Swap(load_command
->cmd
)); 
 970             else if (cmd 
== LC_CODE_SIGNATURE
) 
 971                 signature 
= reinterpret_cast<struct linkedit_data_command 
*>(load_command
); 
 972             else if (cmd 
== LC_SYMTAB
) 
 973                 symtab 
= reinterpret_cast<struct symtab_command 
*>(load_command
); 
 977         if (signature 
== NULL
) 
 978             size 
= mach_header
.GetSize(); 
 980             size 
= mach_header
.Swap(signature
->dataoff
); 
 981             _assert(size 
<= mach_header
.GetSize()); 
 984         if (symtab 
!= NULL
) { 
 985             auto end(mach_header
.Swap(symtab
->stroff
) + mach_header
.Swap(symtab
->strsize
)); 
 986             _assert(end 
<= size
); 
 987             _assert(end 
>= size 
- 0x10); 
 991         size_t alloc(allocate(size
)); 
 993         auto *fat_arch(mach_header
.GetFatArch()); 
 994         uint32_t align(fat_arch 
== NULL 
? 0 : source
.Swap(fat_arch
->align
)); 
 995         offset 
= Align(offset
, 1 << align
); 
 997         uint32_t limit(size
); 
 999             limit 
= Align(limit
, 0x10); 
1001         allocations
.push_back(CodesignAllocation(mach_header
, offset
, size
, limit
, alloc
, align
)); 
1002         offset 
+= size 
+ alloc
; 
1003         offset 
= Align(offset
, 16); 
1008     if (source
.IsFat()) { 
1009         fat_header fat_header
; 
1010         fat_header
.magic 
= Swap(FAT_MAGIC
); 
1011         fat_header
.nfat_arch 
= Swap(uint32_t(allocations
.size())); 
1012         put(output
, &fat_header
, sizeof(fat_header
)); 
1013         position 
+= sizeof(fat_header
); 
1015         _foreach (allocation
, allocations
) { 
1016             auto &mach_header(allocation
.mach_header_
); 
1019             fat_arch
.cputype 
= Swap(mach_header
->cputype
); 
1020             fat_arch
.cpusubtype 
= Swap(mach_header
->cpusubtype
); 
1021             fat_arch
.offset 
= Swap(allocation
.offset_
); 
1022             fat_arch
.size 
= Swap(allocation
.limit_ 
+ allocation
.alloc_
); 
1023             fat_arch
.align 
= Swap(allocation
.align_
); 
1024             put(output
, &fat_arch
, sizeof(fat_arch
)); 
1025             position 
+= sizeof(fat_arch
); 
1029     _foreach (allocation
, allocations
) { 
1030         auto &mach_header(allocation
.mach_header_
); 
1032         pad(output
, allocation
.offset_ 
- position
); 
1033         position 
= allocation
.offset_
; 
1035         std::vector
<std::string
> commands
; 
1037         _foreach (load_command
, mach_header
.GetLoadCommands()) { 
1038             std::string 
copy(reinterpret_cast<const char *>(load_command
), load_command
->cmdsize
); 
1040             switch (mach_header
.Swap(load_command
->cmd
)) { 
1041                 case LC_CODE_SIGNATURE
: 
1046                     auto segment_command(reinterpret_cast<struct segment_command 
*>(©
[0])); 
1047                     if (strncmp(segment_command
->segname
, "__LINKEDIT", 16) != 0) 
1049                     size_t size(mach_header
.Swap(allocation
.limit_ 
+ allocation
.alloc_ 
- mach_header
.Swap(segment_command
->fileoff
))); 
1050                     segment_command
->filesize 
= size
; 
1051                     segment_command
->vmsize 
= Align(size
, 0x1000); 
1054                 case LC_SEGMENT_64
: { 
1055                     auto segment_command(reinterpret_cast<struct segment_command_64 
*>(©
[0])); 
1056                     if (strncmp(segment_command
->segname
, "__LINKEDIT", 16) != 0) 
1058                     size_t size(mach_header
.Swap(allocation
.limit_ 
+ allocation
.alloc_ 
- mach_header
.Swap(segment_command
->fileoff
))); 
1059                     segment_command
->filesize 
= size
; 
1060                     segment_command
->vmsize 
= Align(size
, 0x1000); 
1064             commands
.push_back(copy
); 
1067         if (allocation
.alloc_ 
!= 0) { 
1068             linkedit_data_command signature
; 
1069             signature
.cmd 
= mach_header
.Swap(LC_CODE_SIGNATURE
); 
1070             signature
.cmdsize 
= mach_header
.Swap(uint32_t(sizeof(signature
))); 
1071             signature
.dataoff 
= mach_header
.Swap(allocation
.limit_
); 
1072             signature
.datasize 
= mach_header
.Swap(allocation
.alloc_
); 
1073             commands
.push_back(std::string(reinterpret_cast<const char *>(&signature
), sizeof(signature
))); 
1076         size_t begin(position
); 
1079         _foreach(command
, commands
) 
1080             after 
+= command
.size(); 
1082         std::stringbuf altern
; 
1084         struct mach_header 
header(*mach_header
); 
1085         header
.ncmds 
= mach_header
.Swap(uint32_t(commands
.size())); 
1086         header
.sizeofcmds 
= mach_header
.Swap(after
); 
1087         put(output
, &header
, sizeof(header
)); 
1088         put(altern
, &header
, sizeof(header
)); 
1089         position 
+= sizeof(header
); 
1091         if (mach_header
.Bits64()) { 
1092             auto pad(mach_header
.Swap(uint32_t(0))); 
1093             put(output
, &pad
, sizeof(pad
)); 
1094             put(altern
, &pad
, sizeof(pad
)); 
1095             position 
+= sizeof(pad
); 
1098         _foreach(command
, commands
) { 
1099             put(output
, command
.data(), command
.size()); 
1100             put(altern
, command
.data(), command
.size()); 
1101             position 
+= command
.size(); 
1104         uint32_t before(mach_header
.Swap(mach_header
->sizeofcmds
)); 
1105         if (before 
> after
) { 
1106             pad(output
, before 
- after
); 
1107             pad(altern
, before 
- after
); 
1108             position 
+= before 
- after
; 
1111         auto top(reinterpret_cast<char *>(mach_header
.GetBase())); 
1113         std::string 
overlap(altern
.str()); 
1114         overlap
.append(top 
+ overlap
.size(), Align(overlap
.size(), 0x1000) - overlap
.size()); 
1116         put(output
, top 
+ (position 
- begin
), allocation
.size_ 
- (position 
- begin
)); 
1117         position 
= begin 
+ allocation
.size_
; 
1119         pad(output
, allocation
.limit_ 
- allocation
.size_
); 
1120         position 
+= allocation
.limit_ 
- allocation
.size_
; 
1122         size_t saved(save(output
, allocation
.limit_
, overlap
, top
)); 
1123         if (allocation
.alloc_ 
> saved
) 
1124             pad(output
, allocation
.alloc_ 
- saved
); 
1125         position 
+= allocation
.alloc_
; 
1129 typedef std::map
<uint32_t, std::string
> Blobs
; 
1131 static void insert(Blobs 
&blobs
, uint32_t slot
, const std::stringbuf 
&buffer
) { 
1132     auto value(buffer
.str()); 
1133     std::swap(blobs
[slot
], value
); 
1136 static void insert(Blobs 
&blobs
, uint32_t slot
, uint32_t magic
, const std::stringbuf 
&buffer
) { 
1137     auto value(buffer
.str()); 
1139     blob
.magic 
= Swap(magic
); 
1140     blob
.length 
= Swap(uint32_t(sizeof(blob
) + value
.size())); 
1141     value
.insert(0, reinterpret_cast<char *>(&blob
), sizeof(blob
)); 
1142     std::swap(blobs
[slot
], value
); 
1145 static size_t put(std::streambuf 
&output
, uint32_t magic
, const Blobs 
&blobs
) { 
1147     _foreach (blob
, blobs
) 
1148         total 
+= blob
.second
.size(); 
1150     struct SuperBlob super
; 
1151     super
.blob
.magic 
= Swap(magic
); 
1152     super
.blob
.length 
= Swap(uint32_t(sizeof(SuperBlob
) + blobs
.size() * sizeof(BlobIndex
) + total
)); 
1153     super
.count 
= Swap(uint32_t(blobs
.size())); 
1154     put(output
, &super
, sizeof(super
)); 
1156     size_t offset(sizeof(SuperBlob
) + sizeof(BlobIndex
) * blobs
.size()); 
1158     _foreach (blob
, blobs
) { 
1160         index
.type 
= Swap(blob
.first
); 
1161         index
.offset 
= Swap(uint32_t(offset
)); 
1162         put(output
, &index
, sizeof(index
)); 
1163         offset 
+= blob
.second
.size(); 
1166     _foreach (blob
, blobs
) 
1167         put(output
, blob
.second
.data(), blob
.second
.size()); 
1172 void resign(void *idata
, size_t isize
, std::streambuf 
&output
, const std::string 
&name
, const std::string 
&entitlements
) { 
1173     uint8_t pageshift(0x0c); 
1174     uint32_t pagesize(1 << pageshift
); 
1176     resign(idata
, isize
, output
, fun([&](size_t size
) -> size_t { 
1177         size_t alloc(sizeof(struct SuperBlob
)); 
1179         uint32_t special(0); 
1181         special 
= std::max(special
, CSSLOT_REQUIREMENTS
); 
1182         alloc 
+= sizeof(struct BlobIndex
); 
1185         if (entitlements
.size() != 0) { 
1186             special 
= std::max(special
, CSSLOT_ENTITLEMENTS
); 
1187             alloc 
+= sizeof(struct BlobIndex
); 
1188             alloc 
+= sizeof(struct Blob
); 
1189             alloc 
+= entitlements
.size(); 
1192         special 
= std::max(special
, CSSLOT_CODEDIRECTORY
); 
1193         alloc 
+= sizeof(struct BlobIndex
); 
1194         alloc 
+= sizeof(struct Blob
); 
1195         alloc 
+= sizeof(struct CodeDirectory
); 
1196         alloc 
+= name
.size() + 1; 
1198         uint32_t normal((size 
+ pagesize 
- 1) / pagesize
); 
1199         alloc 
= Align(alloc 
+ (special 
+ normal
) * SHA_DIGEST_LENGTH
, 16); 
1201     }), fun([&](std::streambuf 
&output
, size_t limit
, const std::string 
&overlap
, const char *top
) -> size_t { 
1205             std::stringbuf data
; 
1208             put(data
, CSMAGIC_REQUIREMENTS
, requirements
); 
1210             insert(blobs
, CSSLOT_REQUIREMENTS
, data
); 
1213         if (entitlements
.size() != 0) { 
1214             std::stringbuf data
; 
1215             put(data
, entitlements
.data(), entitlements
.size()); 
1216             insert(blobs
, CSSLOT_ENTITLEMENTS
, CSMAGIC_EMBEDDED_ENTITLEMENTS
, data
); 
1220             std::stringbuf data
; 
1222             uint32_t special(0); 
1223             _foreach (blob
, blobs
) 
1224                 special 
= std::max(special
, blob
.first
); 
1225             uint32_t normal((limit 
+ pagesize 
- 1) / pagesize
); 
1227             CodeDirectory directory
; 
1228             directory
.version 
= Swap(uint32_t(0x00020001)); 
1229             directory
.flags 
= Swap(uint32_t(0)); 
1230             directory
.hashOffset 
= Swap(uint32_t(sizeof(Blob
) + sizeof(CodeDirectory
) + name
.size() + 1 + SHA_DIGEST_LENGTH 
* special
)); 
1231             directory
.identOffset 
= Swap(uint32_t(sizeof(Blob
) + sizeof(CodeDirectory
))); 
1232             directory
.nSpecialSlots 
= Swap(special
); 
1233             directory
.codeLimit 
= Swap(uint32_t(limit
)); 
1234             directory
.nCodeSlots 
= Swap(normal
); 
1235             directory
.hashSize 
= SHA_DIGEST_LENGTH
; 
1236             directory
.hashType 
= CS_HASHTYPE_SHA1
; 
1237             directory
.spare1 
= 0x00; 
1238             directory
.pageSize 
= pageshift
; 
1239             directory
.spare2 
= Swap(uint32_t(0)); 
1240             put(data
, &directory
, sizeof(directory
)); 
1242             put(data
, name
.c_str(), name
.size() + 1); 
1244             uint8_t storage
[special 
+ normal
][SHA_DIGEST_LENGTH
]; 
1245             uint8_t (*hashes
)[SHA_DIGEST_LENGTH
] = storage 
+ special
; 
1247             memset(storage
, 0, sizeof(*storage
) * special
); 
1249             _foreach (blob
, blobs
) { 
1250                 auto local(reinterpret_cast<const Blob 
*>(&blob
.second
[0])); 
1251                 sha1((uint8_t *) (hashes 
- blob
.first
), local
, Swap(local
->length
)); 
1255                 for (size_t i 
= 0; i 
!= normal 
- 1; ++i
) 
1256                     sha1(hashes
[i
], (pagesize 
* i 
< overlap
.size() ? overlap
.data() : top
) + pagesize 
* i
, pagesize
); 
1258                 sha1(hashes
[normal 
- 1], top 
+ pagesize 
* (normal 
- 1), ((limit 
- 1) % pagesize
) + 1); 
1260             put(data
, storage
, sizeof(storage
)); 
1262             insert(blobs
, CSSLOT_CODEDIRECTORY
, CSMAGIC_CODEDIRECTORY
, data
); 
1265         return put(output
, CSMAGIC_EMBEDDED_SIGNATURE
, blobs
); 
1269 void resign(void *idata
, size_t isize
, std::streambuf 
&output
) { 
1270     resign(idata
, isize
, output
, fun([](size_t size
) -> size_t { 
1272     }), fun([](std::streambuf 
&output
, size_t limit
, const std::string 
&overlap
, const char *top
) -> size_t { 
1277 int main(int argc
, char *argv
[]) { 
1283     little_ 
= endian
.byte
[0]; 
1298     uint32_t flag_CPUType(_not(uint32_t)); 
1299     uint32_t flag_CPUSubtype(_not(uint32_t)); 
1301     const char *flag_I(NULL
); 
1308     std::vector
<std::string
> files
; 
1311         fprintf(stderr
, "usage: %s -S[entitlements.xml] <binary>\n", argv
[0]); 
1312         fprintf(stderr
, "   %s -e MobileSafari\n", argv
[0]); 
1313         fprintf(stderr
, "   %s -S cat\n", argv
[0]); 
1314         fprintf(stderr
, "   %s -Stfp.xml gdb\n", argv
[0]); 
1318     for (int argi(1); argi 
!= argc
; ++argi
) 
1319         if (argv
[argi
][0] != '-') 
1320             files
.push_back(argv
[argi
]); 
1321         else switch (argv
[argi
][1]) { 
1322             case 'r': flag_r 
= true; break; 
1323             case 'e': flag_e 
= true; break; 
1325             case 'D': flag_D 
= true; break; 
1327             case 'a': flag_a 
= true; break; 
1331                 if (argv
[argi
][2] != '\0') { 
1332                     const char *cpu 
= argv
[argi
] + 2; 
1333                     const char *colon 
= strchr(cpu
, ':'); 
1334                     _assert(colon 
!= NULL
); 
1336                     flag_CPUType 
= strtoul(cpu
, &arge
, 0); 
1337                     _assert(arge 
== colon
); 
1338                     flag_CPUSubtype 
= strtoul(colon 
+ 1, &arge
, 0); 
1339                     _assert(arge 
== argv
[argi
] + strlen(argv
[argi
])); 
1351                 if (argv
[argi
][2] != '\0') { 
1352                     const char *xml 
= argv
[argi
] + 2; 
1353                     entitlements
.open(xml
, O_RDONLY
, PROT_READ
, MAP_PRIVATE
); 
1359                 if (argv
[argi
][2] == '-') 
1363                     timev 
= strtoul(argv
[argi
] + 2, &arge
, 0); 
1364                     _assert(arge 
== argv
[argi
] + strlen(argv
[argi
])); 
1369                 flag_I 
= argv
[argi
] + 2; 
1377     _assert(!flag_S 
|| !flag_r
); 
1379     if (files
.empty()) usage
: { 
1383     size_t filei(0), filee(0); 
1384     _foreach (file
, files
) try { 
1385         const char *path(file
.c_str()); 
1386         const char *base 
= strrchr(path
, '/'); 
1390             dir
.assign(path
, base
++ - path 
+ 1); 
1394         const char *name(flag_I 
?: base
); 
1397         if (flag_S 
|| flag_r
) { 
1398             Map 
input(path
, O_RDONLY
, PROT_READ
, MAP_PRIVATE
); 
1400             temp 
= dir 
+ "." + base 
+ ".cs"; 
1401             std::filebuf output
; 
1402             _assert(output
.open(temp
.c_str(), std::ios::out 
| std::ios::trunc 
| std::ios::binary
) == &output
); 
1405                 resign(input
.data(), input
.size(), output
); 
1407                 resign(input
.data(), input
.size(), output
, name
, entitlements
); 
1411         Map 
mapping(!temp
.empty() ? temp
.c_str() : path
, flag_T 
|| flag_s
); 
1412         FatHeader 
fat_header(mapping
.data(), mapping
.size()); 
1414         _foreach (mach_header
, fat_header
.GetMachHeaders()) { 
1415             struct linkedit_data_command 
*signature(NULL
); 
1416             struct encryption_info_command 
*encryption(NULL
); 
1419                 if (mach_header
.GetCPUType() != flag_CPUType
) 
1421                 if (mach_header
.GetCPUSubtype() != flag_CPUSubtype
) 
1426                 printf("cpu=0x%x:0x%x\n", mach_header
.GetCPUType(), mach_header
.GetCPUSubtype()); 
1428             _foreach (load_command
, mach_header
.GetLoadCommands()) { 
1429                 uint32_t cmd(mach_header
.Swap(load_command
->cmd
)); 
1432                 else if (cmd 
== LC_CODE_SIGNATURE
) 
1433                     signature 
= reinterpret_cast<struct linkedit_data_command 
*>(load_command
); 
1434                 else if (cmd 
== LC_ENCRYPTION_INFO 
|| cmd 
== LC_ENCRYPTION_INFO_64
) 
1435                     encryption 
= reinterpret_cast<struct encryption_info_command 
*>(load_command
); 
1436                 else if (cmd 
== LC_ID_DYLIB
) { 
1437                     volatile struct dylib_command 
*dylib_command(reinterpret_cast<struct dylib_command 
*>(load_command
)); 
1445                             dylib_command
->dylib
.timestamp 
= 0; 
1446                             timed 
= hash(reinterpret_cast<uint8_t *>(mach_header
.GetBase()), mach_header
.GetSize(), timev
); 
1449                         dylib_command
->dylib
.timestamp 
= mach_header
.Swap(timed
); 
1455                 _assert(encryption 
!= NULL
); 
1456                 encryption
->cryptid 
= mach_header
.Swap(0); 
1460                 _assert(signature 
!= NULL
); 
1462                 uint32_t data 
= mach_header
.Swap(signature
->dataoff
); 
1464                 uint8_t *top 
= reinterpret_cast<uint8_t *>(mach_header
.GetBase()); 
1465                 uint8_t *blob 
= top 
+ data
; 
1466                 struct SuperBlob 
*super 
= reinterpret_cast<struct SuperBlob 
*>(blob
); 
1468                 for (size_t index(0); index 
!= Swap(super
->count
); ++index
) 
1469                     if (Swap(super
->index
[index
].type
) == CSSLOT_ENTITLEMENTS
) { 
1470                         uint32_t begin 
= Swap(super
->index
[index
].offset
); 
1471                         struct Blob 
*entitlements 
= reinterpret_cast<struct Blob 
*>(blob 
+ begin
); 
1472                         fwrite(entitlements 
+ 1, 1, Swap(entitlements
->length
) - sizeof(struct Blob
), stdout
); 
1477                 _assert(signature 
!= NULL
); 
1479                 uint32_t data 
= mach_header
.Swap(signature
->dataoff
); 
1481                 uint8_t *top 
= reinterpret_cast<uint8_t *>(mach_header
.GetBase()); 
1482                 uint8_t *blob 
= top 
+ data
; 
1483                 struct SuperBlob 
*super 
= reinterpret_cast<struct SuperBlob 
*>(blob
); 
1485                 for (size_t index(0); index 
!= Swap(super
->count
); ++index
) 
1486                     if (Swap(super
->index
[index
].type
) == CSSLOT_CODEDIRECTORY
) { 
1487                         uint32_t begin 
= Swap(super
->index
[index
].offset
); 
1488                         struct CodeDirectory 
*directory 
= reinterpret_cast<struct CodeDirectory 
*>(blob 
+ begin
); 
1490                         uint8_t (*hashes
)[SHA_DIGEST_LENGTH
] = reinterpret_cast<uint8_t (*)[SHA_DIGEST_LENGTH
]>(blob 
+ begin 
+ Swap(directory
->hashOffset
)); 
1491                         uint32_t pages 
= Swap(directory
->nCodeSlots
); 
1494                             for (size_t i 
= 0; i 
!= pages 
- 1; ++i
) 
1495                                 sha1(hashes
[i
], top 
+ 0x1000 * i
, 0x1000); 
1497                             sha1(hashes
[pages 
- 1], top 
+ 0x1000 * (pages 
- 1), ((data 
- 1) % 0x1000) + 1); 
1502         if (!temp
.empty()) { 
1504             _syscall(stat(path
, &info
)); 
1506             _syscall(chown(temp
.c_str(), info
.st_uid
, info
.st_gid
)); 
1508             _syscall(chmod(temp
.c_str(), info
.st_mode
)); 
1509             _syscall(unlink(path
)); 
1510             _syscall(rename(temp
.c_str(), path
)); 
1514     } catch (const char *) {