• Unfortunately, we have experienced significant hard drive damage that requires urgent maintenance and rebuilding. The forum will be a state of read only until we install our new drives and rebuild all the configurations needed. Please follow our Facebook page for updates, we will be back up shortly! (The forum could go offline at any given time due to the nature of the failed drives whilst awaiting the upgrades.) When you see an Incapsula error, you know we are in the process of migration.

[Guide][Release?]Protocol / Encryption library.

Custom Title Activated
Loyal Member
Joined
May 26, 2007
Messages
5,545
Reaction score
1,315
Changing the Encryption / Protocol
Contents
Introduction
Part 1. Server Side
Downloads
Part 2. Client Side
Credits​
Introduction

Many people have spoken about using the "Encryption" to prevent people connecting to your server with a different client. I'm not convinced "Encryption" is the right word, but I may be being pedantic. I don't consider a simple 1 byte Binary Exclusive Or to be an "Encryption", though it does serve as a simple plain text obfuscater. (i.e. it makes unencrypted plain text packets look much less like unencrypted plain text packets)

As far as I can tell, this is the only security on packets between your client and your server in PT however. Because if it's wrong the client and server cannot communicate at all, I refer to it as a "Protocol". Call it what you will, this is the primary differentiation between a Korean, Japanese or Chinese server, and the reason why (aside from the IP address and port) you cannot connect a client from one to a server for another... and even with 1 byte as your "key" there are still 253 more keys to choose from.

If you choose the "key" 0, however, then anything anybody says in global, private or whisper (PM) is broadcast over the internet in plain 8-bit ASCII... you can read it with a packet sniffer without any translation at all. Something to look out for, is that the GM authentication is sent to the server as a whisper. :eek: Additionally, most of the clients I've tried keep the line of text spoken in a fixed size buffer, and do not zero it between lines, so if you say a long line (complex GM authentication) and then a short one. "@Hi" then every character over and above those posted in the second message is sent out in the next packet. Not very secure at all... but then, it's only a game, right?

Part 1. Server Side
This is actually the easy half of the job. The original KPT server release (a modified jPT server) had 3 routines patched out of it. These three routines, I have turned back into assembler source code that will build as a DLL for use in the ModPT (Modular Priston Tale) project that I'm working on. It should work natively there, but I'm going to tell you how you can use this DLL in your own server.

I've provided the source code of the DLL, as well as an example English / Japanese Test build binary executable. The source code contains an EQUate statement that will match any location the protocol key is required, so that you can simply replace the value assigned to that Equate in order to change the protocol your server works on. But if you are no good at building DLLs from source, or just CBA to download the DLL Build Environment I posted in an earlier tutorial, you can just Olly the pre-built .dll file instead.

Downloads
New V2 (all 4 routines):-
View attachment Protocol_V2.rar
[strike]




Original v1:-

NG

[/strike]​
The built DLL exports the functions Protocol1(), Protocol2(), Protocol3() and Protocol4()... I haven't yet found a better way to distinguish the purpose of each. I know how many arguments are passed to each one, but I've not even deciphered which one does what, or what it's true datatype is as yet, and the final "Protocol.dll" will probably have the Port number in it one way or another too.

In any event, they relate to the 3 functions that are patched in KPT, ET2.2 and every other PT server I have seen... though I have seen some that have patched the patches. :s That's a lot easier to do if you have this in a DLL which you have the source code for. ;)

