• Unfortunately, we have experienced significant hard drive damage that requires urgent maintenance and rebuilding. The forum will be a state of read only until we install our new drives and rebuild all the configurations needed. Please follow our Facebook page for updates, we will be back up shortly! (The forum could go offline at any given time due to the nature of the failed drives whilst awaiting the upgrades.) When you see an Incapsula error, you know we are in the process of migration.

[C++ / Delphi - Source] decrypt gameguard *.ini, *.cfg files

NN - Nord & Noob
Loyal Member
Joined
Jul 15, 2004
Messages
1,207
Reaction score
689
This example show how to decrypt config files of GameGuard
eg: MuEng.ini, Mu.ini, Update.cfg etc.

Code:
unit Unit6;

{
 C:\Program Files (x86)\WEBZEN\Mu\GameGuard\MuEng.ini

[GAMEMON]
GAME_NAME=MuEng
UPDATE_SERVER=nprotect.muonline.webzen.net
UPDATE_PATH=/GameGuard/MUGlobal/RealServer/
BACKUP_SERVER=
BACKUP_PATH=
OPTION_VALUE=0
SPEEDCHECK_INTERVAL=1000
GAMECRC=1
USE_GGSCAN=1
SENDERRLOG=3
LOG_SERVER=211.215.21.138
LIMIT_TYAVPDOWN=10
CHECK_GAMEBLOCK=1
USB_EJECT=1


C:\Program Files (x86)\WEBZEN\Mu\MuEngTest.ini
[GAMEMON]
GAME_NAME=MuEngTest
UPDATE_SERVER=nprotect.muonline.webzen.net
UPDATE_PATH=/GameGuard/MUGlobal/TestServer/
BACKUP_SERVER=
BACKUP_PATH=
OPTION_VALUE=0
SPEEDCHECK_INTERVAL=1000
SENDERL=1
GAMECRC=1
USE_GGSCAN=1
SENDERRLOG=3
USE_PROXY=1
REVISION=47
LOG_SERVER=211.233.43.45


C:\Games\MU1_08A+_Full\Mu.ini
[GAMEMON]
GAME_NAME=Mu
UPDATE_SERVER=npro-mu.nefficient.co.kr
UPDATE_PATH=/nProtect/GameGuard/MU/RealServer/
BACKUP_SERVER=
BACKUP_PATH=
OPTION_VALUE=0
SPEEDCHECK_INTERVAL=1000
SENDERL=1
GAMECRC=1
SENDERRLOG=1
USE_GGSCAN=1
REVISION=47
*)

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, wcrypt2;

type
  TForm6 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form6: TForm6;

implementation

{$R *.dfm}

