Compare commits

...

2 Commits

Author SHA1 Message Date
alfiecg24 bbdd0fdcdd Fix if statement that broke app installations 2023-12-10 16:10:31 +00:00
alfiecg24 16d4771621 Defend against apps with encrypted binaries 2023-12-10 15:47:58 +00:00
21 changed files with 205 additions and 136 deletions

View File

@ -9,4 +9,4 @@ $(TARGET): $(wildcard src/*.m src/*.c)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
clean: clean:
@rm -f $(TARGET) @rm -f $(TARGET)

View File

@ -10,7 +10,6 @@
#include <choma/MemoryStream.h> #include <choma/MemoryStream.h>
#include <choma/FileStream.h> #include <choma/FileStream.h>
#include <choma/BufferedStream.h> #include <choma/BufferedStream.h>
#include <choma/Signing.h>
#include <choma/SignOSSL.h> #include <choma/SignOSSL.h>
#include <choma/CodeDirectory.h> #include <choma/CodeDirectory.h>
#include <choma/Base64.h> #include <choma/Base64.h>
@ -122,6 +121,12 @@ int apply_coretrust_bypass(const char *machoPath)
{ {
MachO *macho = macho_init_for_writing(machoPath); MachO *macho = macho_init_for_writing(machoPath);
if (!macho) return -1; if (!macho) return -1;
if (macho_is_encrypted(macho)) {
printf("Error: MachO is encrypted, please use a decrypted app!\n");
macho_free(macho);
return 2;
}
CS_SuperBlob *superblob = macho_read_code_signature(macho); CS_SuperBlob *superblob = macho_read_code_signature(macho);
if (!superblob) { if (!superblob) {
@ -137,8 +142,19 @@ int apply_coretrust_bypass(const char *machoPath)
CS_DecodedBlob *mainCodeDirBlob = csd_superblob_find_blob(decodedSuperblob, CSSLOT_CODEDIRECTORY, NULL); CS_DecodedBlob *mainCodeDirBlob = csd_superblob_find_blob(decodedSuperblob, CSSLOT_CODEDIRECTORY, NULL);
CS_DecodedBlob *alternateCodeDirBlob = csd_superblob_find_blob(decodedSuperblob, CSSLOT_ALTERNATE_CODEDIRECTORIES, NULL); CS_DecodedBlob *alternateCodeDirBlob = csd_superblob_find_blob(decodedSuperblob, CSSLOT_ALTERNATE_CODEDIRECTORIES, NULL);
CS_DecodedBlob *entitlementsBlob = csd_superblob_find_blob(decodedSuperblob, CSSLOT_ENTITLEMENTS, NULL);
CS_DecodedBlob *derEntitlementsBlob = csd_superblob_find_blob(decodedSuperblob, CSSLOT_DER_ENTITLEMENTS, NULL);
if (!entitlementsBlob && !derEntitlementsBlob && macho->machHeader.filetype == MH_EXECUTE) {
printf("Error: Unable to find existing entitlements blobs in executable MachO, please make sure to ad-hoc sign with entitlements before running the bypass.\n");
csd_blob_free(mainCodeDirBlob);
if (alternateCodeDirBlob) csd_blob_free(alternateCodeDirBlob);
macho_free(macho);
return -1;
}
if (!mainCodeDirBlob) { if (!mainCodeDirBlob) {
printf("Error: Unable to find code directory, make sure the input binary is ad-hoc signed?\n"); printf("Error: Unable to find code directory, make sure the input binary is ad-hoc signed.\n");
return -1; return -1;
} }

View File

@ -12,63 +12,74 @@
// Blob index // Blob index
typedef struct __BlobIndex { typedef struct __BlobIndex {
uint32_t type; uint32_t type;
uint32_t offset; uint32_t offset;
} CS_BlobIndex; } CS_BlobIndex;
// CMS superblob // CMS superblob
typedef struct __SuperBlob { typedef struct __SuperBlob {
uint32_t magic; uint32_t magic;
uint32_t length; uint32_t length;
uint32_t count; uint32_t count;
CS_BlobIndex index[]; CS_BlobIndex index[];
} CS_SuperBlob; } CS_SuperBlob;
typedef struct __GenericBlob { typedef struct __GenericBlob {
uint32_t magic; /* magic number */ uint32_t magic; /* magic number */
uint32_t length; /* total length of blob */ uint32_t length; /* total length of blob */
char data[]; char data[];
} CS_GenericBlob; } CS_GenericBlob;
// CMS blob magic types // CMS blob magic types
enum { enum {
CSBLOB_REQUIREMENT = 0xfade0c00, CSMAGIC_REQUIREMENT = 0xfade0c00,
CSBLOB_REQUIREMENTS = 0xfade0c01, CSMAGIC_REQUIREMENTS = 0xfade0c01,
CSBLOB_CODEDIRECTORY = 0xfade0c02, CSMAGIC_CODEDIRECTORY = 0xfade0c02,
CSBLOB_EMBEDDED_SIGNATURE = 0xfade0cc0, CSMAGIC_EMBEDDED_SIGNATURE = 0xfade0cc0,
CSBLOB_DETACHED_SIGNATURE = 0xfade0cc1, CSMAGIC_EMBEDDED_SIGNATURE_OLD = 0xfade0b02,
CSBLOB_ENTITLEMENTS = 0xfade7171, CSMAGIC_EMBEDDED_ENTITLEMENTS = 0xfade7171,
CSBLOB_DER_ENTITLEMENTS = 0xfade7172, CSMAGIC_EMBEDDED_DER_ENTITLEMENTS = 0xfade7172,
CSBLOB_SIGNATURE_BLOB = 0xfade0b01 CSMAGIC_DETACHED_SIGNATURE = 0xfade0cc1,
} CS_BlobType; CSMAGIC_BLOBWRAPPER = 0xfade0b01,
CSMAGIC_EMBEDDED_LAUNCH_CONSTRAINT = 0xfade8181,
} CS_BlobMagic;
enum { enum {
CSSLOT_CODEDIRECTORY = 0, CSSLOT_CODEDIRECTORY = 0,
CSSLOT_INFOSLOT = 1, CSSLOT_INFOSLOT = 1,
CSSLOT_REQUIREMENTS = 2, CSSLOT_REQUIREMENTS = 2,
CSSLOT_RESOURCEDIR = 3, CSSLOT_RESOURCEDIR = 3,
CSSLOT_APPLICATION = 4, CSSLOT_APPLICATION = 4,
CSSLOT_ENTITLEMENTS = 5, CSSLOT_ENTITLEMENTS = 5,
CSSLOT_DER_ENTITLEMENTS = 7, CSSLOT_DER_ENTITLEMENTS = 7,
CSSLOT_ALTERNATE_CODEDIRECTORIES = 0x1000, CSSLOT_LAUNCH_CONSTRAINT_SELF = 8,
CSSLOT_ALTERNATE_CODEDIRECTORY_MAX = 5, CSSLOT_LAUNCH_CONSTRAINT_PARENT = 9,
CSSLOT_ALTERNATE_CODEDIRECTORY_LIMIT = CSSLOT_ALTERNATE_CODEDIRECTORIES + CSSLOT_ALTERNATE_CODEDIRECTORY_MAX, CSSLOT_LAUNCH_CONSTRAINT_RESPONSIBLE = 10,
CSSLOT_SIGNATURESLOT = 0x10000 CSSLOT_LIBRARY_CONSTRAINT = 11,
CSSLOT_ALTERNATE_CODEDIRECTORIES = 0x1000, /* first alternate CodeDirectory, if any */
CSSLOT_ALTERNATE_CODEDIRECTORY_MAX = 5, /* max number of alternate CD slots */
CSSLOT_ALTERNATE_CODEDIRECTORY_LIMIT = CSSLOT_ALTERNATE_CODEDIRECTORIES + CSSLOT_ALTERNATE_CODEDIRECTORY_MAX, /* one past the last */
CSSLOT_SIGNATURESLOT = 0x10000,
CSSLOT_IDENTIFICATIONSLOT = 0x10001,
CSSLOT_TICKETSLOT = 0x10002,
} CS_SlotType; } CS_SlotType;
typedef struct s_CS_DecodedBlob { typedef struct s_CS_DecodedBlob {
struct s_CS_DecodedBlob *next; struct s_CS_DecodedBlob *next;
uint32_t type; uint32_t type;
MemoryStream *stream; MemoryStream *stream;
} CS_DecodedBlob; } CS_DecodedBlob;
typedef struct s_CS_DecodedSuperBlob { typedef struct s_CS_DecodedSuperBlob {
uint32_t magic; uint32_t magic;
struct s_CS_DecodedBlob *firstBlob; struct s_CS_DecodedBlob *firstBlob;
} CS_DecodedSuperBlob; } CS_DecodedSuperBlob;
// Convert blob magic to readable blob type string // Convert blob magic to readable blob type string
char *cs_blob_magic_to_string(int magic); const char *cs_blob_magic_to_string(uint32_t magic);
const char *cs_slot_type_to_string(uint32_t slotType);
// Extract Code Signature to file // Extract Code Signature to file
int macho_extract_cs_to_file(MachO *macho, CS_SuperBlob *superblob); int macho_extract_cs_to_file(MachO *macho, CS_SuperBlob *superblob);

