Skip to content

Instantly share code, notes, and snippets.

@maxton
Last active September 17, 2019 01:19
Show Gist options
  • Save maxton/c7ba029878a521d6ae12510a185b3d2b to your computer and use it in GitHub Desktop.
Save maxton/c7ba029878a521d6ae12510a185b3d2b to your computer and use it in GitHub Desktop.
GHL iOS Title Update 2.0 arm32 RE
// 1b7cdc
string get_key_prefix(int key_type)
{
key_prefixes = {
0 => "a",
1 => "b",
2 => "c",
3 => "d",
4 => "e",
5 => "f",
6 => "g",
7 => "h",
8 => "i",
9 => "j",
10 => "p",
11 => "m",
12 => "q",
13 => "GHL",
14 => "s",
15 => "t",
16 => "ghtf",
17 => "ghlo",
18 => "x",
}
return key_prefixes[key_type];
}
// 1871fc
string format_keyname(int key_type, int key_index)
{
return string::format("%s%d", get_key_prefix(key_type, 0), key_index);
}
// 17aa2c
void format_stem_pathnames(string trackName)
{
// trackname is something like GHL1000
hash = md5(trackName + "ScoobyDoo");
key_index = hash[15] % 10;
key_type = 13;
keyname = format_keyname(key_type, key_index);
// keyname is something like GHL0
song_filename = string::format("/encrypted/Tracks/Stagefright/%s/Audio/%s_song.wem?keyname=%s", trackName, trackName, keyname);
l_gtr_filename = string::format("/encrypted/Tracks/Stagefright/%s/Audio/%s_guitar_left.wem?keyname=%s", trackName, trackName, keyname);
r_gtr_filename = string::format("/encrypted/Tracks/Stagefright/%s/Audio/%s_guitar_right.wem?keyname=%s", trackName, trackName, keyname);
}
enum EMaskOptions {
NETWORK = 0,
LOCAL = 1,
NONE = 2,
}
local_mask = "59b0671493c204dc05a5f0fedb4ab4be";
// 421a34
void CEncryptionKeyStore::ApplyMask(
astruct *param_1,
char *salt,
EMaskOptions mode,
byte *key,
byte *iv,
uint id) {
byte hash_1[16];
byte hash_2[16];
if (mode == NETWORK) {
hash_1 = md5(string::format("%s%u", param_1->network_salt.c_str(), id));
}
else if(mode == LOCAL) {
hash_1 = parseHex16(param_1->hash_mask);
}
else { // mode == NONE
hash_1 = { 0 };
}
hash_2 = md5("FSGK" + salt);
for(int i = 0; i < 16; i++)
{
key[i] = key[i] ^ hash_1[i] ^ param_1->random_data[i] ^ hash_2[i];
iv[i] = iv[i] ^ hash_1[i] ^ param_1->random_data[i + 16] ^ hash_2[i];
}
return;
}
// 421848
void CEncryptionKeyStore::StoreKeys(
CEncryptionKeyStore *this,
char *name,
byte *key,
byte *iv,
EMaskOptions maskOpt,
uint id) {
if(maskOpt > 1) return;
CEncryptionKeyStore::ApplyMask(this, name, use_key_from_struct, key, iv, id);
this->keyHashMap->Insert(name, key);
this->ivHashMap->Insert(name, iv);
}
// 42190c
void CEncryptionKeyStore::AddKeys(CEncryptionKeyStore *this,char *name,char *key_hex,char *iv_hex, EMaskOptions maskOpt,uint id)
{
if ((param_1->random_data == 0 || salt == 0) || (key_init == 0 || iv_init == 0))
return;
key = asciiToHex(key_init);
iv = asciiToHex_backwards(iv_init + 0x1e); // this is done backwards for whatever reason...?
CEncryptionKeyStore::StoreKeys(this,name,key,iv,maskOpt,id);
}
unsigned char keys[160] = {
0x2E, 0xF3, 0x18, 0x76, 0xFE, 0x4D, 0xD6, 0x3E,
0x61, 0xBD, 0x57, 0xF2, 0xC5, 0x01, 0x66, 0xEA,
0x79, 0x0E, 0x96, 0x00, 0xFE, 0xE3, 0x90, 0x80,
0x3C, 0x30, 0xC7, 0x3A, 0x52, 0x73, 0xEE, 0x8F,
0xD3, 0x49, 0x19, 0x4D, 0x75, 0x5B, 0x9F, 0x63,
0x88, 0xE6, 0x58, 0x3D, 0xDD, 0x8B, 0x30, 0xF2,
0xBC, 0xA8, 0xBB, 0x38, 0x84, 0x75, 0x18, 0xE7,
0x65, 0xC5, 0x3C, 0x94, 0x50, 0xD6, 0xF7, 0x40,
0x26, 0x1A, 0x8C, 0x34, 0xC3, 0x52, 0x06, 0x01,
0x88, 0xD5, 0x0C, 0xD2, 0xF0, 0x18, 0xD8, 0x96,
0x3E, 0xDB, 0xE2, 0x00, 0x86, 0x4E, 0x38, 0x8F,
0xBA, 0xE5, 0x1F, 0x91, 0xDB, 0x0A, 0x6C, 0x33,
0xB0, 0x7A, 0x8A, 0x85, 0x6F, 0xBA, 0x98, 0x21,
0x8F, 0x14, 0xF1, 0x59, 0xB8, 0x79, 0xF1, 0xB3,
0xF0, 0x57, 0x1D, 0x47, 0xC5, 0x3F, 0xD8, 0xAF,
0x37, 0xC7, 0x64, 0x28, 0xA8, 0x75, 0x75, 0xA5,
0x22, 0xF3, 0x27, 0x50, 0xC0, 0xE7, 0x8A, 0xC8,
0x87, 0x91, 0xBB, 0x17, 0x93, 0xDA, 0x04, 0x85,
0x9C, 0xC4, 0x19, 0x63, 0xAA, 0x8E, 0x9F, 0x5C,
0x5B, 0x1B, 0xCE, 0x57, 0x31, 0x19, 0x75, 0x6E,
};
unsigned char ivs[160] = {
0x0D, 0x20, 0x76, 0x3A, 0x50, 0x77, 0xEF, 0x28,
0x9B, 0x8E, 0xB9, 0xEE, 0x5D, 0x3F, 0xDB, 0x51,
0xEA, 0x16, 0x2F, 0x5F, 0x0A, 0x9A, 0xAA, 0xFC,
0x6C, 0x03, 0xC9, 0x3C, 0x0B, 0x78, 0x3D, 0xCE,
0xFE, 0x21, 0x24, 0x7D, 0x4C, 0x46, 0x0F, 0x57,
0xFC, 0x05, 0x3E, 0xA6, 0xBB, 0x3E, 0xBB, 0x81,
0x38, 0xC0, 0x4E, 0x20, 0x35, 0x37, 0x3F, 0x1E,
0x87, 0x7F, 0xCC, 0xE2, 0x12, 0x58, 0xEC, 0xE5,
0x5F, 0x29, 0x59, 0x71, 0x65, 0x7A, 0x71, 0x20,
0xCA, 0x4D, 0xA7, 0x4C, 0x7C, 0xCE, 0x74, 0xDC,
0x29, 0x7D, 0x91, 0x92, 0xC5, 0xAE, 0xCB, 0x86,
0xF5, 0x94, 0x70, 0x7F, 0x8B, 0x72, 0xDE, 0x9F,
0xA2, 0xDB, 0xC9, 0x26, 0x33, 0xF5, 0x4A, 0x2D,
0x55, 0x15, 0x13, 0x8F, 0xEF, 0x7D, 0x99, 0x5B,
0xA8, 0x75, 0x58, 0x06, 0xC5, 0x4A, 0x2E, 0x82,
0x7B, 0x4D, 0xAF, 0x78, 0xE2, 0xE6, 0x74, 0x43,
0x15, 0xE5, 0x41, 0xFC, 0x43, 0xC9, 0x1D, 0x51,
0xC0, 0x41, 0xB2, 0xBA, 0x84, 0xD8, 0xAD, 0x66,
0x17, 0x3B, 0x16, 0xAB, 0x15, 0x7A, 0x83, 0xE4,
0xC0, 0x19, 0x13, 0x56, 0xCA, 0xB0, 0x7E, 0xCD,
};
// 17a8d4
void InitTrackKeys()
{
for(int i = 0; i < 10; i++)
{
// simplifying a deep call stack and guessing a bit here
CEncryptionKeyStore::StoreKeys(
getKeyStoreHandle(),
format_keyname(13, i),
keys + (16 * i),
ivs + (16 * i),
0,
i);
}
prefix = format_keyname(15, unk_the_key_index);
keyStore = getKeyStoreHandle()->store;
CEncryptionKeyStore::AddKeys(keyStore, prefix, "1e8f4dcc59f9b82ba8d4ad194bdc9a40", "b91c358888553ffb602c88b8ebc8ec80",1,0);
}
// 4219d4
void store_blank_keys(CEncryptionKeyStore *store,char *keyName,char *key_init,char *iv_init, uint maskOpt,uint id)
{
if ((param_1->random_data == 0 || keyName == 0) || (key_init == 0 || iv_init == 0))
return;
key = new byte[16];
iv = new byte[16];
CEncryptionKeyStore::StoreKeys(store, keyName, key, iv, maskOpt, id);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment