Skocz do zawartości
  • 👋 Witaj na MPCForum!

    Przeglądasz forum jako gość, co oznacza, że wiele świetnych funkcji jest jeszcze przed Tobą! 😎

    • Pełny dostęp do działów i ukrytych treści
    • Możliwość pisania i odpowiadania w tematach
    • System prywatnych wiadomości
    • Zbieranie reputacji i rozwijanie swojego profilu
    • Członkostwo w jednej z największych społeczności graczy

    👉 Dołączenie zajmie Ci mniej niż minutę – a zyskasz znacznie więcej!

    Zarejestruj się teraz

[TuT] Nietestowana blokada najnowszego Unpackera..


Rekomendowane odpowiedzi

Opublikowano

Zmieniłem w pliku fileextractor.py wszystkie nazwy button na asd i taki efekt:

asdnpk.png.

W żaden z tych tekstów nie da się nacisnąć więc jest to swego rodzaju blokada.

Koniec z MPCForum.pl i ogółem z metinem

:D

 

sunp.png

Sygnatura wykonana przez

Isuribi aka Amelka.

Opublikowano

Tylko teraz pytanie jak zablokować root przed rozpakowaniem. Sposób z ??? odpada, jest unpacker pomijający dane pliki. Programy do niby to blokowania czy innych tam gówien średnio działają bo można takie pliki normalnie rozpakować. Pozostaje jedynie napisać własnego packera..

Koniec z MPCForum.pl i ogółem z metinem

:D

 

sunp.png

Sygnatura wykonana przez

Isuribi aka Amelka.

Opublikowano

Root przed rozpakowaniem? Cóż na to jest dużo sposobów z którymi większość sobie nie radzi. Pomyśle w najbliższym czasie nad zablokowaniem plików eix i epk. A jak narazie to zawsze coś już jesteśmy krok do przodu z zabezpieczeniem się przed Unpackerem. Już nim nic nie wypakują :) Stare unpackery wrócą do łask i myślenie nad rozpakowaniem plików starymi sposobami ;)

Opublikowano

Cóż, na epvp jest source packera w cpp, jeśli ktoś ogarnia to może go przerobić jak mu się tylko podoba z dodatkowymi zabezpieczeniami. Mimo wszystko pomysł z zabezpieczeniem świetny.

Koniec z MPCForum.pl i ogółem z metinem

:D

 

sunp.png

Sygnatura wykonana przez

Isuribi aka Amelka.

Opublikowano

Hm, to z łatwością da się ominąć, wystarczy podglądnąć programem od Cranka zawartość zapakowanych plików. :)

Your superman is here, bitch!

Opublikowano

Dobrze idzie :)

Ale i tak będą coraz to nowsze unpackery, ale dobrze że chociaż to...

Widać sposoby jak lz już nie są jakieś znaczące :|

Ciekawi mnie sposób pakowania plików zabezpieczonych jak patch czy season

Gdyby umieć zabezpieczyć tak pliki, praktycznie nie dałoby się ich rozpakować.

Jak coś źle, to mnie poprawcie :D

sygnatura niezgodna z regulaminem forum mpc rozdział II pkt. 7

Opublikowano

Powszechnie dostępne unpackery mają możliwość rozpakowywania plików z type 0, 1 i 2. YMIR tworzy pliki z type 3 i 4 na które unpackery są non pub.

Koniec z MPCForum.pl i ogółem z metinem

:D

 

sunp.png

Sygnatura wykonana przez

Isuribi aka Amelka.

Opublikowano

Mh, więc packery na type 3,4 też są ? :>

W cenie się nie orientujesz pewnie ? :)

sygnatura niezgodna z regulaminem forum mpc rozdział II pkt. 7

Opublikowano

Phaa kupowanie... Kupisz i co Ci to da? no rozpakujesz jakieś tam pliki i będzie to działać przez powiedzmy 2 miesiące... Potem znowu nowe zabezpieczenie i co ? Znowu kupujesz? Lepiej się samemu nauczyć jak to przerabiać itp. aby nie musieć nic kupować i polegać na własnych umiejętnościach.

 

Prosiłbym o jakieś pliki z type 3 i 4 żeby ktoś na speedyshare wrzucił. Może udałoby mi się coś z tym pokombinować.

Opublikowano

Spatchuj PL'a, metin2_xmas_patch czy jakoś tak. Renifery już są wyciągnięte ale możesz poćwiczyć ;)

Koniec z MPCForum.pl i ogółem z metinem

:D

 

sunp.png

Sygnatura wykonana przez

Isuribi aka Amelka.

Opublikowano

Source Metin2 File Extractor:

 

 

 

/*
Metin2FileExtractor
pushedx
edxLabs

This program serves as a file extractor for the Metin2 data files. The
EIX files are the header files and the EPK files are the data files.
The data can be uncompressed, encrypted, and/or compressed. This code
shows how the client performs the logic.

This was a "for fun" project and done in about ~12 hours of work. I am
releasing this tool and the source code to the elitepvperss' Metin2
community to help spread new knowledge. I have no immediate plans for
a file editor at this time as I'm not playing the game or doing
anything with it. Maybe sometime later though.

I hope you enjoy!
*/

