[Guide] Extracting Parsed Packets in Silkroad

07/20/2009 20:32 pushedx#16
Quote:
Originally Posted by prezlee44 View Post
missing preprocessor from the code:
#include <iostream>

And the definition of the edx class is missing. :)
Where can i find it?
Are you using Visual Studio 7.0 or later?

The common.h/common.cpp code is located in [Only registered and activated users can see links. Click Here To Register...].

Quote:
Originally Posted by maniek2006men View Post
How to get codecave_ReadBytes pointer?
i mean "edx::CreateCodeCave(0x4C42FC, 7, codecave_ReadBytes);"

I got all pointers but i don't know how to get this one.
I'll be posting a small update with some additional information soon, but here's the new addresses:

Code:
// Bin: 33 C0 89 46 10 89 46 14 C7 46 08 00 00 00 00 C7 46 04 00 00 00 00 8B C6 5E C2 04 00 CC
#define CC_ExtractSentPacket_Address 0x535BA0
// 56 57 8D 9B 00 00 00 00 8B 73 08 81 E6 FF 0F 00 80 8B FD
#define CC_ExtractSentPacket_Address_1 0x504C4C
// 64 A1 00 00 00 00 50 B8 08 10 00 00
#define CC_ExtractSentPacket_Address_2 0x76F36E

// 2nd call under "SR_RESET_CLIENT"; Case 3369 of switch 007794AA
#define CC_ExtractPacket_Address_1 0x6DC080
// End of read byte function
#define CC_ExtractPacket_Address_2 0x4F312C
//007794AA   .  3D 69330000   CMP EAX,3369                             ;  Switch (cases 3369..B495)
#define CC_ExtractPacket_Address_3 0x7794AA
#define CC_ExtractPacket_Address_4 0x779555
The one you are asking is CC_ExtractPacket_Address_2 I believe. The code in the client is:
Code:
004F312C  |> \5E            POP ESI
004F312D  |.  8BC3          MOV EAX,EBX
004F312F  |.  5B            POP EBX
004F3130  \.  C2 0800       RETN 8
07/21/2009 03:13 schlurmann#17
Why do you use WriteProcessMemory when you're injected?
07/21/2009 04:58 pushedx#18
Quote:
Originally Posted by schlurmann View Post
Why do you use WriteProcessMemory when you're injected?
If you are talking about in the OnInject function, there is no reason in particular, other than I used that code from another project of mine where it was needed. You could use the other provided WriteBytes function if you wanted to though.

There are cases where you should use WPM if you are inside DLLMain and injected into a process rather than a memcpy since the CRT might not yet be initialized (for the DLL versions) and you get a nasty error when trying to start the program. Using a static CRT should avoid that issue, but it's easy to forget to change that. This issue is always avoided in my case since I call the exported function after DLLMain is finished, so all functions are safe to use.
07/21/2009 17:54 schlurmann#19
Quote:
Originally Posted by pushedx View Post
If you are talking about in the OnInject function, there is no reason in particular, other than I used that code from another project of mine where it was needed. You could use the other provided WriteBytes function if you wanted to though.

There are cases where you should use WPM if you are inside DLLMain and injected into a process rather than a memcpy since the CRT might not yet be initialized (for the DLL versions) and you get a nasty error when trying to start the program. Using a static CRT should avoid that issue, but it's easy to forget to change that. This issue is always avoided in my case since I call the exported function after DLLMain is finished, so all functions are safe to use.
It's unecessary when you're injected. Just use a pointer. And I never got any errors with that.
07/22/2009 16:15 pushedx#20
I've made a little update for the new (unpacked) client. This version should be a lot easier to update in the future as opposed to the original version posted. This guides code is also combined with the other guides for extracting built packets. This is the simple version of the analyzer that just has the code for console logging and is ready for you to do with it what you want.

DLL.h
Code:
#pragma once