{
Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F

00000190                                  4D 75 2E 69 6E 69             Mu.ini
000001A0   00 6E A1 09 59 E6 56 30  CE 02 65 3C 32 5E 44 FE    n YęV0Ī e<2^Dž
000001B0   2F 67 47 8C FA A8 C8 BC  5F 1D 46 1D F4 A5 57 67   /gGŒśØČ¼_ F ōWg
000001C0   AC 7E CB 7B 47 D4 64 F9  4D 26 5B C0 CD 92 D9 17   ¬~Ė{GŌdłM&[ĄĶ’Ł
000001D0   AE E2 06 14 94 54 69 0A  9F 9E 30 AF A2 F4 B3 B2   ®ā  ”Ti Ÿ˛0Æ¢ō³²
000001E0   68 22 26 81 32 07 00 00  00 40 00 00 00 21 26 81   h"& 2    @   !&
000001F0   32                                                 2
}

procedure TForm6.Button1Click(Sender: TObject);
type
  TGameGuard_Header = packed record
   FirstSignature: Cardinal;
   FileNameSize: Cardinal;
   SignatureSize: Cardinal;
   SecondSignature: Cardinal;
  end;
  PGameGuard_Header = ^TGameGuard_Header;

const
 FPUBKEY: array [0 .. 83] of Byte = (
  $06, $02, $00, $00, $00, $24, $00, $00, $52, $53, $41, $31, $00, $02, $00,
  $00, $01, $00, $01, $00, $FB, $E3, $FC, $09, $AF, $AE, $65, $8C, $96, $4C,
  $C5, $37, $D2, $A4, $77, $E7, $4C, $41, $C2, $CF, $F2, $FE, $2D, $9C, $80,
  $94, $0C, $88, $6D, $B3, $84, $9F, $8C, $22, $A0, $C9, $CD, $C0, $AB, $30,
  $65, $82, $42, $3C, $EE, $3C, $A8, $B7, $11, $D6, $22, $FA, $FB, $23, $F7,
  $72, $CD, $E7, $D0, $6F, $6A, $8E, $96, $E3);

 KEY: array [0 .. 9] of Byte = ($65, $63, $74, $47, $61, $6D, $65, $4D, $6F, $6E);

(*
    DataHdr: array[0 .. 89] of byte = (
  	$4D, $75, $45, $6E, $67, $2E, $69, $6E, $69, $00, // name
    $35, $3C, $05, $11, $01, $07, $24, $B5, $6A, $19, $B2, $A8, $38, $F6, $BD, $E3, // sig
    $21, $7A, $03, $20, $5B, $97, $72, $71, $1F, $36, $48, $B5, $E1, $CB, $9C, $01, // na
    $AA, $21, $DE, $CA, $B4, $6E, $D0, $DD, $53, $0B, $11, $A8, $67, $EC, $CD, $E4, // tu
    $8D, $BA, $E2, $23, $9C, $74, $E7, $33, $BF, $F6, $9D, $3A, $66, $BC, $1B, $D6, // re

    $22, $26, $81, $32,  //keyF
    $0A, $00, $00, $00,  //FileName - 10
    $40, $00, $00, $00,  //Signatures len - 64
    $21, $26, $81, $32   //KeyS
  );
*)

 SIGNATURE1 = $32812622;
 SIGNATURE2 = $32812621;
var
 Fs: TStream;
 Buffer: TBytes;
 Header: TGameGuard_Header;

 Len: DWORD;
 Signature: TBytes;
 i: Integer;
 Result: string;

 hProv: HCRYPTPROV;
 hHash: HCRYPTHASH;
 hKey: HCRYPTKEY;
begin
 try
  Fs := TFileStream.Create('C:\Users\Ronaldo\Downloads\update(1).cfg', fmOpenRead);
   try
    SetLength(Buffer, Fs.Size);
    Fs.ReadBuffer(Buffer[0], Length(Buffer));
   finally
    Fs.Free;
   end;
 except

 end;

  Len := Length(Buffer);
  Len := Len - SizeOf(TGameGuard_Header);
  Header := PGameGuard_Header(@Buffer[Len])^;
  Len := Len - (Header.FileNameSize  + Header.SignatureSize);



  if not (SIGNATURE1 = Header.FirstSignature) or not (SIGNATURE2 = Header.SecondSignature) then
   MessageDlg('0', mtWarning, [mbOK], 0);

  SetLength(Signature, Header.SignatureSize);
  Move(Buffer[Len + Header.FileNameSize], Signature[0], Length(Signature));

 if not CryptAcquireContext(@hProv, nil, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) then
  MessageDlg('1', mtWarning, [mbOK], 0);

 if not CryptCreateHash(hProv, CALG_MD5, 0, 0, @hHash) then
  MessageDlg('2', mtWarning, [mbOK], 0);

 if not CryptImportKey(hProv, @FPUBKEY[0], SizeOf(FPUBKEY), 0, 0, @hKey) then
  MessageDlg('3', mtWarning, [mbOK], 0);

 if not CryptHashData(hHash, @Buffer[0], len + Header.FileNameSize, 0) then
  MessageDlg('4', mtWarning, [mbOK], 0);

 if not CryptVerifySignature(hHash, @Signature[0], Header.SignatureSize, hKey, nil, 0) then
  MessageDlg('5', mtWarning, [mbOK], 0);

 CryptDestroyKey(hKey);
 CryptDestroyHash(hHash);

 if not CryptCreateHash(hProv, CALG_MD5, 0, 0, @hHash) then
  MessageDlg('6', mtWarning, [mbOK], 0);

 if not CryptHashData(hHash, @KEY[0], SizeOf(KEY), 0) then
  MessageDlg('7', mtWarning, [mbOK], 0);

 if not CryptDeriveKey(hProv, CALG_RC4, hHash, 0, @hKey)  then
  MessageDlg('8', mtWarning, [mbOK], 0);

 if not CryptDecrypt(hKey, 0, True, 0, @Buffer[0], @Len) then
  MessageDlg('9', mtWarning, [mbOK], 0);

 CryptDestroyKey(hKey);
 CryptDestroyHash(hHash);
 CryptReleaseContext(hProv, 0);

 for i := 0 to Len -1  do
  Result := Result + Chr(Buffer[i]);

 Memo1.Clear;
 Memo1.Lines.Add(Result)
end;

end.

Original code was in C++, i converted it to Delphi and share as it is ( i dont rember author of C++ code ) :glare:

Encryption uses Private key.. :thumbdown: so i believe there is not posible to modify file and encrypt it back T_T

C++
Code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <windows.h>
#include <wincrypt.h>

#include <winsock.h>

#define VER     "0.1"
#define KEY     "ectGameMon"
#define SIGN1   0x32812622
#define SIGN2   0x32812621
#define PUBKEY  "\x06\x02\x00\x00\x00\x24\x00\x00\x52\x53\x41\x31\x00\x02\x00\x00" \
                "\x01\x00\x01\x00\xFB\xE3\xFC\x09\xAF\xAE\x65\x8C\x96\x4C\xC5\x37" \
                "\xD2\xA4\x77\xE7\x4C\x41\xC2\xCF\xF2\xFE\x2D\x9C\x80\x94\x0C\x88" \
                "\x6D\xB3\x84\x9F\x8C\x22\xA0\xC9\xCD\xC0\xAB\x30\x65\x82\x42\x3C" \
                "\xEE\x3C\xA8\xB7\x11\xD6\x22\xFA\xFB\x23\xF7\x72\xCD\xE7\xD0\x6F" \
                "\x6A\x8E\x96\xE3"


void std_err(int type);


int main(int argc, char *argv[]) {
    FILE        *fd;
    struct stat xstat;
    HCRYPTPROV  hProv;
    HCRYPTHASH  hHash;
    HCRYPTKEY   hKey;
    DWORD       len;
    u_int      buffsz;
    u_char      *buff,
                *input,
                *output,
                *filename,
                *signature;

    struct gameguard_header {
        u_int  sign1;
        u_int  filename_size;
        u_int  signature_size;
        u_int  sign2;
    } *gh = NULL;


    setbuf(stdout, NULL);

    fputs("\n"
        "GameGuard files decrypter "VER"\n"
        "by Luigi Auriemma\n"
        "e-mail: aluigi@autistici.org\n"
        "web:    aluigi.org\n"
        "\n", stdout);

    if(argc < 3) {
        printf("\n"
            "Usage: %s <input_file> <output_file>\n"
            "\n", argv[0]);
        exit(1);
    }

    input  = argv[1];
    output = argv[2];

    printf("- open input file:     %s\n", input);
    fd = fopen(input, "rb");
    if(!fd) std_err(0);

    fstat(fileno(fd), &xstat);
    buffsz = xstat.st_size;
    printf("  filesize:            %u\n", buffsz);

    buff = malloc(buffsz);
    if(!buff) std_err(0);
    len = fread(buff, 1, buffsz, fd);
    fclose(fd);

    len -= sizeof(struct gameguard_header);
    gh = (struct gameguard_header *)(buff + len);
    len -= (gh->filename_size + gh->signature_size);

    if((gh->sign1 != SIGN1) ||
       (gh->sign2 != SIGN2)) {
        printf("\n"
            "Alert: the signs in the file don't match the default signs, I try to continue:\n"
            "       0x%08x (should be 0x%08x) and 0x%08x (should be 0x%08x)\n"
            "\n",
            gh->sign1, SIGN1,
            gh->sign2, SIGN2);
    }

    filename  = buff + len;
    printf("- built-in filename:   %s\n", filename);
    signature = buff + len + gh->filename_size;

    if(!CryptAcquireContext(
        &hProv,
        NULL,
        MS_DEF_PROV,
        PROV_RSA_FULL,
        CRYPT_VERIFYCONTEXT)) std_err(1);

            /* VERIFY SIGNATURE */

    fputs("- verify signature:", stdout);

    if(!CryptCreateHash(
        hProv,
        CALG_MD5,
        0,
        0,
        &hHash)) std_err(1);

    if(!CryptImportKey(
        hProv,
        PUBKEY,
        sizeof(PUBKEY) - 1,
        0,
        0,
        &hKey)) std_err(1);

    if(!CryptHashData(
        hHash,
        buff,
        len + gh->filename_size,
        0)) std_err(1);

    if(!CryptVerifySignature(
        hHash,
        signature,
        gh->signature_size,
        hKey,
        NULL,
        0)) {
        fputs("    WRONG!\n", stdout);
    } else {
        fputs("    OK\n", stdout);
    }

    CryptDestroyKey(hKey);
    CryptDestroyHash(hHash);

            /* DECRYPT DATA */

    if(!CryptCreateHash(
        hProv,
        CALG_MD5,
        0,
        0,
        &hHash)) std_err(1);

    if(!CryptHashData(
        hHash,
        KEY,
        sizeof(KEY) - 1,
        0)) std_err(1);

    if(!CryptDeriveKey(
        hProv,
        CALG_RC4,
        hHash,
        0,
        &hKey)) std_err(1);

    if(!CryptDecrypt(
        hKey,
        0,
        TRUE,
        0,
        buff,
        &len)) std_err(1);

    printf("- write output file:   %s\n", output);
    fd = fopen(output, "wb");
    if(!fd) std_err(0);
    fwrite(buff, len, 1, fd);
    fclose(fd);

    CryptDestroyKey(hKey);
    CryptDestroyHash(hHash);
    CryptReleaseContext(hProv, 0);
    free(buff);
    fputs("- Finished\n", stdout);
    return(0);
}



void std_err(int type) {
    if(type) {
        printf("\n"
            "Error: error during the usage of the cryptography (0x%lx)\n"
            "       If you received a sign error before means this is not a valid GameGuard\n"
            "       INI file\n"
            "\n", GetLastError());
    } else {
        perror("\nError");
    }
    exit(1);
}
 
Back
Top