[Delphi - Source] decrypt Skill.bmd
Reversed it on Global MuOnline client when its was S5 ;)
S6 have new charater - Rage Fighter so structure, block size (BLOCK_SIZE = $58;) have some small changes
Source:
Code:
unit Unit29;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
const
ITEM_SKILL = 'C:\Program Files (x86)\Webzen\Mu\Data\Local\Eng\skill_eng.bmd';
BLOCK_SIZE = $58;
type
TSkillInfo = array [0 .. $49] of Byte;
PSkillInfo = ^TSkillInfo;
type
TSkill_Info_Log = packed record
SkillID: Integer;
Req_mana: Word;
Req_Stamina: Word;
end;
PSkill_Info_Log = ^TSkill_Info_Log;
type
TObj_SkillInfo = packed record
Name: array [0 .. 31] of AnsiChar;
SkillLevel: Word;
Damage: Word;
Mana: Word;
Agility: Word;
Distance: Cardinal;
TimeDelay: Cardinal;
Req_Energy: Cardinal;
Req_Level: Word;
Property_1: Byte;
UseType: Byte;
Brand: Byte;
KillCount: Byte;
Req_Stats_0: Byte;
Req_Stats_1: Byte;
Req_Stats_2: Byte;
DW_SM: Byte;
DK_BK: Byte;
Elf_ME: Byte;
MG: Byte;
DL: Byte;
SUM: Byte;
Rage: Byte;
IconNumber: Byte;
SkillType: Byte;
end;
PObj_SkillInfo = ^TObj_SkillInfo;
type
TForm31 = class(TForm)
Memo1: TMemo;
Button1: TButton;
ComboBox1: TComboBox;
Button2: TButton;
Button3: TButton;
Button4: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure ComboBox1Change(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form31: TForm31;
a: TArray<TObj_SkillInfo>;
implementation
{$R *.dfm}
procedure _DecryptBlock(var Block: TSkillInfo);
const
Key : array [0 .. 2] of Byte = ($FC, $CF, $AB);
var
i: Integer;
begin
for i := 0 to BLOCK_SIZE do
begin
Block[i] := Block[i] xor Key[i mod 3];
end;
end;
(*
$50, $6F, $69, $73, $6F, $6E, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
$1E, $00, $0C, $00, $2A, $00, $00, $00, $06, $00, $00, $00, $00, $00, $00, $00,
$64, $00, $00, $00, $00, $00, $01, $00, $00, $00, $00, $00, $00, $01, $00, $00,
$01, $00, $00, $00, $00, $00, $02, $00, $00, $00, $00, $00, $00, $00, $00, $00
*)
procedure TForm31.Button1Click(Sender: TObject);
var
Fs: TStream;
Buffer: TBytes;
i, e, TotalBlocks: Integer;
x: TSkillInfo;
begin
try
Fs := TFileStream.Create(ITEM_SKILL, fmOpenRead);
try
SetLength(Buffer, Fs.Size -4);
Fs.ReadBuffer(Buffer[0], Length(Buffer));
finally
Fs.Free
end;
for i := 0 to 299 do
begin
x := PSkillInfo(@Buffer[(i * BLOCK_SIZE)])^;
_DecryptBlock(x);
SetLength(a, High(a) +2);
a[i] := PObj_SkillInfo(@x[0])^;
Memo1.Lines.Add(IntToStr(i)+ ' '+(a[i].Name)+ ' BK can use it? (0: No / 1: Yes / 2: Only BK / 3: Next; ('+ IntToStr(a[i].DK_BK)+') AG: '+IntToStr(a[i].Distance));
end;
except
On E: Exception do
begin
Memo1.Lines.Add(E.Message);
Exit;
end;
end;
end;
procedure TForm31.Button2Click(Sender: TObject);
var
i: Integer;
x: PSkill_Info_Log;
begin
ComboBox1.Items.Clear;
for i := low(a) to high(a) do
if (a[i].DK_BK > 0) and (a[i].Distance > 0) then
begin
New(x);
x^.SkillID := i;
x^.Req_mana := a[i].Mana;
x^.Req_Stamina := a[i].Agility;
ComboBox1.Items.AddObject(A[i].Name,Pointer(x));
end;
ComboBox1.ItemIndex := 0;
end;
procedure TForm31.ComboBox1Change(Sender: TObject);
begin
Memo1.Lines.Add(
' Skill: ' + ComboBox1.Items[ComboBox1.ItemIndex] +
' Skill ID: ' + IntToStr(PSkill_Info_Log(ComboBox1.Items.Objects[ComboBox1.ItemIndex])^.SkillID)+
' Need Mana: ' + IntToStr(PSkill_Info_Log(ComboBox1.Items.Objects[ComboBox1.ItemIndex])^.Req_mana)+
' Need Stamina: ' + IntToStr(PSkill_Info_Log(ComboBox1.Items.Objects[ComboBox1.ItemIndex])^.Req_Stamina)
)
end;
end.
Ps. i also have Items.bmd decrypt source somewhere on HDD (if i dont deleted it) if i found i share it to, if i dint share it allready
Tip to < D2010 users "a: TArray<TObj_SkillInfo>;" rename it to a: array of TObj_SkillInfo;
Have fun with it - more power to DELPHI :ott1:
1 Attachment(s)
Re: [Delphi - Source] decrypt Skill.bmd
http://www.youtube.com/watch?v=-RFA0KBbPwQ
reversed all again for my own needs!
Code:
unit Unit19;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm19 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
const
BLOCK_SIZE = $58;
MAX_SKILL = $28A;
type
TObj_SkillBlock = array [0 .. BLOCK_SIZE -1] of Byte;
PObj_SkillBlock = ^TObj_SkillBlock;
TObj_SkillArray = array[0 .. MAX_SKILL -1] of TObj_SkillBlock;
PObj_SkillArray = ^TObj_SkillArray;
TObj_SkillInfo = packed record
Name: array [0 .. $31] of AnsiChar; // $31 ? 0_o
SkillLevel: Word;
Damage: Word;
Mana: Word;
Agility: Word;
Distance: Cardinal;
TimeDelay: Cardinal;
Req_Energy: Cardinal;
Req_Level: Word;
Property_1: Byte;
UseType: Byte;
Brand: Byte;
KillCount: Byte;
Req_Stats_0: Byte;
Req_Stats_1: Byte;
Req_Stats_2: Byte;
DW_SM: Byte;
DK_BK: Byte;
Elf_ME: Byte;
MG: Byte;
DL: Byte;
SUM: Byte;
Rage: Byte;
IconNumber: Byte;
SkillType: Byte;
end; // 46
PObj_SkillInfo = ^TObj_SkillInfo;
TObj_SkillInfoArray = array[0 .. MAX_SKILL -1] of TObj_SkillInfo;
PObj_SkillInfoArray = ^TObj_SkillInfoArray;
var
Form19: TForm19;
implementation
{$R *.dfm}
function 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));
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 _DecryptBlock(var Block: TObj_SkillBlock);
const
Key : array [0 .. 2] of Byte = ($FC, $CF, $AB);
var
K: Integer;
begin
for K := 0 to BLOCK_SIZE -1 do
Block[K] := Block[K] xor Key[K mod 3];
end;
procedure TForm19.Button1Click(Sender: TObject);
const
ITEM_SKILL = 'C:\Program Files (x86)\Webzen\Mu\Data\Local\Eng\skill_eng.bmd';
var
Buffer: TBytes;
X: TObj_SkillArray;
K: Integer;
Skill: TObj_SkillInfoArray;
begin
ShowMessage(IntToStr(SizeOf(TObj_SkillInfo)));
Buffer := ReadBMDFile(ITEM_SKILL);
if Buffer = nil then
Exit
else
begin
X := PObj_SkillArray(@Buffer[0])^;
for K := 0 to MAX_SKILL -1 do
_DecryptBlock(X[K]);
Skill := PObj_SkillInfoArray(@X[0])^;
end;
end;
end.
Reversed from current gmo client (Season6 ep 2 r 3)
PS.
Name: array [0 .. $31] of AnsiChar; // $31 ? 0_o
this aint right, i just added size to fix record ;)
Re: [Delphi - Source] decrypt Skill.bmd
i dont know delphi..haha..but tnx for the source...nice release..sir mauka..i will try to learn this delphi..^^...