avatar_Mr.Kernighan

Расшифровка BMD файлов в MU Online и Development - Алгоритмы, Item.bmd, XorEnc3

Автор Mr.Kernighan, 2012 Июнь 27, 02:49

« назад - далее »

0 Пользователи и 1 гость просматривают эту тему.

Ключевые слова [SEO] mu onlinedevelopmentitem.bmdрасшифровка bmd файловxorenc3

Mr.Kernighan

Вообщем, практикую пока вайсверса, поэтому решил начать с Item.bmd. Собственно вот небольшой код расшифровки Item.bmd файла.
Кстати, main 1.07x (и версии выше, может еще быть и пару версий ниже я не проверял) перед тем как начать расшифровку по алгоритму XorEnc3 сначала расшифровывает какой-то ключ, я без понятий что это за ключ...
Ниже собственно и код расшифровки этого ключа. Ключ этот бесполезен и без него можно расшифровать файл Item.bmd, вообщем реверсил все что было в коде.
Функция DecryptKey получает последний параметр что-то вроде ключа: DecryptKey((int)pDstBuf, ITEM_TOTAL_SIZE, 0xE2F1U);
Так вот, возвращаемый результат расшифрованного ключа сравнивается с ключом EncKey и только после сравнения двух этих ключей на равность происходит расшифровка файла. (Ну по крайней мере так устроено у WebZen)

*Примечание: Без этого ключа тоже можно расшифровать файл, так просто устроено у webzen.

Код расшифровки ключа

Перед XorEnc3

Спойлер
int EncKey;
GetFileSize(&EncKey, 1, 4, fp);

int DecryptKey(int pSrcBuf, int Size, unsigned short EncKey)
{
int Dst;
int DecryptedKey = EncKey << 9;

for (unsigned int i = 0; i <= Size - 4; i += 4)
{
memcpy(&Dst, (const void*)(i + pSrcBuf), 4U);

int rest = (EncKey + (i >> 2)) % 2;

if (rest)
{
if (rest == 1)
DecryptedKey += Dst;
}
else
{
DecryptedKey ^= Dst;
}

if (!(i % 10))
DecryptedKey ^= (unsigned int)(DecryptedKey + EncKey) >> ((i >> 2) % 8 + 1);
}
return DecryptedKey;
}
[свернуть]

Все алгоритмы для расшифровки файлов для версии main 1.07X, вероятно будет работать и с версиями старше но не со всеми.

Item.bmd.
Спойлер
#include <iostream>

#include <stdio.h>
#include <conio.h>
#include <windows.h>

const int ITEM_LINE_SIZE = 84;

struct ItemEx
{
char ItemName[30];
BYTE b31;
BYTE b32;
BYTE b33;
BYTE b34;
BYTE b35;
BYTE b36;
BYTE b37;
BYTE b38;
BYTE b39;
BYTE b40;
BYTE b41;
BYTE b42;
BYTE b43;
BYTE b44;
BYTE b45;
BYTE b46;
BYTE b47;
BYTE b48;
BYTE b49;
BYTE b50;
BYTE b51;
BYTE b52;
BYTE b53;
BYTE b54;
BYTE b55;
BYTE b56;
BYTE b57;
BYTE b58;
BYTE b59;
BYTE b60;
BYTE b61;
BYTE b62;
BYTE b63;
BYTE b64;
BYTE b65;
BYTE b66;
BYTE b67;
BYTE b68;
BYTE b69;
BYTE b70;
BYTE b71;
BYTE b72;
BYTE b73;
BYTE b74;
BYTE b75;
BYTE b76;
BYTE b77;
BYTE b78;
BYTE b79;
BYTE b80;
BYTE b81;
BYTE b82;
BYTE b83;
BYTE b84;
};
ItemEx *pItem;

char *DecryptXorEnc(char *lpSrcBuf, int Size)
{
BYTE XorKeys[3] = { 0xFC, 0xCF, 0xAB };

for (int i = 0; i < Size; ++i)
lpSrcBuf[i] ^= XorKeys[i % 3];

return lpSrcBuf;
}

size_t GetFileSize(void *pSrcBuf, size_t Size, size_t Count, FILE *fp)
{
fseek(fp, 0 , SEEK_END);
int ItemSz = ftell(fp);
rewind(fp);
size_t Result = fread(pSrcBuf, Count, Size, fp);
return Result;
}

