Register for your free account! | Forgot your password?

Go Back   elitepvpers > Silkroad Online > SRO Guides & Templates
You last visited: Today at 02:38

  • Please register to post and access all features, it's quick, easy and FREE!


[Guide] Extracting Built Packets in Silkroad

Reply
 
Old   #1
 
elite*gold: 260
Join Date: Aug 2008
Posts: 526
Received Thanks: 3,311
[Guide] Extracting Built Packets in Silkroad

Extracting Built Packets in Silkroad

I. Purpose

This guide will provide a complement to the previous guide of extracting the parsed packets in Silkroad. This time, we will learn how to extract packets the client sends the serer as they are built. Because most of the concepts in and theory are the same, this guide will be much shorter than the previous so please refer back to that article for all the nitty-gritty details.

An article like this is also just as important to understand as the previous was for any development that makes use of packets. If you are writing a client based tool, a clientless tool, or even a Silkroad emulator, you need to understand how packets are built and the format they follow. Using the techniques provided in this guide should help you achieve that.

I wanted to do make this a separate article as the previous one was getting pretty long itself. With all of the concepts explained already though, we can move through this one pretty fast. This lies in line with my first guide explaining how each article will relate to the others in one way or the other and once we have our base knowledge base established, we can do fun stuff. In addition, there are a few tricky parts in replicating the client's logic that we have not come across yet.

II. Requirements

If you have been keeping up with the previous guides, you should be able to follow everything presented here. There are no new concepts used. There is a bit more assembly logic used here though, but everything is based off our previously established concepts of codecaves and inline patching.

In order to be able to follow along this guide, you will need:
• OllyDbg 1.10 (or equivalent)
• Visual Studio 2008 (or equivalent)

III. Theory

As I discussed in the previous guide, most games use code that greatly simplifies the programming challenges that lies ahead of them. When programming a networked game, there are a lot of things the developer must take into account when designing code. When it comes to packets, the developer has to figure out a way to make sure the client cannot spam the same packet over and over flooding the server.

Silkroad does just this with a simple packet opcode checking function. While I have not explored the internals of this function in a great degree at this time, just understanding that such a function exists can greatly help in our client reversing endeavors. The client will first check the opcode to see if such a packet can be sent. If it cannot, then the function usually skips execution by jumping over the packet building code.

Assuming the packet checking function is successful, the client will then build a new packet with the given opcode. Similarly to the opcode checking function, I’ve not actively explored the internals of how packet objects are constructed, but given I know C++ programming, it’s not hard to imagine how the process goes. We can hook this function to get the opcode of our current packet that is being built just as we were able to easily get the opcode of the packet that was being processed before.

Similarly to a ReadBytes function there is also a WriteBytes function. We can hook this function and simply rip out the data as it is being passed into the packet’s data buffer. By looking at multiple sections of code that build packets, we can also look for some final function that is called on the packet object to know when we are done building the packet. We know such a function has to exist because the client has to put in security bytes into the packets and actually dispatch the packet for sending to the server.

So, with this theory in mind as well as the knowledge gained in the previous guide, we can get started!

IV. Implementation

In order to get started, we need to know a packet opcode that is sent. By now, this information can easily be obtained, so there is no need to work from scratch to obtain one. If we had to, we would just breakpoint on a WSASend call and trace back the buffer until we could determine where the opcode was in the packet.

For this example, I will be using the character action packet, which uses an opcode of 0x7017. In order to find where the functionality lies for a packet that is sent to the server, we just have to search for the opcode! To begin our search, right click on the main assembly window and choose Search for -> All constants. Type in 7017 under the hexadecimal box and hit Ok. We get a new window that has search results in it and we can see we have a couple of entries. Double click on the first one to go to the client’s location.

We arrive in the main function that builds the 0x7017 packets. We know this because we see our opcode listed. Using what we learned in the theory section, we should first see a function call that checks to see if the packet can be used or not. We find that to be the case because there is a conditional jump after the first opcode but before the second that skips over a large part of the function. So far so good!

Next, we should be finding a function that writes bytes to the packet buffer. If we remember how the ReadBytes function was setup, it took two parameters, the buffer and the size. The WriteBytes should be no different. If we were to trace the function, we would quickly find the function and be able to identify the parameters.