#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <stdio.h>
#include <string>
#include <vector>
#include <sstream>

//--------------------------------------------------------------------------

// Dumps a complete archive
bool DumpArchive(const char * inFolder, const char * name);

//--------------------------------------------------------------------------

int main(int argc, char * argv[])
{
system("cls");
printf("Welcome to the Metin2 File Extractor!\n");
printf("This program was made by pushedx for the elitepvpers' Metin2 community.\n");
printf("This is a free tool for all to use.\n");
printf("It should work on the US/DE version files but Korea is not tested.\n");
printf("Enjoy \n\n");
if(argc != 3)
{
	printf("Usage: Metin2FileExtractor <Path to PAK folder> <Archive title>\n");
	printf("Examples:\n");
	printf("\tMetin2FileExtractor \"C:\\Program Files\\Subagames\\Metin2\\pack\" BGM\n");
	printf("\tMetin2FileExtractor \"C:\\Program Files\\Subagames\\Metin2\\pack\" PC\n");
	printf("\tMetin2FileExtractor \"C:\\Program Files\\Metin2_Germany\\pack\" ETC\n");
	printf("\tMetin2FileExtractor \"C:\\Program Files\\Metin2_Germany\\pack\" root\n");
	system("pause");
	return -1;
}
std::string safecheck = argv[2];
if(safecheck.find_first_of("!@#$%^&*()+={}[]|\\:\";\'<>?,./") != std::string::npos)
{
	printf("Error: The Archive title (%s) contains invalid characters. The program will now exit.\n", argv[2]);
	return -1;
}
printf("Beginning the archive dump. Please be patient while it finishes.\n\n");
bool result = DumpArchive(argv[1], argv[2]);
if(result == true)
{
	printf("The archive dump was successful!\n");
}
else
{
	printf("The archive dump was not successful.\n");
}
printf("Thank you for using the Metin2 File Extractor!\n");
system("pause");
return 0;
}

//--------------------------------------------------------------------------

// The expected magic header value
#define LZ_KEY 0x5A4F434D

//--------------------------------------------------------------------------

struct TEntry1
{
DWORD index;
char filename[160];
DWORD dw1;
DWORD dw2;
DWORD dw3;
DWORD dwSrcSize;
DWORD unpackedCRC;
DWORD dwFileOffset;
BYTE packedType;
BYTE b2;
BYTE b3;
BYTE b4;
};

struct TEntry2
{
DWORD header;
DWORD decryptedBlockSize;
DWORD compressedBlockSize;
DWORD decompressedBlockSize;
};

struct TEntry3
{
DWORD header;
DWORD version;
DWORD fileCount;
};

//--------------------------------------------------------------------------

// For decompressing (ripped from client)
BYTE gLZOData[] =
{
0xB9, 0x9E, 0xB0, 0x02, 0x6F, 0x69, 0x81, 0x05,
0x63, 0x98, 0x9B, 0x28, 0x79, 0x18, 0x1A, 0x00,
};

// For decrypting (ripped from client)
BYTE gLZOData2[] =
{
0x22, 0xB8, 0xB4, 0x04, 0x64, 0xB2, 0x6E, 0x1F,
0xAE, 0xEA, 0x18, 0x00, 0xA6, 0xF6, 0xFB, 0x1C,
};

//--------------------------------------------------------------------------

// Utility decompress function
__declspec(naked) void ASM_LZO_FUNC1()
{
__asm
{
	MOV EDX, DWORD PTR SS:[ESP + 0x08]
	MOV ECX, DWORD PTR SS:[ESP + 0x04]
	PUSH EBX
	PUSH EBP
	PUSH ESI
	MOV ESI, DWORD PTR SS:[ESP + 0x18]
	PUSH EDI
	MOV EAX, 0xC6EF3720
	MOV EDI, 0x20
	LEA EBX, DWORD PTR DS:[EBX]
LABEL1:
	MOV EBX, EDX
	SHR EBX, 0x5
	MOV EBP, EDX
	SHL EBP, 0x4
	XOR EBX, EBP
	MOV EBP, EAX
	SHR EBP, 0x0B
	AND EBP, 0x03
	MOV EBP, DWORD PTR DS:[ESI + EBP * 0x04]
	ADD EBP, EAX
	ADD EBX, EDX
	XOR EBX, EBP
	SUB ECX, EBX
	MOV EBX, ECX
	SHR EBX, 0x05
	MOV EBP, ECX
	SHL EBP, 0x04
	XOR EBX, EBP
	ADD EAX, 0x61C88647
	MOV EBP, EAX
	AND EBP, 0x03
	MOV EBP, DWORD PTR DS:[ESI + EBP * 0x04]
	ADD EBX, ECX
	ADD EBP, EAX
	XOR EBX, EBP
	SUB EDX, EBX
	DEC EDI
JNZ LABEL1
	MOV EAX, DWORD PTR SS:[ESP + 0x20]
	POP EDI
	POP ESI
	POP EBP
	MOV DWORD PTR DS:[EAX], EDX
	MOV DWORD PTR DS:[EAX + 0x04], ECX
	POP EBX
	RETN
}
}

//--------------------------------------------------------------------------