bool ReadItemBmd(char *pFileName)
{
const int ITEM_TOTAL_LINE_SIZE = ITEM_LINE_SIZE << 13;

pItem = new ItemEx();

char *lpDstBuf = new char[ITEM_TOTAL_LINE_SIZE];
char *lpSrcBuf = new char[ITEM_TOTAL_LINE_SIZE];

FILE *fp = NULL;
if ((fp = fopen(pFileName, "rb")) == NULL)
return false;

FILE *sp = NULL;
if ((sp = fopen(".\ItemDec.txt", "w")) == NULL)
return false;

GetFileSize(lpDstBuf, 1, ITEM_TOTAL_LINE_SIZE , fp);

for (int i = 0; i < ITEM_TOTAL_LINE_SIZE  / ITEM_LINE_SIZE; ++i)
{
lpSrcBuf = DecryptXorEnc(&lpDstBuf[i * ITEM_LINE_SIZE], ITEM_LINE_SIZE);
memcpy(pItem, &lpSrcBuf[0], ITEM_LINE_SIZE);
fprintf(sp, "[%30s][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d][%3d]n",
pItem->ItemName, pItem->b31, pItem->b32, pItem->b33, pItem->b34, pItem->b35, pItem->b36, pItem->b37, pItem->b38, pItem->b39, pItem->b40, pItem->b41, pItem->b42, pItem->b43, pItem->b44, pItem->b45, pItem->b46, pItem->b47, pItem->b48, pItem->b49, pItem->b50,
pItem->b51, pItem->b52, pItem->b53, pItem->b54, pItem->b55, pItem->b56, pItem->b57, pItem->b58, pItem->b59, pItem->b60, pItem->b61, pItem->b62, pItem->b63, pItem->b64, pItem->b65, pItem->b66, pItem->b67, pItem->b68, pItem->b69, pItem->b70, pItem->b71, pItem->b72,
pItem->b73, pItem->b74, pItem->b75, pItem->b76, pItem->b77, pItem->b78, pItem->b79, pItem->b80, pItem->b81, pItem->b82, pItem->b83, pItem->b84);
}

delete [] lpDstBuf, lpSrcBuf;
lpDstBuf = lpSrcBuf = NULL;
delete pItem;
pItem = NULL;

fclose(fp);
fclose(sp);
return true;
}

int main(void)
{
if (!ReadItemBmd(".\Item.bmd"))
{
MessageBoxA(NULL, "Item.bmd - File corrupted.", "Error", MB_ICONERROR);
::ExitProcess(0);
}
std::cout << "Press key!" << std::endl;
std::cin.get(); return 0;
};
[свернуть]

Skill.bmd.
Спойлер
#include <iostream>

#include <stdio.h>
#include <conio.h>
#include <windows.h>

const int SKILL_LINE_SIZE = 80;
const int SKILL_TOTAL_LINE_SIZE = 600;

struct SkillEx
{
char SkillName[32];
WORD wLevel;      // 34
wORD wDamage;    // 36
WORD wReqMana;    // 38
WORD wAG;      // 40
WORD wDistance;  // 42
DWORD dwDelay;    // 46
BYTE wMagic;      // 47
BYTE wLeader;      // 48
BYTE wResistance; // 49
BYTE wType;      // 50
BYTE wUseType;      // 51
BYTE wBrand;      // 52
BYTE wCount;      // 53
BYTE wStatus1;      // 54
BYTE wStatus2;      // 55
BYTE wStatus3;      // 56
BYTE DW;      // 57
BYTE DK;      // 58
BYTE ELF;      // 59
BYTE MG;      // 60
BYTE DL;      // 61
BYTE SUM;      // 62
BYTE IconNumber;  // 63
BYTE SkillType;  // 64
BYTE Unkw1;      // 65
BYTE Unkw2;      // 66
BYTE Unkw3;      // 67
BYTE Unkw4;      // 68
BYTE Unkw5;      // 69
BYTE Unkw6;      // 70
BYTE Unkw7;      // 71
BYTE Unkw8;      // 72
BYTE Unkw9;      // 73
BYTE Unkw10;      // 74
BYTE Unkw11;      // 75
BYTE Unkw12;      // 76
BYTE Unkw13;      // 77
BYTE Unkw14;      // 78
BYTE Unkw15;      // 79
BYTE Unkw16;      // 80
};
SkillEx *pSkill; // 80

