[Guild Wars] Packet encryption

Status
Not open for further replies.
Newbie Spellweaver
Joined
Feb 1, 2007
Messages
96
Reaction score
0
I've started work on a Guild Wars server emulator in C/C++. The login server is currently working up to the point where communication is encrypted. However, I've been unable to break the encryption. I've found the routine using OllyDbg and it appears to be:

[ key XOR source = encrypted/decrypted byte]

However, the "key" byte goes through a multitude of changes beforehand that I've been unable to pinpoint the source of. I've run GW.exe through PEiD with the Kanal plugin. BASE64 table, CRC32, MD5, and SHA-1 were found.

The last plain text packet the client sends is always 66 bytes in length. It appears to have a 2 byte header([00][42]) which leaves 64 bytes of data. I think this may be the key packet.

The actual point of encryption/decryption is found at: 0x0053724B

So, if you happen to know what encryption Guild Wars utilizes or would like to help, please reply.

~Theora
 
Wow, very nice on your progress so far. I really hope you can get this working. Someone needs to help her with this packet encryp, if I knew how I would help.
 
Theora

Sry guys but Theora will not be posting back on what he has found... well atleast not for the next few days his computer or internet or sompthing does not like any of you! :lol: jk... it just wont let him on the website...
 
Last edited:
Aw, well I really hope he makes some progress.
 
normally when this happens they don't return or return couple of months later and says WHO ARE YOU!
 
I was going to post this in the morning. But I seem to be unable to access this site. It seems to be an IP block. I'm posting this using a proxy. Made quite a lot of progress today...at least compared to the previous 4-5 days. I don't really now how long I've been working on this. Hopefully this issue will be resolved soon.

------

Actually I'm a guy. Though that should not change anything besides perception. I use this alias out of fear of being reported for breach of EULA and TOS. My normal nick is well known on some GW fansites. =(

Back to the topic at hand. I've already seen that page Dradden. The gw.dat file could possibly come into play during development but not for packet cracking. Thoughtful of you to help though. =)

The E/D function takes three arguments, (size of source data, source data addr, ?)
The packet I suspect contains the key is different every time the client connects to the authorization server. Except for the first two bytes. It is generated shortly after a connection is established. I'm not sure how it is generated nor how it is utilized in the E/D function.

The E/D function is called from two different places. This place depends on whether it is encrypting or decrypting. After receiving data, it is not immediately decrypted. It is instead copied into another buffer and decrypted at a later time.

There was just an update to the client. All my addresses are invalid. I'll update this post with the new addresses.

Crypto()=0x00537163
Connect()

* 0x004030A1
* 0x005DDE0

Recv()

* 0x00403428
* 0x0055D5A5

Send()

* 0x004030DD
* 0x00403214
* 0x0040334F
* 0x0055D6B7
* 0x0055DB70

E/D called from:

* 0x00535135 (When encrypting)
* 0x005355BF (When decrypting)

Function call when decrypting:

Code:
 PUSH EAX                                 ; /Arg3  Possibly, output data buffer addr? 
PUSH EBX                                 ; |Arg2  Source data address
PUSH EDI                                 ; |Arg1  Source data size
MOV DWORD PTR SS:[EBP 8],EAX             ; Store arg3 in EBP 8
CALL Gw.00537140                         ; \Gw.00537140  Calls the E/D function
Encryption Function:
Code:
PUSH EBP                                                 ;  Start of the encryption function
MOV EBP,ESP
MOV EAX,DWORD PTR SS:[EBP 8]         ;Fill EAX with souce data size
PUSH ESI
MOV ESI,DWORD PTR DS:[ECX]         ;Move the DWORD from ECX into ESI for our first offset
PUSH EDI
MOV EDI,DWORD PTR DS:[ECX 4]         ;Moves ECX 4(second offset?) into EDI, not sure what for
TEST EAX,EAX
JBE SHORT Gw.005371B7                      ;Not taken on decryption not sure about encryption
MOV EAX,DWORD PTR SS:[EBP 10]
MOV EDX,DWORD PTR SS:[EBP C]
SUB EDX,EAX
PUSH EBX
MOV DWORD PTR SS:[EBP 10],EDX        ;Store an addr. Offset from EAX to reach the actual source data. EAX is output data buffer.
MOV EDX,DWORD PTR SS:[EBP 8]        ;Get source data length
MOV DWORD PTR SS:[EBP 8],EDX        ;Store source data length