Finally, we need to find a common function that is called after the packet building is complete. In order to do this, we will simply follow the call to the opcode setting function and look at all the other addresses that make calls to the function. We should be able to find a common function that is called in all of them and we do.

Here is an annotated screenshot of the entire function:


Now that we know the logic of how packets are built. All we have to do is setup the code to extract the data. This code is going to be really similar to the previous guide’s code, so I will not go through it in detail.

However, there were a few very tricky things to figure out during the process. Packets that are spanned across multiple opcodes for example, such as group spawn, make use of our packet writing functions! I came up with a little approach that should fix that issue for us.

Next, there was a problem replacing the client logic in the codecave. Since the code made use of the stack, it would incorrectly compile in Visual Studio this making the client disconnect. To fix this issue, I just used more commands to replicate the logic as it would be if it was done the long way.

Issues like these are not uncommon when working with game clients. When you have unexpected behavior and are sure your code is right, you have to be sure you do not have a problem like this. When I first wrote the code I was sure it was right and tracked the problem down to the WriteBytes codecave. I figured the stack operation should work fine, but it doesn’t.

After replacing the code, it worked perfectly! Chalk that up as a lesson learned of how tricky this development can get at times. The code for stealing the opcode seemed to work just fine, so I'm not really sure why this wouldn't either.

Here is our final DLL.cpp file:

Code:
#include <windows.h>
#include "../common/common.h"

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

// Function prototype
void UserOnInject();