char *DecryptXorEnc(char *lpSrcBuf, int Size)
{
BYTE XorKeys[3] = { 0xFC, 0xCF, 0xAB };

for (int i = 0; i < Size; ++i)
lpSrcBuf[i] ^= XorKeys[i % 3];

return lpSrcBuf;
}

size_t GetFileSize(void *pSrcBuf, size_t Size, size_t Count, FILE *fp)
{
fseek(fp, 0 , SEEK_END);
int ItemSz = ftell(fp);
rewind(fp);
size_t Result = fread(pSrcBuf, Count, Size, fp);
return Result;
}

bool ReadSkillBmd(char *pFileName)
{
pSkill = new SkillEx();

char *lpDstBuf = new char[SKILL_TOTAL_LINE_SIZE * SKILL_LINE_SIZE];
char *lpSrcBuf = new char[SKILL_TOTAL_LINE_SIZE * SKILL_LINE_SIZE];

FILE *fp = NULL;
if ((fp = fopen(pFileName, "rb")) == NULL)
return false;

FILE *sp = NULL;
if ((sp = fopen(".\SkillDec.txt", "w")) == NULL)
return false;

GetFileSize(lpDstBuf, 1, SKILL_TOTAL_LINE_SIZE * SKILL_LINE_SIZE, fp);

for (int i = 0; i < SKILL_TOTAL_LINE_SIZE; ++i)
{
lpSrcBuf = DecryptXorEnc(&lpDstBuf[i * SKILL_LINE_SIZE], SKILL_LINE_SIZE);
memcpy(pSkill, &lpSrcBuf[0], SKILL_LINE_SIZE);
fprintf(sp, "[%s][%d][%d][%d][%d][%d][%d][%d][%d][%d][%d][%d][%d][%d][%d][%d][%d][%d][%d][%d][%d  [%d][%d][%d][%d][%d][%d][%d][%d][%d][%d][%d][%d][%d][%d][%d][%d][%d][%d][%d][%d]",
pSkill->SkillName, pSkill->wLevel, pSkill->wDamage, pSkill->wReqMana, pSkill->wAG, pSkill->wDistance, pSkill->dwDelay, pSkill->wMagic, pSkill->wLeader, pSkill->wResistance,
pSkill->wType, pSkill->wUseType, pSkill->wBrand, pSkill->wCount, pSkill->wStatus1, pSkill->Status2, pSkill->Status3, pSkill->DW, pSkill->DK, pSkill->ELF, pSkill->MG, pSkill->DL, pSkill->SUM
pSkill->IconNumber, pSkill->SkillType, pSkill->Unkw1, pSkill->Unkw2, pSkill->Unkw3, pSkill->Unkw4, pSkill->Unkw5, pSkill->Unkw6, pSkill->Unkw7, pSkill->Unkw8, pSkill->Unkw9, pSkill->Unkw10,
pSkill->Unkw11, pSkill->Unkw12, pSkill->Unkw13, pSkill->Unkw14, pSkill->Unkw15, pSkill->Unkw16);
}

delete [] lpDstBuf, lpSrcBuf;
lpDstBuf = lpSrcBuf = NULL;
delete pSkill;
pSkill = NULL;

fclose(fp);
fclose(sp);
return true;
}

int main(void)
{
if (!ReadSkillBmd(".\Skill.bmd"))
{
MessageBoxA(NULL, "Skill.bmd - File corrupted.", "Error", MB_ICONERROR);
::ExitProcess(0);
}
std::cout << "Press key!" << std::endl;
std::cin.get(); return 0;
};
[свернуть]

Gate.bmd
Спойлер
#include <iostream>

#include <stdio.h>
#include <conio.h>
#include <windows.h>

const int GATE_LINE_SIZE = 14;
const int GATE_TOTAL_LINE_SIZE = 512

struct GateEx
{
BYTE Flag;
BYTE Map;
BYTE X1;
BYTE X2;
BYTE Y1;
BYTE Y2;
WORD wGateNumber;
BYTE Dir;
BYTE bBattleZone;
WORD wLevel; // Походу требуемый уровень для прохода
WORD wBattleZoneLvlReq;
};
GateEx *pGate; // 14