// Bin: 33 C0 89 46 10 89 46 14 C7 46 08 00 00 00 00 C7 46 04 00 00 00 00 8B C6 5E C2 04 00 CC
// First line in function
#define CC_ExtractSentPacket_Address 0x535BA0

// 56 57 8D 9B 00 00 00 00 8B 73 08 81 E6 FF 0F 00 80 8B FD
// MOV EBX,ECX
// MOV DWORD PTR SS:[ESP+10],EAX
#define CC_ExtractSentPacket_Address_1 0x504C4C

// 64 A1 00 00 00 00 50 B8 08 10 00 00
// MOV EAX, 1008
#define CC_ExtractSentPacket_Address_2 0x76F9DE

// 2nd call address under "SR_RESET_CLIENT"; Case 3369 of switch 007794AA
// CALL sro_clie.006DC6F0 <--
#define CC_ExtractPacket_Address_1 0x6DC6F0

// End of ReadBytes function
// POP ESI
// MOV EAX,EBX
// POP EBX
// RETN 8
#define CC_ExtractPacket_Address_2 0x4F312C

// First CMP above "MSGID:0x%04X Wait My Char Data !!!"
//CMP EAX, 3369
#define CC_ExtractPacket_Address_3 0x779B1A

// Line of second call below "SR_RESET_CLIENT"; Case 3369 of switch 007794AA
// --> 00779555   .  E8 262BF6FF   CALL 200_clie.006DC080
#define CC_ExtractPacket_Address_4 0x779BC5
DLL.cpp
Code:
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include "../common/common.h"
#include "DLL.h"

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

// Global instance handle to this DLL
HMODULE gInstance = NULL;

// Function prototype
void UserOnInject();
void UserOnDeinitialize();

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

// Main DLL entry point
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ulReason, LPVOID lpReserved)
{
	UNREFERENCED_PARAMETER(lpReserved);
	if(ulReason == DLL_PROCESS_ATTACH)
	{
		gInstance = hModule;
		// Do not notify this DLL of thread based events
		DisableThreadLibraryCalls(hModule);
	}
	else if(ulReason == DLL_PROCESS_DETACH)
	{
		UserOnDeinitialize();
	}
	return TRUE;
}

// This is the main function that is called when the DLL is injected into the process
extern "C" __declspec(dllexport) void OnInject(DWORD address, LPDWORD bytes)
{
	// Restore the original bytes at the OEP
	DWORD wrote = 0;
	WriteProcessMemory(GetCurrentProcess(), UlongToPtr(address), bytes, 6, &wrote);

	// Call our user function to keep this function clean
	UserOnInject();
}

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

namespace CC_ExtractSentPacket
{
	DWORD currentOpcode;
	LPBYTE currentBuffer;
	DWORD currentSize;

	void OnProcessDataStart()
	{
		printf("[ClientToServer][%X]\n", currentOpcode);
	}

	void ProcessData()
	{
		for(DWORD x = 0; x < currentSize; ++x)
		{
			printf("%.2X ", currentBuffer[x]);
			if((x+1)%16 == 0)
				printf("\n");
		}
		printf("\n");
	}

	void OnProcessDataEnd()
	{
		printf("\n\n");
	}

	void EnableParseHook();
	void DisableParseHook();

	DWORD codecave_SetOpcode_ReturnAddress = 0;
	__declspec(naked) void codecave_SetOpcode()
	{
		__asm pop codecave_SetOpcode_ReturnAddress
		__asm MOV AX,WORD PTR SS:[ESP + 0x04] // Original code
		__asm mov currentOpcode, eax
		__asm pushad
		EnableParseHook(); // Start hooking writes
		__asm popad
		__asm push codecave_SetOpcode_ReturnAddress
		__asm ret
	}