// Decompress function in the client
__declspec(naked) void ASM_LZO_CHECKKEY()
{
__asm
{
	MOV EAX,DWORD PTR SS:[ESP + 0x10]
	MOV ECX, EAX
	AND ECX, 0x80000007
JNG LABEL1
	DEC ECX
	OR ECX, 0xFFFFFFF8
	INC ECX
LABEL1:
JE LABEL2
	SUB EAX, ECX
	ADD EAX, 8
	MOV DWORD PTR SS:[ESP + 0x10],EAX
JMP LABEL3;
LABEL2:
	MOV DWORD PTR SS:[ESP + 0x10],EAX
LABEL3:
	PUSH EBX
	MOV EBX, EAX
	SAR EBX, 0x03
	TEST EBX, EBX
JLE LABEL5

	PUSH EBP
	//MOV EBP, lzoData
	MOV EBP, [ESP + 0x14]

	PUSH ESI
	//MOV ESI, inData
	MOV ESI, [ESP + 0x14]

	PUSH EDI
	//MOV EDI, outBuffer
	MOV EDI, [ESP + 0x14]
LABEL4:
	MOV EAX,DWORD PTR DS:[ESI]
	MOV ECX,[ESI + 0x04]
	PUSH EDI
	PUSH EBP
	PUSH EAX
	PUSH ECX
CALL ASM_LZO_FUNC1
	ADD ESP, 0x10
	ADD EDI, 0x08
	ADD ESI, 0x08
	DEC EBX
JNZ LABEL4
	MOV EAX,DWORD PTR SS:[ESP + 0x20]
	POP EDI
	POP ESI
	POP EBP
LABEL5:
	POP EBX
	RET
}
}

//--------------------------------------------------------------------------

// Wrapper function to decompress data
int LZObject_CheckKey(LPBYTE outBuffer, LPBYTE inData, LPBYTE lzoData, DWORD dwSize)
{
int result = 1;
__asm
{
	mov edx, dwSize

	mov ecx, inData
	sub ecx, 4

	mov eax, lzoData

	mov edi, outBuffer

	push edx
	push eax
	push ecx
	push edi

	call ASM_LZO_CHECKKEY

	MOV EDX, DWORD PTR DS:[EDI]
	MOV EAX, LZ_KEY
	ADD ESP, 0x10
	CMP EDX, EAX
	JE LABEL1
	mov result, 0
LABEL1:
	NOP
}
return result;
}

//--------------------------------------------------------------------------

