Register for your free account! | Forgot your password?

Go Back   elitepvpers > Popular Games > Silkroad Online > SRO Coding Corner
You last visited: Today at 02:58

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

Advertisement



Getting blowfish key and using the algorithm

Discussion on Getting blowfish key and using the algorithm within the SRO Coding Corner forum part of the Silkroad Online category.

Reply
 
Old   #1
 
elite*gold: 0
Join Date: Dec 2010
Posts: 27
Received Thanks: 1
Getting blowfish key and using the algorithm

Good evening

I am still busy with the packets of silkroad and I'm now trying to understand on how to decrypt the packets but I'm having some problems with it.
I read drew benton's artikel about the silkroad security but I still don't know on which blowfish key is used to decrypt the packets.
let's say these four packets are the first 4
Code:
S -> C
00000   25 00 00 50 00 00 0e d2  a9 27 80 2d c3 23 6c f6    %..P.....'.-.#l.
00016   00 00 00 62 00 00 00 8d  ac fe 38 3d d0 9c ef 67    ...b......8=...g
00032   f7 bc 46 6b 73 d0 70 e5  1d b8 56                   ..Fks.p...V

C -> S
00000   0c 00 00 50 ec cb 98 d5  9c 3e 7d 03 94 b0 9c 60    ...P.....>}....`
00016   92 56                                               .V

S -> C
00000   09 00 00 50 00 00 10 4c  f8 b7 1d e2 79 3c b5       ...P...L....y<.

C -> S
00000   00 00 00 90 80 8e                                   ......
I know that the first 2 bytes are the size of the packet data the 2 after those the opcode and the 2 after the opcode the security bytes. But in which packet is the actual blowfish key which is used to encrypt and decrypt some packets?
is it this one: d2 a9 27 80 2d c3 23 6c of the first packet starting with the 7th byte or is it the one in the 3rd packet also beginning at the 7th byte? and i read something about the key which is also encrypted or something like that is that true?

Thank you
sjaakie100 is offline  
Old 01/05/2011, 22:42   #2
 
bootdisk's Avatar
 
elite*gold: 0
Join Date: Sep 2010
Posts: 134
Received Thanks: 41
bot90210's guide would be a great addition to your current inquiry.
Also, by seeing drew's source attached to that guide you will get what you want to know since it goes step by step to get that.
bootdisk is offline  
Thanks
1 User
Old 01/05/2011, 22:59   #3

 
elite*gold: 260
Join Date: Aug 2008
Posts: 560
Received Thanks: 3,779
There is a "handshake process" that runs that comes up with the final Blowfish keys used. Grab my project. It contains the latest version of my security code. Once you get it, you will want to start looking over the silkroad_security.h / silkroad_security.cpp files.

Lines 458 - 522 of silkroad_security.cpp contain the relevant code you are asking about.
Code:
			if( packet_opcode != 0x5000 )
			{
				throw( std::runtime_error( "[SilkroadSecurityData::Handshake] Received an illogical handshake packet (programmer error)." ) );
			}

			uint8_t flag = packet_data.Read< uint8_t >();

			TFlags * flags = (TFlags *)&flag;

			if( m_security_flag == 0 )
			{
				m_security_flag = flag;
			}

			if( flags->blowfish )
			{
				m_initial_blowfish_key = packet_data.Read< uint64_t >();
				m_blowfish.Initialize( &m_initial_blowfish_key, sizeof( m_initial_blowfish_key ) );
			}

			if( flags->security_bytes )
			{
				m_seed_count = packet_data.Read< uint32_t >();
				m_crc_seed = packet_data.Read< uint32_t >();
				SetupCountByte( m_seed_count );
			}

			if( flags->handshake )
			{
				m_handshake_blowfish_key = packet_data.Read< uint64_t >();
				m_value_g = packet_data.Read< uint32_t >();
				m_value_p = packet_data.Read< uint32_t >();
				m_value_A = packet_data.Read< uint32_t >();

				m_value_x = static_cast< uint32_t >( rng() & 0x7FFFFFFF );

				m_value_B = G_pow_X_mod_P( m_value_p, m_value_x, m_value_g );
				m_value_K = G_pow_X_mod_P( m_value_p, m_value_x, m_value_A );

				uint64_t key_array = MAKELONGLONG_( m_value_A, m_value_B );
				KeyTransformValue( key_array, m_value_K, LOBYTE_( LOWORD_( m_value_K ) ) & 0x03 );
				m_blowfish.Initialize( &key_array, 8 );

				m_client_key = MAKELONGLONG_( m_value_B, m_value_A );
				KeyTransformValue( m_client_key, m_value_K, LOBYTE_( LOWORD_( m_value_B ) ) & 0x07 );
				m_blowfish.Encode( &m_client_key, 8, &m_client_key, 8 );
			}

			if( flags->handshake_response )
			{
				m_challenge_key = packet_data.Read< uint64_t >();

				uint64_t expected_challenge_key = MAKELONGLONG_( m_value_A, m_value_B );
				KeyTransformValue( expected_challenge_key, m_value_K, LOBYTE_( LOWORD_( m_value_A ) ) & 0x07 );
				m_blowfish.Encode( &expected_challenge_key, 8, &expected_challenge_key, 8 );

				if( m_challenge_key != expected_challenge_key )
				{
					throw( std::runtime_error( "[SilkroadSecurityData::Handshake] Server signature error." ) );
				}

				KeyTransformValue( m_handshake_blowfish_key, m_value_K, 0x3 );
				m_blowfish.Initialize( &m_handshake_blowfish_key, 8 );
			}
Depending on the security mode ( the first data byte of the 0x5000 packet, 0x0E ) you have to read specific parts of the packet in order. That security flag is really just a bitstruct of different fields, so the following struct explans that:
Code:
#pragma pack( push, 1 )
struct TFlags
{
	uint8_t none : 1;
	uint8_t blowfish : 1;
	uint8_t security_bytes : 1;
	uint8_t handshake : 1;
	uint8_t handshake_response : 1;
	uint8_t _6 : 1;
	uint8_t _7 : 1;
	uint8_t _8 : 1;
};
#pragma pack( pop )
When the security flag is 0x0E and it's cast to that struct, you end up getting the blowfish, security_bytes, and handshake fields set. As a result, if you trace through the previously posted code, the m_initial_blowfish_key field is read first, then the m_seed_count and m_crc_seed fields, followed by the m_handshake_blowfish_key, m_value_g, m_value_p, and m_value_A fields.

Since the Handshake flag is set, the initial blowfish key sent from the Blowfish flag is overwritten by the one generated in the Handshake logic. If no Handshake flag was sent, then the initial blowfish key would be used instead. After the Handshake process starts, the second security packet you get, with data flag 0x10, has the handshake_response field set, so that logic executes. In that portion of the code, a the final Blowfish key is calculated and used.

To better understand the whole process, take a look at the DH Key Exchange protocol, which is what Silkroad uses. The Blowfish is a little-endian implementation, so it is not compatible as-is with standard Blowfish.

So it can be a complicated process to understand first, but you can spend some time looking through the code and following the logic to see how it all works together.
pushedx is offline  
Thanks
11 Users
Old 01/06/2011, 19:11   #4
 
elite*gold: 0
Join Date: Dec 2010
Posts: 27
Received Thanks: 1
Wow thank you guys very much for your answer. A great explenation drew. I downloaded your project and it's really really usefull. I think I'll be able to understand the handshake process after viewing your code and trying some stuff
I've one question. I see that you generate all those security bytes and responses in your projects but is it possible to have something like winpcap which just sniffs the packets and extracts the keys to decrypt the packets after those or do you create a key or something during the handshake process which is only available in the client?

Thank you

By the way, I'm sorry for my english.

EDIT:

I'm sorry but this is way offtopic but to pushedx I used your edxSilkroadLoader5 but I'm not getting some packets with the packet parser enabled. for example the packet of the server list doesn't show up.
sjaakie100 is offline  
Old 01/06/2011, 22:49   #5

 
elite*gold: 260
Join Date: Aug 2008
Posts: 560
Received Thanks: 3,779
Quote:
Originally Posted by sjaakie100 View Post
I've one question. I see that you generate all those security bytes and responses in your projects but is it possible to have something like winpcap which just sniffs the packets and extracts the keys to decrypt the packets after those or do you create a key or something during the handshake process which is only available in the client?
Nope, given the packets from both sides in the middle, you cannot deduce enough information to decipher the entire handshake. Take a look at this. The only way it'd be possible is if you were to make the client use a predefined non-random value for their 'a', which is what my Patch Seed option does in the loader. That was from before I had done the entire process and it was the only way it'd work.

Quote:
I'm sorry but this is way offtopic but to pushedx I used your edxSilkroadLoader5 but I'm not getting some packets with the packet parser enabled. for example the packet of the server list doesn't show up.
The packet parser is just for AgentServer packets. The client uses a different manual style parsing for the GatewayServer packets. Check out this topic, by lesderid for some specific information on those packets. For more information on my packet parsing and building parsing logic, have a look at: #5 and #6 of my .

Also with the packet parser, some packets are "spanned" across many different individual packets and then rebuilt in another function. So you won't see every single packet being parsed, only the packets the client has to physically parse. For the spanned packets, the opcode won't be correct. That tool is just to show how the client parses 99% of the packets, you still have to do a little extra work for the 1% it doesn't do. I.e., it'll read some entire buffers then subparse manually rather than use the packet interface. For stuff like that you'll have to do yourself.

For development, the best thing to do is run the auto-parser + proxy (like ) so you get the full packet stream in the proxy + tools to inject and analyze as well as the auto parser to see how most packets are actually parsed. That toolset should give you almost everything you need, but some client reversing will still be needed for some packets anyways.
pushedx is offline  
Old 01/16/2011, 19:56   #6
 
viky909's Avatar
 
elite*gold: 0
Join Date: Sep 2009
Posts: 40
Received Thanks: 2
Great Work all and special thanks for pushedx for his tools

I want to say something :-

I follow some guides from you and now trying to understand the silkroad packets , but

Like login action : get some packets from server and client
But if somehow I can inject this packets ; it work fine too ?!

I mean is this how bots use to auto log in ?!
and is this the same way for sending packets for moving and killing mobs ?!

"Im trying to make simple bot for personal Use .However, Sniffing packet work only on private server like Srevolution from Xcoding team as isro now is crowded ! "

If so ; should I decrypt packets and send them to client or just send them encrypted ?
and how to do that [Simple mode please ].
Need little help on those questions :d

[Sorry for my bad English]
viky909 is offline  
Old 03/14/2011, 20:56   #7
 
elite*gold: 0
Join Date: Dec 2010
Posts: 27
Received Thanks: 1
Hi all,

I'm having a really hard time to understand the **** encryption I've digged in drew's code for many many hours but I still don't get how to logic works. I know that the blowfish key is encryption which needs to be decrypted with the initial blowfish key (if i'm correct) but the code from the silkroad article didn't worked cause when I sended the first packet from the cilent to the server I didn't get any response. And I don't get the latest silkroadsecurity.h and .cpp by drew benton. it looks like magic cause it's soo big.

is there a more easier way to just get the key from the packets so you don't have to generate the key's by yourself but to just sniff them from the packet?
sjaakie100 is offline  
Old 03/15/2011, 11:47   #8

 
elite*gold: 260
Join Date: Aug 2008
Posts: 560
Received Thanks: 3,779
The only "cheat" you can do is make the client use a fixed random seed, but you would still have to understand the entire client security process.

Try browsing through the version instead of the C++ version if it doesn't make much sense.

Basically, there are 3 main functions you need to look through:

1. SecurityAPI::Recv

Breaks up the TCP stream into logical packets first. Once you have logical packets, you can then process them.

So for you, first you need to understand how to break down the stream into packets. That's pretty simple, as you read two bytes and check the size. If the size is > 0x8000, then the packet is encrypted, if it's not, then it isn't. If the packet is encrypted, the payload size has to be % 8 (since that is what Blowfish requires) so you have to add 0 - 7 bytes to make the size % 8 (NOTE: The payload includes the 4 byte header for encrypted packets). If the packet is not encrypted, then the payload size is 4 (rest of the header) + the packet size. Once you know how many bytes of data you need, you just recv until you have them.

Now, you have raw 'packets' ready for processing.

2. SecurityAPI::Handshake

The logic that handles the entire security system. If the packet has an opcode of 0x5000 or 0x9000, it is part of the security system, so the Handshake function will process it. The packet format is dynamic depending on the mode. To see how the packet is generated, take a look at the SecurityAPI::GenerateSecurity function to understand the values. The client processes the packet the same way it is built, except that it reads rather than wrties.

3. SecurityAPI::FormatPacket

The logic for sending packets. For Client to Server packets, what goes on here simply depends on the security mode.

There's not much to understand about the encryption itself; it's just little-endian . What you are having trouble with is understanding the actual Handshake process.

To understand the handshake process better, read up on the Diffie–Hellman key exchange.

Once you understand the DH-KE algorithm, they just use a few custom functions (KeyTransformValue in the C# code) to scramble the data a little to prevent it from being 'trivial' to reimplement without digging through the client.

So basically it works like this:

1. Client connects to the server; server sends the initial security packet.

2. Client processes the security packet based on the mode (1st byte, look at my SecurityFlags structure) If:
blowfish - The initial blowfish key is read from the packet.
security_bytes - The base security bytes are read from the packet
handshake - The handshake values are read from the packet; a new blowfish key is used (read up on the DH-KE to understand why)

3. Client will send a response based on the security mode. Upon security acceptance, 0x9000 is finally sent and then regular packets begin (identify, 0x2001)

The logic isn't as complex as it might look at first. The reason there is so much code is because the security API handles literally everything for you, so all you have to do is use the API and not worry about anything else. Also, the server processing code is included so that adds quite a bit of extra code, but it is a complete solution. The Silkroad security supports multiple modes so additional processing has to be done to ensure all modes are supported. SRO is the only game I've ever seen that does this, so it is quite unique.

You can grab a more recent, but currently outdated C++ version . I'd still recommend going through the C# code as well if you are familiar with that language as it is the most recent version I have. If you look through say a really old copy like , it works but there is noticeably more work and complications you have to deal with. My latest versions are designed around hiding all of that from the user.

Hope that helps!
pushedx is offline  
Thanks
3 Users
Old 03/16/2011, 09:03   #9
 
elite*gold: 0
Join Date: Dec 2010
Posts: 27
Received Thanks: 1
Thank you so much I digged through your C# project and managed to get trough the handshake process I still don't really know how it exactly works but I will definitly read the Diffie hellman key exchange article. The most important thing for me was to get something working and once that's done I can test some things too see how it really works

Again thank you very much for your great explanations!
sjaakie100 is offline  
Old 03/17/2011, 19:49   #10
 
elite*gold: 0
Join Date: Dec 2010
Posts: 27
Received Thanks: 1
Just another quick question is the handshake process for the gameserver the same as the login server?
sjaakie100 is offline  
Old 03/17/2011, 22:58   #11
 
InvincibleNoOB's Avatar
 
elite*gold: 20
Join Date: Mar 2007
Posts: 4,277
Received Thanks: 2,990
Yes.
InvincibleNoOB is offline  
Reply


Similar Threads Similar Threads
brauche vorschläge für rabot algorithm
10/01/2008 - Guild Wars - 6 Replies
da ich gerade an einem ra-bot schreibe, suche/brauche ich einige schöne vorschläge für den kampf. !nicht, die skills, welche der bot benutzen soll oder welche charakterklasse! -wann sollte man angreifen? -wie lange angreifen/ wann ein wechsel stattfinden soll, etc? -auf was genau sollte man reagieren? -nur gruppenmitglieder verfolgen oder feinere laufwege (wie die laufwege generieren?)? vlt. habt ihr schon ra-bots geschrieben. wie habt ihr die kampfsituation ausgearbeitet?
INTERESTED IN STUDYING THE PACKET ALGORITHM OF THE CLIENT.EXE
08/25/2008 - Perfect World - 7 Replies
just wait for updates



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


Powered by vBulletin®
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2025 elitepvpers All Rights Reserved.