INC ESI                                                   ;The first instruction of the loop , increment our offset value
AND ESI,0FF                                            ;keep only first byte of ESI, max size of ESI 255 or FF
MOV DL,BYTE PTR DS:[ECX ESI 8]        ;Move the first byte of the key into DL
ADD EDX,EDI                                         ;Add our other offset(2) onto EDX
AND EDX,0FF                                          ;Only keep the first byte
MOV EDI,EDX                                          ;EDX becomes our new offset in EDI
MOV DL,BYTE PTR DS:[ECX ESI 8]        ;retrieve our key byte again using offset(1)
MOV BL,BYTE PTR DS:[ECX EDI 8]        ;grab another byte from the key using our new offset(2)
MOV BYTE PTR DS:[ECX ESI 8],BL        ;Start the swap of the two key bytes, move BL into DL's source
MOV BYTE PTR DS:[ECX EDI 8],DL        ;Move DL into BL's source
MOV BL,BYTE PTR DS:[ECX ESI 8]        ;BL stays the same
ADD EDX,EBX                                             ;Add the two key values together
MOV EBX,DWORD PTR SS:[EBP 10]        ;EAX=output data buffer, EAX EBX=source buffer
AND EDX,0FF                                           ;Keep only the first byte
MOV DL,BYTE PTR DS:[EDX ECX 8]        ;EDX is our offset(3) now and we grab a key value
XOR DL,BYTE PTR DS:[EBX EAX]           ;Decrypt/Encrypt using XOR, EBX EAX contains our source data
INC EAX                                                  ;Move one byte in both the source buffer and output buffer
MOV BYTE PTR DS:[EAX-1],DL                  ;Store out encrypted/decrypted value in the output buffer
MOV EDX,DWORD PTR SS:[EBP 8]         ;Load the amount of data into EDX
DEC EDX                                                   ;decrease this, it is the loop counter, once it reaches 0 the jump fails
MOV DWORD PTR SS:[EBP 8],EDX        ;store it again
JNZ SHORT Gw.00537163            ;Go back to INC ESI unless EDX==0

--Not concerned in further code--
What I suspect is the key format:

[4 byte dword] ESI offset offset(1)
[4 byte dword] Is in EDI and is a second offset? offset(2)
[remainder]
 
Last edited:
Wow mate, hope you get this working. Wish I knew C++ so bad..
 
Mostly cracked. Give me a key and I can decrypt/encrypt now. I just need to figure out how the server gets the key.
 
Nice job mate!
 
This is very nice i play guild wars in official servers and i love it but the idea of an emulated server where you can play alone and tweak the things you dont like its very cool. Hope mate you dont give up, thank you for your efforts :)
best regards
 
Yet another wrench placed in a pillow and thrown. The key is different after each use. For example:
Code:
Client                                                        Server
-------                                                      -----------
Key0                                                          key0
Client encrypts packet with key0 and sends it which modifies its version of the key.
key1        pck->>>>>>>>>>>>           key0 
Server deciphers packet with key0 and its key is modified
key1                                                          key1

This won't cause problems until examining encrypted packets later on. I wonder what the code does about invalid packets. Packets that have been modified from the original encrypted one. The keys would lose sync and an encrypted communication would have to be re-established.

I'm working on how the server gets the key from the client. It sends it in the packet. But it seems to be in a compressed form. My attempts thus far to locate the code that does this have failed. I'm going to examine the client for constants in the code.

46 is found:
  • 0x00432E5D O
  • 0x00477E02 ?
  • 0x0058E123 O
  • 0x005A29F3 O

Matches for 108(264 dec):

  • 0x00432A97 OX
  • 0x00587657 OX
  • 0x007B37DF ?

I'll manually go through that list this afternoon. =( Finished and backed up just in case an update comes.

This attempt seems to have failed completely. I'm back at Saturday's progress.
 
Last edited:
Very nice! I play Guild Wars too and when I saw this I got interested. I wish I could help but, yea C++ isn't my forte, I only know a little bit from teaching myself. Well, anyway good luck and I hope I can help in any way in the future.
 
Keep it mate up, I'd help you but I don't know C++ /decrypting.
 
Have not progressed at all. I still can't seem to figure out how the server gets the key. I know it is sent in a packet that is 66 bytes in length. 2 bytes being the header and the remainder being some form of the key. The key is 264 bytes in length. 2 integers and 256 bytes. I'm supposing the each byte in the packet stands for four bytes of the key. 64*4=256+8=264 The first two integers always start out as zero as I've seen from observations. The packet sent before the 66 byte packet is always the same so I doubt it has any relevance. For example:
68=20 B9 55 D7

I'm going to write a program to test this theory. If this is the case then another 0x68 that appears should generate those same bytes. I hope it works. ><

EDIT: It fails.
 
Status
Not open for further replies.
Back