// Ripped from the client via OllyDbg. It was tedious, but simple work since
// you can set labels in OllyDbg for the new jump locations.
__declspec(naked) void ASM_LZO_DECOMPRESS()
{
__asm
{
	MOV EAX,DWORD PTR SS:[ESP+0x08]
	PUSH EBX
	MOV EBX,DWORD PTR SS:[ESP+0x14]
	PUSH EBP
	PUSH ESI
	MOV ESI,DWORD PTR SS:[ESP+0x10]
	MOV DWORD PTR DS:[EBX],0x00
	PUSH EDI
	MOV CL,BYTE PTR DS:[ESI]
	LEA EBP,DWORD PTR DS:[ESI+EAX]
	MOV EAX,DWORD PTR SS:[ESP+0x1C]
	CMP CL,0x11
JBE label1
	AND ECX,0xFF
	SUB ECX,0x11
	INC ESI
	CMP ECX,0x04
JB label2
label3:
	MOV DL,BYTE PTR DS:[ESI]
	MOV BYTE PTR DS:[EAX],DL
	INC EAX
	INC ESI
	DEC ECX
JNZ label3
JMP label4
label1:
	XOR ECX,ECX
	MOV CL,BYTE PTR DS:[ESI]
	INC ESI
	CMP ECX,0x10
JNB label5
	TEST ECX,ECX
JNZ label6
	CMP BYTE PTR DS:[ESI],0x00
JNZ label7
label8:
	MOV DL,BYTE PTR DS:[ESI+0x01]
	ADD ECX,0xFF
	INC ESI
	TEST DL,DL
JE label8
label7:
	XOR EDX,EDX
	MOV DL,BYTE PTR DS:[ESI]
	INC ESI
	LEA ECX,DWORD PTR DS:[ECX+EDX+0x0F]
label6:
	MOV EDX,DWORD PTR DS:[ESI]
	ADD ESI,0x04
	MOV DWORD PTR DS:[EAX],EDX
	ADD EAX,0x04
	DEC ECX											 //  Switch (cases 1..4)
JE label4
	CMP ECX,0x04
JB label9
label10:
	MOV EDX,DWORD PTR DS:[ESI]						 //  Default case of switch 0055BACA
	SUB ECX,0x04
	MOV DWORD PTR DS:[EAX],EDX
	ADD EAX,0x04
	ADD ESI,0x04
	CMP ECX,0x04
JNB label10
	TEST ECX,ECX
JBE label4
label11:
	MOV DL,BYTE PTR DS:[ESI]
	MOV BYTE PTR DS:[EAX],DL
	INC EAX
	INC ESI
	DEC ECX
JNZ label11
JMP label4
label9:
	MOV DL,BYTE PTR DS:[ESI]						   //  Cases 2,3,4 of switch 0055BACA
	MOV BYTE PTR DS:[EAX],DL
	INC EAX
	INC ESI
	DEC ECX
JNZ label9
label4:
	XOR ECX,ECX										 //  Case 1 of switch 0055BACA
	MOV CL,BYTE PTR DS:[ESI]
	INC ESI
	CMP ECX,0x10
JNB label5
	SHR ECX,0x02
	MOV EDX,EAX
	SUB EDX,ECX
	XOR ECX,ECX
	MOV CL,BYTE PTR DS:[ESI]
	SHL ECX,0x02
	SUB EDX,ECX
	MOV CL,BYTE PTR DS:[EDX-0x801]
	SUB EDX,0x0801
	INC ESI
	MOV BYTE PTR DS:[EAX],CL
	INC EAX
	INC EDX
lable28:
	MOV CL,BYTE PTR DS:[EDX]
	MOV BYTE PTR DS:[EAX],CL
	MOV DL,BYTE PTR DS:[EDX+0x01]
	INC EAX
	MOV BYTE PTR DS:[EAX],DL
	INC EAX
label14:
	MOV CL,BYTE PTR DS:[ESI-0x02]
	AND ECX,0x03
JE label1
label2:
	MOV DL,BYTE PTR DS:[ESI]
	MOV BYTE PTR DS:[EAX],DL
	INC EAX
	INC ESI
	DEC ECX
JNZ label2
	XOR ECX,ECX
	MOV CL,BYTE PTR DS:[ESI]
	INC ESI
label5:
	CMP ECX,0x40										  //  Switch (cases 0..3F)
JB label12
	MOV EDX,ECX										 //  Default case of switch label5
	MOV EDI,EAX
	SHR EDX,0x02
	AND EDX,0x07
	SUB EDI,EDX
	XOR EDX,EDX
	MOV DL,BYTE PTR DS:[ESI]
	SHL EDX,0x03
	SUB EDI,EDX
	DEC EDI
	INC ESI
	SHR ECX,0x05
	DEC ECX
label25:
	MOV DL,BYTE PTR DS:[EDI]
	MOV BYTE PTR DS:[EAX],DL
	MOV DL,BYTE PTR DS:[EDI+0x01]
	INC EAX
	INC EDI
	MOV BYTE PTR DS:[EAX],DL
	INC EAX
	INC EDI
label13:
	MOV DL,BYTE PTR DS:[EDI]
	MOV BYTE PTR DS:[EAX],DL
	INC EAX
	INC EDI
	DEC ECX
JNZ label13
JMP label14
label12:
	CMP ECX,0x20
JB label15
	AND ECX,0x1F										  //  Cases 20,21,22,23,24,25,26,27,28,29,2A,2B,2C,2D,2E,2F,30,31,32,33,34,35,36,37,38,39,3A,3B,3C,3D,3E,3F of switch label5
JNZ label16
	CMP BYTE PTR DS:[ESI],0
JNZ label17
label18:
	MOV DL,BYTE PTR DS:[ESI+0x01]
	ADD ECX,0xFF
	INC ESI
	TEST DL,DL
JE label18
label17:
	XOR EDX,EDX
	MOV DL,BYTE PTR DS:[ESI]
	INC ESI
	LEA ECX,DWORD PTR DS:[ECX+EDX+0x1F]
label16:
	XOR EDX,EDX
	MOV EDI,EAX
	MOV DX,WORD PTR DS:[ESI]
	SHR EDX,0x02
	SUB EDI,EDX
	DEC EDI
	ADD ESI,0x02
JMP label19
label15:
	CMP ECX,0x10
JB label20
	MOV EDX,ECX										 //  Cases 10,11,12,13,14,15,16,17,18,19,1A,1B,1C,1D,1E,1F of switch label5
	MOV EDI,EAX
	AND EDX,0x08
	SHL EDX,0x0B
	SUB EDI,EDX
	AND ECX,0x07
JNZ label21
	CMP BYTE PTR DS:[ESI],0x00
JNZ label22
label23:
	MOV DL,BYTE PTR DS:[ESI+0x01]
	ADD ECX,0xFF
	INC ESI
	TEST DL,DL
JE label23
label22:
	XOR EDX,EDX
	MOV DL,BYTE PTR DS:[ESI]
	INC ESI
	LEA ECX,DWORD PTR DS:[ECX+EDX+0x07]
label21:
	XOR EDX,EDX
	MOV DX,WORD PTR DS:[ESI]
	ADD ESI,0x02
	SHR EDX,0x02
	SUB EDI,EDX
	CMP EDI,EAX
JE label24
	SUB EDI,0x4000
label19:
	CMP ECX,0x06
JB label25
	MOV EDX,EAX
	SUB EDX,EDI
	CMP EDX,0x04
JL label25
	MOV EDX,DWORD PTR DS:[EDI]
	ADD EDI,0x04
	MOV DWORD PTR DS:[EAX],EDX
	ADD EAX,0x04
	SUB ECX,0x02
label26:
	MOV EDX,DWORD PTR DS:[EDI]
	SUB ECX,0x04
	MOV DWORD PTR DS:[EAX],EDX
	ADD EAX,0x04
	ADD EDI,0x04
	CMP ECX,0x04
JNB label26
	TEST ECX,ECX
JBE label14
label27:
	MOV DL,BYTE PTR DS:[EDI]
	MOV BYTE PTR DS:[EAX],DL
	INC EAX
	INC EDI
	DEC ECX
JNZ label27
JMP label14
label20:
	SHR ECX,0x02										   //  Cases 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F of switch label5
	MOV EDX,EAX
	SUB EDX,ECX
	XOR ECX,ECX
	MOV CL,BYTE PTR DS:[ESI]
	SHL ECX,0x02
	SUB EDX,ECX
	DEC EDX
	INC ESI
JMP lable28
label24:
	MOV ECX,DWORD PTR SS:[ESP+0x1C]
	SUB EAX,ECX
	CMP ESI,EBP
	MOV DWORD PTR DS:[EBX],EAX
JNZ label29
	POP EDI
	POP ESI
	POP EBP
	XOR EAX,EAX
	POP EBX
	RETN
label29:
	SBB EAX,EAX
	POP EDI
	AND AL,0xFC
	POP ESI
	POP EBP
	ADD EAX, -4
	POP EBX
	RETN
}
}