Right, so if you put the .dll file (either the one provided or one you built from the source I've given here) in your server folder, you can add it, and it's 3 functions to the import tables of your server following the guide I posted about adding code to your server with DLLs. (that's the one that has my in it)

Once you have done that, you need to update the calls in your server, you should find them at the following locations:-
Protocol1() is called from
00451FC3 call 004513E0
Protocol2() is called from
0056F47E call 004515A0
Protocol3() is called from
00451F06 call 00451500
Protocol4() is called from
0056F45A call 00451470
0058848A call 00451470
All of which is noted in the source code. The other mentioned address is where these routines are found in the GFantasy section created by the Global Fantasy team whom, I presume, the original KPT server came from in the first place. That's the big blob of extra section in the server that Shagpub, QuantumFusion, Sandurr and the rest of SGPT / Frogg / rPT etc old guard have always put any patches they wanted to add.

I believe Xternal and Xtreme PT still work this way, presume Frogg still do, but know that whom ever StrangeFay works with have moved on from this method at least once, and are (at least aiming to) work from DLLs. They may use the LoadLibrary()... GetProcAddress() method which is popular with cheater / trainer / hacker RCEs because a) it can be loaded at a known point in the programs execution and b) you can get your DllMain() function run at the right point to dynamically patch the executable at run time for DLL injection... As I've said, I don't rate that method for what we are doing, because we don't want to patch anything at runtime... we want a nice stable server with minimal messy tampering. So LoadLibrary() is fine if you want a plugin / optional patch which will automatically revert back to normal operation if the DLL isn't found, but otherwise, lets let the kernel load, map, link and initialise our library for us. In fact, if you want to enable your server to "optionally" load an extra encryption library which should be run at these points only if the DLL exists in the server folder, or some other specified location, you can add LoadLibrary() code to your DLL at in these functions. You could then use optional non-public encryption for "test days" when normal users should be banned from the server, and only "testers" with a non-public client should be able to log in. Then again, I would just swap out the Protocol.dll with a different one, renaming the original to Protocol.normal before installing the "test" Protocol.dll.

Of course, you could just build this assembler into your own extended section, or if you have the usual GFantasy section, it should have them in, and you can change the "key" where it is marked in my source listing.

The other thing to watch out for, is that the Global Fantasy team made the normal CALL operations, and then JMPout to the GFantasy section replacements... that wastes CPU time (a tiny bit, but quite often under heavy server load) and is not very "clean" however, it is safer than patching the root CALL, and if the CALL was a JMP SHORT I would agree with their choice utterly. You could JMP out to your DLL where they did to their new section, but it's not normal to JMP into DLL exports, as they shouldn't know where to JMP back in... these routines don't either, they RETurn to the address the CALL PUSHed onto the stack before it JuMPed the instruction pointer out to your routine.
The CALL instruction is essentially a shorthand for:-
PUSH EIP
JMP
<destination>
and RET / RETN is essentially a:-
POP EIP
You may find that you have to JMP out to the new section to make the call indirect, as an indirect call takes up more bytes than a direct one, or you may find a cave or some other solution. ;)

I will mention that from this source, provided you process only the same memory buffer as this code does, and match your encoding and decoding code at both the server and the client, you should be able to implement any kind of encoding you like. Compression, RSA / PGP encryption or SSL/TLS... anything. You don't have to use Assembler either.

You can build your DLL in C or C++ if you want to, so long as you build an x86 Win32 PE, not a MSIL CLR DLL or an x64 DLL or an IA64 DLL or anything, and follow the arguements as passed on the stack by the server ( or ) you should be fine.

I only use Assembler because I want to exactly mimic the existing operation of the original server and be sure that it will use a DLL exactly like the original code, with no deviation in operation down to the very last instruction... you can't do that in higher level languages... but once you are happy that everything works 100% as normal with the exported original code, then any problems presented with a DLL written in a higher level language are entirely down to your code, or the way your compiler linked the DLL.

That might sound rude, but if it was my C/C++ built DLL, I would want to be absolutely sure of that, so I hope you do to. To clarify... I know that if my high level DLL doesn't work as expected, it's the fault of my DLL, it's not because I haven't linked it to the main program properly, it can't be, because the Assembler DLL, identical to the original server code but built as an external library, works just fine. So my high level source, or the project file, or compiler switches or something in that high level build process is at fault... I don't have to waste time looking again at my edits to the server EXE, I already know that that half of the job is all good.
 

Attachments