	DWORD codecave_WriteBytes_ReturnAddress = 0;
	__declspec(naked) void codecave_WriteBytes()
	{
		__asm pop codecave_WriteBytes_ReturnAddress

		__asm mov currentBuffer, eax
		__asm mov currentSize, ebp

		__asm pushad
		ProcessData();
		__asm popad

		// Even though this comes first, we will use EBX and then fix it up
		// afterwards. This is ok since ECX is not disturbed.
		//__asm MOV EBX, ECX

		// This line seems to give the client problems when compiled in VS,
		// so we have to rewrite it a little. This might be one of the hardest
		// things to figure out if you were doing this yourself and not
		// too experienced.
		//__asm MOV DWORD PTR SS:[ESP + 0x10],EAX

		__asm
		{
			mov ebx, esp
			add ebx, 0x10
			mov [ebx], eax
		}

		// Now set our EBX value to what it should be
		__asm MOV EBX, ECX

		__asm push codecave_WriteBytes_ReturnAddress
		__asm ret
	}

	DWORD codecave_PostProcessPacket1_ReturnAddress;
	__declspec(naked) void codecave_PostProcessPacket1()
	{
		__asm pop codecave_PostProcessPacket1_ReturnAddress

		// We choose this line because it is the easiest to codecave and won't likely change
		__asm MOV EAX, 0x1008 // Remember #s have to be in HEX! 1008 != 0x1008

		__asm pushad
		DisableParseHook();
		OnProcessDataEnd();
		__asm popad

		__asm push codecave_PostProcessPacket1_ReturnAddress
		__asm ret
	}

	void EnableParseHook()
	{
		// A little trick I came up with to filter out the packets received
		// that make use of this functionality. Not sure if it'll always work,
		// but it "should" since the higher 4 bytes of any C->S packet in the
		// executable will be 0 since they are hard coded into the client!
		DWORD result = currentOpcode & 0xFFFF0000;

		//printf("Result = %i\n", result); // Debugging
		if(result == 0)
		{
			// Hook the byte writing function
			edx::CreateCodeCave(CC_ExtractSentPacket_Address_1, 6, codecave_WriteBytes);

			// Hook the post build processing function
			edx::CreateCodeCave(CC_ExtractSentPacket_Address_2, 5, codecave_PostProcessPacket1);

			// Let the user know we have an new packet being built
			OnProcessDataStart();
		}
	}

	void DisableParseHook()
	{
		// Restore the byte writing function code
		static BYTE patch1[] = {0x8B, 0xD9, 0x89, 0x44, 0x24, 0x10};
		edx::WriteBytes(CC_ExtractSentPacket_Address_1, patch1, 6);

		// Restore the post build processing function code
		static BYTE patch2[] = {0xB8, 0x08, 0x10, 0x00, 0x00};
		edx::WriteBytes(CC_ExtractSentPacket_Address_2, patch2, 5);
	}

	void Setup()
	{
		edx::CreateCodeCave(CC_ExtractSentPacket_Address, 5, codecave_SetOpcode);
	}
}

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

namespace CC_ExtractPacket
{
	FARPROC fpHandler = (FARPROC)CC_ExtractPacket_Address_1;

	DWORD currentOpcode;
	LPBYTE currentBuffer;
	DWORD currentSize;

	void OnProcessDataStart()
	{
		printf("[ServerToClient][%X]\n", currentOpcode);
	}

	void ProcessData()
	{
		for(DWORD x = 0; x < currentSize; ++x)
		{
			printf("%.2X ", currentBuffer[x]);
			if((x+1)%16 == 0)
				printf("\n");
		}
		printf("\n");
	}

	void OnProcessDataEnd()
	{
		printf("\n\n");
	}

	DWORD codecave_ExtractPacket_ReturnAddress = 0;

	__declspec(naked) void codecave_ExtractPacket()
	{
		__asm pop codecave_ExtractPacket_ReturnAddress
		__asm mov currentOpcode, eax
		__asm pushad
		OnProcessDataStart();
		__asm popad
		__asm CMP EAX, 0x3369 // Original code
		__asm push codecave_ExtractPacket_ReturnAddress
		__asm ret
	}

