IsAppEncrypted.m 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. // Copyright (c) 2017 Landon J. Fuller <landon@landonf.org>
  2. // All rights reserved.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //
  22. // Comment from
  23. // <a href="http://iphonedevwiki.net/index.php/Crack_prevention">iPhone Dev
  24. // Wiki Crack Prevention</a>:
  25. // App Store binaries are signed by both their developer and Apple. This
  26. // encrypts the binary so that decryption keys are needed in order to make the
  27. // binary readable. When iOS executes the binary, the decryption keys are used
  28. // to decrypt the binary into a readable state where it is then loaded into
  29. // memory and executed. iOS can tell the encryption status of a binary via the
  30. // cryptid structure member of LC_ENCRYPTION_INFO MachO load command. If
  31. // cryptid is a non-zero value then the binary is encrypted.
  32. //
  33. // 'Cracking' works by letting the kernel decrypt the binary then siphoning the
  34. // decrypted data into a new binary file, resigning, and repackaging. This will
  35. // only work on jailbroken devices as codesignature validation has been
  36. // removed. Resigning takes place because while the codesignature doesn't have
  37. // to be valid thanks to the jailbreak, it does have to be in place unless you
  38. // have AppSync or similar to disable codesignature checks.
  39. //
  40. // More information at
  41. // <a href="http://landonf.org/2009/02/index.html">Landon Fuller's blog</a>
  42. #import "third_party/IsAppEncrypted/Public/IsAppEncrypted.h"
  43. #import <mach-o/dyld.h>
  44. #import <objc/objc.h>
  45. /// The encryption info struct and constants are missing from the iPhoneSimulator SDK, but not from
  46. /// the iPhoneOS or Mac OS X SDKs. Since one doesn't ever ship a Simulator binary, we'll just
  47. /// provide the definitions here.
  48. #if TARGET_OS_SIMULATOR && !defined(LC_ENCRYPTION_INFO)
  49. #define LC_ENCRYPTION_INFO 0x21
  50. struct encryption_info_command {
  51. uint32_t cmd;
  52. uint32_t cmdsize;
  53. uint32_t cryptoff;
  54. uint32_t cryptsize;
  55. uint32_t cryptid;
  56. };
  57. #endif
  58. BOOL IsAppEncrypted(void) {
  59. const struct mach_header *executableHeader = NULL;
  60. for (uint32_t i = 0; i < _dyld_image_count(); i++) {
  61. const struct mach_header *header = _dyld_get_image_header(i);
  62. if (header && header->filetype == MH_EXECUTE) {
  63. executableHeader = header;
  64. break;
  65. }
  66. }
  67. if (!executableHeader) {
  68. return NO;
  69. }
  70. BOOL is64bit = (executableHeader->magic == MH_MAGIC_64);
  71. uintptr_t cursor = (uintptr_t)executableHeader +
  72. (is64bit ? sizeof(struct mach_header_64) : sizeof(struct mach_header));
  73. const struct segment_command *segmentCommand = NULL;
  74. uint32_t i = 0;
  75. while (i++ < executableHeader->ncmds) {
  76. segmentCommand = (struct segment_command *)cursor;
  77. if (!segmentCommand) {
  78. continue;
  79. }
  80. if ((!is64bit && segmentCommand->cmd == LC_ENCRYPTION_INFO) ||
  81. (is64bit && segmentCommand->cmd == LC_ENCRYPTION_INFO_64)) {
  82. if (is64bit) {
  83. struct encryption_info_command_64 *cryptCmd =
  84. (struct encryption_info_command_64 *)segmentCommand;
  85. return cryptCmd && cryptCmd->cryptid != 0;
  86. } else {
  87. struct encryption_info_command *cryptCmd = (struct encryption_info_command *)segmentCommand;
  88. return cryptCmd && cryptCmd->cryptid != 0;
  89. }
  90. }
  91. cursor += segmentCommand->cmdsize;
  92. }
  93. return NO;
  94. }