View File

@ -30,11 +30,16 @@ FAT *fat_init_from_memory_stream(MemoryStream *stream);
// Initialise a FAT structure using the path to the file // Initialise a FAT structure using the path to the file
FAT *fat_init_from_path(const char *filePath); FAT *fat_init_from_path(const char *filePath);
//FAT *fat_init_from_path_for_writing(const char *filePath);
// Find macho with cputype and cpusubtype in FAT, returns NULL if not found // Find macho with cputype and cpusubtype in FAT, returns NULL if not found
MachO *fat_find_slice(FAT *fat, cpu_type_t cputype, cpu_subtype_t cpusubtype); MachO *fat_find_slice(FAT *fat, cpu_type_t cputype, cpu_subtype_t cpusubtype);
// Create a FAT structure from an array of MachO structures
FAT *fat_create_for_macho_array(char *firstInputPath, MachO **machoArray, int machoArrayCount);
// Add a MachO to the FAT structure
int fat_add_macho(FAT *fat, MachO *macho);
// Free all elements of the FAT structure // Free all elements of the FAT structure
void fat_free(FAT *fat); void fat_free(FAT *fat);

View File

@ -57,6 +57,12 @@ MachO *macho_init(MemoryStream *stream, struct fat_arch_64 archDescriptor);
// Initialize a single slice macho for writing to it // Initialize a single slice macho for writing to it
MachO *macho_init_for_writing(const char *filePath); MachO *macho_init_for_writing(const char *filePath);
// Create an array of MachO objects from an array of paths
MachO **macho_array_create_for_paths(char **inputPaths, int inputPathsCount);
// Check if a MachO is encrypted
bool macho_is_encrypted(MachO *macho);
void macho_free(MachO *macho); void macho_free(MachO *macho);
#endif // MACHO_SLICE_H #endif // MACHO_SLICE_H