	DWORD codecave_ReadBytes_ReturnAddress = 0;

	__declspec(naked) void codecave_ReadBytes()
	{
		__asm pop codecave_ReadBytes_ReturnAddress

		__asm mov currentBuffer, eax
		__asm mov currentSize, ebx

		__asm pushad
		ProcessData();
		__asm popad

		// Emulate the rest of the function since our codecave overlaps it all
		__asm POP ESI
		__asm MOV EAX,EBX
		__asm POP EBX
		__asm RET 8
	}

	void EnableParseHook()
	{
		edx::CreateCodeCave(CC_ExtractPacket_Address_2, 7, codecave_ReadBytes);
	}

	void DisableParseHook()
	{
		static BYTE patch[] = {0x5E, 0x8B, 0xC3, 0x5B, 0xC2, 0x08, 0x00};
		edx::WriteBytes(CC_ExtractPacket_Address_2, patch, 7);
		OnProcessDataEnd();
	}

	DWORD codecave_InvokeHandlers_ReturnAddress;
	__declspec(naked) void codecave_InvokeHandlers()
	{
		__asm pop codecave_InvokeHandlers_ReturnAddress

		__asm pushad
		EnableParseHook();
		__asm popad

		// We have to use this trick as VS does not support calling direct memory addresses
		__asm call fpHandler

		__asm pushad
		DisableParseHook();
		__asm popad

		__asm push codecave_InvokeHandlers_ReturnAddress
		__asm ret
	}

	void Setup()
	{
		edx::CreateCodeCave(CC_ExtractPacket_Address_3, 5, codecave_ExtractPacket);
		edx::CreateCodeCave(CC_ExtractPacket_Address_4, 5, codecave_InvokeHandlers);
	}
}

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

// The function where we place all our logic
void UserOnInject()
{
	// Create a debugging console
	edx::CreateConsole("edxAnalyzer Debugging Console");

	// Mutex for the launcher, no patches required to start Silkroad now
	CreateMutexA(0, 0, "Silkroad Online Launcher");
	CreateMutexA(0, 0, "Ready");

	CC_ExtractSentPacket::Setup();
	CC_ExtractPacket::Setup();
}

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

void UserOnDeinitialize()
{
}

//-------------------------------------------------------------------------
I've also attached a GUI version of the analyzer from edx33 so the packets log to the GUI window instead of the console. That version is a much nicer development tool, but it's just a temporary solution for now. For users of the 2008 EE, you can't compile the project because of the resource editing limitations in EE, so I've also attached a binary version. If it doesn't work for you, your unpacked client might be different from mine.

[Only registered and activated users can see links. Click Here To Register...]

One important thing to note about this method is that some packets don't display correctly or some seem parsed weird. The reason for this has to do with how the client works. This method is not a 100% accurate way of how the client parses the packets because the client maintains packet states internally so it can discard some data.

That means some packets might parse unexpectedly or only show portions of their data payload rather than the full packet. An example is B505, where if you cast Grasswalk, you won't see 10 bytes but rather 5, but if you cast another buff, you'll see 10 bytes. if you look at the raw packets in edx33, you'd have seen both packets actually contained 10 bytes. Just keep that in mind before relying solely on this feature because it can have an effect on your resulting code.

I am rewriting a lot of my previous released code, so I'll try to get updates posted to the important guides when I can, but as you can imagine, I'm pretty busy ;)
07/22/2009 20:16 theonly112#21
Dont works for me :S. Can you upload your Client?
07/23/2009 22:05 pushedx#22
Quote:
Originally Posted by theonly112 View Post
Dont works for me :S. Can you upload your Client?
Sorry, but my unpacked client generates quite a few false positives (5 total). That's enough to where I'm not comfortable uploading the file. I would assume this is from something in the new 3mb worth of code that was added into the client, but I'd rather now upload something that has any false positives scans...
07/25/2009 19:29 hack0r89#23
well. what did you use for unpacking?
i tried stripper_v213b9
it works automaticly and result: [Only registered and activated users can see links. Click Here To Register...]
07/29/2009 09:59 nbk_naruto#24
thnx for the guide, this will help me and friend
08/02/2009 15:24 prezlee44#25
Quote:
Originally Posted by pushedx View Post
Are you using Visual Studio 7.0 or later?