char *DecryptXorEnc(char *lpSrcBuf, int Size)
{
BYTE XorKeys[3] = { 0xFC, 0xCF, 0xAB };
for (int i = 0; i < Size; ++i)
lpSrcBuf[i] ^= XorKeys[i % 3];
return lpSrcBuf;
}

size_t GetFileSize(void *pSrcBuf, size_t Size, size_t Count, FILE *fp)
{
fseek(fp, 0 , SEEK_END);
int ItemSz = ftell(fp);
rewind(fp);
size_t Result = fread(pSrcBuf, Count, Size, fp);
return Result;
}

bool ReadGateBmd(char *pFileName)
{
pGate = new GateEx();

char *lpDstBuf = new char[GATE_LINE_SIZE * GATE_TOTAL_LINE_SIZE];
char *lpSrcBuf = new char[GATE_LINE_SIZE * GATE_TOTAL_LINE_SIZE];

FILE *fp = NULL;
if ((fp = fopen(pFileName, "rb")) == NULL)
return false;

FILE *sp = NULL;
if ((sp = fopen(".\GateDec.txt", "w")) == NULL)
return false;

GetFileSize(lpDstBuf, 1, GATE_LINE_SIZE * GATE_TOTAL_LINE_SIZE, fp);

for (int i = 0; i < GATE_TOTAL_LINE_SIZE; ++i)
{
lpSrcBuf = DecryptXorEnc(&lpDstBuf[GATE_LINE_SIZE * i], GATE_LINE_SIZE);
memcpy(pGate, &lpSrcBuf[0], GATE_LINE_SIZE);
fprintf(sp, "[%d][%d][%d][%d][%d][%d][%d][%d][%d][%d][%d]n",
pGate->Flag, pGate->Map, pGate->X1, pGate->X2, pGate->Y1, pGate->Y2, pGate->wGateNumber, pGate->Dir, pGate->bBattleZone, pGate->wLevel, pGate->wBattleZoneLvlReq);
}

delete [] lpDstBuf, lpSrcBuf;
lpDstBuf = lpSrcBuf = NULL;
delete pGate;
pGate = NULL;

fclose(fp);
fclose(sp);
return true;
}

int main(void)
{
if (!ReadGateBmd(".\Gate.bmd"))
{
MessageBoxA(NULL, "Gate.bmd - File corrupted.", "Error", MB_ICONERROR);
::ExitProcess(0);
}
std::cout << "Press key!" << std::endl;
std::cin.get(); return 0;
};
[свернуть]

Filter.bmd
Спойлер
#include <iostream>

#include <stdio.h>
#include <conio.h>
#include <windows.h>

const int FILTER_LINE_SIZE = 20;
const int FILTER_TOTAL_LINE_SIZE = 1000;

struct FilterEx
{
char FilterText[20];
};
FilterEx *pFilter;

char *DecryptXorEnc(char *lpSrcBuf, int Size)
{
BYTE XorKeys[3] = { 0xFC, 0xCF, 0xAB };
for (int i = 0; i < Size; ++i)
lpSrcBuf[i] ^= XorKeys[i % 3];
return lpSrcBuf;
}

size_t GetFileSize(void *pSrcBuf, size_t Size, size_t Count, FILE *fp)
{
fseek(fp, 0 , SEEK_END);
int ItemSz = ftell(fp);
rewind(fp);
size_t Result = fread(pSrcBuf, Count, Size, fp);
return Result;
}

bool ReadFilterBmd(char *pFileName)
{
pFilter = new FilterEx();

char *lpDstBuf = new char[FILTER_TOTAL_LINE_SIZE * FILTER_LINE_SIZE];
char *lpSrcBuf = new char[FILTER_TOTAL_LINE_SIZE * FILTER_LINE_SIZE];

FILE *fp = NULL;
if ((fp = fopen(pFileName, "rb")) == NULL)
return false;

FILE *sp = NULL;
if ((sp = fopen(".\FilterDec.txt", "w")) == NULL)
return false;

GetFileSize(lpDstBuf, 1, FILTER_TOTAL_LINE_SIZE * FILTER_LINE_SIZE, fp);

for (int i = 0; i < FILTER_TOTAL_LINE_SIZE; ++i)
{
lpSrcBuf = DecryptXorEnc(&lpDstBuf[i * FILTER_LINE_SIZE], FILTER_LINE_SIZE);
memcpy(pFilter, &lpSrcBuf[0], FILTER_LINE_SIZE);
fprintf(sp, "[%s]n", pFilter->FilterText);
}

delete [] lpDstBuf, lpSrcBuf;
lpDstBuf = lpSrcBuf = NULL;
delete pFilter;
pFilter = NULL;

fclose(fp);
fclose(sp);
return true;
}

