· 7 years ago · Jul 10, 2018, 07:44 AM
1// 3.71 IPL
2
3void (* main_bin_entry)(void) = (void *)0x04000000;
4
5// 0x040F0000
6void _start()
7{
8 *0xBC100050 |= 0x00007000; // 12/13/14 (ddr, nand, apb) busclk enable
9 *0xBC100078 |= 0x00000002; // nand io enable
10 *0xBE24000C = 1; // gpio port clear
11 *0xBE240000 |= 0x00000001;
12 *0xBC10007C |= 0x00000001; // gpio io enable
13
14 SYNC();
15
16 sp = 0x040FFF00;
17 decrypt((void *)0xBFC00040, 0x280, g_seed64_1, g_seed64_2, &main_bin, 0x6520);
18
19 // kill it all
20 memset(&g_preipl_sha_combine, 0, 0x280);
21 memset(&g_seed64_1, 0, 64);
22 memset(&g_seed64_2, 0, 64);
23
24 // kill stack and heap
25 memset(&main_bin+sizeof(main_bin), 0, 0x040FFF00-&main_bin+sizeof(main_bin)); // inline
26
27 sceKernelDcacheWritebackAll();
28
29 cop0.ctrl.unk17 = *0xBFC00FFC;
30
31 // the first time ipl run
32 if (*0xBFC00FFC >= 0)
33 {
34 // li $t0, 0x040F0188
35 // jr $t0
36 // nop
37 *0xBFD00000 = 0x3C080000 | (0x040F0188 >> 16);
38 *0xBFD00004 = 0x35080000 | (0x040F0188 & 0xFFFF);
39 *0xBFD00008 = 0x01000008;
40 *0xBFD0000C = 0;
41
42 SYNC();
43
44 *0xBC10004C |= 0x00000002; // reset SC cpu
45
46 while(1) SYNC();
47 } // else the second time ipl run (or ME first-time run?)
48
49 memset((void*)0xBFC00000, 0, 0x1000); // inlined
50
510x040F0188:
52
53 cop0.status.SR = 0x60000000; // Status register
54 cop0.status.Cause = 0; // Cause of last exception
55 *0xBC100004 = -1;
56 sceKernelDcacheInvalidateAll();
57
58 // clear the 4KB RAM (was previously mapped to 0xBFD00000)
59 memset((void*)0xBFC00000, 0, 0x1000); // inlined
60 // copy Payload seeds
61 memcpy((void*)0xBFC00000, 0x040FFF00, 0x100); // inlined
62 memset((void*)0x040FFF00, 0, 0x100); // inlined
63
64 sp = 0x040FFF00;
65 // decompress part2 ipl (main.bin)
66 if (sceKernelGzipDecompress(0x04000000, 0xE0000, &main_bin, 0) < 0) while(1);
67
68 // clear caches
69 sceKernelDcacheWritebackAll();
70 sceKernelIcacheInvalidateAll();
71
72 sp = 0x040FFF00;
73 // call part2 ipl (main.bin)
74 main_bin_entry(); // jumps to 0x04000000, does not return
75}
76
77#define HASH_SIZE (32)
78
79// address:0x040F1D00
80u32 g_preipl_sha_combine[160] =
81{
82 0x31D6E207, 0xED1BDD56, 0x4541ECD3, 0xF6069237, 0x9FAB96AD, 0x4B98E931, 0x4CAAD856, 0x6C61EBA7,
83 0x408DE639, 0xF812F1FC, 0x23F8E5CC, 0x453EBA96, 0x2A90299E, 0x85409029, 0x27F1BDF3, 0xF7EE62B5,
84 0x4340E5D2, 0xD5D9C127, 0x0F8F3522, 0xCE4D5A7B, 0x9F574BA7, 0x115F4772, 0xDE79F5FE, 0x34F5DAA6,
85 0x87426F96, 0xA2A087C9, 0x7C727CEF, 0x63C75C40, 0xAF6D629C, 0x6E02B967, 0xE074B4A9, 0xDEBAEFC3,
86 0xE21B9042, 0x13FB034B, 0xB6669D78, 0x3AF3E6E2, 0x0FF93282, 0x1AE584D8, 0x067B9427, 0x5C96C2BD,
87 0x1D807F7B, 0x109962B6, 0x12C47D60, 0x2C8A5D53, 0x6B033959, 0x4BA06F15, 0xDA66D039, 0x23243EB8,
88 0x33F49E9C, 0xADB70AA7, 0xBCAD1D29, 0xBD821329, 0xF8001340, 0x66463488, 0xE7153E50, 0xF05186A5,
89 0xB9E477CB, 0x25B7C7D2, 0x5BA3AEC5, 0x713ABB3D, 0x425E12AE, 0x6955F221, 0x1DF2D872, 0x14FBD592,
90 0x735B4BCB, 0xA72E178D, 0xB6FDDD19, 0xCF123490, 0x8DF8D866, 0x9A149623, 0x1B394456, 0x32B641B8,
91 0xA00F3ABB, 0x1682A4B5, 0x4BA7DA83, 0x672ADF2D, 0xD4BCC799, 0xC9FB1B62, 0x0C801472, 0x22C01573,
92 0x99EC0114, 0x0169E9E2, 0xBF85CD36, 0x748CFC88, 0x5CB339EB, 0xA0BBB8FE, 0xFEB61258, 0x03CA42D5,
93 0xD362D8E3, 0xBE92543D, 0x8DFEB104, 0xE453E259, 0x9C4BCE32, 0xBBB2D7CC, 0x465B299B, 0xBFEAFFDF,
94 0x1C89B9C8, 0x46A2A41E, 0x2B4E36C5, 0xB7776FCF, 0x9577F317, 0x5748DCAD, 0xC3B23DEB, 0x3BD63ED0,
95 0x839C29B3, 0x465B032F, 0xC2B0A33A, 0xA125D9D0, 0xF80CF1CD, 0xAC47D8C0, 0x610D4085, 0x4C6A66D0,
96 0x5B9D4F8D, 0x1AE81FA7, 0x9FA9986D, 0x7AC23F97, 0xE64D35DB, 0x6A6251C3, 0xB5331A8D, 0x95FDA731,
97 0x80ACB9F6, 0x626E057C, 0x3BD91F20, 0x582BF9C5, 0x1E25CA35, 0xBB26B559, 0x2CAC171F, 0x3CE96C90,
98 0xED68424E, 0xCB0B7D92, 0xDEB00641, 0xC244ED6B, 0x8E89A974, 0xAE61FB16, 0xC399322A, 0x38C0D6E3,
99 0x1C19CE06, 0x077F0B2B, 0xC3FAE25F, 0x210BC9DD, 0xA48D0547, 0x6021E1D8, 0xDCF8608B, 0x3099913B,
100 0x2CBA81B1, 0xFDF79A76, 0xBB3989A5, 0xB39070A4, 0x3A4022EE, 0x44622334, 0xE93A474B, 0x411FD84C,
101 0x829DF280, 0x05836B9E, 0x4E8E58D1, 0x63EE93EE, 0x4C951F7B, 0xD6C0CF7D, 0xF8727788, 0x26322796
102};
103
104// address:0x040F1F80
105u8 g_seed64_1[64] =
106{
107 0x33, 0xB2, 0x94, 0xBF, 0xF0, 0x18, 0x5C, 0xDF,
108 0x25, 0x5C, 0x04, 0xF6, 0x80, 0x29, 0x8D, 0xA6,
109 0x1F, 0xC6, 0x3A, 0xF1, 0x24, 0xD7, 0x52, 0xA7,
110 0x53, 0xFC, 0x90, 0xBB, 0xBB, 0x89, 0x9D, 0x54,
111 0x24, 0x2C, 0x64, 0x08, 0x41, 0x99, 0x4E, 0x7A,
112 0x49, 0xD5, 0xF4, 0xE5, 0xC4, 0xC0, 0x90, 0x28,
113 0xD0, 0x47, 0x64, 0x48, 0xD5, 0x1D, 0x46, 0x83,
114 0x46, 0x3F, 0xF9, 0x5E, 0x75, 0xDD, 0x86, 0x3C
115};
116
117// address:0x040F1FC0
118u8 g_seed64_2[64] =
119{
120 0xFA, 0xD6, 0xA8, 0x8E, 0xB5, 0xC8, 0x67, 0x6F,
121 0x22, 0x7D, 0x7C, 0x25, 0xA9, 0x74, 0xB2, 0x64,
122 0xCD, 0x63, 0x69, 0xAA, 0x99, 0x45, 0x99, 0xAE,
123 0x96, 0x57, 0xEC, 0x7B, 0xD8, 0xAC, 0xCB, 0x48,
124 0xB5, 0x34, 0x69, 0x7C, 0x38, 0x98, 0xE9, 0xF0,
125 0x6D, 0xFA, 0x73, 0xCF, 0xBC, 0x89, 0xAE, 0xC5,
126 0x2D, 0x13, 0xAC, 0x11, 0xFF, 0xD7, 0x56, 0xEE,
127 0x3E, 0xBF, 0x8F, 0xB5, 0xC5, 0xDF, 0xFB, 0x71
128};
129
130// address:0x040F2000
131u8 g_preipl_hash_xor[HASH_SIZE] =
132{
133 0x9A, 0x44, 0x72, 0x97, 0x9B, 0xDB, 0x41, 0x45,
134 0x3A, 0x03, 0x9F, 0xD9, 0xEC, 0x2D, 0xF8, 0x0A,
135 0x13, 0xC6, 0x99, 0xBB, 0xB7, 0x1A, 0xCE, 0x91,
136 0x17, 0xEB, 0x91, 0x66, 0xC5, 0x09, 0xC9, 0xE7
137};
138
139// address:0x040F2020
140u8 g_preipl_hash_checksum = 0x20;
141
142
143/*
144 * ADDRESS: 0x040F1048
145 *
146 * preiplBuf - part of the preipl used to seed the prng
147 * preiplBufSize - size of the preipl buffer to pass (usually 0x280 bytes)
148 * seed64_1 - 64-byte buffer to seed a sha256 hash (passed to decrypt_buffer())
149 * seed64_2 - 64-byte buffer to seed a sha256 hash (passed to decrypt_buffer())
150 * mainbin - encrypted main.bin buffer
151 * mainbin_size - sizeof the encrypted main.bin buffer
152 *
153 */
154void decrypt_main_bin(void *preiplBuf, int preiplBufSize, void *seed64_1, void *seed64_2, void *mainbin, int mainbin_Size)
155{
156 SceMt19937Context ctx; // context of the MT19937 prng
157
158 u8 hash[HASH_SIZE]; // sha256 hash to be used to gen the seed for the prng (in decrypt_buffer func)
159 u32 rand[1024]; // buffer to combine the preipl+random num (used as seed to gen the sha256 hash)
160
161 // seed the prng with preipl address
162 sceMt19937Init(&ctx, (u32)preiplBuf);
163
164 // Generate 4KB of random number+preipl (used as seed to gen the sha256 hash)
165 for (i=0; i<1024; i++)
166 rand[i] = *(u32 *)&preiplBuf[i] + sceMt19937UInt(&ctx);
167
168 // generate the 256-bit hash (used to gen the seed for the prng later)
169 gen_hmac(g_preipl_sha_combine, preiplBufSize, rand, sizeof(rand), &hash);
170
171 // kill the buffers after theyve been used
172 memset(&rand, 0, sizeof(rand));
173 memset(&ctx, 0, sizeof(ctx));
174
175 // generate checksum of the sha256 hash
176 u8 checksum = 0;
177 for (i=0; i<HASH_SIZE; i++)
178 checksum += hash[i];
179
180 // check if sha256 hash checksum is correct (0x20 in 3.71)
181 if (checksum == g_preipl_hash_checksum)
182 {
183 // xor with a global buffer stored in ipl to gain
184 // the final hash used to gen the seed for the prng
185 // in the next function
186 for (i=0; i<HASH_SIZE; i++)
187 hash[i] ^= g_preipl_hash_xor[i];
188 }
189
190 // decrypt it (will fail if above step is not taken, ie. if sha256 hash wrong checksum)
191 decrypt_buffer(hash, sizeof(hash), seed64_1, seed64_2, mainbin, mainbin_Size);
192}
193
194
195/*
196 * ADDRESS: 0x040F0E70
197 *
198 * seed - seed buffer for hash (used to gen hash for prng seed)
199 * seedSize - sizeof seed
200 * secretkey1 - buffer to seed the sha256 hash for the prng seed
201 * secretkey2 - buffer to seed the sha256 hash for the xor key
202 * buf - the encrypted buffer to decrypt
203 * bufSize - sizeof of the encrypted buffer
204 *
205 */
206void decrypt_buffer(void *seed, int seedSize, u8 *secretkey1, u8 *secretkey2, void *buf, int bufSize)
207{
208 SceMt19937Context ctx; // prng context
209
210 u32 hmac[8]; // hmac-sha256 to be used for 624-byte initial prng state
211 u32 randomNum[16]; // 64-byte random number used to gen the xor key
212 u32 xorKey[8]; // key used to xor with ciphertext to get plaintext
213
214
215 // generate hmac of the seed to be used for 624-byte initial prng state
216 gen_hmac(secretkey1, 64, seed, seedSize, hmac);
217
218 // setup seed state of the pseudo random number generator
219 ctx.count = 0;
220 for (i=0; i<624; i+=8)
221 memcpy(ctx.state[i], hmac, 32); // fill initial prng state repeatedly with hmac
222
223 // kill the hmac
224 memset(hmac, 0, sizeof(hmac));
225
226
227 // skip the first 624 numbers of the MT
228 // (which were filled repeatedly with the 256-bit hash)
229 for (i=0; i<624; i++)
230 sceMt19937UInt(&ctx);
231
232 // for each 32-bytes of ciphertext
233 for (i=0; i<bufSize; i+=32)
234 {
235 // gen 64-bytes random number
236 for (j=0; j<16; j++)
237 randomNum[j] = sceMt19937UInt(&ctx);
238
239 sceMt19937UInt(&ctx); // skip the next random number
240
241 // generate the 32-byte xor key
242 gen_hmac(secretkey2, 64, randomNum, 64, &xorKey);
243
244 // xor 32-bytes to get plaintext
245 for (j=0; j<8; j++)
246 buf[j] ^= xorKey[j];
247 }
248
249 // kill all
250 memset(&xorKey, 0, sizeof(xorKey));
251 memset(&randomNum, 0, sizeof(randomNum));
252 memset(&ctx, 0, sizeof(ctx));
253}
254
255/*
256 * ADDRESS: 0x040F0CC8
257 *
258 * secretkey - used to generate seed (seed used to init sha256 context)
259 * keylen - sizeof secretkey (obviously)
260 * buf - used to generate stage1 hash (stage1 hash used to generate final hash)
261 * bufSize - sizeof buf (obviously)
262 * hash - sha256 hash to be returned
263 *
264 */
265void gen_hmac(const u8 *secretkey, u32 keylen, const void *buf, int bufsize, u8 *hash)
266{
267 SceSha256Context ctx; // sizeof == 0x70
268
269 u8 keybuf[64];
270 u8 stage1_hash[32];
271
272 // if no buffer for stage1 hash just hash the secretkey then
273 if (!buf || (bufSize==0))
274 sceSha256Digest(secretkey, keylen, hash); return;
275
276
277 memset(keybuf, 0, sizeof(keybuf));
278
279 if (keylen <= 64)
280 sceSha256Digest(secretkey, keylen, keybuf); // gen keybuf from secretkey
281 else
282 memcpy(keybuf, secretkey, keylen); // otherwise just copy into keybuf
283
284
285 // Use buf to generate first stage hash
286 for (i=0; i<sizeof(keybuf); i++)
287 keybuf[i] ^= 0x36;
288
289 sceSha256BlockInit(&ctx);
290 sceSha256BlockUpdate(&ctx, keybuf, sizeof(keybuf));
291 sceSha256BlockUpdate(&ctx, buf, bufSize);
292 sceSha256BlockResult(&ctx, stage1_hash);
293
294
295 // Use the stage1 hash to generate final hash
296 for (i=0; i<sizeof(keybuf); i++)
297 keybuf[i] ^= (0x36 ^ 0x5C);
298
299 sceSha256BlockInit(&ctx);
300 sceSha256BlockUpdate(&ctx, keybuf, sizeof(keybuf));
301 sceSha256BlockUpdate(&ctx, stage1_hash, sizeof(stage1_hash));
302 sceSha256BlockResult(&ctx, hash);
303
304
305 // clean up
306 memset(ctx, 0, sizeof(ctx));
307 memset(keybuf, 0, sizeof(keybuf));
308 memset(stage1_hash, 0, sizeof(stage1_hash));
309}
310
311
312// 0x040F1598
313int sceSha256Digest(const u8 *plain, u32 len, u8 *digest)
314{
315 // not yet
316}
317
318// 0x040F1654
319int sceSha256BlockInit(SceSha1Context *pContext)
320{
321 // not yet
322}
323
324// 0x040F11CC
325int sceSha256BlockUpdate(SceSha1Context *pContext, const u8 *plain, u32 len)
326{
327 // not yet
328}
329
330// 0x040F139C
331int sceSha256BlockResult(SceSha1Context *pContext, u8 *digest)
332{
333 // not yet
334}
335
336// 0x040F16F0
337void sceSha256Core(u32 *blk, u32 *h)
338{
339 // not yet
340}
341
342
343
344typedef struct SceMt19937Context
345{
346 u32 count;
347 u32 state[624];
348} SceMt19937Context;
349
350
351// 0x040F1B60
352int sceMt19937Init(SceMt19937Context *pCtx, u32 seed)
353{
354 u32 *p;
355 int i;
356
357 // Setup seed for MT
358 pCtx->state[0] = seed;
359 p = &pCtx->state[1];
360
361 for (i=1; i<N; i++)
362 {
363 *p = 1812433253 * (p[-1] ^ (p[-1] >> 30)) + i;
364 p++;
365 }
366
367 pCtx->count = 0;
368
369 // skip first 624 numbers (ie. skip the seed state)
370 for (i=0; i<N; i++)
371 sceMt19937UInt(pCtx);
372
373 return 0;
374}
375
376/* Period parameters */
377#define N 624
378#define M 397
379#define MATRIX_A 0x9908b0df /* constant vector a */
380#define UPPER_MASK 0x80000000 /* most significant w-r bits */
381#define LOWER_MASK 0x7fffffff /* least significant r bits */
382
383/* Tempering parameters */
384#define TEMPERING_MASK_B 0x9d2c5680
385#define TEMPERING_MASK_C 0xefc60000
386#define TEMPERING_SHIFT_U(y) (y >> 11)
387#define TEMPERING_SHIFT_S(y) (y << 7)
388#define TEMPERING_SHIFT_T(y) (y << 15)
389#define TEMPERING_SHIFT_L(y) (y >> 18)
390
391// 0x040F1BF0
392// return pseudo-random unsigned int
393u32 sceMt19937UInt(SceMt19937Context *pCtx)
394{
395 u32 i, u, v, x, y, rand;
396
397 i = pCtx->count;
398 u = pCtx->state[i];
399
400 if (i < (N-1))
401 {
402 v = pCtx->state[i+1];
403 pCtx->count++;
404 }
405 else
406 {
407 v = pCtx->state[0];
408 pCtx->count = 0;
409 }
410
411 y = (u & UPPER_MASK) | (v & LOWER_MASK);
412
413 if (v & 1)
414 x = (y>>1) ^ MATRIX_A;
415 else
416 x = (y>>1);
417
418 if (i < (N-M))
419 u = x ^ pCtx->state[i+M];
420 else
421 u = x ^ pCtx->state[i+M-N];
422
423
424 rand = u;
425 rand ^= TEMPERING_SHIFT_U(rand);
426 rand ^= TEMPERING_SHIFT_S(rand) & TEMPERING_MASK_B;
427 rand ^= TEMPERING_SHIFT_T(rand) & TEMPERING_MASK_C;
428 rand ^= TEMPERING_SHIFT_L(rand);
429
430 return(rand);
431}