The common.h/common.cpp code is located in [Only registered and activated users can see links. Click Here To Register...].
I using Microsoft Visual Studio 2008 professional.
What type of project need for this Guide?
ATL or CLR or MFC?

Edit: Now i know... I didn't ask. I found the answer in the loader guide.
08/02/2009 16:32 pushedx#26
I will provide an updated code and analyzer after tomorrow's inspection. I came up with a new patch that I think fixes most of the bugs I mentioned about some opcodes not being parsed right or at all.
08/05/2009 21:57 pushedx#27
Here is the new Analyzer for 1.205. I fixed some bugs with the packet parsings so all packets should hopefully parse correctly now. Also attached is the complete project to use as a new base for future updates.

[Only registered and activated users can see links. Click Here To Register...]

Here is the new source code as well:

DLL.h
Code:
#pragma once

// Bin: 33 C0 89 46 10 89 46 14 C7 46 08 00 00 00 00 C7 46 04 00 00 00 00 8B C6 5E C2 04 00 CC
// First line in function
#define CC_ExtractSentPacket_Address 0x535BF0

// 56 57 8D 9B 00 00 00 00 8B 73 08 81 E6 FF 0F 00 80 8B FD
// MOV EBX,ECX
// MOV DWORD PTR SS:[ESP+10],EAX
#define CC_ExtractSentPacket_Address_1 0x504C9C

// 64 A1 00 00 00 00 50 B8 08 10 00 00
// MOV EAX, 1008
#define CC_ExtractSentPacket_Address_2 0x76FBCE

// Find sequence
//push ebx
//call eax
//cmp eax, 1
#define CC_ExtractPacket_Address_1 0xA865C0

// End of ReadBytes function
// POP ESI
// MOV EAX,EBX
// POP EBX
// RETN 8
#define CC_ExtractPacket_Address_2 0x4F317C
DLL.cpp
Code:
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include "../common/common.h"
#include "DLL.h"
#include "Analyzer.h"

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

// Global instance handle to this DLL
HMODULE gInstance = NULL;

// Function prototype
void UserOnInject();
void UserOnDeinitialize();

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

// Main DLL entry point
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ulReason, LPVOID lpReserved)
{
	UNREFERENCED_PARAMETER(lpReserved);
	if(ulReason == DLL_PROCESS_ATTACH)
	{
		gInstance = hModule;
		// Do not notify this DLL of thread based events
		DisableThreadLibraryCalls(hModule);
	}
	else if(ulReason == DLL_PROCESS_DETACH)
	{
		UserOnDeinitialize();
	}
	return TRUE;
}

// This is the main function that is called when the DLL is injected into the process
extern "C" __declspec(dllexport) void OnInject(DWORD address, LPDWORD bytes)
{
	// Restore the original bytes at the OEP
	DWORD wrote = 0;
	WriteProcessMemory(GetCurrentProcess(), UlongToPtr(address), bytes, 6, &wrote);

	// Call our user function to keep this function clean
	UserOnInject();
}

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

namespace CC_ExtractSentPacket
{
	DWORD currentOpcode;
	LPBYTE currentBuffer;
	DWORD currentSize;

	void OnProcessDataStart()
	{
		Analyzer_SetOpcode((WORD)currentOpcode, false);
	}

	void ProcessData()
	{
		Analyzer_StreamData(currentBuffer, currentSize);
	}

	void OnProcessDataEnd()
	{
		Analyzer_EndPacket();
	}

	void EnableParseHook();
	void DisableParseHook();