int main(void)
{
if (!ReadFilterBmd(".\Filter.bmd"))
{
MessageBoxA(NULL, "Filter.bmd - File corrupted.", "Error", MB_ICONERROR);
::ExitProcess(0);
}
std::cout << "Press key!" << std::endl;
std::cin.get(); return 0;
};
[свернуть]

FilterName.bmd
Спойлер
#include <iostream>

#include <stdio.h>
#include <conio.h>
#include <windows.h>

const int FILTERNAME_LINE_SIZE = 20;
const int FILTERNAME_TOTAL_LINE_SIZE = 500;

struct FilterNameEx
{
char FilterNameText[20];
};
FilterNameEx *pFilterName;

char *DecryptXorEnc(char *lpSrcBuf, int Size)
{
BYTE XorKeys[3] = { 0xFC, 0xCF, 0xAB };
for (int i = 0; i < Size; ++i)
lpSrcBuf[i] ^= XorKeys[i % 3];
return lpSrcBuf;
}

size_t GetFileSize(void *pSrcBuf, size_t Size, size_t Count, FILE *fp)
{
fseek(fp, 0 , SEEK_END);
int ItemSz = ftell(fp);
rewind(fp);
size_t Result = fread(pSrcBuf, Count, Size, fp);
return Result;
}

bool ReadFilterNameBmd(char *pFileName)
{
pFilterName = new FilterNameEx();

char *lpDstBuf = new char[FILTERNAME_TOTAL_LINE_SIZE * FILTERNAME_LINE_SIZE];
char *lpSrcBuf = new char[FILTERNAME_TOTAL_LINE_SIZE * FILTERNAME_LINE_SIZE];

FILE *fp = NULL;
if ((fp = fopen(pFileName, "rb")) == NULL)
return false;

FILE *sp = NULL;
if ((sp = fopen(".\FilterNameDec.txt", "w")) == NULL)
return false;

GetFileSize(lpDstBuf, 1, FILTERNAME_TOTAL_LINE_SIZE * FILTERNAME_LINE_SIZE, fp);

for (int i = 0; i < FILTERNAME_TOTAL_LINE_SIZE; ++i)
{
lpSrcBuf = DecryptXorEnc(&lpDstBuf[i * FILTERNAME_LINE_SIZE], FILTERNAME_LINE_SIZE);
memcpy(pFilterName, &lpSrcBuf[0], FILTERNAME_LINE_SIZE);
fprintf(sp, "[%s]n", pFilterName->FilterNameText);
}

delete [] lpDstBuf, lpSrcBuf;
lpDstBuf = lpSrcBuf = NULL;
delete pFilterName;
pFilterName = NULL;

fclose(fp);
fclose(sp);
return true;
}

int main(void)
{
if (!ReadFilterNameBmd(".\FilterName.bmd"))
{
MessageBoxA(NULL, "FilterName.bmd - File corrupted.", "Error", MB_ICONERROR);
::ExitProcess(0);
}
std::cout << "Press key!" << std::endl;
std::cin.get(); return 0;
};
[свернуть]

Dialog.bmd
Спойлер
#include <iostream>

#include <stdio.h>
#include <conio.h>
#include <windows.h>

const int DIALOG_LINE_SIZE = 1024;
const int DIALOG_TOTAL_LINES = 200;

struct DialogEx
{
char DialogText[1024];
};
DialogEx *pDialog;

char *DecryptXorEnc(char *lpSrcBuf, int Size)
{
BYTE XorKeys[3] = { 0xFC, 0xCF, 0xAB };

for (int i = 0; i < Size; ++i)
lpSrcBuf[i] ^= XorKeys[i % 3];

return lpSrcBuf;
}

size_t GetFileSize(char *pSrcBuf, size_t Size, size_t Count, FILE *fp)
{
size_t Result = fread(pSrcBuf, Size, Count, fp);
return Result;
}

