mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-10-07 14:28:12 +03:00
aindump: add decrypt mode
Add -d,--decrypt option to dump decrypted ain file (for reverse engineering).
This commit is contained in:
@@ -237,6 +237,7 @@ struct ain {
|
||||
|
||||
const char *ain_strerror(int error);
|
||||
const char *ain_strtype(struct ain *ain, enum ain_data_type type, int struct_type);
|
||||
uint8_t *ain_read(const char *path, long *len, int *error);
|
||||
struct ain *ain_open(const char *path, int *error);
|
||||
void ain_free(struct ain *ain);
|
||||
|
||||
|
||||
@@ -594,12 +594,10 @@ static bool ain_is_encrypted(uint8_t *buf)
|
||||
return !strncmp((char*)magic, "VERS", 4) && !magic[5] && !magic[6] && !magic[7];
|
||||
}
|
||||
|
||||
struct ain *ain_open(const char *path, int *error)
|
||||
uint8_t *ain_read(const char *path, long *len, int *error)
|
||||
{
|
||||
FILE *fp;
|
||||
long len;
|
||||
uint8_t *buf = NULL;
|
||||
struct ain *ain = NULL;
|
||||
|
||||
if (!(fp = fopen(path, "rb"))) {
|
||||
*error = AIN_FILE_ERROR;
|
||||
@@ -608,17 +606,17 @@ struct ain *ain_open(const char *path, int *error)
|
||||
|
||||
// get size of AIN file
|
||||
fseek(fp, 0, SEEK_END);
|
||||
len = ftell(fp);
|
||||
*len = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
// read AIN file into memory
|
||||
buf = xmalloc(len + 4); // why +4?
|
||||
fread(buf, 1, len, fp);
|
||||
buf = xmalloc(*len + 4); // why +4?
|
||||
fread(buf, 1, *len, fp);
|
||||
fclose(fp);
|
||||
|
||||
// check magic
|
||||
if (!strncmp((char*)buf, "AI2\0\0\0\0", 8)) {
|
||||
uint8_t *uc = decompress_ain(buf, &len);
|
||||
uint8_t *uc = decompress_ain(buf, len);
|
||||
if (!uc) {
|
||||
*error = AIN_INVALID;
|
||||
goto err;
|
||||
@@ -626,13 +624,25 @@ struct ain *ain_open(const char *path, int *error)
|
||||
free(buf);
|
||||
buf = uc;
|
||||
} else if (ain_is_encrypted(buf)) {
|
||||
decrypt_ain(buf, len);
|
||||
decrypt_ain(buf, *len);
|
||||
} else {
|
||||
printf("%.4s\n", buf);
|
||||
*error = AIN_UNRECOGNIZED_FORMAT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
return buf;
|
||||
err:
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct ain *ain_open(const char *path, int *error)
|
||||
{
|
||||
long len;
|
||||
struct ain *ain = NULL;
|
||||
uint8_t *buf = ain_read(path, &len, error);
|
||||
|
||||
// read data into ain struct
|
||||
struct ain_reader r = {
|
||||
.buf = buf,
|
||||
|
||||
+28
-1
@@ -92,6 +92,7 @@ static void print_function(FILE *out, struct ain *ain, struct ain_function *f)
|
||||
static void ain_dump_functions(FILE *f, struct ain *ain)
|
||||
{
|
||||
for (int i = 0; i < ain->nr_functions; i++) {
|
||||
fprintf(f, "0x%x:\t", i);
|
||||
print_function(f, ain, &ain->functions[i]);
|
||||
}
|
||||
}
|
||||
@@ -244,6 +245,21 @@ static void ain_audit(FILE *f, struct ain *ain)
|
||||
fflush(f);
|
||||
}
|
||||
|
||||
static void ain_decrypt(FILE *f, const char *path)
|
||||
{
|
||||
int err;
|
||||
long len;
|
||||
uint8_t *ain;
|
||||
|
||||
if (!(ain = ain_read(path, &len, &err))) {
|
||||
ERROR("Failed to open ain file: %s\n", ain_strerror(err));
|
||||
}
|
||||
|
||||
fwrite(ain, len, 1, f);
|
||||
fflush(f);
|
||||
free(ain);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
bool dump_version = false;
|
||||
@@ -260,6 +276,7 @@ int main(int argc, char *argv[])
|
||||
bool dump_global_group_names = false;
|
||||
bool dump_enums = false;
|
||||
bool audit = false;
|
||||
bool decrypt = false;
|
||||
char *output_file = NULL;
|
||||
FILE *output = stdout;
|
||||
int err = AIN_SUCCESS;
|
||||
@@ -282,12 +299,13 @@ int main(int argc, char *argv[])
|
||||
{ "global-group-names", no_argument, 0, 'r' },
|
||||
{ "enums", no_argument, 0, 'e' },
|
||||
{ "audit", no_argument, 0, 'A' },
|
||||
{ "decrypt", no_argument, 0, 'd' },
|
||||
{ "output", required_argument, 0, 'o' },
|
||||
};
|
||||
int option_index = 0;
|
||||
int c;
|
||||
|
||||
c = getopt_long(argc, argv, "hVcCfgSmlsFeAo:", long_options, &option_index);
|
||||
c = getopt_long(argc, argv, "hVcCfgSmlsFeAdo:", long_options, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
@@ -337,6 +355,9 @@ int main(int argc, char *argv[])
|
||||
case 'A':
|
||||
audit = true;
|
||||
break;
|
||||
case 'd':
|
||||
decrypt = true;
|
||||
break;
|
||||
case 'o':
|
||||
output_file = xstrdup(optarg);
|
||||
break;
|
||||
@@ -360,6 +381,11 @@ int main(int argc, char *argv[])
|
||||
free(output_file);
|
||||
}
|
||||
|
||||
if (decrypt) {
|
||||
ain_decrypt(output, argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(ain = ain_open(argv[0], &err))) {
|
||||
ERROR("Failed to open ain file: %s\n", ain_strerror(err));
|
||||
return 1;
|
||||
@@ -395,4 +421,5 @@ int main(int argc, char *argv[])
|
||||
ain_audit(output, ain);
|
||||
|
||||
ain_free(ain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user