morsisko / NosCrypto

A reverse engineered packet cryptography - encryption and decryption routines to emulate NosTale client or server in Python.
MIT License
9 stars 1 forks source link

WorldEncryption is not similar to the official server in some packets. #4

Open venous1642 opened 2 years ago

venous1642 commented 2 years ago

Hi. I found that packet that has '\n' followed by the char(the char that should XOR by 0xFF only ex. "clist_end\n") the new line should XOR by 0xFF as well, but in this repo, the new line is consider to be encrypted in encryption table.

example : plain packet => "clist_end\n" encrypted packet from the official => "\x0A\x9C\x93\x96\x8C\x8B\xA0\x9A\x91\x9B\xF5\xFF" encrypted packet from this repo => "\x09\x9c\x93\x96\x8C\x8B\xA0\x9A\x91\x9B\x81\xE0\xFF"

This won't affect the decryption in the client. The client decryption is capable to decrypt both encrypted packets to the desired result.

morsisko commented 2 years ago

Hello,

thanks for your report. May I know how did you get the "official" payload? This is easy to change in the repo (in fact you just need to replace the encryption/decryption tables from Server.py with those from Client.py), however I remember I introduced it on purpose, because I saw the server has got the new line character in the encryption table. I need to double check it.

venous1642 commented 2 years ago

Thank you very much for the prompt reply. I get the official packet via the client itself. I simply put the breakpoint the recv function of winsock, then I directly read the buffer.

I guess replace the encryption table won't solve the problem. Because the method that new line is encoded depend on the previous character.

plain text => "clist_start 0\n" The previous character is '0', which is in the encryption table. the new line in the text should be encrypted by the the index in the encryption table and so on. => the index of 0x0A in the encryption table is 0xE. the position of new line is odds => left shift by 4 => 0xE << 4 = 0xE0 encrypted text => "0x0B, 0x9C, 0x93, 0x96, 0x8C, 0x8B, 0xA0, 0x8C, 0x8B, 0x9E, 0x8D, 0x8B, 0x83, 0x14, 0xE0, 0xFF"

plain text => "clist_end\n" The previously character is 'd', which is not in the encryption table. the new line in this text should be xored with 0xFF. => 0x0A XOR 0xFF = 0xF5 encrypted text => "0x0A, 0x9C, 0x93, 0x96, 0x8C, 0x8B, 0xA0, 0x9A, 0x91, 0x9B, 0xF5, 0xFF"

As the result, the way that new line is packed is depend on the previous character.

morsisko commented 2 years ago

When you change the lines number 3 & 4 in Server.py from

_ENCRYPTION_TABLE = [0x00, 0x20, 0x2D, 0x2E, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x0A, 0x00]
_DECRYPTION_TABLE = [0x00, 0x20, 0x2D, 0x2E, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0xFF, 0x00]

to

_ENCRYPTION_TABLE = [0x00, 0x20, 0x2D, 0x2E, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0xFF, 0x00]
_DECRYPTION_TABLE = [0x00, 0x20, 0x2D, 0x2E, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x0A, 0x00]

does it work as intended?

That is how it works after the change:

>>> Server.WorldEncrypt("clist_start 0\n".encode("ascii"))
b'\x0b\x9c\x93\x96\x8c\x8b\xa0\x8c\x8b\x9e\x8d\x8b\x82\x14\x01\xf5\xff'
>>> Server.WorldEncrypt("clist_end\n".encode("ascii"))
b'\n\x9c\x93\x96\x8c\x8b\xa0\x9a\x91\x9b\xf5\xff'

So it looks like the "clist_start 0\n" is encrypted correctly, but what about "clist_end\n"? What is the desired output for this in your opinion?

venous1642 commented 2 years ago

sorry for late response. Yeah the clist_end\n seems to be corrected, but the clist_start 0\n is incorrect.

Your result after change encrypted table.

Server.WorldEncrypt("clist_start 0\n".encode("ascii"))
b'\x0b\x9c\x93\x96\x8c\x8b\xa0\x8c\x8b\x9e\x8d\x8b\x82\x14\x01\xf5\xff'

The correct one is

\x0B\x9C\x93\x96\x8C\x8B\xA0\x8C\x8B\x9E\x8D\x8B\x83\x14\xE0\xFF

It seems like the last 4 bytes is in correct.

Here is a full packet that I received from official. Encrypted:

\x0B\x9C\x93\x96\x8C\x8B\xA0\x8C\x8B\x9E\x8D\x8B\x83\x14\xE0\xFF\x05\x9C\x93\x96\x8C\x8B\x83\x14\x10\x04\x8C\x8C\x8C\x8C\xFE\x14\x15\x15\x1B\x14\x14\x15\x14\x12\x53\x56\x35\x3C\x32\x53\x25\x32\x53\x25\x32\x53\x25\x15\x11\x51\x51\x25\x32\x53\x25\x32\x53\x25\x32\x53\x25\x32\x53\x25\x32\x53\x25\x32\x53\x25\x32\x53\x25\x32\x53\x25\x32\x53\x25\x32\x53\x25\x32\x53\x25\x32\x53\x25\x89\x32\x53\x14\x14\xE0\xFF\x0A\x9C\x93\x96\x8C\x8B\xA0\x9A\x91\x9B\xF5\xFF

Decrypted:

clist_start 0\nclist 0 ssss 0 1 1 7 0 0 1 0 -1.12.1.8.-1.-1.-1.-1.-1.-1 1  1 1 -1.-1.-1.-1.-1.-1.-1.-1.-1.-1.-1.-1.-1.-1.-1.-1.-1.-1.-1.-1.-1.-1.-1.-1.-1.-1. 0 0\nclist_end\n