bool ReadDialogBmd(char *pFileName)
{
pDialog = new DialogEx();

FILE *fp;
if ((fp = fopen(pFileName, "rb")) == NULL)
return false;

FILE *sp;
if ((sp = fopen(".\DialogDec.txt", "w")) == NULL)
return false;

char *lpDstBuf = new char [DIALOG_LINE_SIZE ];

for (int i = 0; i < DIALOG_TOTAL_LINES; ++i)
{
GetFileSize(lpDstBuf, DIALOG_LINE_SIZE, 1, fp);
DecryptXorEnc(&lpDstBuf[0], DIALOG_LINE_SIZE);
memcpy(pDialog, &lpDstBuf[0], DIALOG_LINE_SIZE);
fprintf(sp, "[%s]n", pDialog->DialogText);
}

delete pDialog;
pDialog = NULL;

delete [] lpDstBuf;
lpDstBuf = NULL;

fclose(fp);
fclose(sp);

return true;
}

int main(void)
{
if (!ReadDialogBmd(".\Dialog.bmd"))
{
MessageBoxA(NULL, "Dialog.bmd - File corrupted.", "Error", MB_ICONERROR);
::ExitProcess(0);
}
std::cout << "Press key!" << std::endl;
std::cin.get(); return 0;
};
[свернуть]

Text.bmd
Спойлер
#include <iostream>
#include <vector>
#include <windows.h>
#include <fstream>

#define FILE_PATH ".\Text.bmd"

enum PROGRAM { SUCCESS = 0, WARNING = 1 };

struct TextEx
{
char *Text;
};
TextEx *pText;

size_t GetFileSize(void *lpSrcBuf, size_t Size, size_t Count, FILE *fp)
{
size_t result = fread(lpSrcBuf, Size, Count, fp);
return result;
}

void DecryptXorEnc(char *lpSrcBuf, int Size)
{
BYTE XorKeys[3] = { 0xFC, 0xCF, 0xAB };

for (int i = 0; i < Size; ++i)
lpSrcBuf[i] ^= XorKeys[i % 3];
}

bool ReadTextBmd(char pFileName[], int Size)
{
FILE *fp, *sp;

if ((fp = fopen(pFileName, "rb")) == NULL) return false;
if ((sp = fopen(".\TextDec.txt", "w")) == NULL) return false;

char *lpSrcBuf    = (char*)malloc(strlen(pFileName) + 1);
strcpy(&lpSrcBuf[0], pFileName);
GetFileSize(&lpSrcBuf[0], 6, 1, fp);
int TotalLines = HIWORD(*(int*)lpSrcBuf); // *(int*)lpSrcBuf + 2

if ((*(int*)lpSrcBuf & 0xFFFF) == 0x5447) // Crc
{
pText = new TextEx();

for (int i = 0; i < TotalLines; ++i)
{
GetFileSize((char*)lpSrcBuf, 8, 1, fp);
WORD LineIndex = *(WORD*)&lpSrcBuf[0];
WORD LineTextSize = *(WORD*)&lpSrcBuf[4];
printf("Line Index: %d Line Size: %dn", LineIndex, LineTextSize);
pText[LineIndex].Text = (char*)malloc(LineTextSize + 1);
GetFileSize(&pText[LineIndex].Text[0], 1, LineTextSize, fp);
DecryptXorEnc(&pText[LineIndex].Text[0], LineTextSize);
*(pText[LineIndex].Text + LineTextSize) = '';
fprintf(sp, "[%d][%s]n", LineIndex, pText[LineIndex].Text);
}

free((char*)lpSrcBuf); lpSrcBuf = NULL;
}

fclose(fp);
std::cout << "Decrypted!";
std::cin.get();
return true;
}

int main(void)
{
if (!ReadTextBmd(FILE_PATH, 64))
{
char Msg[30];
sprintf(Msg, "%s - File corrupted.", FILE_PATH);
MessageBoxA(NULL, Msg, "Error", MB_ICONERROR);
return WARNING;
}

std::cin.get();
return SUCCESS;
}
[свернуть]

File: Dec2.dat

Standard xor keys by WebZen

[0x3F08A79B][0xE25CC287][0x93D27AB9][0x20DEA7BF] -> 0x93B6CC
Results of encrypted keys after decryption by WebZen code.

#Module block
0818CB84  6E 1E 01 00 | A5 AD 01 00 | 1B 82 01 00 | 32 9C 02 00  n.Ґ�.,.2њ.
Hex: 0x00011E6E - 0x0001ADA5 - 0x0001821B - 0x00029C32
Dec: 73326 - 109989 - 98843 - 171058