//--------------------------------------------------------------------------

// Decompress wrapper function
void LZObject_Decompress(LPBYTE src, DWORD srcLen, LPBYTE dst, DWORD * ptrNewLen, void * workMemory)
{
__asm
{
	MOV EDI, src
	MOV EAX, dst
	push workMemory
	MOV EDX, ptrNewLen
	push EDX
	MOV EDX, srcLen
	PUSH EAX
	PUSH EDX
	ADD EDI, 4
	PUSH EDI
	call ASM_LZO_DECOMPRESS
	ADD ESP, 0x14
	TEST EAX, EAX
	JE LABEL1
	INT 3 // Error, don't continue
LABEL1:
	NOP
}
}

//--------------------------------------------------------------------------

// Tokenizes a string into a vector
std::vector<std::string> TokenizeString(const std::string& str, const std::string& delim)
{
// http://www.gamedev.net/community/forums/topic.asp?topic_id=381544#TokenizeString
using namespace std;
vector<string> tokens;
size_t p0 = 0, p1 = string::npos;
while(p0 != string::npos)
{
	p1 = str.find_first_of(delim, p0);
	if(p1 != p0)
	{
		string token = str.substr(p0, p1 - p0);
		tokens.push_back(token);
	}
	p0 = str.find_first_not_of(delim, p1);
}
return tokens;
}

//--------------------------------------------------------------------------

// Saves the file to a specific folder based on the path. The root
// directory I choose to use is named 'output'.
void SaveFile(const char * originalFilename, LPBYTE outBuffer, DWORD outBufferSize)
{
std::stringstream dirPath;
std::vector<std::string> pathTokens = TokenizeString(originalFilename, "\\/");

dirPath << "output";
CreateDirectoryA(dirPath.str().c_str(), NULL);
dirPath << "\\";

size_t index = 0;
for(index = 0; index < pathTokens.size() - 1; ++index)
{
	if(pathTokens[index].find_first_of(":") != std::string::npos)
		continue;
	dirPath << pathTokens[index];
	CreateDirectoryA(dirPath.str().c_str(), NULL);
	dirPath << "\\";
}

dirPath << pathTokens[index];

FILE * of = fopen(dirPath.str().c_str(), "wb");
if(of)
{
	fwrite(outBuffer, 1, outBufferSize, of);
	fclose(of);
}
else
{
	printf("Could not save the file %s\n", dirPath.str().c_str());
}
}

//--------------------------------------------------------------------------