You must be registered for see attachments list
Last edited:
Custom Title Activated
Loyal Member
Joined
May 26, 2007
Messages
5,545
Reaction score
1,315
Part 2. Client Side
This is where you really have to get your hands dirty. I can't tell you exactly what to do to make your client operate on a new key, because the code that works them is actually formatted quite differently in each client I've looked at. Most of them do basically the same thing, however, and we can all attest to that by the fact that it's not that hard to make the server work with them again. The one that really is different, is the PTV client... that would take some considerable effort to alter.

Okay... there should be three routines in the client which are equivalent to the ones we put in Protocol.dll to run on the server. They don't look the same, and while some of that may be different compiler optimization options, and the fact that the server was compiled with Visual Studio 6, and the clients are compiled with a variety of versions from there on upwards, I suspect someone has been in an tweaked these routines a tad. At least for some of the clients... and PTV is tweaked a lot, but not just in this respect.

The easiest way I've found of doing this is to open the client in Olly, and use the "Imprecise search patterns" (See Olly documentation "help.pdf") to look for the command "XOR R8,CONST" which means, any 8-bit register XORed with any 8-bit CONSTant... or any constant actually, but you can only XOR same size datatypes.

There are sometimes an XOR R8,01 or something, and you should find an XOR R8,FE in the client that was originally posed as adding the new Sanc map before I patched that out. In that case it was "encrypting" the IP address embedded in the client much the same way the client "encrypts" packets. But on the whole, you should find 2 or three functions which have one of the keys I mention at the top of my source... depending on which client they originated from.

Of course, now we are all going to be changing the "key" to our packets, the value in the client you are using could be anything... but I guess, if you got it connecting to your server already, you can look up the "key" in your Protocol.dll, or in the sections of code JuMPed to at the locations mentioned in Part 1.

I haven't tried, but I suspect you could actually use different keys for different types of packets... and of course, if you are looking to use an entirely different "encryption" protocol, you will probably want to replace the entire sub-routine which controls this in your client, and only need to use this search to locate those routines.

I imagine you will want to keep these routines in the executable game.exe client side, because if you put it in a DLL there, the same advantage you have server-side to chop and change encryption at will, is then presented to would be abusers. :s Let's try not to let that one get out shall we. ;)

Please don't bother putting it in a DLL and encrypting that DLL with an Exe packer... I know I'm not a fan of this, but it's doubly lame here because a hacker will not bother to unpack you DLL, he will just write a new one based on the source I've shared here... he'll keep tweaking the keys until his client connects. Only bother to encrypt your DLL if you are creating an entirely new encryption that has nothing to do with XOR.

Let me give you some examples of simple techniques which would be hard to mimic without seeing the code:-

  • Reverse the order of the bytes. Or shuffle based upon some predictable, but changing value. (Seeded random)
  • Switch the key for each byte, maybe sequentially, maybe based upon a seeded random number, maybe based upon the value of the last byte, before, or after it was XORed?
  • Use ROR or ROL (Rotate bits operations) don't use both. XD Use the opposite one on the server to the one used on the client.
  • Try working on 16 / 32 bit figures with any of these operations.
Each of these are non-destructive (reversible) manipulations of a number stored in memory, none of them can overflow or carry, regardless of what data they are passed. That's what you are looking for.

Because it's useful for all sorts of things, an excerpt from the Olly Manual:-
Imprecise search patterns

