X-Git-Url: https://git.saurik.com/ldid.git/blobdiff_plain/122621c5586e9859fea83fa8abce68ceefb353d9..ab113d2205a8e142ffccfe3b385877a7330009b9:/ldid.cpp?ds=sidebyside diff --git a/ldid.cpp b/ldid.cpp index 16824d5..ff9358d 100644 --- a/ldid.cpp +++ b/ldid.cpp @@ -1,5 +1,5 @@ -/* JocStrap - Java/Objective-C Bootstrap - * Copyright (C) 2007 Jay Freeman (saurik) +/* ldid - (Mach-O) Link-Loader Identity Editor + * Copyright (C) 2007-2010 Jay Freeman (saurik) */ /* @@ -78,6 +78,9 @@ struct mach_header { #define MH_MAGIC 0xfeedface #define MH_CIGAM 0xcefaedfe +#define MH_MAGIC_64 0xfeedfacf +#define MH_CIGAM_64 0xcffaedfe + #define MH_DYLDLINK 0x4 #define MH_EXECUTE 0x2 @@ -90,14 +93,14 @@ struct load_command { uint32_t cmdsize; } _packed; -#define LC_REQ_DYLD 0x80000000 +#define LC_REQ_DYLD uint32_t(0x80000000) -#define LC_SEGMENT 0x01 -#define LC_LOAD_DYLIB 0x0c -#define LC_ID_DYLIB 0x0d -#define LC_UUID 0x1b -#define LC_CODE_SIGNATURE 0x1d -#define LC_REEXPORT_DYLIB (0x1f | LC_REQ_DYLD) +#define LC_SEGMENT uint32_t(0x01) +#define LC_LOAD_DYLIB uint32_t(0x0c) +#define LC_ID_DYLIB uint32_t(0x0d) +#define LC_UUID uint32_t(0x1b) +#define LC_CODE_SIGNATURE uint32_t(0x1d) +#define LC_REEXPORT_DYLIB uint32_t(0x1f | LC_REQ_DYLD) struct dylib { uint32_t name; @@ -175,12 +178,14 @@ int32_t Swap_(int32_t value) { return Swap_(static_cast(value)); } +bool little_(true); + uint16_t Swap(uint16_t value) { - return true ? Swap_(value) : value; + return little_ ? Swap_(value) : value; } uint32_t Swap(uint32_t value) { - return true ? Swap_(value) : value; + return little_ ? Swap_(value) : value; } int16_t Swap(int16_t value) { @@ -198,8 +203,12 @@ class Framework { private: void *base_; size_t size_; - mach_header *mach_header_; + + struct mach_header *mach_header_; + struct load_command *load_command_; + bool swapped_; + bool bits64_; public: uint16_t Swap(uint16_t value) const { @@ -244,9 +253,27 @@ class Framework { } found: - if (Swap(mach_header_->magic) == MH_CIGAM) - swapped_ = !swapped_; - else _assert(Swap(mach_header_->magic) == MH_MAGIC); + switch (Swap(mach_header_->magic)) { + case MH_CIGAM: + swapped_ = !swapped_; + case MH_MAGIC: + bits64_ = false; + break; + + case MH_CIGAM_64: + swapped_ = !swapped_; + case MH_MAGIC_64: + bits64_ = true; + break; + + default: + _assert(false); + } + + void *post = mach_header_ + 1; + if (bits64_) + post = (uint32_t *) post + 1; + load_command_ = (struct load_command *) post; _assert( Swap(mach_header_->filetype) == MH_EXECUTE || @@ -263,14 +290,22 @@ class Framework { return base_; } - size_t GetSize() { + size_t GetSize() const { return size_; } + uint32_t GetCPUType() const { + return Swap(mach_header_->cputype); + } + + uint16_t GetCPUSubtype() const { + return Swap(mach_header_->cpusubtype) & 0xff; + } + std::vector GetLoadCommands() { std::vector load_commands; - struct load_command *load_command = reinterpret_cast(mach_header_ + 1); + struct load_command *load_command = load_command_; for (uint32_t cmd = 0; cmd != Swap(mach_header_->ncmds); ++cmd) { load_commands.push_back(load_command); load_command = (struct load_command *) ((uint8_t *) load_command + Swap(load_command->cmdsize)); @@ -378,13 +413,13 @@ class Pointer { } }; -#define CSMAGIC_CODEDIRECTORY 0xfade0c02 -#define CSMAGIC_EMBEDDED_SIGNATURE 0xfade0cc0 -#define CSMAGIC_ENTITLEMENTS 0xfade7171 +#define CSMAGIC_CODEDIRECTORY uint32_t(0xfade0c02) +#define CSMAGIC_EMBEDDED_SIGNATURE uint32_t(0xfade0cc0) +#define CSMAGIC_ENTITLEMENTS uint32_t(0xfade7171) -#define CSSLOT_CODEDIRECTORY 0 -#define CSSLOT_REQUIREMENTS 2 -#define CSSLOT_ENTITLEMENTS 5 +#define CSSLOT_CODEDIRECTORY uint32_t(0) +#define CSSLOT_REQUIREMENTS uint32_t(2) +#define CSSLOT_ENTITLEMENTS uint32_t(5) struct BlobIndex { uint32_t type; @@ -430,6 +465,13 @@ void sha1(uint8_t *hash, uint8_t *data, size_t size) { } int main(int argc, const char *argv[]) { + union { + uint16_t word; + uint8_t byte[2]; + } endian = {1}; + + little_ = endian.byte[0]; + bool flag_R(false); bool flag_t(false); bool flag_p(false); @@ -538,7 +580,7 @@ int main(int argc, const char *argv[]) { size_t size = _not(size_t); const char *arch; { Framework framework(path); - framework->flags |= MH_DYLDLINK; + framework->flags = framework.Swap(framework.Swap(framework->flags) | MH_DYLDLINK); _foreach (load_command, framework.GetLoadCommands()) { uint32_t cmd(framework.Swap((*load_command)->cmd)); @@ -553,10 +595,31 @@ int main(int argc, const char *argv[]) { if (size == _not(size_t)) size = framework.GetSize(); - switch (framework->cputype) { - case 12: switch (framework->cpusubtype) { + switch (framework.GetCPUType()) { + case 7: switch (framework.GetCPUSubtype()) { + case 3: arch = "i386"; break; + default: arch = NULL; break; + } break; + + case 12: switch (framework.GetCPUSubtype()) { case 0: arch = "arm"; break; case 6: arch = "armv6"; break; + case 9: arch = "armv7"; break; + default: arch = NULL; break; + } break; + + case 18: switch (framework.GetCPUSubtype()) { + case 10: arch = "ppc7400"; break; + default: arch = NULL; break; + } break; + + case 16777223: switch (framework.GetCPUSubtype()) { + case 3: arch = "x86_64"; break; + default: arch = NULL; break; + } break; + + case 16777234: switch (framework.GetCPUSubtype()) { + case 0: arch = "ppc64"; break; default: arch = NULL; break; } break; @@ -591,7 +654,7 @@ int main(int argc, const char *argv[]) { if (woffset != _not(uintptr_t)) { Pointer wvalue(framework.GetPointer(woffset)); if (wvalue == NULL) - printf("(null) %p\n", woffset); + printf("(null) %p\n", reinterpret_cast(woffset)); else printf("0x%.08x\n", *wvalue); } @@ -704,14 +767,14 @@ int main(int argc, const char *argv[]) { offset += sizeof(struct CodeDirectory); directory->blob.magic = Swap(CSMAGIC_CODEDIRECTORY); - directory->version = Swap(0x00020001); - directory->flags = Swap(0); + directory->version = Swap(uint32_t(0x00020001)); + directory->flags = Swap(uint32_t(0)); directory->codeLimit = Swap(data); directory->hashSize = 0x14; directory->hashType = 0x01; directory->spare1 = 0x00; directory->pageSize = 0x0c; - directory->spare2 = Swap(0); + directory->spare2 = Swap(uint32_t(0)); directory->identOffset = Swap(offset - begin); strcpy(reinterpret_cast(blob + offset), base);