Skip to content

Commit

Permalink
Allow specifying an identifier in ct_bypass
Browse files Browse the repository at this point in the history
  • Loading branch information
alfiecg24 committed Nov 28, 2024
1 parent fe5aef7 commit aea439b
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 9 deletions.
100 changes: 100 additions & 0 deletions src/CodeDirectory.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,21 @@ const char *cs_hash_type_to_string(int hashType)
}
}

int cs_hash_type_to_length(int hashType)
{
switch (hashType) {
case CS_HASHTYPE_SHA160_160:
return 0x14;
case CS_HASHTYPE_SHA256_256:
case CS_HASHTYPE_SHA256_160:
return 0x20;
case CS_HASHTYPE_SHA384_384:
return 0x30;
default:
return 0;
}
}

const char* cs_slot_to_string(int slot)
{
switch (slot) {
Expand Down Expand Up @@ -226,6 +241,60 @@ int csd_code_directory_set_team_id(CS_DecodedBlob *codeDirBlob, char *newTeamID)
return 0;
}

int csd_code_directory_set_identifier(CS_DecodedBlob *codeDirBlob, char *newIdentifier)
{
CS_CodeDirectory codeDir;
csd_blob_read(codeDirBlob, 0, sizeof(codeDir), &codeDir);
CODE_DIRECTORY_APPLY_BYTE_ORDER(&codeDir, BIG_TO_HOST_APPLIER);

size_t newIdentifierSize = strlen(newIdentifier)+1;

int32_t shift = 0;
uint32_t initialIDOffset = 0;
char *previousIdentifier = csd_code_directory_copy_identifier(codeDirBlob, &initialIDOffset);
if (previousIdentifier) {
uint32_t previousIdentifierSize = strlen(previousIdentifier)+1;
csd_blob_delete(codeDirBlob, initialIDOffset, previousIdentifierSize);
shift -= previousIdentifierSize;
free(previousIdentifier);
}

if (initialIDOffset) {
codeDir.identOffset = initialIDOffset;
}
else {
uint32_t teamOffset = 0;
char *team = csd_code_directory_copy_team_id(codeDirBlob, &teamOffset);
if (!team) {
// TODO: handle this properly
// Calculate size of initial cd struct and place teamID after that
return -1;
}
codeDir.identOffset = teamOffset - strlen(team) + 1;
free(team);
}

// Insert new team ID
csd_blob_insert(codeDirBlob, codeDir.identOffset, newIdentifierSize, newIdentifier);
shift += newIdentifierSize;

// Shift other offsets as needed (Since we inserted data in the middle)
if (codeDir.teamOffset != 0 && codeDir.teamOffset > initialIDOffset) {
codeDir.teamOffset += shift;
}
if (codeDir.hashOffset != 0 && codeDir.hashOffset > initialIDOffset) {
codeDir.hashOffset += shift;
}
if (codeDir.scatterOffset != 0 && codeDir.scatterOffset > initialIDOffset) {
codeDir.scatterOffset += shift;
}

// Write changes to codeDir struct
CODE_DIRECTORY_APPLY_BYTE_ORDER(&codeDir, HOST_TO_BIG_APPLIER);
csd_blob_write(codeDirBlob, 0, sizeof(codeDir), &codeDir);
return 0;
}

uint32_t csd_code_directory_get_flags(CS_DecodedBlob *codeDirBlob)
{
uint32_t flags = 0;
Expand Down Expand Up @@ -478,4 +547,35 @@ void csd_code_directory_update(CS_DecodedBlob *codeDirBlob, MachO *macho)
uint32_t offsetOfBlobToReplace = codeDir.hashOffset + (pageNumber * codeDir.hashSize);
csd_blob_write(codeDirBlob, offsetOfBlobToReplace, codeDir.hashSize, pageHash);
}
}

