From bbafc3d7acb77e7dbcd6a56026030015dfcb151e Mon Sep 17 00:00:00 2001 From: Aiden Isik Date: Mon, 30 Jun 2025 18:07:26 +0100 Subject: [PATCH 1/3] Re-add comments to some files --- src/setdata/pagedescriptors.c | 6 +++++- src/write/headerhash.c | 13 ++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/setdata/pagedescriptors.c b/src/setdata/pagedescriptors.c index c6543c3..a67795f 100644 --- a/src/setdata/pagedescriptors.c +++ b/src/setdata/pagedescriptors.c @@ -39,12 +39,15 @@ int setPageDescriptors(FILE *pe, struct peData *peData, struct secInfoHeader *se if(!secInfoHeader->descriptors) { return ERR_OUT_OF_MEM; } - struct pageDescriptor *descriptors = secInfoHeader->descriptors; + struct pageDescriptor *descriptors = secInfoHeader->descriptors; // So we don't dereference an unaligned pointer + // Setting size/info data and calculating hashes for page descriptors for(int64_t i = secInfoHeader->pageDescCount - 1; i >= 0; i--) { + // Get page type (rwx) descriptors[i].sizeAndInfo = getRwx(secInfoHeader, peData, i); + // Init sha1 hash struct sha1_ctx shaContext; sha1_init(&shaContext); @@ -62,6 +65,7 @@ int setPageDescriptors(FILE *pe, struct peData *peData, struct secInfoHeader *se return ERR_FILE_READ; } + // For little endian systems, swap into big endian for hashing, then back (to keep struct endianness consistent) #ifdef LITTLE_ENDIAN_SYSTEM descriptors[i].sizeAndInfo = __builtin_bswap32(descriptors[i].sizeAndInfo); #endif diff --git a/src/write/headerhash.c b/src/write/headerhash.c index f430023..8bd612e 100644 --- a/src/write/headerhash.c +++ b/src/write/headerhash.c @@ -22,6 +22,7 @@ // to determine the hash, but reading the file we just created is easier. int setHeaderSha1(FILE *xex) { + // Get basefile offset if(fseek(xex, 0x8, SEEK_SET) != 0) { return ERR_FILE_READ; } @@ -30,6 +31,7 @@ int setHeaderSha1(FILE *xex) if(errno != SUCCESS) { return errno; } + // Get secinfo offset if(fseek(xex, 0x10, SEEK_SET) != 0) { return ERR_FILE_READ; } @@ -38,13 +40,15 @@ int setHeaderSha1(FILE *xex) if(errno != SUCCESS) { return errno; } - uint32_t endOfImageInfo = secInfoOffset + 0x8 + 0x174; - uint32_t remainingSize = basefileOffset - endOfImageInfo; + uint32_t endOfImageInfo = secInfoOffset + 0x8 + 0x174; // 0x8 == image info offset in security info, 0x174 == length of that + uint32_t remainingSize = basefileOffset - endOfImageInfo; // How much data is between end of image info and basefile (we hash that too) + // Init sha1 hash struct sha1_ctx shaContext; memset(&shaContext, 0, sizeof(shaContext)); sha1_init(&shaContext); + // Hash first part (remainder of headers is done first, then the start) uint8_t *remainderOfHeaders = malloc(remainingSize); if(!remainderOfHeaders) @@ -67,6 +71,7 @@ int setHeaderSha1(FILE *xex) sha1_update(&shaContext, remainingSize, remainderOfHeaders); nullAndFree((void **)&remainderOfHeaders); + // Hash from start up to image info (0x8 into security header) uint32_t headersLen = secInfoOffset + 0x8; uint8_t *headersStart = malloc(headersLen); @@ -90,11 +95,13 @@ int setHeaderSha1(FILE *xex) sha1_update(&shaContext, headersLen, headersStart); nullAndFree((void **)&headersStart); + // Get final hash uint8_t headerHash[20]; memset(headerHash, 0, sizeof(headerHash)); sha1_digest(&shaContext, 20, headerHash); - if(fseek(xex, secInfoOffset + 0x164, SEEK_SET) != 0) + // Finally, write it out + if(fseek(xex, secInfoOffset + 0x164, SEEK_SET) != 0) // 0x164 == offset in secinfo of header hash { return ERR_FILE_READ; } if(fwrite(headerHash, 1, 20, xex) != 20) From 38187b17a52865318596bab7630098685904c6a9 Mon Sep 17 00:00:00 2001 From: Aiden Isik Date: Wed, 2 Jul 2025 00:24:18 +0100 Subject: [PATCH 2/3] Fix bug where on some platforms (inc. Windows), duplicate IAT entries would be written --- CMakeLists.txt | 2 +- src/pemapper/pemapper.c | 5 +++++ synthxex.scm | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f02d424..cf05e94 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,7 +72,7 @@ execute_process( if(${VERSION_STRING} MATCHES "^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9]+-g[0-9a-f]+(-dirty)?)?$") add_compile_definitions(SYNTHXEX_VERSION="${VERSION_STRING}") else() - add_compile_definitions(SYNTHXEX_VERSION="v0.0.4") # Only used as a fallback + add_compile_definitions(SYNTHXEX_VERSION="v0.0.5") # Only used as a fallback endif() # Setting install target settings... diff --git a/src/pemapper/pemapper.c b/src/pemapper/pemapper.c index 98464ed..8885277 100644 --- a/src/pemapper/pemapper.c +++ b/src/pemapper/pemapper.c @@ -40,6 +40,7 @@ int xenonifyIAT(FILE *basefile, struct peData *peData) // Loop through each import and handle it's IAT entry for(uint32_t j = 0; j < peData->peImportInfo.tables[i].importCount; j++) { + // Read in the current IAT entry uint32_t iatEntry = get32BitFromPE(basefile); if(errno != SUCCESS) @@ -60,6 +61,10 @@ int xenonifyIAT(FILE *basefile, struct peData *peData) if(fwrite(&iatEntry, sizeof(uint32_t), 1, basefile) < 1) { return ERR_FILE_WRITE; } + + // Call file positioning function between reads and writes to the same file. + // This is mandated by the C standard. + fseek(basefile, 0, SEEK_CUR); } } diff --git a/synthxex.scm b/synthxex.scm index 2d5d7fc..ae4c757 100644 --- a/synthxex.scm +++ b/synthxex.scm @@ -31,7 +31,7 @@ ;;; Hardcoded fallback version in case we can't rely on git -(define synthxex-fallback-version "v0.0.4") +(define synthxex-fallback-version "v0.0.5") ;;; Determine the version of SynthXEX we are building From ea64ac981ce76ca0bebe179241fa72a5e69f912e Mon Sep 17 00:00:00 2001 From: Aiden Isik Date: Wed, 16 Jul 2025 23:24:33 +0100 Subject: [PATCH 3/3] Use val field of getopt option struct --- src/main.c | 153 +++++++++++++++++++++++++++-------------------------- 1 file changed, 77 insertions(+), 76 deletions(-) diff --git a/src/main.c b/src/main.c index 2b3e678..638c0e5 100644 --- a/src/main.c +++ b/src/main.c @@ -164,13 +164,13 @@ int main(int argc, char **argv) { static struct option longOptions[] = { - { "help", no_argument, 0, 0 }, - { "version", no_argument, 0, 0 }, - { "libs", no_argument, 0, 0 }, - { "skip-machine-check", no_argument, 0, 0 }, - { "input", required_argument, 0, 0 }, - { "output", required_argument, 0, 0 }, - { "type", required_argument, 0, 0 }, + { "help", no_argument, 0, 'h' }, + { "version", no_argument, 0, 'v' }, + { "libs", no_argument, 0, 'l' }, + { "skip-machine-check", no_argument, 0, 's' }, + { "input", required_argument, 0, 'i' }, + { "output", required_argument, 0, 'o' }, + { "type", required_argument, 0, 't' }, { 0, 0, 0, 0 } }; @@ -202,85 +202,86 @@ int main(int argc, char **argv) while((option = getopt_long(argc, argv, "hvlsi:o:t:", longOptions, &optIndex)) != -1) { - if(option == 'h' || option == '?' || (option == 0 && strcmp(longOptions[optIndex].name, "help") == 0)) + switch(option) { - dispHelp(argv); - freeAllMainStructs(&offsets, &xexHeader, &secInfoHeader, &peData, - &optHeaderEntries, &optHeaders); - return SUCCESS; - } - else if(option == 'v' || (option == 0 && strcmp(longOptions[optIndex].name, "version") == 0)) - { - dispVer(); - freeAllMainStructs(&offsets, &xexHeader, &secInfoHeader, &peData, - &optHeaderEntries, &optHeaders); - return SUCCESS; - } - else if(option == 'l' || (option == 0 && strcmp(longOptions[optIndex].name, "libs") == 0)) - { - dispLibs(); - freeAllMainStructs(&offsets, &xexHeader, &secInfoHeader, &peData, - &optHeaderEntries, &optHeaders); - return SUCCESS; - } - else if(option == 's' || (option == 0 && strcmp(longOptions[optIndex].name, "skip-machine-check") == 0)) - { - printf("%s WARNING: Skipping machine ID check.\n", SYNTHXEX_PRINT_STEM); - skipMachineCheck = true; - } - else if(option == 'i' || (option == 0 && strcmp(longOptions[optIndex].name, "input") == 0)) - { - gotInput = true; - pePath = malloc(strlen(optarg) + 1); - - if(pePath == NULL) - { - printf("%s ERROR: Out of memory. Aborting.\n", SYNTHXEX_PRINT_STEM); - nullAndFree((void **)&xexfilePath); + case 'v': + dispVer(); freeAllMainStructs(&offsets, &xexHeader, &secInfoHeader, &peData, &optHeaderEntries, &optHeaders); - return -1; - } + return SUCCESS; - strcpy(pePath, optarg); - } - else if(option == 'o' || (option == 0 && strcmp(longOptions[optIndex].name, "output") == 0)) - { - gotOutput = true; - xexfilePath = malloc(strlen(optarg) + 1); - - if(xexfilePath == NULL) - { - printf("%s ERROR: Out of memory. Aborting.\n", SYNTHXEX_PRINT_STEM); - nullAndFree((void **)&pePath); + case 'l': + dispLibs(); freeAllMainStructs(&offsets, &xexHeader, &secInfoHeader, &peData, &optHeaderEntries, &optHeaders); - return -1; - } + return SUCCESS; - strcpy(xexfilePath, optarg); - } - else if(option == 't' || (option == 0 && strcmp(longOptions[optIndex].name, "type") == 0)) - { - if(strcmp(optarg, "title") == 0) - { xexHeader->moduleFlags = XEX_MOD_FLAG_TITLE; } - else if(strcmp(optarg, "titledll") == 0) - { xexHeader->moduleFlags = XEX_MOD_FLAG_TITLE | XEX_MOD_FLAG_DLL; } - else if(strcmp(optarg, "sysdll") == 0) - { xexHeader->moduleFlags = XEX_MOD_FLAG_EXPORTS | XEX_MOD_FLAG_DLL; } - else if(strcmp(optarg, "dll") == 0) - { xexHeader->moduleFlags = XEX_MOD_FLAG_DLL; } - else - { - printf("%s ERROR: Invalid type override \"%s\" (valid: title, titledll, sysdll, dll). Aborting.\n", - SYNTHXEX_PRINT_STEM, optarg); + case 's': + printf("%s WARNING: Skipping machine ID check.\n", SYNTHXEX_PRINT_STEM); + skipMachineCheck = true; + break; - nullAndFree((void **)&pePath); - nullAndFree((void **)&xexfilePath); + case 'i': + gotInput = true; + pePath = malloc(strlen(optarg) + 1); + + if(pePath == NULL) + { + printf("%s ERROR: Out of memory. Aborting.\n", SYNTHXEX_PRINT_STEM); + nullAndFree((void **)&xexfilePath); + freeAllMainStructs(&offsets, &xexHeader, &secInfoHeader, &peData, + &optHeaderEntries, &optHeaders); + return -1; + } + + strcpy(pePath, optarg); + break; + + case 'o': + gotOutput = true; + xexfilePath = malloc(strlen(optarg) + 1); + + if(xexfilePath == NULL) + { + printf("%s ERROR: Out of memory. Aborting.\n", SYNTHXEX_PRINT_STEM); + nullAndFree((void **)&pePath); + freeAllMainStructs(&offsets, &xexHeader, &secInfoHeader, &peData, + &optHeaderEntries, &optHeaders); + return -1; + } + + strcpy(xexfilePath, optarg); + break; + + case 't': + if(strcmp(optarg, "title") == 0) + { xexHeader->moduleFlags = XEX_MOD_FLAG_TITLE; } + else if(strcmp(optarg, "titledll") == 0) + { xexHeader->moduleFlags = XEX_MOD_FLAG_TITLE | XEX_MOD_FLAG_DLL; } + else if(strcmp(optarg, "sysdll") == 0) + { xexHeader->moduleFlags = XEX_MOD_FLAG_EXPORTS | XEX_MOD_FLAG_DLL; } + else if(strcmp(optarg, "dll") == 0) + { xexHeader->moduleFlags = XEX_MOD_FLAG_DLL; } + else + { + printf("%s ERROR: Invalid type override \"%s\" (valid: title, titledll, sysdll, dll). Aborting.\n", + SYNTHXEX_PRINT_STEM, optarg); + + nullAndFree((void **)&pePath); + nullAndFree((void **)&xexfilePath); + freeAllMainStructs(&offsets, &xexHeader, &secInfoHeader, &peData, + &optHeaderEntries, &optHeaders); + return -1; + } + + break; + + case 'h': + default: + dispHelp(argv); freeAllMainStructs(&offsets, &xexHeader, &secInfoHeader, &peData, &optHeaderEntries, &optHeaders); - return -1; - } + return SUCCESS; } }