Fix search for ADX encryption type-9 key

This commit is contained in:
Alex Barney 2017-06-17 16:23:30 -05:00
parent 27419d1a43
commit a1ab700764

View File

@ -548,6 +548,8 @@ static int find_key(STREAMFILE *file, uint8_t type, uint16_t *xor_start, uint16_
{ {
/* try to guess key */ /* try to guess key */
#define MAX_FRAMES (INT_MAX/0x8000) #define MAX_FRAMES (INT_MAX/0x8000)
struct { uint16_t start, mult, add; } *keys = NULL;
int keycount = 0, keymask = 0;
int scales_to_do; int scales_to_do;
int key_id; int key_id;
@ -582,82 +584,52 @@ static int find_key(STREAMFILE *file, uint8_t type, uint16_t *xor_start, uint16_
if (type == 8) if (type == 8)
{ {
/* guess each of the keys */ keys = &keys_8;
for (key_id=0;key_id<keys_8_count;key_id++) { keycount = keys_8_count;
/* test pre-scales */ keymask = 0x6000;
uint16_t xor = keys_8[key_id].start;
uint16_t mult = keys_8[key_id].mult;
uint16_t add = keys_8[key_id].add;
int i;
for (i=0;i<bruteframe &&
((prescales[i]&0x6000)==(xor&0x6000) ||
prescales[i]==0);
i++) {
xor = xor * mult + add;
}
if (i == bruteframe)
{
/* test */
for (i=0;i<scales_to_do &&
(scales[i]&0x6000)==(xor&0x6000);i++) {
xor = xor * mult + add;
}
if (i == scales_to_do)
{
*xor_start = keys_8[key_id].start;
*xor_mult = keys_8[key_id].mult;
*xor_add = keys_8[key_id].add;
rc = 1;
goto find_key_cleanup;
}
}
}
} }
else if (type == 9) else if (type == 9)
{ {
/* smarter XOR as seen in PSO2, can't do an exact match so we /* smarter XOR as seen in PSO2. The scale is technically 13 bits,
* have to search for the lowest */ * but the maximum value assigned by the encoder is 0x1000.
long best_score = MAX_FRAMES * 0x1fff; * This is written to the ADX file as 0xFFF, leaving the high bit
* empty, which is used to validate a key */
keys = &keys_9;
keycount = keys_9_count;
keymask = 0x1000;
}
/* guess each of the keys */ /* guess each of the keys */
for (key_id=0;key_id<keys_9_count;key_id++) { for (key_id=0;key_id<keycount;key_id++) {
/* run past pre-scales */ /* test pre-scales */
uint16_t xor = keys_9[key_id].start; uint16_t xor = keys[key_id].start;
uint16_t mult = keys_9[key_id].mult; uint16_t mult = keys[key_id].mult;
uint16_t add = keys_9[key_id].add; uint16_t add = keys[key_id].add;
int i; int i;
long total_score = 0;
for (i=0;i<bruteframe;i++) { for (i=0;i<bruteframe &&
xor = xor * mult + add; ((prescales[i]&keymask)==(xor&keymask) ||
} prescales[i]==0);
i++) {
if (i == bruteframe) xor = xor * mult + add;
{
/* test */
for (i=0;i<scales_to_do && total_score < best_score;i++) {
xor = xor * mult + add;
total_score += (scales[i]^xor)&0x1fff;
}
if (total_score < best_score)
{
*xor_start = keys_9[key_id].start;
*xor_mult = keys_9[key_id].mult;
*xor_add = keys_9[key_id].add;
best_score = total_score;
}
}
} }
/* arbitrarily decide if we have won? */ if (i == bruteframe)
if (best_score < scales_to_do * 0x1000)
{ {
rc = 1; /* test */
for (i=0;i<scales_to_do &&
(scales[i]&keymask)==(xor&keymask);i++) {
xor = xor * mult + add;
}
if (i == scales_to_do)
{
*xor_start = keys[key_id].start;
*xor_mult = keys[key_id].mult;
*xor_add = keys[key_id].add;
rc = 1;
goto find_key_cleanup;
}
} }
} }
} }