thessium - readthedocs.org

of 26 /26
Thessium Release 0.0.0 Jul 13, 2019

Author: others

Post on 29-Nov-2021

0 views

Category:

Documents


0 download

Embed Size (px)

TRANSCRIPT

ThessiumContents
1 Networking 1 1.1 Calculating the checksum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.2 Connection dataflow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.3 Count/Security Byte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.4 Handshake & Session Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.5 Known MsgId’s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.6 Module identification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.7 MsgID’s by ID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.8 Types used in networking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2 Engine 7 2.1 Landscape . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3 Files 9 3.1 2D Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 3.2 3D Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 3.3 Map / Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 3.4 Shader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 3.5 Audio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 3.6 Container . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4 Reverse Engineering 19 4.1 Where to get info? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 4.2 Giveaways . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
5 Recommended Tools 21 5.1 x64dbg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 5.2 CheatEngine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 5.3 ReClass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 5.4 NTCore Explorer Suite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 5.5 ResHacker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 5.6 Interactive Disassembler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
i
ii
1.1.1 Algorithm
The game’s checksum calculation is just a generic CRC32 checksum algorithm. It’s the fast implementation because it uses a pre-calculated table.
Usually, the table is generated from a fixed poly. In our case, the poly is selected by the server from a list of 256 different polys. The selected index of the poly in the list is transmitted in the first handshake message.
1.1.2 Operation
• The checksum includes all bytes of the message.
• Since the checksum byte is part of the calculation, it’s treated as 0 for the calculation.
1.1.3 Trivia
• Some third-party implementations just ship all 256 tables (65.536 bytes) pre-generated as code.
1.2 Connection dataflow
1.2.1 Establishing a connection
In order to establish a new connection, two major things must be done aside from opening a TCP connection.
1
Handshake
The HANDSHAKE (5000) exchanges security settings and parameters. The first packet is always send from the server- side and contains information about which securtiy settings to enable and which initial parameters to use. Depeding on which settings are enabled, a Diffie-Hellman keyexchange and a challenge are performed.
If the handshake was successful, the client-side sends the ESTABLISHED (9000) message. Any error will lead to an immediate termination of the TCP connection.
Read more in: Handshake & Session Control.
Identification
Once the session is established, the local and remote-side exchange their identities using IDENTIFICATION (2001). The server sends it’s identity first. The client has to answer with it’s identity. Any unexpected data or invalid identies will lead to an immediate termination of the TCP connection.
Read more in: Module identification.
1.2.2 Maintaining a connection
Keeping a connection alive is easy. The client has to send a message at least every 5 seconds. It doesn’t matter which message is. When no messages are received by the server for 5 seconds, the server will terminate the connection. The server will not try to keep the connection alive in any way. When the client has no message to send, it sends a PING (2002).
1.2.3 Closing a connection
There is no known message to end a connection properly (to be checked).
1.3 Count/Security Byte
Each message is stamped with a counter. This is done to avoid replay-attacks and message injection. Basically each message gets an increasing number. All messages need to stay in order. If a number appears out of order, the connection will be terminated.
To make it less obvious, the game uses a pseudo-random-number-generator algorithm. It’s seeded with an initial value and will generate unobvious numbers. Security by obscurity was already a thing back then.
Sadly, the name of the used algorithm is still unknown. It’s operations have been reverse engineered, but its still a big chunk of unreadable code.
TODO: Put code here
1.4 Handshake & Session Control
The very first messages after opening the TCP connection are the handshake. The server also describes these as session. That’s why this article is also titled Session Control. In order to communicate with a server or a client, we need to open a session.
The server sends the first message after the TCP connection is established. Depending on the selected security features, the client has to send a proper answer.
2 Chapter 1. Networking
Remark: The three remaining bits are unused.
1.5 Known MsgId’s
1.5.2 SR_Client
1.7.1 IDENTIFICATION (2001)
Used for telling the remote end the identity/purpose of our local end. The endpoint will also use this to verify that the other endpoints identity is compatible with its own. e.g. the GatewayServer will only talk to SR_Client’s on it’s public port.
Invalid identities will lead to an immediate termination of the connection.
Size Type Name Desc * string Identity Type of the module 1 bool IsLocal false = Machine to Machine, true = Module to Module
Valid identities are:
Thessium, Release 0.0.0
1.7.2 PING (2002)
Empty message. Send by the client after no message is send in 5 seconds.
1.7.3 HANDSHAKE (5000)
Size Type Name Desc 1 byte security_options Enabled security options
If Blowfish 8 byte[] static_blowfish_key Static Blowfish key If SecurityBytes 1 byte crc_seed Poly of the CRC table generation
1 byte count_seed Initial seed for count byte If Handshake 4 int dh_generator Diffie-Hellmann generator
4 int dh_prime Diffie-Hellmann prime 4 int dh_shared_secret Diffie-Hellmann shared secret
Security Options
1.7.4 ESTABLISHED (9000)
Empty message. Send by the client to confirm the established session.
1.8 Types used in networking
1.8.1 Simple types
Type Size Range char 1 -128 to 127 byte 1 0 to 255 short 2 –32,768 to 32,767 ushort 2 0 to 6,535 int 4 –2,147,483,648 to 2,147,483,647 uint 4 0 to 4,294,967,295 float 4 3.4E +/- 38 (7 digits)
See: https://msdn.microsoft.com/en-us/library/s3f49ktz.aspx
string
Size Type Name Desc 2 ushort Length Length of the string * char Text Text of the string in ASCII
1.8. Types used in networking 5
Thessium, Release 0.0.0
2.1 Landscape
The landscape is divided in two major types: Terrain and Dungeon. Terrain-landscapes are mainly supplied by the Navmesh (.nvm) for collision and Map Mesh (.m), Map Object (.o) and Map T (.t) for rendering. Usually all regions that have a sky are Terrain-typed. Dungeon-types are made of Dungeon (.dof). You may know the typical dungeons e.g. Donwhang Cave or Jangan Cave, but also Capture the Flag is a dungeon.
The client will show only two dimensional coordinates. But since this is a 3D game, it has to be handled different. Positioning on the map is split into regions and relative coordinates. It’s like having a usual map with these squares used for roughly finding a location and using millimeters from the top and left to specify an exact location.
The region is mostly represented as one number, but it’s actually two different numbers. You need to display it in hexa-decimal notation, it wont make sense otherwise.
region = 0x6A35 would be region.X = 0x35 and region.Y = 0x6A.
The first bit of the region is reserved for choosing between Terrain and Dungeon type. The first bit is generally also known as the sign bit as it tells if a number is negative. So if you see a negative number for the region, you can tell it’s inside a dungeon.
7
Files
Over the years, many of the properitary file formats have been reverse engineered. This is a collection of known information.
3.1 2D Graphics
3.1.2 Bitmap (.dat)
These files are used as images in the launcher only. They are just renamed Bitmaps. Change the ending to .bmp and open them in any Image Editor you like.
Renamed Bitmap, 24 Bit?, Alpha Color Key,
3.1.3 Direct Draw Image (.ddj)
This format is very simple. The whole file looks like this:
struct DDJ {
char[12] magic;
}
Since the header does not contain useful information, you can just skip the first 20 bytes and load the remaining bytes as a Direct Draw Surface.
3.1.4 Window Description (OLD) (.txt)
3.2 3D Graphics
3.2.1 Compound (.cpd)
3.2.2 Animation (.ban)
Versions:
Region Version Vietnam 188
1 12 byte header; 2 int unk; 3 int unk ; 4 string name; //name of the animation 5 int duration; 6 int framesPerSecond; 7 int unk; 8 int keyframeCount; 9 int[keyframeCount] keyframes; // timings of the keyframes, so you can interpolate
→between two poses. 10 int boneCount; // Amount of bones that have transformations that are
→diffrent from their bind poses. 11 for(int i = 0; i < boneCount;i++) 12 { 13 string boneName; 14 int count; // same as keyframeCount 15 for(int p = 0; p < count;p++) 16 { 17 Quaternion rotation; 18 Vector3 translation; 19 //These two together give you the transformation
→Matrix relative to it's partent bone/joint. 20 } 21 } 22 //End of file
10 Chapter 3. Files
Thessium, Release 0.0.0
3.2.3 Mesh (.bms)
Stores one (partial) mesh of a resource. Due to vertice count limitations, a mesh may be split into multiple separated mesh-files.
JMXVBMS_0110
3.2.4 Material (.bmt)
3.2.5 Skeleton (.bsk)
Skeleton of an object. Basically a weighted mapping of vertices to bones.
JMXVBSK 0101
3.2.6 Resource (.bsr)
A resource combines Animation (.ban), Mesh (.bms), Material (.bmt) and Skeleton (.bsk) to an usable ingame object.
JMXVRES 0109
Trivia
• The resource loader of the server requires all data files, not just the ones required for collision detection.
3.2.7 Particle (.efp)
3.3 Map / Environment
3.3.1 Navmesh (.nvm)
3.3.2 AINavData (.dat)
3.3.3 Dungeon (.dof)
Versions:
0101
1 // File structure for: Dungeon File(*.dof) 2 // Created by: DaxterSoul - 2014 3 // Encoding: Windows Codepage: 949 (Korean) as some of the roomObjectName, entryNames
→or pointNames are Korean. 4
5 12 byte[] Header //JMXVDOF 0101 supported →only
6 4 uint pointerRoomObjects 7 4 uint pointerObjectConnections 8 4 uint pointerLinks 9 4 uint pointerObjectGroups
10 4 uint pointerIndexNames 11 4 uint pointerUnk5 // Has been 0 in every
→file... 12 4 uint pointerUnk6 // Has been 0 in every
→file... 13 4 uint pointerDungeonBoundingBoxes 14 2 ushort unk_ushort0 // Has been 0xFFFF in
→every file... 15 2 ushort unk_ushort1 // Has been 0x0400 in
→every file... 16 2 ushort dungeonNameLength 17 * string dungeonName // Has been "Noname" in
→every file... -> used as projectName in MapEditor. 18 4 uint unk_uint0 // Has been 0xFFFFFFFF in
→every file... 19 4 uint unk_uint1 // Has been 0xFFFFFFFF in
→every file... 20 2 ushort regionID // Used in packets and
→database for whole Dungeon. Used in minimap_d as center- or origin-region (stores _ →default_).
21
22 //pointerDungeonBoundingBoxes will get you here 23 24 float[] dungeon_AABB // width = AABB[3] -
→AABB[0], height = AABB[4] - AABB[1], length = AABB[5] - AABB[2] 24 24 float[] dungeon_OOBB // width = OOBB[3] -
→OOBB[0], height = OOBB[4] - OOBB[1], length = OOBB[5] - OOBB[2] 25
26 //pointerRoomObjects will get you here
(continues on next page)
12 Chapter 3. Files
33 2 ushort roomObject.NameLength 34 * string roomObject.Name 35
36 4 float roomObject.unk_floot0 // Has been 0 in every →file...
37 4 float roomObject.X 38 4 float roomObject.Z 39 4 float roomObject.Y 40 4 float roomObject.YAW // Google it... and use
→this: 57.2957795 for calculation 41 4 float roomObject.PITCH // Google it... and don't
→ask for missing roll, this is no flight simulator... 42 24 float[] roomObject.AABB // width = aabb[3] -
→aabb[0], height= aabb[4] - aabb[1], length = aabb[5] - aabb[2] 43 4 float roomObject.unk_float12 // Seems fixed to -2,
→848866E+38 44 4 float roomObject.unk_float13 // Seems fixed to -2,
→288091E+38 45 4 float roomObject.unk_float14 // Example: -150 46 4 float roomObject.unk_float15 // Example: 1456 47 4 float roomObject.unk_float16 // Example: 0,001 48
49 1 byte roomObject.extraFlagA 50 if(roomObject.extraFlagA == 0x01) 51 { 52 4 float roomObject.ExtraA.unk_float0 // Example: 750 53 4 float roomObject.ExtraA.unk_float1 // Example: 680 54 4 float roomObject.ExtraA.unk_float2 // Example: 50 55 4 float roomObject.ExtraA.unk_float3 // Example: 0,08 56 } 57
58 1 byte roomObject.extraFlagB 59 if(roomObject.extraFlagB == 0x02) 60 { 61 4 float roomObject.ExtraB.unk_float0 // Example: 0,1871207 62 4 float roomObject.ExtraB.unk_float1 // Example: 0 63 4 float roomObject.ExtraB.unk_float2 // Example: -0,8803339 64 4 float roomObject.ExtraB.unk_float3 // Example: 0 65 4 float roomObject.ExtraB.unk_float4 // Example: 2,932153 66 4 float roomObject.ExtraB.unk_float5 // Example: 0 67 4 float roomObject.ExtraB.unk_float6 // Example: 3,503246E-42 68 } 69
70 4 uint roomObject.unk_uint0 // Has been 0 in every →file...
71 4 uint roomObject.roomIndex // Used for roomNames 72 4 uint roomObject.floorIndex // Used for floorNames 73
74 4 uint roomObject.connectedObjectCount //List of directly- →connected objects. Example: 70, 146
75 for (int i = 0; i < roomObject.connectedObjectCount; i++) (continues on next page)
3.3. Map / Environment 13
76 { 77 4 uint objectIndex 78 } 79
80 4 uint roomObject.indirectConnectedObjectCount //List of indirectly- →connected objects. Example: 70, 4, 146, 80
81 for (int i = 0; i < roomObject.indirectConnectedObjectCount; i++) 82 { 83 4 uint objectIndex 84 } 85
86 4 uint roomObject.entryCounter 87 4 uint roomObject.unk_uint1 //Either 0 or 1 88 for (int entryIndex = 0; entryIndex < roomObject.entryCounter; entryIndex++) 89 { 90 //Contains Flames, Stones, Jewelry, Water, and other stuff... 91 2 ushort entry.NameLength 92 * string entry.Name 93
94 2 ushort entry.PathLength 95 * string entry.Path 96
97 4 float entry.X 98 4 float entry.Z 99 4 float entry.Y
100
101 4 float entry.Roll 102 4 float entry.Yaw 103 4 float entry.Pitch 104
105 4 float entry.ScaleWidth 106 4 float entry.ScaleHeight 107 4 float entry.ScaleLength 108
109 4 uint entry.extraFlag // I've seen this as 0x00 →for Flames (Torch & Lamps), 0x02 for Stones (impassable), 0x04 for Water
110 if(entry.extraFlag == 0x04) //Water... 111 { 112 4 uint waterExta 113 } 114
115 4 uint entry.ID 116 4 float entry.unk_float0 117 //1962.75232 for out_obj_stone 118 //902.9495 for out_obj_door 119 //-3.18711172E+38 and similar for water 120 } 121
122 4 uint roomObject.pointCounter 123 for (int pointIndex = 0; pointIndex < roomObject.pointCounter; pointIndex++) 124 { 125 2 ushort point.NameLength 126 * string point.Name 127
128 4 float point.X 129 4 float point.Z 130 4 float point.Y
(continues on next page)
14 Chapter 3. Files
131
132 4 float point.Roll 133 4 float point.Yaw 134 4 float point.Pitch 135
136 4 float point.Width 137 4 float point.Height 138 4 float point.Length 139
140 4 float point.float09 // also Roll 141 4 float point.float10 // also Yaw 142 4 float point.float11 // also Pitch 143 4 float point.float12 // Example: 0,8 144 4 float point.float13 // Example: 0,007 145 4 float point.float14 // Example: 3E-05 146 } 147 } 148
149 //pointerLinks will get you here 150 4 uint unk_uint2 151 4 uint unk_uint3 152 4 uint unk_uint4 153 4 uint linkCounter 154 for (int linkIndex = 0; linkIndex < linkCounter; linkIndex++) 155 { 156 4 uint link.ID 157 4 uint link.connectionCount 158 for (int i = 0; i < link.connectionCount; i++) 159 { 160 4 uint objectIndex 161 } 162 } 163
164 //pointerObjectConnections will get you here 165 4 uint objectConnectionCounter //Always equal to
→roomObjectCounter? 166 for (int objectIndex = 0; objectIndex < objectConnectionCounter; objectIndex++) 167 { 168 4 uint connectedObjectCount 169 for (int i = 0; i < connectedObjectCount; i++) 170 { 171 4 uint connectedObjectIndex 172 } 173 } 174
175 //pointerIndexNames will get you here 176 4 uint roomCounter 177 for (int roomIndex = 0; roomIndex < roomCounter; roomIndex++) 178 { 179 //Some of them might be empty but thats no problem... 180 2 ushort roomNameLength 181 * string roomName 182 } 183 4 uint floorCounter 184 for (int floorIndex = 0; floorIndex < roomCounter; floorIndex++) 185 { 186 //Some of them might be empty but thats no problem...
(continues on next page)
3.3. Map / Environment 15
187 2 ushort floorNameLength 188 * string floorName 189 } 190
191 //pointerObjectGroups 192 4 uint objectGroupCounter 193 for (int i = 0; i < objectGroupCounter; i++) 194 { 195 2 ushort group.NameLength 196 * string group.Name 197 4 uint group.Flag //0 or 1 -> Service? 198 4 uint group.objectCount 199 for (int ii = 0; ii < group.objectCount; ii++) 200 { 201 4 uint objectIndex 202 } 203 } 204 //EOF
3.3.4 Object Information / Index
Indexed list of object filenames. Maps numbers used in other files to strings / paths.
Versions:
JMXVOBJI1000
Region Version Unknown Open Beta
CSV-style list with spaces (' ') as separator. Strings need to be encapsulated in double quotes ("my string")
JMXVOBJI1000 // <Number of lines> // <First line> // <Second line> // ... // <nth line>
Example
(continues on next page)
16 Chapter 3. Files
00010 0x00000000 "res\bldg\china\cj_ferry\cj_ferry_bottle.bsr" 00011 0x00000001 "res\bldg\china\dunhuang\ferry\naruter_fish01.bsr" 00012 0x00000000 "res\nature\china\dunhuang\ferry\w_cd_budawal.bsr" 00013 0x00000001 "res\nature\china\dunhuang\ferry\w_cd_stonwal04.bsr" 00014 0x00000000 "res\nature\china\dunhuang\ferry\w_cd_stonwal11.bsr" 00015 0x00000000 "res\nature\china\dunhuang\ferry\w_cd_small_stonwal.bsr"
3.3.5 Map Mesh (.m)
3.3.6 Map Object (.o)
3.3.7 Map T (.t)
Abstract
Joymax Pak File is used to store the games data files. The format is fragmented; index data and content data are stored in no specific location. Index data is stored in blocks of X entries and is encrypted using Blowfish (LINK). The content data is neither encrypted nor compressed in any way.
3.4. Shader 17
Thessium, Release 0.0.0
Trivia
• Joymax’s implementation does not support defragmentation. Pak Files can only grow.

CHAPTER 4
Reverse Engineering
Reversing a new executable from scratch can be a tough challenge. The community around the game has become very closed regarding information. This page is for sharing offsets.
4.1 Where to get info?
1. Look on the net. There is plenty of info in existing code.
2. Look at the binary. Many debug strings can tell you what the code does.
3. Look at the binary, again. Some may contain runtime type information (RTTI). This will tell you class names, inheritance and (virtual) member functions.
4. Ask. Just ask. If you form a polite, well asked question, you will most-likeley get an answer.
5. If you’re really desperate: Compile a test-binary with the same compiler and stdlib and use tools like K4m1n0 to find similarities.
6. Still no luck? . . . dig deep into the binary . . . some functions may remain unknown for days, weeks, even months.
4.2 Giveaways
4.2.1 Offsets
19
Offset Description Type Client 0xDEADBEEF Example data offset that does nothing data VSRO 188 0x008311C0 WndProc code VSRO 188 0x008328C0 WinMain code VSRO 188 0x009EC570 CNavigationDeadreckon::MoveToCoords(short, struct D3DVECTOR *) code VSRO 188 0x009D87C0 CICPlayer::Render code VSRO 188 0x00BAD750 CGFXVideo3d::EndScene code VSRO 188 0x00BAED40 CGFXVideo3d::BeginScene code VSRO 188
4.2.2 Structures
Some reverse engineered structures to play around in ReClass.
1 // This camera class is a demonstration, it's not the real one 2 struct CCamera 3 { 4 D3DVECTOR position; 5 D3DVECTOR rotation; 6 }
20 Chapter 4. Reverse Engineering
CHAPTER 5
Recommended Tools
5.1 x64dbg
Website: https://x64dbg.com/
A great debugger and disassembler. Has some bugs here and there but is really powerful.
5.2 CheatEngine
Website: https://www.cheatengine.org/
5.3 ReClass
Website: many
There are many flavors of ReClass. Pick the one that fits your needs. If you’re unsure which one to choose, just pick the original one.
5.4 NTCore Explorer Suite
Website: https://ntcore.com/?page_id=388
NTCore got a great set of tools. CFF Explorer is really useful for making changes to the PE Header.
Oldschool Resource Editor. The resources of a portable executable are underestimated. Aside from the application icon, resources can also contain strings, images, forms or even large binary objects.
5.6 Interactive Disassembler
Website: https://www.hex-rays.com/
IDA is a really powerful binary analysis tool. It’s definitely the right tool for the job, even if it has some flaws. IDA v7.0 was released as a freeware recently, with some limitations of course, so give it a try.
22 Chapter 5. Recommended Tools