Compare commits
No commits in common. "main" and "synthxex-0.0.4" have entirely different histories.
main
...
synthxex-0
6 changed files with 82 additions and 99 deletions
|
@ -72,7 +72,7 @@ execute_process(
|
||||||
if(${VERSION_STRING} MATCHES "^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9]+-g[0-9a-f]+(-dirty)?)?$")
|
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}")
|
add_compile_definitions(SYNTHXEX_VERSION="${VERSION_STRING}")
|
||||||
else()
|
else()
|
||||||
add_compile_definitions(SYNTHXEX_VERSION="v0.0.5") # Only used as a fallback
|
add_compile_definitions(SYNTHXEX_VERSION="v0.0.4") # Only used as a fallback
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Setting install target settings...
|
# Setting install target settings...
|
||||||
|
|
153
src/main.c
153
src/main.c
|
@ -164,13 +164,13 @@ int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
static struct option longOptions[] =
|
static struct option longOptions[] =
|
||||||
{
|
{
|
||||||
{ "help", no_argument, 0, 'h' },
|
{ "help", no_argument, 0, 0 },
|
||||||
{ "version", no_argument, 0, 'v' },
|
{ "version", no_argument, 0, 0 },
|
||||||
{ "libs", no_argument, 0, 'l' },
|
{ "libs", no_argument, 0, 0 },
|
||||||
{ "skip-machine-check", no_argument, 0, 's' },
|
{ "skip-machine-check", no_argument, 0, 0 },
|
||||||
{ "input", required_argument, 0, 'i' },
|
{ "input", required_argument, 0, 0 },
|
||||||
{ "output", required_argument, 0, 'o' },
|
{ "output", required_argument, 0, 0 },
|
||||||
{ "type", required_argument, 0, 't' },
|
{ "type", required_argument, 0, 0 },
|
||||||
{ 0, 0, 0, 0 }
|
{ 0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -202,86 +202,85 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
while((option = getopt_long(argc, argv, "hvlsi:o:t:", longOptions, &optIndex)) != -1)
|
while((option = getopt_long(argc, argv, "hvlsi:o:t:", longOptions, &optIndex)) != -1)
|
||||||
{
|
{
|
||||||
switch(option)
|
if(option == 'h' || option == '?' || (option == 0 && strcmp(longOptions[optIndex].name, "help") == 0))
|
||||||
{
|
{
|
||||||
case 'v':
|
dispHelp(argv);
|
||||||
dispVer();
|
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);
|
||||||
freeAllMainStructs(&offsets, &xexHeader, &secInfoHeader, &peData,
|
freeAllMainStructs(&offsets, &xexHeader, &secInfoHeader, &peData,
|
||||||
&optHeaderEntries, &optHeaders);
|
&optHeaderEntries, &optHeaders);
|
||||||
return SUCCESS;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
case 'l':
|
strcpy(pePath, optarg);
|
||||||
dispLibs();
|
}
|
||||||
|
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);
|
||||||
freeAllMainStructs(&offsets, &xexHeader, &secInfoHeader, &peData,
|
freeAllMainStructs(&offsets, &xexHeader, &secInfoHeader, &peData,
|
||||||
&optHeaderEntries, &optHeaders);
|
&optHeaderEntries, &optHeaders);
|
||||||
return SUCCESS;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
case 's':
|
strcpy(xexfilePath, optarg);
|
||||||
printf("%s WARNING: Skipping machine ID check.\n", SYNTHXEX_PRINT_STEM);
|
}
|
||||||
skipMachineCheck = true;
|
else if(option == 't' || (option == 0 && strcmp(longOptions[optIndex].name, "type") == 0))
|
||||||
break;
|
{
|
||||||
|
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 'i':
|
nullAndFree((void **)&pePath);
|
||||||
gotInput = true;
|
nullAndFree((void **)&xexfilePath);
|
||||||
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,
|
freeAllMainStructs(&offsets, &xexHeader, &secInfoHeader, &peData,
|
||||||
&optHeaderEntries, &optHeaders);
|
&optHeaderEntries, &optHeaders);
|
||||||
return SUCCESS;
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,6 @@ int xenonifyIAT(FILE *basefile, struct peData *peData)
|
||||||
// Loop through each import and handle it's IAT entry
|
// Loop through each import and handle it's IAT entry
|
||||||
for(uint32_t j = 0; j < peData->peImportInfo.tables[i].importCount; j++)
|
for(uint32_t j = 0; j < peData->peImportInfo.tables[i].importCount; j++)
|
||||||
{
|
{
|
||||||
// Read in the current IAT entry
|
|
||||||
uint32_t iatEntry = get32BitFromPE(basefile);
|
uint32_t iatEntry = get32BitFromPE(basefile);
|
||||||
|
|
||||||
if(errno != SUCCESS)
|
if(errno != SUCCESS)
|
||||||
|
@ -61,10 +60,6 @@ int xenonifyIAT(FILE *basefile, struct peData *peData)
|
||||||
|
|
||||||
if(fwrite(&iatEntry, sizeof(uint32_t), 1, basefile) < 1)
|
if(fwrite(&iatEntry, sizeof(uint32_t), 1, basefile) < 1)
|
||||||
{ return ERR_FILE_WRITE; }
|
{ 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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,15 +39,12 @@ int setPageDescriptors(FILE *pe, struct peData *peData, struct secInfoHeader *se
|
||||||
if(!secInfoHeader->descriptors)
|
if(!secInfoHeader->descriptors)
|
||||||
{ return ERR_OUT_OF_MEM; }
|
{ return ERR_OUT_OF_MEM; }
|
||||||
|
|
||||||
struct pageDescriptor *descriptors = secInfoHeader->descriptors; // So we don't dereference an unaligned pointer
|
struct pageDescriptor *descriptors = secInfoHeader->descriptors;
|
||||||
|
|
||||||
// Setting size/info data and calculating hashes for page descriptors
|
|
||||||
for(int64_t i = secInfoHeader->pageDescCount - 1; i >= 0; i--)
|
for(int64_t i = secInfoHeader->pageDescCount - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
// Get page type (rwx)
|
|
||||||
descriptors[i].sizeAndInfo = getRwx(secInfoHeader, peData, i);
|
descriptors[i].sizeAndInfo = getRwx(secInfoHeader, peData, i);
|
||||||
|
|
||||||
// Init sha1 hash
|
|
||||||
struct sha1_ctx shaContext;
|
struct sha1_ctx shaContext;
|
||||||
sha1_init(&shaContext);
|
sha1_init(&shaContext);
|
||||||
|
|
||||||
|
@ -65,7 +62,6 @@ int setPageDescriptors(FILE *pe, struct peData *peData, struct secInfoHeader *se
|
||||||
return ERR_FILE_READ;
|
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
|
#ifdef LITTLE_ENDIAN_SYSTEM
|
||||||
descriptors[i].sizeAndInfo = __builtin_bswap32(descriptors[i].sizeAndInfo);
|
descriptors[i].sizeAndInfo = __builtin_bswap32(descriptors[i].sizeAndInfo);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
// to determine the hash, but reading the file we just created is easier.
|
// to determine the hash, but reading the file we just created is easier.
|
||||||
int setHeaderSha1(FILE *xex)
|
int setHeaderSha1(FILE *xex)
|
||||||
{
|
{
|
||||||
// Get basefile offset
|
|
||||||
if(fseek(xex, 0x8, SEEK_SET) != 0)
|
if(fseek(xex, 0x8, SEEK_SET) != 0)
|
||||||
{ return ERR_FILE_READ; }
|
{ return ERR_FILE_READ; }
|
||||||
|
|
||||||
|
@ -31,7 +30,6 @@ int setHeaderSha1(FILE *xex)
|
||||||
if(errno != SUCCESS)
|
if(errno != SUCCESS)
|
||||||
{ return errno; }
|
{ return errno; }
|
||||||
|
|
||||||
// Get secinfo offset
|
|
||||||
if(fseek(xex, 0x10, SEEK_SET) != 0)
|
if(fseek(xex, 0x10, SEEK_SET) != 0)
|
||||||
{ return ERR_FILE_READ; }
|
{ return ERR_FILE_READ; }
|
||||||
|
|
||||||
|
@ -40,15 +38,13 @@ int setHeaderSha1(FILE *xex)
|
||||||
if(errno != SUCCESS)
|
if(errno != SUCCESS)
|
||||||
{ return errno; }
|
{ return errno; }
|
||||||
|
|
||||||
uint32_t endOfImageInfo = secInfoOffset + 0x8 + 0x174; // 0x8 == image info offset in security info, 0x174 == length of that
|
uint32_t endOfImageInfo = secInfoOffset + 0x8 + 0x174;
|
||||||
uint32_t remainingSize = basefileOffset - endOfImageInfo; // How much data is between end of image info and basefile (we hash that too)
|
uint32_t remainingSize = basefileOffset - endOfImageInfo;
|
||||||
|
|
||||||
// Init sha1 hash
|
|
||||||
struct sha1_ctx shaContext;
|
struct sha1_ctx shaContext;
|
||||||
memset(&shaContext, 0, sizeof(shaContext));
|
memset(&shaContext, 0, sizeof(shaContext));
|
||||||
sha1_init(&shaContext);
|
sha1_init(&shaContext);
|
||||||
|
|
||||||
// Hash first part (remainder of headers is done first, then the start)
|
|
||||||
uint8_t *remainderOfHeaders = malloc(remainingSize);
|
uint8_t *remainderOfHeaders = malloc(remainingSize);
|
||||||
|
|
||||||
if(!remainderOfHeaders)
|
if(!remainderOfHeaders)
|
||||||
|
@ -71,7 +67,6 @@ int setHeaderSha1(FILE *xex)
|
||||||
sha1_update(&shaContext, remainingSize, remainderOfHeaders);
|
sha1_update(&shaContext, remainingSize, remainderOfHeaders);
|
||||||
nullAndFree((void **)&remainderOfHeaders);
|
nullAndFree((void **)&remainderOfHeaders);
|
||||||
|
|
||||||
// Hash from start up to image info (0x8 into security header)
|
|
||||||
uint32_t headersLen = secInfoOffset + 0x8;
|
uint32_t headersLen = secInfoOffset + 0x8;
|
||||||
uint8_t *headersStart = malloc(headersLen);
|
uint8_t *headersStart = malloc(headersLen);
|
||||||
|
|
||||||
|
@ -95,13 +90,11 @@ int setHeaderSha1(FILE *xex)
|
||||||
sha1_update(&shaContext, headersLen, headersStart);
|
sha1_update(&shaContext, headersLen, headersStart);
|
||||||
nullAndFree((void **)&headersStart);
|
nullAndFree((void **)&headersStart);
|
||||||
|
|
||||||
// Get final hash
|
|
||||||
uint8_t headerHash[20];
|
uint8_t headerHash[20];
|
||||||
memset(headerHash, 0, sizeof(headerHash));
|
memset(headerHash, 0, sizeof(headerHash));
|
||||||
sha1_digest(&shaContext, 20, headerHash);
|
sha1_digest(&shaContext, 20, headerHash);
|
||||||
|
|
||||||
// Finally, write it out
|
if(fseek(xex, secInfoOffset + 0x164, SEEK_SET) != 0)
|
||||||
if(fseek(xex, secInfoOffset + 0x164, SEEK_SET) != 0) // 0x164 == offset in secinfo of header hash
|
|
||||||
{ return ERR_FILE_READ; }
|
{ return ERR_FILE_READ; }
|
||||||
|
|
||||||
if(fwrite(headerHash, 1, 20, xex) != 20)
|
if(fwrite(headerHash, 1, 20, xex) != 20)
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
|
|
||||||
;;; Hardcoded fallback version in case we can't rely on git
|
;;; Hardcoded fallback version in case we can't rely on git
|
||||||
(define synthxex-fallback-version "v0.0.5")
|
(define synthxex-fallback-version "v0.0.4")
|
||||||
|
|
||||||
|
|
||||||
;;; Determine the version of SynthXEX we are building
|
;;; Determine the version of SynthXEX we are building
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue