1 /* JocStrap - Java/Objective-C Bootstrap 
   2  * Copyright (C) 2007  Jay Freeman (saurik) 
   6  *        Redistribution and use in source and binary 
   7  * forms, with or without modification, are permitted 
   8  * provided that the following conditions are met: 
  10  * 1. Redistributions of source code must retain the 
  11  *    above copyright notice, this list of conditions 
  12  *    and the following disclaimer. 
  13  * 2. Redistributions in binary form must reproduce the 
  14  *    above copyright notice, this list of conditions 
  15  *    and the following disclaimer in the documentation 
  16  *    and/or other materials provided with the 
  18  * 3. The name of the author may not be used to endorse 
  19  *    or promote products derived from this software 
  20  *    without specific prior written permission. 
  22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' 
  23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
  24  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
  25  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
  26  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 
  27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
  28  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  29  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
  30  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
  31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
  32  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 
  33  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
  34  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
  35  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  38 #include "minimal/stdlib.h" 
  39 #include "minimal/string.h" 
  40 #include "minimal/mapping.h" 
  49 #include <sys/types.h> 
  57 #define FAT_MAGIC 0xcafebabe 
  58 #define FAT_CIGAM 0xbebafeca 
  78 #define MH_MAGIC 0xfeedface 
  79 #define MH_CIGAM 0xcefaedfe 
  81 #define MH_DYLDLINK   0x4 
  83 #define MH_EXECUTE    0x2 
  86 #define MH_DYLIB_STUB 0x9 
  93 #define LC_REQ_DYLD  0x80000000 
  95 #define LC_SEGMENT         0x01 
  96 #define LC_LOAD_DYLIB      0x0c 
  97 #define LC_ID_DYLIB        0x0d 
  99 #define LC_CODE_SIGNATURE  0x1d 
 100 #define LC_REEXPORT_DYLIB (0x1f | LC_REQ_DYLD) 
 105     uint32_t current_version
; 
 106     uint32_t compatibility_version
; 
 109 struct dylib_command 
{ 
 115 struct uuid_command 
{ 
 121 struct segment_command 
{ 
 149 struct linkedit_data_command 
{ 
 156 uint16_t Swap_(uint16_t value
) { 
 158         ((value 
>>  8) & 0x00ff) | 
 159         ((value 
<<  8) & 0xff00); 
 162 uint32_t Swap_(uint32_t value
) { 
 163     value 
= ((value 
>>  8) & 0x00ff00ff) | 
 164             ((value 
<<  8) & 0xff00ff00); 
 165     value 
= ((value 
>> 16) & 0x0000ffff) | 
 166             ((value 
<< 16) & 0xffff0000); 
 170 int16_t Swap_(int16_t value
) { 
 171     return Swap_(static_cast<uint16_t>(value
)); 
 174 int32_t Swap_(int32_t value
) { 
 175     return Swap_(static_cast<uint32_t>(value
)); 
 178 uint16_t Swap(uint16_t value
) { 
 179     return true ? Swap_(value
) : value
; 
 182 uint32_t Swap(uint32_t value
) { 
 183     return true ? Swap_(value
) : value
; 
 186 int16_t Swap(int16_t value
) { 
 187     return Swap(static_cast<uint16_t>(value
)); 
 190 int32_t Swap(int32_t value
) { 
 191     return Swap(static_cast<uint32_t>(value
)); 
 194 template <typename Target_
> 
 201     mach_header 
*mach_header_
; 
 205     uint16_t Swap(uint16_t value
) const { 
 206         return swapped_ 
? Swap_(value
) : value
; 
 209     uint32_t Swap(uint32_t value
) const { 
 210         return swapped_ 
? Swap_(value
) : value
; 
 213     int16_t Swap(int16_t value
) const { 
 214         return Swap(static_cast<uint16_t>(value
)); 
 217     int32_t Swap(int32_t value
) const { 
 218         return Swap(static_cast<uint32_t>(value
)); 
 221     Framework(const char *framework_path
) : 
 224         base_ 
= map(framework_path
, 0, _not(size_t), &size_
, false); 
 225         fat_header 
*fat_header 
= reinterpret_cast<struct fat_header 
*>(base_
); 
 227         if (Swap(fat_header
->magic
) == FAT_CIGAM
) { 
 228             swapped_ 
= !swapped_
; 
 230         } else if (Swap(fat_header
->magic
) != FAT_MAGIC
) 
 231             mach_header_ 
= (mach_header 
*) base_
; 
 233             size_t fat_narch 
= Swap(fat_header
->nfat_arch
); 
 234             fat_arch 
*fat_arch 
= reinterpret_cast<struct fat_arch 
*>(fat_header 
+ 1); 
 236             for (arch 
= 0; arch 
!= fat_narch
; ++arch
) { 
 237                 uint32_t arch_offset 
= Swap(fat_arch
->offset
); 
 238                 mach_header_ 
= (mach_header 
*) ((uint8_t *) base_ 
+ arch_offset
); 
 247         if (Swap(mach_header_
->magic
) == MH_CIGAM
) 
 248             swapped_ 
= !swapped_
; 
 249         else _assert(Swap(mach_header_
->magic
) == MH_MAGIC
); 
 252             Swap(mach_header_
->filetype
) == MH_EXECUTE 
|| 
 253             Swap(mach_header_
->filetype
) == MH_DYLIB 
|| 
 254             Swap(mach_header_
->filetype
) == MH_BUNDLE
 
 258     struct mach_header 
*operator ->() const { 
 270     std::vector
<struct load_command 
*> GetLoadCommands() { 
 271         std::vector
<struct load_command 
*> load_commands
; 
 273         struct load_command 
*load_command 
= reinterpret_cast<struct load_command 
*>(mach_header_ 
+ 1); 
 274         for (uint32_t cmd 
= 0; cmd 
!= Swap(mach_header_
->ncmds
); ++cmd
) { 
 275             load_commands
.push_back(load_command
); 
 276             load_command 
= (struct load_command 
*) ((uint8_t *) load_command 
+ Swap(load_command
->cmdsize
)); 
 279         return load_commands
; 
 282     std::vector
<segment_command 
*> GetSegments(const char *segment_name
) { 
 283         std::vector
<struct segment_command 
*> segment_commands
; 
 285         _foreach (load_command
, GetLoadCommands()) 
 286             if (Swap((*load_command
)->cmd
) == LC_SEGMENT
) { 
 287                 segment_command 
*segment_command 
= reinterpret_cast<struct segment_command 
*>(*load_command
); 
 288                 if (strncmp(segment_command
->segname
, segment_name
, 16) == 0) 
 289                     segment_commands
.push_back(segment_command
); 
 292         return segment_commands
; 
 295     std::vector
<section 
*> GetSections(const char *segment_name
, const char *section_name
) { 
 296         std::vector
<section 
*> sections
; 
 298         _foreach (segment
, GetSegments(segment_name
)) { 
 299             section 
*section 
= (struct section 
*) (*segment 
+ 1); 
 302             for (sect 
= 0; sect 
!= Swap((*segment
)->nsects
); ++sect
) { 
 303                 if (strncmp(section
->sectname
, section_name
, 16) == 0) 
 304                     sections
.push_back(section
); 
 312     template <typename Target_
> 
 313     Pointer
<Target_
> GetPointer(uint32_t address
, const char *segment_name 
= NULL
) { 
 314         load_command 
*load_command 
= (struct load_command 
*) (mach_header_ 
+ 1); 
 317         for (cmd 
= 0; cmd 
!= Swap(mach_header_
->ncmds
); ++cmd
) { 
 318             if (Swap(load_command
->cmd
) == LC_SEGMENT
) { 
 319                 segment_command 
*segment_command 
= (struct segment_command 
*) load_command
; 
 320                 if (segment_name 
!= NULL 
&& strncmp(segment_command
->segname
, segment_name
, 16) != 0) 
 323                 section 
*sections 
= (struct section 
*) (segment_command 
+ 1); 
 326                 for (sect 
= 0; sect 
!= Swap(segment_command
->nsects
); ++sect
) { 
 327                     section 
*section 
= §ions
[sect
]; 
 328                     //printf("%s %u %p %p %u\n", segment_command->segname, sect, address, section->addr, section->size); 
 329                     if (address 
>= Swap(section
->addr
) && address 
< Swap(section
->addr
) + Swap(section
->size
)) { 
 330                         //printf("0x%.8x %s\n", address, segment_command->segname); 
 331                         return Pointer
<Target_
>(this, reinterpret_cast<Target_ 
*>(address 
- Swap(section
->addr
) + Swap(section
->offset
) + (char *) mach_header_
)); 
 337             load_command 
= (struct load_command 
*) ((char *) load_command 
+ Swap(load_command
->cmdsize
)); 
 340         return Pointer
<Target_
>(this); 
 343     template <typename Target_
> 
 344     Pointer
<Target_
> GetOffset(uint32_t offset
) { 
 345         return Pointer
<Target_
>(this, reinterpret_cast<Target_ 
*>(offset 
+ (uint8_t *) mach_header_
)); 
 349 template <typename Target_
> 
 352     const Framework 
*framework_
; 
 353     const Target_ 
*pointer_
; 
 356     Pointer(const Framework 
*framework 
= NULL
, const Target_ 
*pointer 
= NULL
) : 
 357         framework_(framework
), 
 362     operator const Target_ 
*() const { 
 366     const Target_ 
*operator ->() const { 
 370     Pointer
<Target_
> &operator ++() { 
 375     template <typename Value_
> 
 376     Value_ 
Swap(Value_ value
) { 
 377         return framework_
->Swap(value
); 
 381 #define CSMAGIC_CODEDIRECTORY      0xfade0c02 
 382 #define CSMAGIC_EMBEDDED_SIGNATURE 0xfade0cc0 
 383 #define CSMAGIC_ENTITLEMENTS       0xfade7171 
 385 #define CSSLOT_CODEDIRECTORY 0 
 386 #define CSSLOT_REQUIREMENTS  2 
 387 #define CSSLOT_ENTITLEMENTS  5 
 402     struct BlobIndex index
[]; 
 405 struct CodeDirectory 
{ 
 410     uint32_t identOffset
; 
 411     uint32_t nSpecialSlots
; 
 421 extern "C" uint32_t hash(uint8_t *k
, uint32_t length
, uint32_t initval
); 
 423 #define CODESIGN_ALLOCATE "arm-apple-darwin9-codesign_allocate" 
 425 void sha1(uint8_t *hash
, uint8_t *data
, size_t size
) { 
 428     SHA1Input(&context
, data
, size
); 
 429     SHA1Result(&context
, hash
); 
 432 int main(int argc
, const char *argv
[]) { 
 447     const void *xmld(NULL
); 
 450     uintptr_t noffset(_not(uintptr_t)); 
 451     uintptr_t woffset(_not(uintptr_t)); 
 453     std::vector
<std::string
> files
; 
 456         fprintf(stderr
, "usage: %s -S[entitlements.xml] <binary>\n", argv
[0]); 
 457         fprintf(stderr
, "   %s -e MobileSafari\n", argv
[0]); 
 458         fprintf(stderr
, "   %s -S cat\n", argv
[0]); 
 459         fprintf(stderr
, "   %s -Stfp.xml gdb\n", argv
[0]); 
 463     for (int argi(1); argi 
!= argc
; ++argi
) 
 464         if (argv
[argi
][0] != '-') 
 465             files
.push_back(argv
[argi
]); 
 466         else switch (argv
[argi
][1]) { 
 467             case 'R': flag_R 
= true; break; 
 468             case 't': flag_t 
= true; break; 
 469             case 'u': flag_u 
= true; break; 
 470             case 'p': flag_p 
= true; break; 
 471             case 'e': flag_e 
= true; break; 
 481                 if (argv
[argi
][2] != '\0') { 
 482                     const char *xml 
= argv
[argi
] + 2; 
 483                     xmld 
= map(xml
, 0, _not(size_t), &xmls
, true); 
 489                 if (argv
[argi
][2] == '-') 
 493                     timev 
= strtoul(argv
[argi
] + 2, &arge
, 0); 
 494                     _assert(arge 
== argv
[argi
] + strlen(argv
[argi
])); 
 500                 noffset 
= strtoul(argv
[argi
] + 2, &arge
, 0); 
 501                 _assert(arge 
== argv
[argi
] + strlen(argv
[argi
])); 
 506                 woffset 
= strtoul(argv
[argi
] + 2, &arge
, 0); 
 507                 _assert(arge 
== argv
[argi
] + strlen(argv
[argi
])); 
 515     if (files
.empty()) usage
: { 
 519     size_t filei(0), filee(0); 
 520     _foreach (file
, files
) try { 
 521         const char *path(file
->c_str()); 
 522         const char *base 
= strrchr(path
, '/'); 
 523         char *temp(NULL
), *dir
; 
 526             dir 
= strndup_(path
, base
++ - path 
+ 1); 
 533             asprintf(&temp
, "%s.%s.cs", dir
, base
); 
 534             const char *allocate 
= getenv("CODESIGN_ALLOCATE"); 
 535             if (allocate 
== NULL
) 
 536                 allocate 
= "codesign_allocate"; 
 538             size_t size 
= _not(size_t); 
 540                 Framework 
framework(path
); 
 541                 framework
->flags 
|= MH_DYLDLINK
; 
 543                 _foreach (load_command
, framework
.GetLoadCommands()) { 
 544                     uint32_t cmd(framework
.Swap((*load_command
)->cmd
)); 
 545                     if (cmd 
== LC_CODE_SIGNATURE
) { 
 546                         struct linkedit_data_command 
*signature 
= reinterpret_cast<struct linkedit_data_command 
*>(*load_command
); 
 547                         size 
= framework
.Swap(signature
->dataoff
); 
 548                         _assert(size 
< framework
.GetSize()); 
 553                 if (size 
== _not(size_t)) 
 554                     size 
= framework
.GetSize(); 
 556                 switch (framework
->cputype
) { 
 557                     case 12: switch (framework
->cpusubtype
) { 
 558                         case 0: arch 
= "arm"; break; 
 559                         case 6: arch 
= "armv6"; break; 
 560                         default: arch 
= NULL
; break; 
 563                     default: arch 
= NULL
; break; 
 567             _assert(arch 
!= NULL
); 
 573                 asprintf(&ssize
, "%u", (sizeof(struct SuperBlob
) + 2 * sizeof(struct BlobIndex
) + sizeof(struct CodeDirectory
) + strlen(base
) + 1 + ((xmld 
== NULL 
? CSSLOT_REQUIREMENTS 
: CSSLOT_ENTITLEMENTS
) + (size 
+ 0x1000 - 1) / 0x1000) * 0x14 + 0xc + (xmld 
== NULL 
? 0 : 0x10 + xmls
) + 15) / 16 * 16); 
 574                 //printf("%s -i %s -a %s %s -o %s\n", allocate, path, arch, ssize, temp); 
 575                 execlp(allocate
, allocate
, "-i", path
, "-a", arch
, ssize
, "-o", temp
, NULL
); 
 580             _syscall(waitpid(pid
, &status
, 0)); 
 581             _assert(WIFEXITED(status
)); 
 582             _assert(WEXITSTATUS(status
) == 0); 
 585         Framework 
framework(temp 
== NULL 
? path 
: temp
); 
 586         struct linkedit_data_command 
*signature(NULL
); 
 589             printf("path%zu='%s'\n", filei
, file
->c_str()); 
 591         if (woffset 
!= _not(uintptr_t)) { 
 592             Pointer
<uint32_t> wvalue(framework
.GetPointer
<uint32_t>(woffset
)); 
 594                 printf("(null) %p\n", woffset
); 
 596                 printf("0x%.08x\n", *wvalue
); 
 599         if (noffset 
!= _not(uintptr_t)) 
 600             printf("%s\n", &*framework
.GetPointer
<char>(noffset
)); 
 602         _foreach (load_command
, framework
.GetLoadCommands()) { 
 603             uint32_t cmd(framework
.Swap((*load_command
)->cmd
)); 
 605             if (flag_R 
&& cmd 
== LC_REEXPORT_DYLIB
) 
 606                 (*load_command
)->cmd 
= framework
.Swap(LC_LOAD_DYLIB
); 
 607             else if (cmd 
== LC_CODE_SIGNATURE
) 
 608                 signature 
= reinterpret_cast<struct linkedit_data_command 
*>(*load_command
); 
 609             else if (cmd 
== LC_UUID
) { 
 610                 volatile struct uuid_command 
*uuid_command(reinterpret_cast<struct uuid_command 
*>(*load_command
)); 
 613                     printf("uuid%zu=%.2x%.2x%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x\n", filei
, 
 614                         uuid_command
->uuid
[ 0], uuid_command
->uuid
[ 1], uuid_command
->uuid
[ 2], uuid_command
->uuid
[ 3], 
 615                         uuid_command
->uuid
[ 4], uuid_command
->uuid
[ 5], uuid_command
->uuid
[ 6], uuid_command
->uuid
[ 7], 
 616                         uuid_command
->uuid
[ 8], uuid_command
->uuid
[ 9], uuid_command
->uuid
[10], uuid_command
->uuid
[11], 
 617                         uuid_command
->uuid
[12], uuid_command
->uuid
[13], uuid_command
->uuid
[14], uuid_command
->uuid
[15] 
 620             } else if (cmd 
== LC_ID_DYLIB
) { 
 621                 volatile struct dylib_command 
*dylib_command(reinterpret_cast<struct dylib_command 
*>(*load_command
)); 
 624                     printf("time%zu=0x%.8x\n", filei
, framework
.Swap(dylib_command
->dylib
.timestamp
)); 
 632                         dylib_command
->dylib
.timestamp 
= 0; 
 633                         timed 
= hash(reinterpret_cast<uint8_t *>(framework
.GetBase()), framework
.GetSize(), timev
); 
 636                     dylib_command
->dylib
.timestamp 
= framework
.Swap(timed
); 
 642             _assert(signature 
!= NULL
); 
 644             uint32_t data 
= framework
.Swap(signature
->dataoff
); 
 645             uint32_t size 
= framework
.Swap(signature
->datasize
); 
 647             uint8_t *top 
= reinterpret_cast<uint8_t *>(framework
.GetBase()); 
 648             uint8_t *blob 
= top 
+ data
; 
 649             struct SuperBlob 
*super 
= reinterpret_cast<struct SuperBlob 
*>(blob
); 
 651             for (size_t index(0); index 
!= Swap(super
->count
); ++index
) 
 652                 if (Swap(super
->index
[index
].type
) == CSSLOT_ENTITLEMENTS
) { 
 653                     uint32_t begin 
= Swap(super
->index
[index
].offset
); 
 654                     struct Blob 
*entitlements 
= reinterpret_cast<struct Blob 
*>(blob 
+ begin
); 
 655                     fwrite(entitlements 
+ 1, 1, Swap(entitlements
->length
) - sizeof(struct Blob
), stdout
); 
 660             _assert(signature 
!= NULL
); 
 662             uint32_t data 
= framework
.Swap(signature
->dataoff
); 
 663             uint32_t size 
= framework
.Swap(signature
->datasize
); 
 665             uint8_t *top 
= reinterpret_cast<uint8_t *>(framework
.GetBase()); 
 666             uint8_t *blob 
= top 
+ data
; 
 667             struct SuperBlob 
*super 
= reinterpret_cast<struct SuperBlob 
*>(blob
); 
 669             for (size_t index(0); index 
!= Swap(super
->count
); ++index
) 
 670                 if (Swap(super
->index
[index
].type
) == CSSLOT_CODEDIRECTORY
) { 
 671                     uint32_t begin 
= Swap(super
->index
[index
].offset
); 
 672                     struct CodeDirectory 
*directory 
= reinterpret_cast<struct CodeDirectory 
*>(blob 
+ begin
); 
 674                     uint8_t (*hashes
)[20] = reinterpret_cast<uint8_t (*)[20]>(blob 
+ begin 
+ Swap(directory
->hashOffset
)); 
 675                     uint32_t pages 
= Swap(directory
->nCodeSlots
); 
 678                         for (size_t i 
= 0; i 
!= pages 
- 1; ++i
) 
 679                             sha1(hashes
[i
], top 
+ 0x1000 * i
, 0x1000); 
 681                         sha1(hashes
[pages 
- 1], top 
+ 0x1000 * (pages 
- 1), ((data 
- 1) % 0x1000) + 1); 
 686             _assert(signature 
!= NULL
); 
 688             uint32_t data 
= framework
.Swap(signature
->dataoff
); 
 689             uint32_t size 
= framework
.Swap(signature
->datasize
); 
 691             uint8_t *top 
= reinterpret_cast<uint8_t *>(framework
.GetBase()); 
 692             uint8_t *blob 
= top 
+ data
; 
 693             struct SuperBlob 
*super 
= reinterpret_cast<struct SuperBlob 
*>(blob
); 
 694             super
->blob
.magic 
= Swap(CSMAGIC_EMBEDDED_SIGNATURE
); 
 696             uint32_t count 
= xmld 
== NULL 
? 2 : 3; 
 697             uint32_t offset 
= sizeof(struct SuperBlob
) + count 
* sizeof(struct BlobIndex
); 
 699             super
->index
[0].type 
= Swap(CSSLOT_CODEDIRECTORY
); 
 700             super
->index
[0].offset 
= Swap(offset
); 
 702             uint32_t begin 
= offset
; 
 703             struct CodeDirectory 
*directory 
= reinterpret_cast<struct CodeDirectory 
*>(blob 
+ begin
); 
 704             offset 
+= sizeof(struct CodeDirectory
); 
 706             directory
->blob
.magic 
= Swap(CSMAGIC_CODEDIRECTORY
); 
 707             directory
->version 
= Swap(0x00020001); 
 708             directory
->flags 
= Swap(0); 
 709             directory
->codeLimit 
= Swap(data
); 
 710             directory
->hashSize 
= 0x14; 
 711             directory
->hashType 
= 0x01; 
 712             directory
->spare1 
= 0x00; 
 713             directory
->pageSize 
= 0x0c; 
 714             directory
->spare2 
= Swap(0); 
 716             directory
->identOffset 
= Swap(offset 
- begin
); 
 717             strcpy(reinterpret_cast<char *>(blob 
+ offset
), base
); 
 718             offset 
+= strlen(base
) + 1; 
 720             uint32_t special 
= xmld 
== NULL 
? CSSLOT_REQUIREMENTS 
: CSSLOT_ENTITLEMENTS
; 
 721             directory
->nSpecialSlots 
= Swap(special
); 
 723             uint8_t (*hashes
)[20] = reinterpret_cast<uint8_t (*)[20]>(blob 
+ offset
); 
 724             memset(hashes
, 0, sizeof(*hashes
) * special
); 
 726             offset 
+= sizeof(*hashes
) * special
; 
 729             uint32_t pages 
= (data 
+ 0x1000 - 1) / 0x1000; 
 730             directory
->nCodeSlots 
= Swap(pages
); 
 733                 for (size_t i 
= 0; i 
!= pages 
- 1; ++i
) 
 734                     sha1(hashes
[i
], top 
+ 0x1000 * i
, 0x1000); 
 736                 sha1(hashes
[pages 
- 1], top 
+ 0x1000 * (pages 
- 1), ((data 
- 1) % 0x1000) + 1); 
 738             directory
->hashOffset 
= Swap(offset 
- begin
); 
 739             offset 
+= sizeof(*hashes
) * pages
; 
 740             directory
->blob
.length 
= Swap(offset 
- begin
); 
 742             super
->index
[1].type 
= Swap(CSSLOT_REQUIREMENTS
); 
 743             super
->index
[1].offset 
= Swap(offset
); 
 745             memcpy(blob 
+ offset
, "\xfa\xde\x0c\x01\x00\x00\x00\x0c\x00\x00\x00\x00", 0xc); 
 749                 super
->index
[2].type 
= Swap(CSSLOT_ENTITLEMENTS
); 
 750                 super
->index
[2].offset 
= Swap(offset
); 
 752                 uint32_t begin 
= offset
; 
 753                 struct Blob 
*entitlements 
= reinterpret_cast<struct Blob 
*>(blob 
+ begin
); 
 754                 offset 
+= sizeof(struct Blob
); 
 756                 memcpy(blob 
+ offset
, xmld
, xmls
); 
 759                 entitlements
->magic 
= Swap(CSMAGIC_ENTITLEMENTS
); 
 760                 entitlements
->length 
= Swap(offset 
- begin
); 
 763             for (size_t index(0); index 
!= count
; ++index
) { 
 764                 uint32_t type 
= Swap(super
->index
[index
].type
); 
 765                 if (type 
!= 0 && type 
<= special
) { 
 766                     uint32_t offset 
= Swap(super
->index
[index
].offset
); 
 767                     struct Blob 
*local 
= (struct Blob 
*) (blob 
+ offset
); 
 768                     sha1((uint8_t *) (hashes 
- type
), (uint8_t *) local
, Swap(local
->length
)); 
 772             super
->count 
= Swap(count
); 
 773             super
->blob
.length 
= Swap(offset
); 
 776                 fprintf(stderr
, "offset (%u) > size (%u)\n", offset
, size
); 
 778             } //else fprintf(stderr, "offset (%zu) <= size (%zu)\n", offset, size); 
 780             memset(blob 
+ offset
, 0, size 
- offset
); 
 785             _syscall(stat(path
, &info
)); 
 786             _syscall(chown(temp
, info
.st_uid
, info
.st_gid
)); 
 787             _syscall(chmod(temp
, info
.st_mode
)); 
 788             _syscall(unlink(path
)); 
 789             _syscall(rename(temp
, path
)); 
 795     } catch (const char *) {