View File

@ -99,6 +99,13 @@
applier(lc, dataoff); \ applier(lc, dataoff); \
applier(lc, datasize); applier(lc, datasize);
#define ENCRYPTION_INFO_COMMAND_APPLY_BYTE_ORDER(eic, applier) \
applier(eic, cmd); \
applier(eic, cmdsize); \
applier(eic, cryptoff); \
applier(eic, cryptsize); \
applier(eic, cryptid);
#define BLOB_INDEX_APPLY_BYTE_ORDER(bi, applier) \ #define BLOB_INDEX_APPLY_BYTE_ORDER(bi, applier) \
applier(bi, type); \ applier(bi, type); \
applier(bi, offset); applier(bi, offset);

View File

@ -6,6 +6,7 @@
#define METRIC_TYPE_FUNCTION_XREF 3 #define METRIC_TYPE_FUNCTION_XREF 3
typedef struct PFSection { typedef struct PFSection {
MachO *macho;
uint64_t fileoff; uint64_t fileoff;
uint64_t vmaddr; uint64_t vmaddr;
uint64_t size; uint64_t size;
@ -13,13 +14,16 @@ typedef struct PFSection {
bool ownsCache; bool ownsCache;
} PFSection; } PFSection;
PFSection *macho_patchfinder_create_section(MachO *macho, const char *filesetEntryId, const char *segName, const char *sectName); PFSection *pf_section_init_from_macho(MachO *macho, const char *filesetEntryId, const char *segName, const char *sectName);
int macho_patchfinder_cache_section(PFSection *section, MachO *fromMacho); int pf_section_read_at_relative_offset(PFSection *section, uint64_t rel, size_t size, void *outBuf);
void macho_patchfinder_section_free(PFSection *section); int pf_section_read_at_address(PFSection *section, uint64_t vmaddr, void *outBuf, size_t size);
uint32_t pf_section_read32(PFSection *section, uint64_t vmaddr);
int pf_section_set_cached(PFSection *section, bool cached);
void pf_section_free(PFSection *section);
typedef struct MetricShared { typedef struct MetricShared {
uint32_t type; uint32_t type;
PFSection *section;
} MetricShared; } MetricShared;
@ -39,6 +43,5 @@ typedef struct BytePatternMetric {
BytePatternAlignment alignment; BytePatternAlignment alignment;
} BytePatternMetric; } BytePatternMetric;
BytePatternMetric *macho_patchfinder_create_byte_pattern_metric(PFSection *section, void *bytes, void *mask, size_t nbytes, BytePatternAlignment alignment); BytePatternMetric *pf_create_byte_pattern_metric(void *bytes, void *mask, size_t nbytes, BytePatternAlignment alignment);
void pf_section_run_metric(PFSection *section, void *metric, void (^matchBlock)(uint64_t vmaddr, bool *stop));
void macho_patchfinder_run_metric(MachO *macho, void *metric, void (^matchBlock)(uint64_t vmaddr, bool *stop));