#EncKey block
Not used when decrypting Dec2.dat

#DecKey block
0818CBA4  73 46 00 00 | 84 76 00 00 | 7D 60 00 00 | 85 2B 00 00  sF..,,v..}`.....+..
Hex: 0x00004673 - 0x00007684 - 0x0000607D - 0x00002B85
Dec: 18035 - 30340 - 24701 - 11141

#XorKey block
0818CBB4  34 F2 00 00 | 99 FB 00 00 | 2E 8A 00 00 | 57 FC 00 00  4т..™ы...Љ..Wь..
Hex: 0x0000F234 - 0x0000FB99 - 0x00008A2E - 0x0000FC57
Dec: 62004 - 64409 - 35374 - 64599

Спойлер
#include <iostream>
#include <Windows.h>

#define DEC2_FILE_PATH ".\Dec2.dat"

enum PROGRAM
{
SUCCESS = 0,
WARNING = 1
};

#pragma pack(push, 1) // byte alignment
struct VorbsFile
{
WORD FileHeader; int Size;
};
VorbsFile Buffer;
#pragma pack(pop)

DWORD dwXorKeys[4] = { 0x3F08A79B, 0xE25CC287, 0x93D27AB9, 0x20DEA7BF };
DWORD dwXorTable[4];
DWORD dwModKeysBuf[4];
DWORD dwEncKeysBuf[4];
DWORD dwDecKeysBuf[4];
DWORD dwXorKeysBuf[4];

bool DecryptDec2(LPSTR pFilePath, WORD wFileHeader, BOOL dwLoadModule, BOOL dwLoadEncKey, BOOL dwLoadDecKey, BOOL dwLoadXorKey)
{
HANDLE hFile = CreateFileA(pFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

if (hFile == INVALID_HANDLE_VALUE || hFile == (HANDLE)HINSTANCE_ERROR || hFile == (HANDLE)HANDLE_FLAG_PROTECT_FROM_CLOSE || hFile == (HANDLE)HANDLE_FLAG_INHERIT)
return false;

DWORD dwBytesRead;

ReadFile(hFile, &Buffer, sizeof(VorbsFile), &dwBytesRead, NULL);

//0087C138  |.  66:8B4424 10  MOV AX,WORD PTR SS:[ESP+10]
//0087C13D  |.  66:3B4424 30  CMP AX,WORD PTR SS:[ESP+30]
if (Buffer.FileHeader == wFileHeader)
{
// 0087C163  |.  C1E1 04 SHL ECX,4
// ECX = bool params sum * sizeof xor table + buffer size || bool params sum * 2 ^ 4 + buffer size
if (Buffer.Size == (dwLoadModule + dwLoadEncKey + dwLoadDecKey + dwLoadXorKey) * sizeof(dwXorTable) + sizeof(Buffer))
{
// sizeof dwXorTable = 16;
// the key size is 4 bytes
// therefore, divide by 4 to get 4 bytes of memory proportion

if (dwLoadModule)
{
ReadFile(hFile, dwXorTable, sizeof(dwXorTable), &dwBytesRead, NULL);

for (int i = 0; i < sizeof(dwXorTable) / 4; i++)
{
dwModKeysBuf[i] =    dwXorKeys[i] ^ dwXorTable[i]; printf("[%x]",  dwModKeysBuf[i]);
}
printf("n");
}

// Not used when decrypting Dec2.dat
if (dwLoadEncKey)
{
ReadFile(hFile, dwXorTable, sizeof(dwXorTable), &dwBytesRead, NULL);

for (int i = 0; i < sizeof(dwXorTable) / 4; i++)
{
dwEncKeysBuf[i] = dwXorKeys[i] ^ dwXorTable[i]; printf("[%x]",  dwEncKeysBuf[i]);
}
printf("n");
}

if (dwLoadDecKey)
{
ReadFile(hFile, dwXorTable, sizeof(dwXorTable), &dwBytesRead, NULL);

for (int i = 0; i < sizeof(dwXorTable) / 4; i++)
{
dwDecKeysBuf[i] =    dwXorKeys[i] ^ dwXorTable[i]; printf("[%x]",  dwDecKeysBuf[i]);
}
printf("n");
}

if (dwLoadXorKey)
{
ReadFile(hFile, dwXorTable, sizeof(dwXorTable), &dwBytesRead, NULL);

for (int i = 0; i < sizeof(dwXorTable) / 4; i++)
{
dwXorKeysBuf[i] =    dwXorKeys[i] ^ dwXorTable[i]; printf("[%x]",  dwXorKeysBuf[i]);
}
printf("n");
}
}
else
{
CloseHandle(hFile);
return false;
}
}
CloseHandle(hFile);
return true;
}

int main()
{
if (!DecryptDec2(DEC2_FILE_PATH, 0x1112, 0x01, 0x00, 0x01, 0x01))
{
char Msg[30];
sprintf(Msg, "%s - File corrupted.", DEC2_FILE_PATH);
MessageBoxA(NULL, Msg, "Error", MB_ICONERROR);
}
std::cout << "Decrypted!" << std::endl;
std::cin.get();
return SUCCESS;
}
[свернуть]

Crazzy-

#1
Так ты ето с майна реверснул?  респект)))
Как я понимаю у вз вместо выплевки в файл идет запись в структуру, или уже от себя добавил?:
интересно, можно ли как то дампануть форматированный код )) так чтобы было больше известно о функциях, а то ведь нереально декомпилировать с етим форматированием

Crazzy-


Mr.Kernighan


Crazzy-

А первая unk 99% что BYTE bBattleZone или bool IsBattleZone

Mr.Kernighan

Думаю BYTE bBattleZone так как в структуре это поле имеет один байт.

LoKsTeR

#6
Получается можно расширить Item.bmd для старых версий клиентов?

Crazzy-

ну это врятле)  для этого нужно еще эмулировать контенеры клиента где хранятся ети данные, и перехукать всё в дллку, гемор в общем0)

NightWish

Цитата: Crazzy- от 2012 Июнь 28, 10:15  ну это врятле)  для этого нужно еще эмулировать контенеры клиента где хранятся ети данные, и перехукать всё в дллку, гемор в общем0)

Но всё-таки можно =)

Crazzy-

а ты имееш введу расширить Item.bmd или расширить саму структуру, чтобы можно было до 512 итемов загружать? если ты про это, то тут дело чуток в другом, и делается намного быстрее и легче)

NightWish

#10
Цитата: Crazzy- от 2012 Июнь 28, 11:10  а ты имееш введу расширить Item.bmd или расширить саму структуру, чтобы можно было до 512 итемов загружать? если ты про это, то тут дело чуток в другом, и делается намного быстрее и легче)

Если можно расширить структуру то зачем расширять item.bmd если можно взять уже готовое :)

Хотя раньше задавался целью расширить именно сам Item.bmd но вижу путь полегче =)

Mr.Kernighan

#11
Добавлен Filter.bmd, FilterName.bmd

Спойлер
qwerty
[свернуть]

Добавлен Dialog.bmd

Спойлер
qwerty
[свернуть]

Killbrum

Надо будет как то тебе помочь и вместе написать хороший редактор для му =)

Mr.Kernighan

Агам, я тебя либай снабжать буду а ты формами

Добавлен Text.bmd. Это было немного по сложнее

fStros


Mr.Kernighan


mx3d

Было бы не плохо если сделать: .smd to .bmd with animation

Mr.Kernighan

#17
Я пока мелкий код реверсил, попозже может подумаю над этим.

Добавлен алгоритм расшифровки ключей в файле Dec2.dat, скоро сделаю и их сохранение.
В скором времени добавлю алгоритм расшифровки, сохранения и для ключей файла Enc1.dat, как для клиентской части так и для серверной. Так что Уважаемые администраторы, это поможет Вам избавиться от некоторых читерских программ что используют стандартные ключики от WebZen которые взаимодействуют с протоколом игры. Поэтому не покупайте у Хакума их за 100$ а лучше пожертвуйте мне на пиво на мой wmz кошелек

ausmann

Цитата: Mr.Kernighan от 2012 Июль 02, 11:55  Nope, I'm from Moldova.

Спойлер
qwerty
[свернуть]

лучшеб написал "канада"

Mr.Kernighan


Похожие темы (5)

Сообщений: 37
Просмотров: 21728

Сообщений: 127
Просмотров: 38285

Сообщений: 32
Просмотров: 12553