- /*
- ** VAC decrypter
- **
- ** Special thanks to wav for some infos.
- */
- #include <stdio.h>
- #include <windows.h>
- #include <conio.h>
- #include <Tlhelp32.h>
- #include "Detours.h"
- // Pointer to the decryption function, as of July 16th 2010.
- UINT32 decryptCall = 0x27EE;
- // Offsets to encrypted code blocks. We loop through these in main().
- UINT32 encryptedCodeBlocks[14] = {
- 0x29CE, 0x35A4, 0x7018, 0x14C7,
- 0x1E4F, 0x218F, 0x7331,
- };
- // A struct for vac_encrypted_func.
- typedef struct {
- UINT8 fcn_number; // Number of the encrypted block (unused?)
- UINT32 fcn_size; // Size of the block
- UINT32 fcn_passes; // Passes during decryption (thanks, wav)
- UINT32 fcn_crc32; // CRC32 of the function
- } vac_encrypted_func;
- /*
- ** Here is the VAC decryption function.
- ** The encryption key is 32 bit and can be brute-forced within a day.
- **
- ** The arguments somePointer and something in the function don't seem to be used by anything during
- ** decryption. These arguments seem to be left over from older versions.
- **
- ** somePointer - random block of memory
- ** something - Always 0x2000, maximum size of encrypted code block.
- ** This value is checked in the comparison anyways.
- **
- ** Likely prototype is:
- ** BOOL __cdecl VacDecryptCode( vac_encrypted_func* dwFunction, UINT32* key, UINT8* c, UINT32 d);
- */
- BOOL (__cdecl *VacDecryptCode)(UINT8* dwDestAddress, UINT32* key, UINT8* somePointer, UINT32 something);
- // The decryption key. To get this, hook VacDecryptCode and log the second argument.
- UINT32 key[5];
- // Something to satisfy the third argument to the function with. I have no idea what this is.
- UINT32 more_buffer[0x10000];
- // The last CRC32 hash calculated. This is done within the decryption routine,
- // so we detour at the end of the function and grab the checksum there.
- UINT32 last_crc = 0;
- // A jump inserted at the end of the CRC32 routine lands us here
- // We monitor CRC32's coming off of CRC32_ProcessBuffer
- void __declspec(naked) Crc32Hook() {
- __asm {
- pop esi
- mov last_crc, eax
- mov [edi], eax
- pop ebx
- retn
- }
- }
- int main( int argc, char** argv ) {
- HMODULE hVac = LoadLibraryA("SourceInit.dat");
- if (!hVac) {
- printf("Can't load VAC client\n");
- return 1;
- }
- UINT8* callPtr = (UINT8*)hVac + 0x27ee;
- UINT8* decode_addr = (UINT8*)hVac + 0x35a4;
- printf("hVac %p, Callptr %p\n", hVac, callPtr);
- printf("decoding at %p\n", decode_addr);
- VacDecryptCode = (BOOL (__cdecl *)(UINT8 *,UINT32 *,UINT8 *,UINT32))callPtr;
- UINT8* patchPtr = (UINT8*)hVac + 0x10e67;
- void (*origCrc32)() = (void(*)())patchPtr;
- // hookens
- DetourTransactionBegin();
- DetourUpdateThread( GetCurrentThread() );
- DetourAttach( (PVOID*)&origCrc32, Crc32Hook);
- DetourTransactionCommit();
- printf("Decrypting...\n");
- more_buffer[0] = 325235235;
- key[0] = 0x61DFBEEA;
- key[1] = 0x1177B262;
- //key[2] = 0x78434FDA;
- //key[3] = 0x5A3957F4;
- printf("Key is %p%p\n", key[1], key[0]);
- // This is pretty much what the real VAC does.
- BOOL result = VacDecryptCode( decode_addr, key, (UINT8*)more_buffer, 0x2000);
- if (result)
- printf("Decrypt successful! key %p%p\n", key[1], key[0]);
- else
- printf("Decrypt failed. Key was %p, more_buffer was %p,\noutput CRC32 was %p\n",
- key[0], more_buffer[0], last_crc);
- return 0;
- }