[Delphi - Source] Calculate BMD file checksum

Results 1 to 4 of 4
  1. #1
    NN - Nord & Noob mauka is offline
    MemberRank
    Jul 2004 Join Date
    1,735Posts

    big grin [Delphi - Source] Calculate BMD file checksum

    Made a new tread to more easy seach for google bot

    ChecksumGen:
    Code:
    function BMDChecksum (var Buffer: TBytes; const Key: DWORD): DWORD;
    var
     F, K: DWORD;
     i, e: Integer;
    begin
     K := Key shl 9;
     i := 0;
     e := 1;
     F := (((K + PDWORD(@Buffer[i])^) + Key) shr e) xor (K + PDWORD(@Buffer[i])^);
    
     while i < Length(Buffer) do
      begin
       if i > 0 then
        begin
         F :=  ((F + Key) shr e ) xor F;
        end;
       inc(i, 4);
       F := F xor PDWORD(@Buffer[i])^;  //A5969BC6
       inc(i, 4);
       F := F + PDWORD(@Buffer[i])^;
       inc(i, 4);
       F := F xor PDWORD(@Buffer[i])^;
       inc(i, 4);
       F := F + PDWORD(@Buffer[i])^;
    
       if e = 1 then
        e := 5
       else
        e := 1
      end;
     Result := F;
    end;
    Example:

    Code:
    {*******************************************************}
    {                                                       }
    {       BMDFIXER                                        }
    {                                                       }
    {       Copyright (C) 2011 6748222@Gmail.com            }
    {                                                       }
    {*******************************************************}
    
    unit uMainFrm;
    
    interface
    
    uses
      Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
      Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls, ABOUT;
    
    const
     ITEM_ENG_BMD                       = $E2F1;
     SKILL_ENG_BMD                      = $5A18;
     ITEMSETTYPE_ENG_BMD                = $E5F1;
     ITEMSETOPTION_ENG_BMD              = $A2F1;
     FILTER_BMD                         = $3E7D;
     MASTERSKILLTREEDATA_BMD            = $2BC1;
     MASTERSKILLTREETOOLTIPDATA_ENG_BMD = $2BC1;
     FILTERNAME_BMD                     = $2BC1;
     ITEMTOOLTIP_BMD                    = $E2F1;
     ITEMLEVELTOOLTIP_BMD               = $E2F1;
     ITEMLEVELTOOLTIPTEXT_BMD           = $E2F1;
    
     FILTER_BMD_BLOCK                   = $14;
    
    type
      TMainFrm = class(TForm)
        Button1: TButton;
        Open: TOpenDialog;
        Log: TMemo;
        Button2: TButton;
        Button3: TButton;
        ListView1: TListView;
        Label1: TLabel;
        procedure Button1Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
        procedure Button2Click(Sender: TObject);
        procedure Button3Click(Sender: TObject);
      private
       Key: DWORD;
      public
       procedure LoadBMD(const FileName: TFileName);
       function ReadBMDFile(const FileName: TFileName): TBytes;
      end;
    
      TFilterName = array [0 .. FILTER_BMD_BLOCK] of Byte;
      PFilterName = ^TFilterName;
    
      TFilterBMD = packed record
       FilterName: array [0 .. $3E8] of TFilterName;
      end;
      PFilterBMD = ^TFilterBMD;
    
    var
      MainFrm: TMainFrm;
      Filter_Array: TFilterBMD;
    
    implementation
    
    {$R *.dfm}
    
    function BMDChecksum (var Buffer: TBytes; const Key: DWORD): DWORD;
    var
     F, K: DWORD;
     i, e: Integer;
    begin
     K := Key shl 9;
     i := 0;
     e := 1;
     F := (((K + PDWORD(@Buffer[i])^) + Key) shr e) xor (K + PDWORD(@Buffer[i])^);
    
     while i < Length(Buffer) do
      begin
       if i > 0 then
        begin
         F :=  ((F + Key) shr e ) xor F;
        end;
       inc(i, 4);
       F := F xor PDWORD(@Buffer[i])^;  //A5969BC6
       inc(i, 4);
       F := F + PDWORD(@Buffer[i])^;
       inc(i, 4);
       F := F xor PDWORD(@Buffer[i])^;
       inc(i, 4);
       F := F + PDWORD(@Buffer[i])^;
    
       if e = 1 then
        e := 5
       else
        e := 1
      end;
     Result := F;
    end;
    
    function TMainFrm.ReadBMDFile(const FileName: TFileName): TBytes;
    var
     Fs: TStream;
    begin
     Result := nil;
     try
      Fs := TFileStream.Create(FileName, fmOpenRead);
       try
        SetLength(Result, Fs.Size);
        Fs.Read(Result[0], Length(Result));
        Fs.Position := Length(Result);
       finally
        Fs.Free;
       end;
     except
      on E: Exception do
       MessageDlg('Failed to open file with error: ' + PWideChar(E.Message), mtError, [mbOK], 0);
     end;
    end;
    
    procedure  TMainFrm.LoadBMD(const FileName: TFileName);
    var
     Fs: TStream;
     CheckSum, FileCheckSum: DWORD;
     Buffer: TBytes;
    begin
     try
      Fs := TFileStream.Create(FileName, fmOpenRead);
       try
        SetLength(Buffer, Fs.Size -4);
        Fs.Read(Buffer[0], Length(Buffer));
        Fs.Position := Length(Buffer);
        Fs.Read(CheckSum, 4)
       finally
        Fs.Free;
       end;
    
      FileCheckSum := BMDChecksum(Buffer, Key);
    
      if (CheckSum = FileCheckSum) then
       Log.Lines.Add('Checksum mached!')
      else
       if MessageBox(0, 'Checksum of file does not mach, fix it?', 'Wrong checksum!', MB_ICONQUESTION or MB_YESNO) = 6 then
        begin
         RenameFile(FileName, FileName + '.ORIGINAL');
    
         try
          Fs := TFileStream.Create(FileName, fmCreate or fmShareExclusive);
          try
           Fs.Write(Buffer[0], Length(Buffer));
           Fs.Write(CheckSum, 4);
          finally
           Fs.Free;
          end;
          Log.Lines.Add('File checksum updated! (:');
         except
          on E: Exception do
           begin
            RenameFile(FileName+ '.ORIGINAL', FileName);
            Log.Lines.Add('ERROR ' + E.Message);
           end;
         end;
         Exit;
        end;
     except
      on E: Exception do
       MessageDlg('Failed to open file with error: ' + PWideChar(E.Message), mtError, [mbOK], 0);
     end;
    end;
    
    procedure TMainFrm.Button1Click(Sender: TObject);
    begin
     if Open.Execute then
      begin
       case Open.FilterIndex -1 of
        0: Key := ITEM_ENG_BMD;
        1: Key := SKILL_ENG_BMD;
        3: Key := ITEMSETTYPE_ENG_BMD;
        4: Key := ITEMSETOPTION_ENG_BMD ;
        5: Key := FILTER_BMD ;
        6: Key := MASTERSKILLTREEDATA_BMD;
        7: Key := MASTERSKILLTREETOOLTIPDATA_ENG_BMD;
        8: Key := FILTERNAME_BMD;
        9: Key := ITEMTOOLTIP_BMD;
       10: Key := ITEMLEVELTOOLTIP_BMD;
       11: Key := ITEMLEVELTOOLTIPTEXT_BMD;
       else
        begin
         MessageDlg('Errrrrorr (:', mtWarning, [mbOK], 0);
         Exit;
        end;
       end;
       LoadBMD(Open.FileName)
      end;
    end;
    
    procedure TMainFrm.Button2Click(Sender: TObject);
    begin
     AboutBox.ShowModal
    end;
    
    function _DecryptBlock(var Block: TFilterName; const BlockSize: DWORD): string;
    const
     Key : array [0 .. 2] of Byte = ($FC, $CF, $AB);
    var
     i: Integer;
    begin
     Result := '';
     for i := 0 to BlockSize do
      begin
       Result := Result + Chr(Block[i] xor Key[i mod 3]);
      end;
    end;
    
    procedure TMainFrm.Button3Click(Sender: TObject);
    const
     Key : array [0 .. 2] of Byte = ($FC, $CF, $AB);
     FILTER_BMD_FILE = 'C:\Program Files (x86)\WEBZEN\Mu\Data\Local\Filter.bmd';
    var
     Buffer: TBytes;
     i: Integer;
    
     CheckSum, NewChecksum: DWORD;
     Fs: TStream;
    begin
     Buffer := ReadBMDFile(FILTER_BMD_FILE);
     if (Buffer = nil) then
      Exit // negribu nehuja kodēt
     else
      begin
       for i := 0 to $3E7 do
        begin
         Filter_Array.FilterName[i] := PFilterName(@Buffer[i * FILTER_BMD_BLOCK])^;
    
         with ListView1.Items.Add do
          begin
           Caption := IntToStr(ListView1.Items.Count);
           SubItems.Add(_DecryptBlock(Filter_Array.FilterName[i], FILTER_BMD_BLOCK));
          end;
        end;
      end;
    (*
         {TEST CHECKSUMM and CLEAR FILTERED NAMES}
          CheckSum := PDWord(@Buffer[Length(Buffer) - 4])^;
          Log.Lines.Add(Format('Original checksum is: %x',[CheckSum]));
    
          {Clear filter names}
          FillChar(Buffer[0], Length(Buffer), 0);
          CheckSum := 0;
          SetLength(Buffer, Length(Buffer) - 4);
    
           {Encrypt Buffer}
          for i := 0 to $3E7 do
           Buffer[i] := Buffer[i] xor Key[i mod 3];
    
          {Gen checksum}
          CheckSum := BMDChecksum(Buffer, FILTER_BMD);
          Log.Lines.Add(Format('New checksum is: %x',[CheckSum]));
    
          {Resotre size and set new checksum}
          SetLength(Buffer, Length(Buffer) +4);
          PDWord(@Buffer[Length(Buffer) - 4])^ := CheckSum;
    
          try
           Fs := TFileStream.Create(ExtractFilePath(Application.ExeName) + 'Filter.bmd', fmCreate or fmShareExclusive);
           try
            Fs.Write(Buffer[0], Length(Buffer))
           finally
            Fs.Free
           end;
          except
           on E: Exception do
            Log.Lines.Add('ERROR ' + E.Message);
          end;
        end;
    *)
    end;
    
    procedure TMainFrm.FormCreate(Sender: TObject);
    begin
     Log.Lines.Clear;
     Caption := 'BMDFIXER ver 0.00000000000 and 0000000.2 (:';
    {$REGION 'Debug'}
     {$IFDEF DEBUG}
      Open.InitialDir := 'C:\Program Files (x86)\WEBZEN\Mu\Data\Local\Eng';
     {$ENDIF}
    {$ENDREGION}
    end;
    
    end.
    The is no such a shit as copyright i just layze change header from copyrights to author

    Ps. Started reversing it cause get bored of PWNED by FILTER!!
    Here i started to finnaly code it, but its still dont bypass resourceguard
    Code:
    procedure TMainFrm.Button3Click(Sender: TObject);
    const
     Key : array [0 .. 2] of Byte = ($FC, $CF, $AB);
     FILTER_BMD_FILE = 'C:\Program Files (x86)\WEBZEN\Mu\Data\Local\Filter.bmd';
    var
     Buffer: TBytes;
     i: Integer;
    
     CheckSum: DWORD;
     Fs: TStream;
    begin
     Buffer := ReadBMDFile(FILTER_BMD_FILE);
     if (Buffer = nil) then
      Exit // negribu nehuja kodēt
     else
      begin
       for i := 0 to $3E7 do
        begin
         Filter_Array.FilterName[i] := PFilterName(@Buffer[i * FILTER_BMD_BLOCK])^;
    
         with ListView1.Items.Add do
          begin
           Caption := IntToStr(ListView1.Items.Count);
           SubItems.Add(_DecryptBlock(Filter_Array.FilterName[i], FILTER_BMD_BLOCK));
          end;
        end;
    
         {TEST CHECKSUMM and CLEAR FILTERED NAMES}
          CheckSum := PDWord(@Buffer[Length(Buffer) - 4])^;
          Log.Lines.Add(Format('Original checksum is: %x',[CheckSum]));
    
          {Clear filter names}
          FillChar(Buffer[0], Length(Buffer), 0);
          CheckSum := 0;
          SetLength(Buffer, Length(Buffer) -4);
    
           {Encrypt Buffer}
          for i := 0 to Length(Buffer) do
           Buffer[i] := Buffer[i] xor Key[i mod 3];
    
          {Gen checksum}
          CheckSum := BMDChecksum(Buffer, FILTER_BMD);
          Log.Lines.Add(Format('New checksum is: %x',[CheckSum]));
    
          try
           Fs := TFileStream.Create(ExtractFilePath(Application.ExeName) + 'Filter.bmd', fmCreate or fmShareExclusive);
           try
            Fs.Write(Buffer[0], Length(Buffer));
            Fs.Write(CheckSum, 4)
           finally
            Fs.Free
           end;
          except
           on E: Exception do
            Log.Lines.Add('ERROR ' + E.Message);
          end;
      end;
    end;
    Binnary of project can be found HERE Get source from GC

    Spamm on;
    Check it, BOR will release in next 2 days BOR CHECKSUM FIXER OF BMD xD
    Spamm off;

    Home:
    http://code.google.com/p/bmdfixer/downloads/list
    Attached Files Attached Files
    Last edited by mauka; 24-11-12 at 11:11 AM. Reason: Updated atachament


  2. #2
    NN - Nord & Noob mauka is offline
    MemberRank
    Jul 2004 Join Date
    1,735Posts

    Re: [Delphi - Source] Calculate BMD file checksum

    Layze update archive. There is bug in example, u need change folowed func to this one:
    Code:
    procedure  TMainFrm.LoadBMD(const FileName: TFileName);
    var
     Fs: TStream;
     CheckSum, FileCheckSum: DWORD;
     Buffer: TBytes;
    begin
     try
      Fs := TFileStream.Create(FileName, fmOpenRead);
       try
        SetLength(Buffer, Fs.Size -4);
        Fs.Read(Buffer[0], Length(Buffer));
        Fs.Position := Length(Buffer);
        Fs.Read(CheckSum, 4)
       finally
        Fs.Free;
       end;
    
      FileCheckSum := BMDChecksum(Buffer, Key);
    
      if (CheckSum = FileCheckSum) then
       Log.Lines.Add('Checksum mached!')
      else
       if MessageBox(0, 'Checksum of file does not mach, fix it?', 'Wrong checksum!', MB_ICONQUESTION or MB_YESNO) = 6 then
        begin
         RenameFile(FileName, FileName + '.ORIGINAL');
    
         try
          Fs := TFileStream.Create(FileName, fmCreate or fmShareExclusive);
          try
           Fs.Write(Buffer[0], Length(Buffer));
           Fs.Write(FileCheckSum, 4);
          finally
           Fs.Free;
          end;
          Log.Lines.Add('File checksum updated! (:');
         except
          on E: Exception do
           begin
            RenameFile(FileName+ '.ORIGINAL', FileName);
            Log.Lines.Add('ERROR ' + E.Message);
           end;
         end;
         Exit;
        end;
     except
      on E: Exception do
       MessageDlg('Failed to open file with error: ' + PWideChar(E.Message), mtError, [mbOK], 0);
     end;
    end;
    Code:
    procedure TMainFrm.Button1Click(Sender: TObject);
    begin
     if Open.Execute then
      begin
       case Open.FilterIndex -1 of
        0: Key := ITEM_ENG_BMD;
        1: Key := SKILL_ENG_BMD;
        2: Key := ITEMSETTYPE_ENG_BMD;
        3: Key := ITEMSETOPTION_ENG_BMD;
        4: Key := FILTER_BMD ;
        5: Key := MASTERSKILLTREEDATA_BMD;
        6: Key := MASTERSKILLTREETOOLTIPDATA_ENG_BMD;
        7: Key := FILTERNAME_BMD;
        8: Key := ITEMTOOLTIP_BMD;
        9: Key := ITEMLEVELTOOLTIP_BMD;
       10: Key := ITEMLEVELTOOLTIPTEXT_BMD;
       else
        begin
         MessageDlg('Errrrrorr (:', mtWarning, [mbOK], 0);
         Exit;
        end;
       end;
       LoadBMD(Open.FileName)
      end;
    end;
    I marked bug in this color

    PS. Please note that its only gen a new checksum of BMD file, but dont bypass resource guard.. T_T im layze now, but maybe later check what it do and update code with it xD

    Code:
    [ResourceGuard] Error: Data/Local/filter.bmd file is modified.
    Have fun!
    Last edited by mauka; 26-12-11 at 02:16 PM.

  3. #3
    Member DeathArmy is offline
    MemberRank
    Dec 2009 Join Date
    84Posts

    Re: [Delphi - Source] Calculate BMD file checksum

    check the resourceguard

  4. #4
    NN - Nord & Noob mauka is offline
    MemberRank
    Jul 2004 Join Date
    1,735Posts

    Re: [Delphi - Source] Calculate BMD file checksum

    RG checksum can be calculated, but its compare calculated value with const value. I dint checked it alot, but looks like RG checksums values are stored in GameGuard.csr file!

    So for me its useless... cracking gameguard.csr?! i rather then crack RG xD
    For server developers is usefull, but definetly not for me xD

    If u like u can check this tread, there u can see gen func of RG checksum



Advertisement