	DWORD codecave_SetOpcode_ReturnAddress = 0;
	__declspec(naked) void codecave_SetOpcode()
	{
		__asm pop codecave_SetOpcode_ReturnAddress
		__asm MOV AX,WORD PTR SS:[ESP + 0x04] // Original code
		__asm mov currentOpcode, eax
		__asm pushad
		EnableParseHook(); // Start hooking writes
		__asm popad
		__asm push codecave_SetOpcode_ReturnAddress
		__asm ret
	}

	DWORD codecave_WriteBytes_ReturnAddress = 0;
	__declspec(naked) void codecave_WriteBytes()
	{
		__asm pop codecave_WriteBytes_ReturnAddress

		__asm mov currentBuffer, eax
		__asm mov currentSize, ebp

		__asm pushad
		ProcessData();
		__asm popad

		// Even though this comes first, we will use EBX and then fix it up
		// afterwards. This is ok since ECX is not disturbed.
		//__asm MOV EBX, ECX

		// This line seems to give the client problems when compiled in VS,
		// so we have to rewrite it a little. This might be one of the hardest
		// things to figure out if you were doing this yourself and not
		// too experienced.
		//__asm MOV DWORD PTR SS:[ESP + 0x10],EAX

		__asm
		{
			mov ebx, esp
			add ebx, 0x10
			mov [ebx], eax
		}

		// Now set our EBX value to what it should be
		__asm MOV EBX, ECX

		__asm push codecave_WriteBytes_ReturnAddress
		__asm ret
	}

	DWORD codecave_PostProcessPacket1_ReturnAddress;
	__declspec(naked) void codecave_PostProcessPacket1()
	{
		__asm pop codecave_PostProcessPacket1_ReturnAddress

		__asm pushad
		DisableParseHook();
		OnProcessDataEnd();
		__asm popad

		// We choose this line because it is the easiest to codecave and won't likely change
		__asm MOV EAX, 0x1008 // Remember #s have to be in HEX! 1008 != 0x1008

		__asm push codecave_PostProcessPacket1_ReturnAddress
		__asm ret
	}

	void EnableParseHook()
	{
		// A little trick I came up with to filter out the packets received
		// that make use of this functionality. Not sure if it'll always work,
		// but it "should" since the higher 4 bytes of any C->S packet in the
		// executable will be 0 since they are hard coded into the client!
		DWORD result = currentOpcode & 0xFFFF0000;

		//printf("Result = %i\n", result); // Debugging
		if(result == 0)
		{
			// Hook the byte writing function
			edx::CreateCodeCave(CC_ExtractSentPacket_Address_1, 6, codecave_WriteBytes);

			// Hook the post build processing function
			edx::CreateCodeCave(CC_ExtractSentPacket_Address_2, 5, codecave_PostProcessPacket1);

			// Let the user know we have an new packet being built
			OnProcessDataStart();
		}
	}

	void DisableParseHook()
	{
		// Restore the byte writing function code
		static BYTE patch1[] = {0x8B, 0xD9, 0x89, 0x44, 0x24, 0x10};
		edx::WriteBytes(CC_ExtractSentPacket_Address_1, patch1, 6);

		// Restore the post build processing function code
		static BYTE patch2[] = {0xB8, 0x08, 0x10, 0x00, 0x00};
		edx::WriteBytes(CC_ExtractSentPacket_Address_2, patch2, 5);
	}

	void Setup()
	{
		edx::CreateCodeCave(CC_ExtractSentPacket_Address, 5, codecave_SetOpcode);
	}
}

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

namespace CC_ExtractPacket
{
	DWORD currentOpcode;
	LPBYTE currentBuffer;
	DWORD currentSize;
	void * packetPtr;

	DWORD lastAddr = 0;

	void OnProcessDataStart()
	{
		Analyzer_SetOpcode((WORD)currentOpcode, true);
	}

	void ProcessData()
	{
		Analyzer_StreamData(currentBuffer, currentSize);
	}

	void OnProcessDataEnd()
	{
		Analyzer_EndPacket();
	}