CS_DecodedBlob *csd_code_directory_init(MachO *macho, int hashType, bool alternate) {
CS_CodeDirectory newCodeDir = { 0 };
memset(&newCodeDir, 0, sizeof(CS_CodeDirectory));
newCodeDir.magic = CSMAGIC_CODEDIRECTORY;
newCodeDir.version = 0x20100;

// Default values
newCodeDir.nSpecialSlots = 7;
newCodeDir.hashType = hashType;
newCodeDir.hashSize = cs_hash_type_to_length(hashType);
newCodeDir.pageSize = 0xC;

newCodeDir.nCodeSlots = (int)(memory_stream_get_size(macho->stream) / pow(2, newCodeDir.pageSize));

// Code limit
// This is everything up to the FADE0CC0 magic

CS_DecodedBlob *blob = malloc(sizeof(CS_DecodedBlob));
blob->type = alternate ? CSSLOT_ALTERNATE_CODEDIRECTORIES : CSSLOT_CODEDIRECTORY;

int finalLength = sizeof(CS_CodeDirectory) + (newCodeDir.nSpecialSlots * newCodeDir.hashSize) + (newCodeDir.nCodeSlots * newCodeDir.hashSize);
newCodeDir.length = finalLength;
void *buffer = malloc(finalLength);
memset(buffer, 0, finalLength);
memcpy(buffer, &newCodeDir, sizeof(CS_CodeDirectory));

blob->stream = buffered_stream_init_from_buffer(buffer, finalLength, 0);

return blob;
}
2 changes: 2 additions & 0 deletions src/CodeDirectory.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ enum CS_HashType {
char *csd_code_directory_copy_identifier(CS_DecodedBlob *codeDirBlob, uint32_t *offsetOut);
char *csd_code_directory_copy_team_id(CS_DecodedBlob *codeDirBlob, uint32_t *offsetOut);
int csd_code_directory_set_team_id(CS_DecodedBlob *codeDirBlob, char *newTeamID);
int csd_code_directory_set_identifier(CS_DecodedBlob *codeDirBlob, char *newIdentifier);
uint32_t csd_code_directory_get_flags(CS_DecodedBlob *codeDirBlob);
void csd_code_directory_set_flags(CS_DecodedBlob *codeDirBlob, uint32_t flags);
uint8_t csd_code_directory_get_hash_type(CS_DecodedBlob *codeDirBlob);
Expand All @@ -57,5 +58,6 @@ unsigned csd_code_directory_calculate_rank(CS_DecodedBlob *codeDirBlob);
int csd_code_directory_calculate_hash(CS_DecodedBlob *codeDirBlob, void *cdhashOut);
int csd_code_directory_print_content(CS_DecodedBlob *codeDirBlob, MachO *macho, bool printSlots, bool verifySlots);
void csd_code_directory_update(CS_DecodedBlob *codeDirBlob, MachO *macho);
CS_DecodedBlob *csd_code_directory_init(MachO *macho, int hashType, bool alternate);

#endif // CODE_DIRECTORY_H
28 changes: 19 additions & 9 deletions tests/ct_bypass/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ void print_usage(const char *self)
printf("\t-o: output file\n");
printf("\t-r: replace input file / replace output file if it already exists\n");
printf("\t-a: input is an .app bundle\n");
printf("\t-t: optional 10-character team ID to use\n");
printf("\t-t: optional team ID to use\n");
printf("\t-I: optional identifier to use\n");
printf("\t-A: optional path to App Store binary to use (will use GTA Car Tracker by default)\n");
printf("\t-h: print this help message\n");
printf("Examples:\n");
Expand Down Expand Up @@ -408,7 +409,7 @@ int update_signature_blob(CS_DecodedSuperBlob *superblob, void *appStoreSigBlob,
return csd_superblob_append_blob(superblob, signatureBlob);
}

int apply_coretrust_bypass(const char *machoPath, char *teamID, char *appStoreBinary)
int apply_coretrust_bypass(const char *machoPath, char *teamID, char *identifier, char *appStoreBinary)
{
MachO *macho = macho_init_for_writing(machoPath);
if (!macho) return -1;
Expand Down Expand Up @@ -500,6 +501,14 @@ int apply_coretrust_bypass(const char *machoPath, char *teamID, char *appStoreBi
// ?. DER entitlements
// 5. Actual CodeDirectory (SHA256)

if (identifier) {
printf("Updating identifier...\n");
if (csd_code_directory_set_identifier(realCodeDirBlob, identifier) != 0) {
printf("Error: failed to set identifier\n");
return 1;
}
}

printf("Updating TeamID...\n");

// Get team ID from AppStore code directory
Expand Down Expand Up @@ -566,7 +575,7 @@ int apply_coretrust_bypass(const char *machoPath, char *teamID, char *appStoreBi
return 0;
}

int apply_coretrust_bypass_wrapper(const char *inputPath, const char *outputPath, char *teamID, char *appStoreBinary)
int apply_coretrust_bypass_wrapper(const char *inputPath, const char *outputPath, char *teamID, char *identifier, char *appStoreBinary)
{
char *machoPath = extract_preferred_slice(inputPath);
if (!machoPath) {
Expand All @@ -575,7 +584,7 @@ int apply_coretrust_bypass_wrapper(const char *inputPath, const char *outputPath
}
printf("extracted best slice to %s\n", machoPath);

int r = apply_coretrust_bypass(machoPath, teamID, appStoreBinary);
int r = apply_coretrust_bypass(machoPath, teamID, identifier, appStoreBinary);
if (r != 0) {
free(machoPath);
return r;
Expand All @@ -594,7 +603,7 @@ int apply_coretrust_bypass_wrapper(const char *inputPath, const char *outputPath
return r;
}

int apply_coretrust_bypass_to_app_bundle(const char *appBundlePath, char *teamID, char *appStoreBinary) {
int apply_coretrust_bypass_to_app_bundle(const char *appBundlePath, char *teamID, char *identifier, char *appStoreBinary) {
// Recursively find all MachO files in the app bundle
DIR *dir;
struct dirent *entry;
Expand All @@ -618,7 +627,7 @@ int apply_coretrust_bypass_to_app_bundle(const char *appBundlePath, char *teamID
if (S_ISDIR(statbuf.st_mode)) {
if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
// Recursive call for subdirectories
r = apply_coretrust_bypass_to_app_bundle(fullpath, teamID, appStoreBinary);
r = apply_coretrust_bypass_to_app_bundle(fullpath, teamID, identifier, appStoreBinary);
}
} else {
// Process file
Expand All @@ -631,7 +640,7 @@ int apply_coretrust_bypass_to_app_bundle(const char *appBundlePath, char *teamID
memory_stream_read(stream, 0, sizeof(magic), &magic);
if (magic == FAT_MAGIC_64 || magic == MH_MAGIC_64) {
printf("Applying bypass to %s.\n", fullpath);
r = apply_coretrust_bypass_wrapper(fullpath, fullpath, teamID, appStoreBinary);
r = apply_coretrust_bypass_wrapper(fullpath, fullpath, teamID, identifier, appStoreBinary);
if (r != 0) {
printf("Error: failed to apply bypass to %s\n", fullpath);
closedir(dir);
Expand All @@ -657,6 +666,7 @@ int main(int argc, char *argv[]) {
bool replace = argument_exists(argc, argv, "-r");
bool appBundle = argument_exists(argc, argv, "-a");
char *teamID = get_argument_value(argc, argv, "-t");
char *identifier = get_argument_value(argc, argv, "-I");
char *appStoreBinary = get_argument_value(argc, argv, "-A");
if (appBundle) {
if (replace || output) {
Expand All @@ -678,7 +688,7 @@ int main(int argc, char *argv[]) {

printf("Applying CoreTrust bypass to app bundle.\n");
printf("CoreTrust bypass eta s0n!!\n");
return apply_coretrust_bypass_to_app_bundle(input, teamID, appStoreBinary);
return apply_coretrust_bypass_to_app_bundle(input, teamID, identifier, appStoreBinary);
}

if (!output && !replace) {
Expand All @@ -702,7 +712,7 @@ int main(int argc, char *argv[]) {
}

printf("CoreTrust bypass eta s0n!!\n");
return apply_coretrust_bypass_wrapper(input, output, teamID, appStoreBinary);
return apply_coretrust_bypass_wrapper(input, output, teamID, identifier, appStoreBinary);
}

#else
Expand Down

0 comments on commit aea439b

Please sign in to comment.