Title Updates
Revision as of 19:27, 3 April 2018 by CelesteBlue (talk | contribs)
Title update downloads are no longer as easy on on PS3. For PSVita title updates, the following path structure is used:
https://gs-sec.ww.|NETWORK|.dl.playstation.net/pl/np/|TITLEID|/|HASH|/|TITLEID|-ver.xml
- NETWORK can be np, sp-int, prod-qa, rc, or e1-np.
- TITLEID is the TitleId of the app. For example: PCSA00007.
- HASH is a secret calculated hash based on the below algorithm:
int main(void) {
char network[0x10];
char titleid[0x10];
// Secret HMAC key found in shell.self
unsigned char key[0x20] = {0x9A, 0x9D, 0x07, 0xD5, 0x61, 0x9C, 0x3F, 0xFD, 0xDF, 0xF7, 0x58, 0xE3, 0xFC, 0x86, 0xC4, 0xB7,
0x79, 0xFD, 0x63, 0x2D, 0x8D, 0xD4, 0x22, 0x54, 0x35, 0xC2, 0xE6, 0x2B, 0x2F, 0x4A, 0x2E, 0x6B };
char uniqdata[0x20];
int i, res;
unsigned char result[0x20];
memset(network, 0, 0x10);
memset(uniqdata, 0, 0x20);
memset(result, 0, 0x20);
memset(titleid, 0, 0x10);
printf("Enter network name (np, prod-qa, sp-int, rc, e1-np):"); scanf_s("%s", network, 0x10);
printf("Enter titleid:"); scanf_s("%s", titleid, 0x10);
sprintf_s(uniqdata, 0x20, "%s_%s", network, titleid);
// Lovely obfuscation
for(i=0; i<0x20; i++)
key[i] ^= 0x7F;
hmac_sha256(key, 0x20, uniqdata, strlen(uniqdata), result);
printf("https://gs-sec.ww.%s.dl.playstation.net/pl/%s/%s/", network, network, titleid);
for(i=0; i<0x20; i++) {
printf("%02x", result[i]);
}
printf("/%s-ver.xml\n", titleid);
// printf("%s\n", orig);
return 0;
}
The hmac_sha256 function is not normal either. The made a couple of error or tweaks so it was not standard. Below is their hmac_sha256 function.
/**
* hmac_sha256_vector - HMAC-SHA256 over data vector (RFC 2104)
* @key: Key for HMAC operations
* @key_len: Length of the key in bytes
* @num_elem: Number of elements in the data vector
* @addr: Pointers to the data areas
* @len: Lengths of the data blocks
* @mac: Buffer for the hash (32 bytes)
*/
void hmac_sha256_vector( u8 *key, size_t key_len, size_t num_elem,
u8 *addr[], size_t *len, u8 *mac)
{
unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */
unsigned char tk[32];
u8 *_addr[6];
size_t _len[6], i;
if (num_elem > 5) {
/*
* Fixed limit on the number of fragments to avoid having to
* allocate memory (which could fail).
*/
return;
}
/* if key is longer than 64 bytes reset it to key = SHA256(key) */
if (key_len > 64) {
sha256_vector(1, &key, &key_len, tk);
key = tk;
key_len = 32;
}
/* the HMAC_SHA256 transform looks like:
*
* SHA256(K XOR opad, SHA256(K XOR ipad, text))
*
* where K is an n byte key
* ipad is the byte 0x36 repeated 64 times
* opad is the byte 0x5c repeated 64 times
* and text is the data being protected */
/* start out by storing key in ipad */
memset(k_pad, 0, sizeof(k_pad));
memcpy(k_pad, key, key_len);
/* XOR key with ipad values */
for (i = 0; i < 64; i++)
k_pad[i] ^= 0x36;
/* perform inner SHA256 */
_addr[0] = k_pad;
_len[0] = 64;
for (i = 0; i < num_elem; i++) {
_addr[i + 1] = addr[i];
_len[i + 1] = len[i];
}
sha256_vector(1 + num_elem, _addr, _len, mac);
// NOTE: SCE HACK - they removed the clearing of the pad in their version.
//memset(k_pad, 0, sizeof(k_pad));
//memcpy(k_pad, key, key_len);
/* XOR key with opad values */
for (i = 0; i < 64; i++)
// NOTE: SCE HACK - they changed the normal 0x5C value to 0x6A
k_pad[i] ^= 0x6A;
/* perform outer SHA256 */
_addr[0] = k_pad;
_len[0] = 64;
_addr[1] = mac;
_len[1] = SHA256_MAC_LEN;
sha256_vector(2, _addr, _len, mac);
}