| 456 | */ |
| 457 | |
| 458 | DWORD DetectFileKeyBySectorSize(LPDWORD EncryptedData, DWORD dwSectorSize, DWORD dwDecrypted0) |
| 459 | { |
| 460 | DWORD dwDecrypted1Max = dwSectorSize + dwDecrypted0; |
| 461 | DWORD dwKey1PlusKey2; |
| 462 | DWORD DataBlock[2]; |
| 463 | |
| 464 | // We must have at least 2 DWORDs there to be able to decrypt something |
| 465 | if(dwSectorSize < 0x08) |
| 466 | return 0; |
| 467 | |
| 468 | // Get the value of the combined encryption key |
| 469 | dwKey1PlusKey2 = (EncryptedData[0] ^ dwDecrypted0) - 0xEEEEEEEE; |
| 470 | |
| 471 | // Try all 256 combinations of dwKey1 |
| 472 | for(DWORD i = 0; i < 0x100; i++) |
| 473 | { |
| 474 | DWORD dwSaveKey1; |
| 475 | DWORD dwKey1 = dwKey1PlusKey2 - StormBuffer[MPQ_HASH_KEY2_MIX + i]; |
| 476 | DWORD dwKey2 = 0xEEEEEEEE; |
| 477 | |
| 478 | // Modify the second key and decrypt the first DWORD |
| 479 | dwKey2 += StormBuffer[MPQ_HASH_KEY2_MIX + (dwKey1 & 0xFF)]; |
| 480 | DataBlock[0] = EncryptedData[0] ^ (dwKey1 + dwKey2); |
| 481 | |
| 482 | // Did we obtain the same value like dwDecrypted0? |
| 483 | if(DataBlock[0] == dwDecrypted0) |
| 484 | { |
| 485 | // Save this key value. Increment by one because |
| 486 | // we are decrypting sector offset table |
| 487 | dwSaveKey1 = dwKey1 + 1; |
| 488 | |
| 489 | // Rotate both keys |
| 490 | dwKey1 = ((~dwKey1 << 0x15) + 0x11111111) | (dwKey1 >> 0x0B); |
| 491 | dwKey2 = DataBlock[0] + dwKey2 + (dwKey2 << 5) + 3; |
| 492 | |
| 493 | // Modify the second key again and decrypt the second DWORD |
| 494 | dwKey2 += StormBuffer[MPQ_HASH_KEY2_MIX + (dwKey1 & 0xFF)]; |
| 495 | DataBlock[1] = EncryptedData[1] ^ (dwKey1 + dwKey2); |
| 496 | |
| 497 | // Now compare the results |
| 498 | if(DataBlock[1] <= dwDecrypted1Max) |
| 499 | return dwSaveKey1; |
| 500 | } |
| 501 | } |
| 502 | |
| 503 | // Key not found |
| 504 | return 0; |
| 505 | } |
| 506 | |
| 507 | // Function tries to detect file encryption key based on expected file content |
| 508 | // It is the same function like before, except that we know the value of the second DWORD |
no outgoing calls
no test coverage detected