// 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);
	}
	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("=== %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(0x4D66CC, 6, codecave_WriteBytes);

			// Hook the post build processing function
			edx::CreateCodeCave(0x741CBE, 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(0x4D66CC, patch1, 6);

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

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

// The function where we place all our logic
void UserOnInject()
{
	// Create a debugging console
	edx::CreateConsole("SilkroadFramework 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();
}
You should be able to compile and run. Here is an example screenshot of the program in action:


V. Conclusion

You should not have a good idea of how it is possible to let your game client do most of the hard work for you, whether it is extracting the received or sent packets. By following this guide, you should be able to greatly speed up packet related development efforts as all you have to do is trigger packets and save how the client parses them. Using this information, you can further your understanding of the client and track down the specific areas in the client responsible for generating certain packets. All you have to do is search for the opcode of interest!

That wraps up this guide! Between this guide and the previous, you should be able to work a lot more efficiently now with building a packet database for use in your programs. I hope you found this it informational and beneficial. Stay tuned for future guides!

Drew “pushedx” Benton
edxLabs



pushedx is offline  
Thanks
19 Users
Old 06/27/2009, 12:30   #2
 
elite*gold: 20
Join Date: Jul 2007
Posts: 2,215
Received Thanks: 1,358
#stick


strukel is offline  
Old 07/22/2009, 16:18   #3
 
elite*gold: 260
Join Date: Aug 2008
Posts: 526
Received Thanks: 3,311
If anyone is interested in an update for .203, I've included this code along with the other guide on Extracting Parsed Packets. See my reply for an updated version and slightly cleaner code to use.

All future updates will probably be done in that guide as it's easier than trying to create two versions to update both guides any update.
pushedx is offline  
Old 07/29/2009, 10:01   #4
 
elite*gold: 0
Join Date: Apr 2007
Posts: 53
Received Thanks: 17
thnx for the guide man, you r verry good


nbk_naruto is offline  
Old 07/31/2009, 14:39   #5
 
elite*gold: 0
Join Date: May 2008
Posts: 259
Received Thanks: 94
error :S

Quote:
1>dll.obj : error LNK2019: unresolved external symbol "int __cdecl edx::CreateCodeCave(unsigned long,unsigned char,void (__cdecl*)(void))" ([email protected]@@[email protected]) referenced in function "void __cdecl CC_ExtractSentPacket::EnableParseHook(void)" ([email protected][email protected]@YAXXZ)
1>dll.obj : error LNK2019: unresolved external symbol "int __cdecl edx::WriteBytes(unsigned long,void *,unsigned long)" ([email protected]@@[email protected]) referenced in function "void __cdecl CC_ExtractSentPacket:isableParseHook(void)" ([email protected][email protected]@YAXXZ)
1>dll.obj : error LNK2019: unresolved external symbol "void __cdecl edx::CreateConsole(char const *)" ([email protected]@@[email protected]) referenced in function "void __cdecl UserOnInject(void)" ([email protected]@YAXXZ)
1>MSVCRTD.lib(crtexe.obj) : error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup
1>C:\Documents and Settings\samet\Belgelerim\Visual Studio 2008\Projects\dll\Debug\dll.exe : fatal error LNK1120: 4 unresolved externals
1>Build log was saved at "file://c:\Documents and Settings\samet\Belgelerim\Visual Studio 2008\Projects\dll\dll\Debug\BuildLog.htm"
1>dll - 5 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
soadmania is offline  
Old 07/31/2009, 14:39   #6
 
elite*gold: 0
Join Date: May 2008
Posts: 259
Received Thanks: 94
error :S

Quote:
1>dll.obj : error LNK2019: unresolved external symbol "int __cdecl edx::CreateCodeCave(unsigned long,unsigned char,void (__cdecl*)(void))" ([email protected]@@[email protected]) referenced in function "void __cdecl CC_ExtractSentPacket::EnableParseHook(void)" ([email protected][email protected]@YAXXZ)
1>dll.obj : error LNK2019: unresolved external symbol "int __cdecl edx::WriteBytes(unsigned long,void *,unsigned long)" ([email protected]@@[email protected]) referenced in function "void __cdecl CC_ExtractSentPacket:isableParseHook(void)" ([email protected][email protected]@YAXXZ)
1>dll.obj : error LNK2019: unresolved external symbol "void __cdecl edx::CreateConsole(char const *)" ([email protected]@@[email protected]) referenced in function "void __cdecl UserOnInject(void)" ([email protected]@YAXXZ)
1>MSVCRTD.lib(crtexe.obj) : error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup
1>C:\Documents and Settings\samet\Belgelerim\Visual Studio 2008\Projects\dll\Debug\dll.exe : fatal error LNK1120: 4 unresolved externals
1>Build log was saved at "file://c:\Documents and Settings\samet\Belgelerim\Visual Studio 2008\Projects\dll\dll\Debug\BuildLog.htm"
1>dll - 5 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
soadmania is offline  
Old 07/31/2009, 15:15   #7
 
elite*gold: 260
Join Date: Aug 2008
Posts: 526
Received Thanks: 3,311
You need to make sure yo add Common.cpp to your project. Refer to for how to setup the project workspace.

Also, have a look at for information about his particular guide. It will not work out of the box with the new client.

Since Joymax seems to be updating more often now, I will wait until they are done patching the client before updating the base guides again. I will update the tools though, but since there's little interest overall for these things, I am not rushing to update each patch.

These guides are more for reference how you can accomplish the task at hand. They are not really meant for copy paste building. Make sure to read through the previous articles to get a good idea of what is going on!
pushedx is offline  
Thanks
1 User
Old 09/22/2009, 15:24   #8
 
elite*gold: 0
Join Date: Nov 2008
Posts: 23
Received Thanks: 1
Do you know if there is any possibility to use such a system for the Launcher? I tried already to find something like a packet handling function (reader/writer...) but there is nothing.

It seems, that the packets are build on the fly without any special packet-builder-class or so. And for the packet-reading... absolutly no plan.. i can't even find the opcodes for this in the client
fanste is offline  
Old 09/23/2009, 20:48   #9
 
elite*gold: 260
Join Date: Aug 2008
Posts: 526
Received Thanks: 3,311
Quote:
Originally Posted by fanste View Post
Do you know if there is any possibility to use such a system for the Launcher? I tried already to find something like a packet handling function (reader/writer...) but there is nothing.

It seems, that the packets are build on the fly without any special packet-builder-class or so. And for the packet-reading... absolutly no plan.. i can't even find the opcodes for this in the client
I had a version of the edxSilkroadLoader that made use of this guide but it was not released. The problem is that, it's hard to add this kind of stuff into the client without affecting stability in one form or another. I noticed the method was not perfect and worked to try and fix it, and I think I did, but for now I am focusing on the proxy side of things and will look into updating the loader again later with a new analyzer.

Some packets are built on the fly and won't be logged with this method, but the majority are built using the functions, so you might miss less than 5 or so in all I think. Mostly the login server related packets are built manually, but I think a few world server might be too. Make sure you are using an unpacked client too for ISRO!

I think I'll try a new approach for this stuff to try and find the best tradeoff of performance, features, and stability. For the latest client though, use the new project (and by new, I mean old, from 205) on as it contains the binary signatures that you can use to update with.
pushedx is offline  
Old 09/23/2009, 22:19   #10
 
elite*gold: 0
Join Date: Nov 2008
Posts: 23
Received Thanks: 1
I think you missunderstood me... or i missunderstnad you, who knows :-P

For the client everything works perfect, as i wrote in the other topic long time ago, but I meant the "Silkroad Online Launcher" (the original one from JM), but as far as i can see (i tried to find something several times) there is no possibility to hook the packet building and reading functions like we are able to do it in the client.
fanste is offline  
Old 09/27/2009, 13:27   #11
 
elite*gold: 0
Join Date: Jun 2008
Posts: 188
Received Thanks: 91
You can modify SR33 / edx33 to work with the Launcher.
maxbot is offline  
Old 01/28/2010, 17:06   #12
 
elite*gold: 0
Join Date: Jan 2008
Posts: 41
Received Thanks: 2
bro if u would post a lil tutorial on how to get started building a sro emulator ... only the basics u'l be my hero
blondutzu1992 is offline  
Old 02/02/2010, 00:06   #13
 
elite*gold: 0
Join Date: Nov 2005
Posts: 7
Received Thanks: 1
Easy as repricate all the packets you see from S->C server to client and thats all, "private" servers requieres alot of work to replicate what the server does, so the quality of the server is equall to the enfort the programmer puts on it, stay away from java, or visual basic if you mean to make a server lol
Googlemano is offline  
Old 02/05/2010, 10:55   #14
 
elite*gold: 0
Join Date: Jan 2008
Posts: 41
Received Thanks: 2
ty for the tips :P
blondutzu1992 is offline  
Old 05/31/2014, 22:55   #15
 
elite*gold: 0
Join Date: Feb 2014
Posts: 829
Received Thanks: 1,204
thanks a lot for this guide


Muhab* is offline  
Reply



« Silkroad-R - Asia Minor Outpost 3 Quest [Video Tutorial] | [Videoguide] Create silkroad server »

Similar Threads
[Guide] Extracting Parsed Packets in Silkroad
03/05/2016 - SRO Coding Corner - 64 Replies
I think you guys are really going to love this guide the most. Using this guide, you will be able to accomplish the holy grail of any game and that's being able to figure out packet formats with very little work! Once again I must give thanks to clockwork for showing me the basics of this approach when I was getting started with this stuff in the past. Extracting Parsed Packets in Silkroad I. Purpose This guide will be especially helpful to anyone that is working with Silkroad packets...
Extracting sounds?
01/03/2010 - Grand Chase - 3 Replies
is there a way to extract sounds from the kom files? or is that against the rules ?
Silkroad built-in autologin discussion
11/19/2009 - SRO Main - Discussions / Questions - 10 Replies
Idk if this has been discussed before, but umm, is there any way to get rid of that damn thing and just use a keypresser, cuz the built-in one is very slow and bad, so, does anyone know?
What built is better
07/09/2009 - SRO Ask the Experts - 7 Replies
my friend is a spear/thunder/fire and i am spear/thunder/ice i wear protector and he wears armor he says if i wear armor that i dont need Ice and that his built is stronger what do ya think is it worth changing to his built i am lvl 46 right now
[Guide]How to analyse Packets on Flyff
04/27/2009 - Flyff PServer - Discussions / Questions - 8 Replies
Hiho Elitepvper, Sinn dieses Guides ist es euch zu zeigen wie ihr Packets snifft und wie ihr sie analysiert. Download: MEGAUPLOAD - The leading online storage and file delivery service Credits: aldimaster Devinepunition



All times are GMT +1. The time now is 02:38.


Powered by vBulletin®
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Abuse
Copyright ©2018 elitepvpers All Rights Reserved.