View File

@ -1,12 +0,0 @@
#ifndef SIGNING_H
#define SIGNING_H
#include <stdio.h>
#include <stdlib.h>
#include <CommonCrypto/CommonCrypto.h>
#include <Security/SecKey.h>
#include <Security/Security.h>
// int signWithRSA(const char *certificateFile, const char *inputFile, const char *outputFile);
#endif // SIGNING_H

View File

@ -1,6 +1,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
int memcmp_masked(const void *str1, const void *str2, unsigned char* mask, size_t n);
uint64_t align_to_size(int size, int alignment); uint64_t align_to_size(int size, int alignment);
int count_digits(int64_t num); int count_digits(int64_t num);
void print_hash(uint8_t *hash, size_t size); void print_hash(uint8_t *hash, size_t size);

Binary file not shown.

View File

@ -11,7 +11,30 @@ char *extract_preferred_slice(const char *fatPath)
FAT *fat = fat_init_from_path(fatPath); FAT *fat = fat_init_from_path(fatPath);
if (!fat) return NULL; if (!fat) return NULL;
MachO *macho = fat_find_preferred_slice(fat); MachO *macho = fat_find_preferred_slice(fat);
if (!macho) return NULL;
#if TARGET_OS_MAC && !TARGET_OS_IPHONE
if (!macho) {
// Check for arm64v8 first
macho = fat_find_slice(fat, CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_V8);
if (!macho) {
// If that fails, check for regular arm64
macho = fat_find_slice(fat, CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_ALL);
if (!macho) {
// If that fails, check for arm64e
macho = fat_find_slice(fat, CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64E);
if (!macho) {
fat_free(fat);
return NULL;
}
}
}
}
#else
if (!macho) {
fat_free(fat);
return NULL;
}
#endif // TARGET_OS_MAC && !TARGET_OS_IPHONE
char *temp = strdup("/tmp/XXXXXX"); char *temp = strdup("/tmp/XXXXXX");
int fd = mkstemp(temp); int fd = mkstemp(temp);
@ -26,30 +49,6 @@ char *extract_preferred_slice(const char *fatPath)
return temp; return temp;
} }
int apply_coretrust_bypass_wrapper(const char *inputPath, const char *outputPath)
{
char *machoPath = extract_preferred_slice(inputPath);
printf("extracted best slice to %s\n", machoPath);
int r = apply_coretrust_bypass(machoPath);
if (r != 0) {
free(machoPath);
return r;
}
r = copyfile(machoPath, outputPath, 0, COPYFILE_ALL | COPYFILE_MOVE | COPYFILE_UNLINK);
if (r == 0) {
chmod(outputPath, 0755);
printf("Signed file! CoreTrust bypass eta now!!\n");
}
else {
perror("copyfile");
}
free(machoPath);
return r;
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
if (argc < 2) return -1; if (argc < 2) return -1;
@ -77,9 +76,11 @@ int main(int argc, char *argv[]) {
printf("Applying CoreTrust bypass...\n"); printf("Applying CoreTrust bypass...\n");
if (apply_coretrust_bypass(machoPath) != 0) { r = apply_coretrust_bypass(machoPath);
if (r != 0) {
printf("Failed applying CoreTrust bypass\n"); printf("Failed applying CoreTrust bypass\n");
return -1; return r;
} }
if (copyfile(machoPath, input, 0, COPYFILE_ALL | COPYFILE_MOVE | COPYFILE_UNLINK) == 0) { if (copyfile(machoPath, input, 0, COPYFILE_ALL | COPYFILE_MOVE | COPYFILE_UNLINK) == 0) {

View File

@ -12,63 +12,74 @@
// Blob index // Blob index
typedef struct __BlobIndex { typedef struct __BlobIndex {
uint32_t type; uint32_t type;
uint32_t offset; uint32_t offset;
} CS_BlobIndex; } CS_BlobIndex;
// CMS superblob // CMS superblob
typedef struct __SuperBlob { typedef struct __SuperBlob {
uint32_t magic; uint32_t magic;
uint32_t length; uint32_t length;
uint32_t count; uint32_t count;
CS_BlobIndex index[]; CS_BlobIndex index[];
} CS_SuperBlob; } CS_SuperBlob;
typedef struct __GenericBlob { typedef struct __GenericBlob {
uint32_t magic; /* magic number */ uint32_t magic; /* magic number */
uint32_t length; /* total length of blob */ uint32_t length; /* total length of blob */
char data[]; char data[];
} CS_GenericBlob; } CS_GenericBlob;
// CMS blob magic types // CMS blob magic types
enum { enum {
CSBLOB_REQUIREMENT = 0xfade0c00, CSMAGIC_REQUIREMENT = 0xfade0c00,
CSBLOB_REQUIREMENTS = 0xfade0c01, CSMAGIC_REQUIREMENTS = 0xfade0c01,
CSBLOB_CODEDIRECTORY = 0xfade0c02, CSMAGIC_CODEDIRECTORY = 0xfade0c02,
CSBLOB_EMBEDDED_SIGNATURE = 0xfade0cc0, CSMAGIC_EMBEDDED_SIGNATURE = 0xfade0cc0,
CSBLOB_DETACHED_SIGNATURE = 0xfade0cc1, CSMAGIC_EMBEDDED_SIGNATURE_OLD = 0xfade0b02,
CSBLOB_ENTITLEMENTS = 0xfade7171, CSMAGIC_EMBEDDED_ENTITLEMENTS = 0xfade7171,
CSBLOB_DER_ENTITLEMENTS = 0xfade7172, CSMAGIC_EMBEDDED_DER_ENTITLEMENTS = 0xfade7172,
CSBLOB_SIGNATURE_BLOB = 0xfade0b01 CSMAGIC_DETACHED_SIGNATURE = 0xfade0cc1,
} CS_BlobType; CSMAGIC_BLOBWRAPPER = 0xfade0b01,
CSMAGIC_EMBEDDED_LAUNCH_CONSTRAINT = 0xfade8181,
} CS_BlobMagic;
enum { enum {
CSSLOT_CODEDIRECTORY = 0, CSSLOT_CODEDIRECTORY = 0,
CSSLOT_INFOSLOT = 1, CSSLOT_INFOSLOT = 1,
CSSLOT_REQUIREMENTS = 2, CSSLOT_REQUIREMENTS = 2,
CSSLOT_RESOURCEDIR = 3, CSSLOT_RESOURCEDIR = 3,
CSSLOT_APPLICATION = 4, CSSLOT_APPLICATION = 4,
CSSLOT_ENTITLEMENTS = 5, CSSLOT_ENTITLEMENTS = 5,
CSSLOT_DER_ENTITLEMENTS = 7, CSSLOT_DER_ENTITLEMENTS = 7,
CSSLOT_ALTERNATE_CODEDIRECTORIES = 0x1000, CSSLOT_LAUNCH_CONSTRAINT_SELF = 8,
CSSLOT_ALTERNATE_CODEDIRECTORY_MAX = 5, CSSLOT_LAUNCH_CONSTRAINT_PARENT = 9,
CSSLOT_ALTERNATE_CODEDIRECTORY_LIMIT = CSSLOT_ALTERNATE_CODEDIRECTORIES + CSSLOT_ALTERNATE_CODEDIRECTORY_MAX, CSSLOT_LAUNCH_CONSTRAINT_RESPONSIBLE = 10,
CSSLOT_SIGNATURESLOT = 0x10000 CSSLOT_LIBRARY_CONSTRAINT = 11,
CSSLOT_ALTERNATE_CODEDIRECTORIES = 0x1000, /* first alternate CodeDirectory, if any */
CSSLOT_ALTERNATE_CODEDIRECTORY_MAX = 5, /* max number of alternate CD slots */
CSSLOT_ALTERNATE_CODEDIRECTORY_LIMIT = CSSLOT_ALTERNATE_CODEDIRECTORIES + CSSLOT_ALTERNATE_CODEDIRECTORY_MAX, /* one past the last */
CSSLOT_SIGNATURESLOT = 0x10000,
CSSLOT_IDENTIFICATIONSLOT = 0x10001,
CSSLOT_TICKETSLOT = 0x10002,
} CS_SlotType; } CS_SlotType;
typedef struct s_CS_DecodedBlob { typedef struct s_CS_DecodedBlob {
struct s_CS_DecodedBlob *next; struct s_CS_DecodedBlob *next;
uint32_t type; uint32_t type;
MemoryStream *stream; MemoryStream *stream;
} CS_DecodedBlob; } CS_DecodedBlob;
typedef struct s_CS_DecodedSuperBlob { typedef struct s_CS_DecodedSuperBlob {
uint32_t magic; uint32_t magic;
struct s_CS_DecodedBlob *firstBlob; struct s_CS_DecodedBlob *firstBlob;
} CS_DecodedSuperBlob; } CS_DecodedSuperBlob;
// Convert blob magic to readable blob type string // Convert blob magic to readable blob type string
char *cs_blob_magic_to_string(int magic); const char *cs_blob_magic_to_string(uint32_t magic);
const char *cs_slot_type_to_string(uint32_t slotType);
// Extract Code Signature to file // Extract Code Signature to file
int macho_extract_cs_to_file(MachO *macho, CS_SuperBlob *superblob); int macho_extract_cs_to_file(MachO *macho, CS_SuperBlob *superblob);

View File

@ -30,11 +30,16 @@ FAT *fat_init_from_memory_stream(MemoryStream *stream);
// Initialise a FAT structure using the path to the file // Initialise a FAT structure using the path to the file
FAT *fat_init_from_path(const char *filePath); FAT *fat_init_from_path(const char *filePath);
//FAT *fat_init_from_path_for_writing(const char *filePath);
// Find macho with cputype and cpusubtype in FAT, returns NULL if not found // Find macho with cputype and cpusubtype in FAT, returns NULL if not found
MachO *fat_find_slice(FAT *fat, cpu_type_t cputype, cpu_subtype_t cpusubtype); MachO *fat_find_slice(FAT *fat, cpu_type_t cputype, cpu_subtype_t cpusubtype);
// Create a FAT structure from an array of MachO structures
FAT *fat_create_for_macho_array(char *firstInputPath, MachO **machoArray, int machoArrayCount);
// Add a MachO to the FAT structure
int fat_add_macho(FAT *fat, MachO *macho);
// Free all elements of the FAT structure // Free all elements of the FAT structure
void fat_free(FAT *fat); void fat_free(FAT *fat);

View File

@ -57,6 +57,12 @@ MachO *macho_init(MemoryStream *stream, struct fat_arch_64 archDescriptor);
// Initialize a single slice macho for writing to it // Initialize a single slice macho for writing to it
MachO *macho_init_for_writing(const char *filePath); MachO *macho_init_for_writing(const char *filePath);
// Create an array of MachO objects from an array of paths
MachO **macho_array_create_for_paths(char **inputPaths, int inputPathsCount);
// Check if a MachO is encrypted
bool macho_is_encrypted(MachO *macho);
void macho_free(MachO *macho); void macho_free(MachO *macho);
#endif // MACHO_SLICE_H #endif // MACHO_SLICE_H

View File

@ -99,6 +99,13 @@
applier(lc, dataoff); \ applier(lc, dataoff); \
applier(lc, datasize); applier(lc, datasize);
#define ENCRYPTION_INFO_COMMAND_APPLY_BYTE_ORDER(eic, applier) \
applier(eic, cmd); \
applier(eic, cmdsize); \
applier(eic, cryptoff); \
applier(eic, cryptsize); \
applier(eic, cryptid);
#define BLOB_INDEX_APPLY_BYTE_ORDER(bi, applier) \ #define BLOB_INDEX_APPLY_BYTE_ORDER(bi, applier) \
applier(bi, type); \ applier(bi, type); \
applier(bi, offset); applier(bi, offset);

View File

@ -6,6 +6,7 @@
#define METRIC_TYPE_FUNCTION_XREF 3 #define METRIC_TYPE_FUNCTION_XREF 3
typedef struct PFSection { typedef struct PFSection {
MachO *macho;
uint64_t fileoff; uint64_t fileoff;
uint64_t vmaddr; uint64_t vmaddr;
uint64_t size; uint64_t size;
@ -13,13 +14,16 @@ typedef struct PFSection {
bool ownsCache; bool ownsCache;
} PFSection; } PFSection;
PFSection *macho_patchfinder_create_section(MachO *macho, const char *filesetEntryId, const char *segName, const char *sectName); PFSection *pf_section_init_from_macho(MachO *macho, const char *filesetEntryId, const char *segName, const char *sectName);
int macho_patchfinder_cache_section(PFSection *section, MachO *fromMacho); int pf_section_read_at_relative_offset(PFSection *section, uint64_t rel, size_t size, void *outBuf);
void macho_patchfinder_section_free(PFSection *section); int pf_section_read_at_address(PFSection *section, uint64_t vmaddr, void *outBuf, size_t size);
uint32_t pf_section_read32(PFSection *section, uint64_t vmaddr);
int pf_section_set_cached(PFSection *section, bool cached);
void pf_section_free(PFSection *section);
typedef struct MetricShared { typedef struct MetricShared {
uint32_t type; uint32_t type;
PFSection *section;
} MetricShared; } MetricShared;
@ -39,6 +43,5 @@ typedef struct BytePatternMetric {
BytePatternAlignment alignment; BytePatternAlignment alignment;
} BytePatternMetric; } BytePatternMetric;
BytePatternMetric *macho_patchfinder_create_byte_pattern_metric(PFSection *section, void *bytes, void *mask, size_t nbytes, BytePatternAlignment alignment); BytePatternMetric *pf_create_byte_pattern_metric(void *bytes, void *mask, size_t nbytes, BytePatternAlignment alignment);
void pf_section_run_metric(PFSection *section, void *metric, void (^matchBlock)(uint64_t vmaddr, bool *stop));
void macho_patchfinder_run_metric(MachO *macho, void *metric, void (^matchBlock)(uint64_t vmaddr, bool *stop));

View File

@ -1,12 +0,0 @@
#ifndef SIGNING_H
#define SIGNING_H
#include <stdio.h>
#include <stdlib.h>
#include <CommonCrypto/CommonCrypto.h>
#include <Security/SecKey.h>
#include <Security/Security.h>
// int signWithRSA(const char *certificateFile, const char *inputFile, const char *outputFile);
#endif // SIGNING_H

View File

@ -1,6 +1,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
int memcmp_masked(const void *str1, const void *str2, unsigned char* mask, size_t n);
uint64_t align_to_size(int size, int alignment); uint64_t align_to_size(int size, int alignment);
int count_digits(int64_t num); int count_digits(int64_t num);
void print_hash(uint8_t *hash, size_t size); void print_hash(uint8_t *hash, size_t size);

Binary file not shown.

View File

@ -666,6 +666,11 @@ int signApp(NSString* appPath)
if (r == 0) { if (r == 0) {
NSLog(@"[%@] Applied CoreTrust bypass!", filePath); NSLog(@"[%@] Applied CoreTrust bypass!", filePath);
} }
else if (r == 2) {
NSLog(@"[%@] Cannot apply CoreTrust bypass on an encrypted binary!", filePath);
fat_free(fat);
return 180;
}
else { else {
NSLog(@"[%@] CoreTrust bypass failed!!! :(", filePath); NSLog(@"[%@] CoreTrust bypass failed!!! :(", filePath);
fat_free(fat); fat_free(fat);
@ -740,6 +745,7 @@ void applyPatchesToInfoDictionary(NSString* appPath)
// 172: no info.plist found in app // 172: no info.plist found in app
// 173: app is not signed and cannot be signed because ldid not installed or didn't work // 173: app is not signed and cannot be signed because ldid not installed or didn't work
// 174: // 174:
// 180: tried to sign encrypted binary
int installApp(NSString* appPackagePath, BOOL sign, BOOL force, BOOL isTSUpdate, BOOL useInstalldMethod) int installApp(NSString* appPackagePath, BOOL sign, BOOL force, BOOL isTSUpdate, BOOL useInstalldMethod)
{ {
NSLog(@"[installApp force = %d]", force); NSLog(@"[installApp force = %d]", force);
@ -1014,6 +1020,7 @@ int uninstallAppById(NSString* appId, BOOL useCustomMethod)
// 166: IPA does not exist or is not accessible // 166: IPA does not exist or is not accessible
// 167: IPA does not appear to contain an app // 167: IPA does not appear to contain an app
// 180: IPA contains an encrypted binary
int installIpa(NSString* ipaPath, BOOL force, BOOL useInstalldMethod) int installIpa(NSString* ipaPath, BOOL force, BOOL useInstalldMethod)
{ {
cleanRestrictions(); cleanRestrictions();

View File

@ -74,6 +74,9 @@ extern NSUserDefaults* trollStoreUserDefaults();
case 179: case 179:
errorDescription = @"The app you tried to install has the same identifier as a system app already installed on the device. The installation has been prevented to protect you from possible bootloops or other issues."; errorDescription = @"The app you tried to install has the same identifier as a system app already installed on the device. The installation has been prevented to protect you from possible bootloops or other issues.";
break; break;
case 180:
errorDescription = @"The app you tried to install contains encrypted binaries, which cannot have the CoreTrust bypass applied to them. Please ensure you install decrypted apps.";
break;
} }
NSError* error = [NSError errorWithDomain:TrollStoreErrorDomain code:code userInfo:@{NSLocalizedDescriptionKey : errorDescription}]; NSError* error = [NSError errorWithDomain:TrollStoreErrorDomain code:code userInfo:@{NSLocalizedDescriptionKey : errorDescription}];