// Dumps a complete archive. I have combined two sets of logic for this,
// but you can separate them if you want a more unique tool that allows
// you to extract individual files or explore the contents.
bool DumpArchive(const char * inFolder, const char * name)
{
HANDLE eixHandle = INVALID_HANDLE_VALUE;
HANDLE epkHandle = INVALID_HANDLE_VALUE;
SECURITY_ATTRIBUTES eixSecurity = {0};
SECURITY_ATTRIBUTES epkSecurity = {0};
DWORD eixFileSize = 0;
DWORD epkFileSize = 0;
HANDLE eixFileMapping = NULL;
HANDLE epkFileMapping = NULL;
LPBYTE eixFileBufferPtr = NULL;
LPBYTE epkFileBufferPtr = NULL;
bool bWasError = false;

std::string eixName_ = inFolder;
if(!(eixName_[eixName_.size() - 1] == '\\' || eixName_[eixName_.size() - 1] == '/'))
{
	eixName_ += "\\";
}
eixName_ += name;
eixName_ += ".eix";

std::string epkName_ = inFolder;
if(!(epkName_[epkName_.size() - 1] == '\\' || epkName_[epkName_.size() - 1] == '/'))
{
	epkName_ += "\\";
}
epkName_ += name;
epkName_ += ".epk";

const char * eixName = eixName_.c_str();
const char * epkName = epkName_.c_str();

eixSecurity.nLength = sizeof(SECURITY_ATTRIBUTES);
eixSecurity.bInheritHandle = TRUE;
eixSecurity.lpSecurityDescriptor = NULL;

epkSecurity.nLength = sizeof(SECURITY_ATTRIBUTES);
epkSecurity.bInheritHandle = TRUE;
epkSecurity.lpSecurityDescriptor = NULL;

// Open the files to access
while(bWasError == false)
{
	eixHandle = CreateFileA(eixName, GENERIC_READ, FILE_SHARE_READ, &eixSecurity, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if(eixHandle == INVALID_HANDLE_VALUE)
	{
		printf("Could not open the %s file. The program will now exit.\n", eixName);
		bWasError = true;
		break;
	}

	epkHandle = CreateFileA(epkName, GENERIC_READ, FILE_SHARE_READ, &epkSecurity, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if(epkHandle == INVALID_HANDLE_VALUE)
	{
		printf("Could not open the %s file. The program will now exit.\n", epkName);
		bWasError = true;
		break;
	}
	break; // All done now
}


// Create the access handles for reading the files
while(bWasError == false)
{
	// We need to store the size of the file for file mapping
	eixFileSize = GetFileSize(eixHandle, NULL);
	if(eixFileSize == INVALID_FILE_SIZE)
	{
		DWORD dwError = GetLastError();
		if(dwError != NO_ERROR)
		{
			printf("There was an error [%i] getting the file size of the %s file. The program will now exit.\n", dwError, eixName);
			bWasError = true;
			break;
		}
	}

	// We need to store the size of the file for file mapping
	epkFileSize = GetFileSize(epkHandle, NULL);
	if(epkFileSize == INVALID_FILE_SIZE)
	{
		DWORD dwError = GetLastError();
		if(dwError != NO_ERROR)
		{
			printf("There was an error [%i] getting the file size of the %s file. The program will now exit.\n", dwError, epkName);
			bWasError = true;
			break;
		}
	}

	// Create a file mapping object
	eixFileMapping = CreateFileMapping(eixHandle, NULL, PAGE_READONLY, 0, eixFileSize, NULL);
	if(eixFileMapping == 0)
	{
		printf("Could not create a file mapping object for the %s file. The program will now exit.\n", eixName);
		bWasError = true;
		break;
	}

	// Create a file mapping object
	epkFileMapping = CreateFileMapping(epkHandle, NULL, PAGE_READONLY, 0, epkFileSize, NULL);
	if(epkFileMapping == 0)
	{
		printf("Could not create a file mapping object for the %s file. The program will now exit.\n", epkName);
		bWasError = true;
		break;
	}

	// Create a file mapping view
	eixFileBufferPtr = reinterpret_cast<LPBYTE>(MapViewOfFile(eixFileMapping, FILE_MAP_READ, 0, 0, eixFileSize));
	if(eixFileBufferPtr == 0)
	{
		printf("Could not create a view of the the %s file. The program will now exit.\n", eixName);
		bWasError = true;
		break;
	}

	// Create a file mapping view
	epkFileBufferPtr = reinterpret_cast<LPBYTE>(MapViewOfFile(epkFileMapping, FILE_MAP_READ, 0, 0, epkFileSize));
	if(epkFileBufferPtr == 0)
	{
		printf("Could not create a view of the the %s file. The program will now exit.\n", epkName);
		bWasError = true;
		break;
	}

	break; // All done now
}


// Now we need to verify the files we just loaded
while(bWasError == false)
{
	// We need at least 12 bytes
	if(eixFileSize < 0x0C)
	{
		printf("The file size for the %s file is too small. The program will now exit.\n", eixName);
		bWasError = true;
		break;
	}

	// Verify the header
	LPDWORD eixHeader = reinterpret_cast<LPDWORD>(eixFileBufferPtr);
	if(*eixHeader != 0x444B5045) // Some hard coded check
	{
		// Important: This value is read from the client itself. If the client updates, this value
		// would need to be updated as well if it ever changed.
		if(*eixHeader != LZ_KEY)
		{
			printf("The file header for the %s file is incorrect. The program will now exit.\n", eixName);
			bWasError = true;
			break;
		}

		// Get a file header pointer from the buffer
		TEntry2 * eixHeader = (TEntry2 *)eixFileBufferPtr;

		// Store a pointer to the encrypted data
		LPBYTE eixDataBuffer = eixFileBufferPtr + 0x14;

		// We don't care about this check because we will create the
		// buffers ourselves in dynamic memory. The game wants to be as
		// efficient as possible though.
		if(eixHeader->decompressedBlockSize <= 0x10000)
		{
		}

		// Allocate space for the decompressed buffer
		LPBYTE decompressedBuffer = new BYTE[eixHeader->decompressedBlockSize];
		memset(decompressedBuffer, 0, eixHeader->decompressedBlockSize);

		// If the contents of the file are not encrypted (no test data yet)
		// So, not going to add the implementation at this time.
		if(eixHeader->decryptedBlockSize == 0)
		{
			printf("[TODO] -- eixHeader of %s is not encrypted!\n", eixName);
			bWasError = true;
			delete [] decompressedBuffer;
			break;
		}

		// We don't care about this check because we will create the
		// buffers ourselves in dynamic memory. The game wants to be as
		// efficient as possible though.
		if(eixHeader->decryptedBlockSize < 0x2000)
		{
		}

		// Create a buffer to decrypt the contents of the exi header into
		LPBYTE compressedBuffer = new BYTE[eixHeader->decryptedBlockSize];
		memset(compressedBuffer, 0, eixHeader->decryptedBlockSize);

		// Try to decrypt the data
		int result = LZObject_CheckKey(compressedBuffer, eixDataBuffer, gLZOData, eixHeader->decryptedBlockSize);
		if(result == 0)
		{
			delete [] decompressedBuffer;
			delete [] compressedBuffer;
			printf("There was an error decrypting the data of the %s file. The program will now exit.\n", eixName);
			bWasError = true;
			break;
		}

		// Try to decompress the data now
		DWORD finalSize = 0;
		LZObject_Decompress(compressedBuffer, eixHeader->compressedBlockSize, decompressedBuffer, &finalSize, 0);

		// Make sure the file size matches
		if(finalSize != eixHeader->decompressedBlockSize)
		{
			delete [] decompressedBuffer;
			delete [] compressedBuffer;
			printf("There was an error decompressing the data of the %s file. The program will now exit.\n", eixName);
			bWasError = true;
			break;
		}

		// Get a pointer to the new file header
		TEntry3 * entry3 = (TEntry3 *)decompressedBuffer;

		// Check the file version
		if(entry3->version != 2)
		{
			delete [] decompressedBuffer;
			delete [] compressedBuffer;
			printf("The version of the %s file is incorrect. Expected (%i) Actual (%i). The program will now exit.\n", eixName, 2, entry3->version);
			bWasError = true;
			break;
		}

		// Make sure we have a match in the number of entries and the expected block size
		if(finalSize != (((entry3->fileCount + entry3->fileCount * 2) << 0x06) + 0x0C))
		{
			delete [] decompressedBuffer;
			delete [] compressedBuffer;
			printf("The pack index file size of the %s file is incorrect. The program will now exit.\n", eixName);
			bWasError = true;
			break;
		}

		// Store a pointer to the block of data
		LPBYTE decompressedBlock = decompressedBuffer + 0x0C;

		// If we have files to process
		if(entry3->fileCount > 0)
		{
			// Build a filename for our dump file
			std::string dumpFileName = eixName;
			dumpFileName = dumpFileName.substr(1 + dumpFileName.find_last_of("\\/"));
			dumpFileName = dumpFileName.substr(0, dumpFileName.find_first_of("."));
			dumpFileName += "_dump.txt";

			// Create the output file for the eix header dump
			FILE * of = fopen(dumpFileName.c_str(), "w");
			if(of == 0)
			{
				printf("There was an error creating the %s file. The header data will not be dumped.\n", dumpFileName.c_str());
			}

			// Loop through all of the files
			for(DWORD x = 0; x < entry3->fileCount; ++x)
			{
				// Create a pointer to the file entry block
				TEntry1 * pEntry = (TEntry1 *)decompressedBlock;

				// Make sure there is a value here
				if(pEntry->dw2 == 0)
				{
					printf("No dw2 field set for the file %s\n", pEntry->filename);
					continue;
				}

				// Simple entry dump
				if(of)
				{
					fprintf(of, "%i. ", pEntry->index);
					fprintf(of, "%s\n", pEntry->filename);
					fprintf(of, "[%.8X]", pEntry->dw1);
					fprintf(of, "[%.8X]", pEntry->dw2);
					fprintf(of, "[%.8X]", pEntry->dw3);
					fprintf(of, "[%.8X]", pEntry->dwSrcSize);
					fprintf(of, "[%.8X]", pEntry->unpackedCRC);
					fprintf(of, "[%.8X]", pEntry->dwFileOffset);
					fprintf(of, "[%.2X %.2X %.2X %.2X]", pEntry->packedType, pEntry->b2, pEntry->b3, pEntry->b4);
					fprintf(of, "\n");
				}

				// Not compressed, no extra header
				if(pEntry->packedType == 0)
				{
					SaveFile(pEntry->filename, epkFileBufferPtr + pEntry->dwFileOffset, pEntry->dwSrcSize);
				}

				// Header and compressed/encrypted
				else
				{
					// Decompress
					if(pEntry->packedType == 1)
					{
						// Calculate the data pointer to the entry data block
						LPBYTE pDataPtr = epkFileBufferPtr + pEntry->dwFileOffset;

						// Get a pointer to the header for this block
						TEntry2 * pEntryHeader = (TEntry2*)pDataPtr;

						// Make sure the header is correct
						DWORD h = *(reinterpret_cast<LPDWORD>(pDataPtr));
						if(h != LZ_KEY)
						{
							printf("The header for %s is incorrect. Expected (%x) Actual (%x).\n", pEntry->filename, LZ_KEY, h);
							continue;
						}

						// Allocate memory for the uncompressed data
						LPBYTE uncompressedData = new BYTE[pEntryHeader->decompressedBlockSize];
						memset(uncompressedData, 0, pEntryHeader->decompressedBlockSize);

						// Decompress the data
						LZObject_Decompress(pDataPtr + 16, pEntryHeader->compressedBlockSize, uncompressedData, &finalSize, 0);

						// Make sure the operation went right
						if(finalSize != pEntryHeader->decompressedBlockSize)
						{
							printf("File size for %s differs from expected. Expected (%i) Actual (%i).\n", pEntry->filename, pEntryHeader->decompressedBlockSize, finalSize);
						}
						else
						{
							SaveFile(pEntry->filename, uncompressedData, pEntryHeader->decompressedBlockSize);
						}

						// Cleanup now
						delete [] uncompressedData;
					}

					// Decrypt + Decompress
					else if(pEntry->packedType == 2)
					{
						// Calculate the data pointer to the entry data block
						LPBYTE pDataPtr = epkFileBufferPtr + pEntry->dwFileOffset;

						// Get a pointer to the header for this block
						TEntry2 * pEntryHeader = (TEntry2*)pDataPtr;

						DWORD h = *(reinterpret_cast<LPDWORD>(pDataPtr));
						if(h != LZ_KEY)
						{
							printf("The header for %s is incorrect. Expected (%x) Actual (%x).\n", pEntry->filename, LZ_KEY, h);
							continue;
						}

						// Create a buffer for the decrypted data
						LPBYTE decryptedData = new BYTE[pEntryHeader->decryptedBlockSize];
						memset(decryptedData, 0, pEntryHeader->decryptedBlockSize);

						// Decrypt the data
						int result = LZObject_CheckKey(decryptedData, pDataPtr + 20, gLZOData2, pEntryHeader->decryptedBlockSize);
						if(result == 0)
						{
							printf("There was an error decrypting the data for the %s file. It will be skipped.\n", pEntry->filename);
							delete [] decryptedData;
							continue;
						}

						// Create a buffer for the final uncompressed data
						LPBYTE uncompressedData = new BYTE[pEntryHeader->decompressedBlockSize];
						memset(uncompressedData, 0, pEntryHeader->decompressedBlockSize);

						// Decompress
						LZObject_Decompress(decryptedData, pEntryHeader->compressedBlockSize, uncompressedData, &finalSize, 0);

						// Make sure the file sizes match
						if(finalSize != pEntryHeader->decompressedBlockSize)
						{
							printf("File size for %s differs from expected. Expected (%i) Actual (%i)\n", pEntry->filename, pEntryHeader->decompressedBlockSize, finalSize);
						}
						else
						{
							SaveFile(pEntry->filename, uncompressedData, pEntryHeader->decompressedBlockSize);
						}

						// Cleanup now
						delete [] decryptedData;
						delete [] uncompressedData;
					}
				}
				decompressedBlock += 0xC0; // next block
			}

			// Close our output file for the header dump file
			if(of)
			{
				fclose(of);
			}
		}

		// Cleanup
		delete [] decompressedBuffer;
		delete [] compressedBuffer;
	}
	else
	{
		// If we get here, we are using an unsupported type of file that
		// was not accessible at the time this tool was written.
		printf("[TODO] -- if(*eixHeader != 0x444B5045)\n");
		bWasError = true;
		break;
	}

	break; // All done now
}

// Cleanup

if(eixFileMapping != 0)
	CloseHandle(eixFileMapping);
if(epkFileMapping != 0)
	CloseHandle(epkFileMapping);

if(eixHandle != INVALID_HANDLE_VALUE)
	CloseHandle(eixHandle);
if(epkHandle != INVALID_HANDLE_VALUE)
	CloseHandle(epkHandle);

// Return the status
return (bWasError == false);
}

//--------------------------------------------------------------------------

 

 

 

Poza tym pisze się "Nie testowana"

KONTO TEGO UŻYTKOWNIKA ZOSTAŁO ZABLOKOWANE

Opublikowano

Jak widać packer obsługuje tylko type 0, 1 i 2 (to source nie zostało stworzone przez tima)

Koniec z MPCForum.pl i ogółem z metinem

:D

 

sunp.png

Sygnatura wykonana przez

Isuribi aka Amelka.

Opublikowano

Trzeba było kupować pół roku temu, teraz ci nikt nie sprzeda.

Co z tego jak już wprowadzają 5 typ plikow.

sygnatura niezgodna z regulaminem forum mpc rozdział II pkt. 7

Opublikowano

Gdyby było source packera to mozna by kombinować, ale jedyne source jakie było na pvpersach to unpack fileextractor, chyba, że dali coś nowego

Opublikowano

Jak narazie zajmuje sie binka z ktorej moge wyciagnac potrzebne mi informacje potem bede sie przejmowal przerobkami packera :P A source mi nie potrzebne mam wlasne.

Opublikowano

a pytanko, był sposób na skompilowanie kilku plików clienta w .bin czy w .exe

Da się tak całego clienta spakować ? :)

sygnatura niezgodna z regulaminem forum mpc rozdział II pkt. 7

Opublikowano

Mam takie małe pytanie do was .. Wiecie może czy ktoś rozpakował już binke z 2011/2012 roku z metka? Czy wyciągali te pliki po prostu tym unpackerem co teraz go pokazali?

Opublikowano

Tenma, taka że możnaby wyciągać samodzielnie pliki z oficjalnych klientów.

Koniec z MPCForum.pl i ogółem z metinem

:D

 

sunp.png

Sygnatura wykonana przez

Isuribi aka Amelka.

Zarchiwizowany

Ten temat przebywa obecnie w archiwum. Dodawanie nowych odpowiedzi zostało zablokowane.

×
×
  • Dodaj nową pozycję...