When searching for command or sequence of commands, you can specify imprecise Assembler patterns that match many different instructions. For example, MOV EAX,ANY will match MOV EAX,ECX; MOV EAX,12345; MOV EAX,[FS:0] and many other commands.
Imprecise patterns use following keywords:
Keyword Matches
R8 Any 8-bit register (AL,BL, CL, DL, AH, BH, CH, DH)
R16 Any 16-bit register (AX, BX, CX, DX, SP, BP, SI, DI)
R32 Any 32-bit register (EAX, EBX, ECX, EDX, ESP, EBP, ESI, EDI)
SEG Any segment register (ES, CS, SS, DS, FS, GS)
FPUREG Any FPU register (ST0..ST7)
MMXREG Any MMX register (MM0..MM7)
SSEREG Any SSE register (XMM0..XMM7)
CRREG Any control register (CR0..CR7)
DRREG Any debug register (DR0..DR7)
CONST Any constant
ANY Any register, constant or memory operand
You can freely combine these keywords in memory addresses, like in the following examples:
Memory address Matches
[CONST] Any fixed memory location, like [400000]
[R32] Memory locations with address residing in register, like [ESI]
[R32+1000] Sum of any 32-bit register and constant 1000, like [EBP+1000]
[R32+CONST] Sum of any 32-bit register and any offset, like [EAX-4] or [EBP+8]
[ANY] Any memory operand, like [ESI] or [FS:EAX*8+ESI+1234]
If you are searching for the sequence of commands, it's important to emphasize the interaction of the commands in a sequence. Suppose that you are looking for all comparisons of two memory operands.
80x86 has no such instruction (except CMPS, but it's slow and requires lengthy preparations). Therefore compiler will generate the following code:
MOV EAX,[location 1]
CMP EAX,[location 2]
However, it is possible that compiler will choose ECX instead of EAX, or any other register. To take into account all such cases, OllyDbg has special depending registers:
Register Meaning
RA, RB All instances of 32-bit register RA in the command or sequence must reference the same register; the same for RB; but RA and RB must be different
R8A, R8B Same as above, but R8A and R8B are 8-bit registers
R16A, R16B Same as above, but R16A and R16B are 16-bit registers
R32A, R32B Same as RA, RB
For example, search for XOR RA,RA will find all commands that use XOR to zero 32-bit register, whereas XOR RA,RB will exclude such cases. Correct sequence for the mentioned example is
MOV RA,[CONST]
CMP RA,[CONST]
There are also several imprecise commands:
Command Matches
JCC Any conditional jump (JB, JNE, JAE...)
SETCC Any conditional set byte command (SETB, SETNE...)
CMOVCC Any conditional move command (CMOVB, CMOVNE...)
FCMOVCC Any conditional floating-point move (FCMOVB, FCMOVE...)​


Credits
I have to thank the following people who (if you read on) pointed out the 4th and final part of packet encoding.
rxaicy
tr1pl3x1
JayMoko
They have since modified their posts, so they don't flood the thread I guess. But without the information in those posts I would not have know about, or been able to share the fourth protocol routine.

Thank you all.
 
Last edited:
Custom Title Activated
Loyal Member
Joined
Jul 21, 2006
Messages
1,638
Reaction score
341
I feel compelled to respond to this post since surprisingly nobody else has so far (it's a good post!)--

Nice work!
 
Last edited:
Custom Title Activated
Loyal Member
Joined
May 26, 2007
Messages
5,545
Reaction score
1,315
Thanks DK. I suspect it will take people a while to get their head around implementing this on their own server.

I did it on a jPT server which I am adding DLL imports for all of the newer edits, so that there are no new sections and no crazy jumps in and out of .text except to isolated DLL imported functions. My ModPT project. But after I wrote it, I tried to do the same thing with Shagpubs ET2v2 server exe, which I consider one of the most stable and cleanly edited of the modern releases. Despite how cleanly and well it has been done, adding more imports to the PE is quite difficult to do right. It seems the more times the PE goes through LordPE (or any of the other PE Editing tools) the less happy it is to take yet another such edit.

So while people have my source here, I suspect the easiest way for you to implement changes to you existing servers will be to simply edit the code in the GFantasy section. It's not pretty, and I don't like to have to recommend that method, but it works more reliably than importing DLL functions on an already heavily edited server.
 
Experienced Elementalist
Joined
Feb 1, 2007
Messages
235
Reaction score
6
Yes Rxaicy is right there are 4 CALLs for the server. I have changed the protocol of the first JPT Server and the connection works with KPT clients. But my trouble is, that I can't see any NPCs, any Monsters and any Users. Can someone help me?
 
Custom Title Activated
Loyal Member
Joined
May 26, 2007
Messages
5,545
Reaction score
1,315
Thanks for spotting that guys... how you posted yesterday IDK. This time yesterday I was still getting no DNS resolution for RaGEZONE. >_<

Yea... the CALL destination is the same for 4 and 5, therefore it's one routine (Protocol4()) but is used in two places.

If it's possible to use different routines in these two places, then there may be a call for exporting the routine twice... eg:-
Code:
ALIGN 4
Protocol4:			; 4096.00451470(guessed Arg1, Arg2)
Protocol5:
     sub esp,0x08                                
     push ebp
     push esi
     push edi
     mov edi,[esp+0x18]		; Arg1
     mov ecx,[edi+0x08]
     mov esi,[edi]
     mov eax,ecx
     shr eax,0x10
     add al,cl
     ...
     ...
     ...
This method will work, and will allow future DLLs to have two different routines. However, I suspect that the client will only accept one coding, and would be confused if packets where encoded differently from these two points.

I'm updating my code base now, so that the additional information provided by my fellows here can be found in the first post... but as the originator, I need to be sure that my understanding of your additional information is correct before I make those updates.
 
Last edited:
Custom Title Activated
Loyal Member
Joined
May 26, 2007
Messages
5,545
Reaction score
1,315
I still haven't updated, because I still don't understand what this 4th routine does, where it is used or what you might use in place of it.

If anyone can explain to me, I'd appreciate that, as the mystery of it may be holding up others trying to "emulate" a server.
 
Custom Title Activated
Loyal Member
Joined
May 26, 2007
Messages
5,545
Reaction score
1,315
Okay. I updated the first posts, and have given credit for the updated code.

I still don't really understand how that fourth routine is working, and I suspect that it is not the OpCode obfuscater which is causing the PTEmu team so much grief getting an unaltered client to connect.

Or am I wrong in that Sheen?
 
Custom Title Activated
Loyal Member
Joined
Jan 28, 2009
Messages
1,320
Reaction score
616
I see that you added 4th "Protocol". I am not sure If I understand those 4 "functions" they encrypt? Decrypt? Server <-> SQL connection is not encrypted (It don't have to be, or maybe it is when SQL DB is on other PC (not local IP))?

Did you try editing "protocols" so they will communicate "decrypted way"?
 
Last edited:
Custom Title Activated
Loyal Member
Joined
May 26, 2007
Messages
5,545
Reaction score
1,315
Nothing to do with SQL Vormav. It's the encoding (encryption / obfuscation) of information sent between client and server via TCP/IP Packets.

If you set the "key" in the source to 00h (0x00 in C, or just 0) then all chatting and other information is plain to read with packet sniffer... however, userID/Password is different (Protoco4 maybe) and there is something else going on with headers and footers concerned with the OpCode.

If you can't get a reliable OpCode for each packet, you can't tell if it's a login, movement, chat packet etc. so you don't know how to process it.

With the server C# PTEmu we have had to disable it in the client to make the client connect. The older Beta clients didn't do it at all, so the old C++ and VB6 Emus never worried about it, and the official server accepts packets with this level of encoding disabled too... but it's hard to see how to make an Emu understand it.

That wasn't my intention when I first released this. What I did intend was that you could change the "key" and hackers would have to use your client, or figure out the "key" to your packets. Or you could even change the XOR for more complex (true) encryption.
 
Experienced Elementalist
Joined
Nov 8, 2004
Messages
279
Reaction score
36
nice post bob, although sorry to bring it alive :)
Reading it makes me feel like a 1700-1800's doctor trying to look at moderns hospital open heart operation >.<
 
Custom Title Activated
Loyal Member
Joined
May 26, 2007
Messages
5,545
Reaction score
1,315
Yes... it is essentially exactly that. Rip out the "implants" created by the original GFantasy team from their added sections (which LordPE made something of a mess of) and place that code in a DLL which you can add an import for, or delay load with LoadLibrary() and include in the memory from a modular, easily changeable file.

Because I provide the source (even as x86 assembler) you can create a completely new protocol / encryption with it, or modify it so that it reads the XOR "key" from an external file, or embedded resource in the DLL or WHY.

I'm sure some people can convert it to C(++), Pascal or Basic. But if I attempted that, my result would be something not much better than a commented cross-compile / cross-assemble.
 
Custom Title Activated
Loyal Member
Joined
Jan 28, 2009
Messages
1,320
Reaction score
616
[...]
I'm sure some people can convert it to C[...]

Here you go:
http://forum.ragezone.com/attachment.php?attachmentid=87636&stc=1&d=1303320961

Use Dev-C++ to compile (as C code)
Ignore:
[Warning] use of cast expressions as lvalues is deprecated


For me it make no sense, variables holds values that I don't understand.
C or assembly it will do same thing and work same way and make as much sense as non.

PS. This is kPT protocol, I called them cryption1, 2, 3, 4 (client have 3 protocols, server have 4)
 

Attachments

You must be registered for see attachments list
Last edited:
Custom Title Activated
Loyal Member
Joined
May 26, 2007
Messages
5,545
Reaction score
1,315
I was told the server had 4, but when I looked, the server had 2 entry points to the same routine... so 4 calls to 3 protocol routines.

Some are intermixed on the same packet.

The Assembler I ripped and commented as well as I could was also from KPT... so effectively, these DLLs should be inter-changeable, and have no effect on the server at all. (except that the export names don't match, and we can't count on the ordinals either, but that's an easy fix, either in source or the server PE)

Thanks a million for that. I'm sure it will be very useful to many people for different people.

I'm certainly going to have a good look at it.
 
Last edited:
Custom Title Activated
Loyal Member
Joined
Jan 28, 2009
Messages
1,320
Reaction score
616
CLIENT 1.98.9

0044E513 call cryption1 (was call sub_44DB30)
0056823A call cryption2 (was call sub_44DBC0)
0044E456 call cryption3 (was call sub_44DC70)

SERVER 4096

00451FC3 cryption1 (was call sub_4513E0)

0056F45A cryption2 (was call sub_451470)
0058848A cryption2 (was call sub_451470)

00451F06 cryption3 (was call sub_451500)
0056F47E cryption4 (was call sub_4515A0)

I numbered them in order they are in server/client (from top to bottom).

diff is here:
Code:
cryption3 in client (line 144):
v8 = a5 ^ v14;
cryption3 in server (line 144):
v8 = a5 ^ v14 ^ 0xED;
and ofc not existing cryption4 in client.


For example PRE AOR client have only 2 protocols and this might be the reason why modern server and PRE AOR client does not understand each other.

__EDIT__

version 2.0.0 have all 3... this one might be better candidate.

__EDIT__2

no diff... but old maps are cool :)

bobsobol - [Guide][Release?]Protocol / Encryption library. - RaGEZONE Forums
 
Last edited:
Custom Title Activated
Loyal Member
Joined
May 26, 2007
Messages
5,545
Reaction score
1,315
All very odd.

I'm sure the parameters should include StartAddress, Length/End, but I'm not sure what else.

XOR encryption and decryption is usually reversible with the same algorithm, but if there is any bit shifting, it should be reversed in the opposite order, or with pre-shifted XOR.

Anyway... I'm deffo looking into this. Is 1.98.9 the current KPT Test client? Or do you have a link you can share. I should check the x86 to have a better chance of spotting it and labelling up in other clients. :D

---EDIT---
Just checked... No we're up to 1.99.8 now. :$: how time flies when you're having fun. :wink:

So yea... a link to Game.exe v1.98.9 or a Diff/BinPatch against v1.99.0 or v1.98.4 (my closest version numbers) would be ace. :thumbup1:
 
Last edited:
Back
Top