	void ProcessPacket()
	{
		LPBYTE lpBuffer = (LPBYTE)packetPtr;
		DWORD packetData = *(LPDWORD)(lpBuffer + 0x18 - 4);
		currentOpcode = *((LPWORD)(lpBuffer + 0x18));
		WORD packetLength = *((LPWORD)(lpBuffer + 0x18 - 16));
		if(lastAddr == packetData)
		{
		}
		else
		{
			lastAddr = packetData;
			OnProcessDataStart();
		}
	}

	DWORD codecave_ReadBytes_ReturnAddress = 0;

	__declspec(naked) void codecave_ReadBytes()
	{
		__asm pop codecave_ReadBytes_ReturnAddress

		__asm mov currentBuffer, eax
		__asm mov currentSize, ebx

		__asm pushad
		ProcessData();
		__asm popad

		// Emulate the rest of the function since our codecave overlaps it all
		__asm POP ESI
		__asm MOV EAX,EBX
		__asm POP EBX
		__asm RET 8
	}

	void EnableParseHook()
	{
		edx::CreateCodeCave(CC_ExtractPacket_Address_2, 7, codecave_ReadBytes);
	}

	void DisableParseHook()
	{
		static BYTE patch[] = {0x5E, 0x8B, 0xC3, 0x5B, 0xC2, 0x08, 0x00};
		edx::WriteBytes(CC_ExtractPacket_Address_2, patch, 7);
		OnProcessDataEnd();
	}

	DWORD codecave_HookPacketProcess_ReturnAddress;
	__declspec(naked) void codecave_HookPacketProcess()
	{
		__asm pop codecave_HookPacketProcess_ReturnAddress

		__asm mov packetPtr, ebx
		__asm pushad
		ProcessPacket();
		EnableParseHook();
		__asm popad

		__asm PUSH EBX
		__asm CALL NEAR EAX
		__asm CMP EAX,1

		__asm pushad
		DisableParseHook();
		__asm popad

		__asm push codecave_HookPacketProcess_ReturnAddress
		__asm ret
	}

	void Setup()
	{
		edx::CreateCodeCave(CC_ExtractPacket_Address_1, 6, codecave_HookPacketProcess);
	}
}

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

// The function where we place all our logic
void UserOnInject()
{
	// Create a debugging console
	//edx::CreateConsole("edxAnalyzer Debugging Console");

	// Mutex for the launcher, no patches required to start Silkroad now
	CreateMutexA(0, 0, "Silkroad Online Launcher");
	CreateMutexA(0, 0, "Ready");

	CC_ExtractSentPacket::Setup();
	CC_ExtractPacket::Setup();

	Analyzer_Setup();
}

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

void UserOnDeinitialize()
{
	Analyzer_Cleanup();
}

//-------------------------------------------------------------------------
08/17/2009 13:33 soadmania#28
Compiled version works great. But i cant compile the source. Resource errors again :/

i have to download VS 2008 :(

btw can u update the DLL.cpp on your first post?
08/22/2009 18:08 fanste#29
I tried to update your code for the current tSRO-client. But im unable to compile it. THe error for the DLL is
Quote:
2>.\DLL.rc(10) : fatal error RC1015: cannot open include file 'afxres.h'.
All what i found out is, that i nned the ATL/MFC? But where can i get it? I tried diffrent things, but everything failed :(
Could it maybe be, that "Visual Studio 2008 Express" won't support it?
08/22/2009 21:31 pushedx#30
Quote:
Originally Posted by fanste View Post
Could it maybe be, that "Visual Studio 2008 Express" won't support it?
Yes, Visual Studio 2008 Express does not come with any of the Gui editing tools, so only a higher version of Visual Studio 2008 can compile projects that come with a Gui.

You can also delete the Gui related stuff and output to a console, but that does not make for a good tool hehe. For the inject Gui, you can create the window yourself, but that adds a lot of extra code so that's why I use the Gui builder.