Showing posts with label rce. Show all posts
Showing posts with label rce. Show all posts
Tuesday, August 13, 2013
It's no IDA, yet?
Tuesday, July 23, 2013
Central Heating - ROM Dump
I had been meaning to try and dump the ROM image of the main cpu of my central heating, but wanted to wait doing that until the weather was a bit better, afterall I didn't want to blow up the chip in the middle of winter.
I actually didn't expect it was going to be possible to dump it, since most devices have a fuse which you can blow to prevent reading out the image, but it was worth the shot.
So took the CPU to work today, since I have access to a universal chip flasher here. To my surprise, the thing read out the chip without problems! So I now have a dump which I can start to reverse. The processor is an ST62T25, unfortunately I don't have a disassembler for that chip, so that will be the next step, writing one.
I actually didn't expect it was going to be possible to dump it, since most devices have a fuse which you can blow to prevent reading out the image, but it was worth the shot.
So took the CPU to work today, since I have access to a universal chip flasher here. To my surprise, the thing read out the chip without problems! So I now have a dump which I can start to reverse. The processor is an ST62T25, unfortunately I don't have a disassembler for that chip, so that will be the next step, writing one.
Saturday, July 20, 2013
Riglol
So a while back, people discovered the Rigol DS2xxx scope firmware contained a developer key to activate all the extra features. This attracted attention from a couple of people to examine the firmware in more detail.
The firmware was reversed by cybernet. He found that the license check was based on ECDSA. The Elliptic Curve implementation was from MIRACL. He then wrote a tool that took the serial number and options + license key and ran the same verification steps to show if the license was correct or not.
This piqued my interest, so I got involved. Read up on Elliptic Curves and gathered the necessary tools. One of the first paths I tried was to check if they were as stupid as Sony, ie. instead of using a random number, they always used the same value, which was how the PS3 security was broken.
Reason why I wanted to check this, was that the MIRACL library only contains a pseudo random number generator, which is seeded by asking the users for a 9 digit seed. If Rigol was lazy, they might have used the same value each time... worth checking out.
However, for this I needed 2 valid license codes, which was a problem...
So I forgot about that and started looking to trying to solve the elliptic curve discrete logarithm problem. I didn't expect to get very far, I mean.. what would be the chance of Rigol screwing up their Elliptic Curve implementation? Right?!
Well it seems the odds were in my favour :-)
After entering all the curve params in a ECDLP Solver, I was greeted with the private key value in less than a second!!
Now here's the weird thing... the values they used are suspiciously similar to a crackme on the net.
To double check my finding, I used the ecsign from the MIRACL SDK to generate a new signature for a fake serial number. Converted the signature values to the license code format, then ran it through cybernet's tool to see if the license was accepted. The last line of the output says it all:
Anyway it was a fun challenge and I learned quite a lot about Elliptic Curves from it.
The firmware was reversed by cybernet. He found that the license check was based on ECDSA. The Elliptic Curve implementation was from MIRACL. He then wrote a tool that took the serial number and options + license key and ran the same verification steps to show if the license was correct or not.
This piqued my interest, so I got involved. Read up on Elliptic Curves and gathered the necessary tools. One of the first paths I tried was to check if they were as stupid as Sony, ie. instead of using a random number, they always used the same value, which was how the PS3 security was broken.
Reason why I wanted to check this, was that the MIRACL library only contains a pseudo random number generator, which is seeded by asking the users for a 9 digit seed. If Rigol was lazy, they might have used the same value each time... worth checking out.
However, for this I needed 2 valid license codes, which was a problem...
So I forgot about that and started looking to trying to solve the elliptic curve discrete logarithm problem. I didn't expect to get very far, I mean.. what would be the chance of Rigol screwing up their Elliptic Curve implementation? Right?!
Well it seems the odds were in my favour :-)
After entering all the curve params in a ECDLP Solver, I was greeted with the private key value in less than a second!!
Now here's the weird thing... the values they used are suspiciously similar to a crackme on the net.
To double check my finding, I used the ecsign from the MIRACL SDK to generate a new signature for a fake serial number. Converted the signature values to the license code format, then ran it through cybernet's tool to see if the license was accepted. The last line of the output says it all:
License Key is VALID
Anyway it was a fun challenge and I learned quite a lot about Elliptic Curves from it.
Tuesday, July 16, 2013
Central Heating - Decoding
After staring some time at the logic capture of my central heating, I was able to decode the way data is encoded by the unit.
The smallest unit in the capture is 6.80ms. It takes 4 units to make up 1 bit/symbol, not exactly a high speed bus. There are 3 different patterns that show up in the cap:
MARK MARK SPACE SPACE
MARK SPACE SPACE SPACE
MARK SPACE MARK SPACE
The transmission has 56 of these patterns, followed by a silence period. This means that each transmission totals 7 bytes. I used the arduino to decode this sequence and output the result on the serial. The MARK SPACE MARK SPACE pattern is decoded as a set bit, while the other 2 decode to a 0 bit. I have no clue as to why there's 2 patterns to indicated a zero, ie. MARK MARK SPACE SPACE and a MARK SPACE SPACE SPACE, maybe it has something to do with providing the remote unit enough power to load up it's internal capacitor, since that unit is completely powered from the 2 wire bus.
I found that to debug the timing of the code, it's quite useful to use an extra IO pin on the arduino, hooked up the the 2nd channel of the oscilloscope and then toggling the line when something goes wrong. By displaying both the CV signal and the debug channel signal on the scope, it was quite easy to see where the code lost track of the signal.
After some fiddling, this is what I got out of the signal:
The communication gives 4 sets of 7 bytes, then repeats. Now it was time to play with the heating and see which values changed...
The smallest unit in the capture is 6.80ms. It takes 4 units to make up 1 bit/symbol, not exactly a high speed bus. There are 3 different patterns that show up in the cap:
MARK MARK SPACE SPACE
MARK SPACE SPACE SPACE
MARK SPACE MARK SPACE
The transmission has 56 of these patterns, followed by a silence period. This means that each transmission totals 7 bytes. I used the arduino to decode this sequence and output the result on the serial. The MARK SPACE MARK SPACE pattern is decoded as a set bit, while the other 2 decode to a 0 bit. I have no clue as to why there's 2 patterns to indicated a zero, ie. MARK MARK SPACE SPACE and a MARK SPACE SPACE SPACE, maybe it has something to do with providing the remote unit enough power to load up it's internal capacitor, since that unit is completely powered from the 2 wire bus.
I found that to debug the timing of the code, it's quite useful to use an extra IO pin on the arduino, hooked up the the 2nd channel of the oscilloscope and then toggling the line when something goes wrong. By displaying both the CV signal and the debug channel signal on the scope, it was quite easy to see where the code lost track of the signal.
After some fiddling, this is what I got out of the signal:
26 66 74 24 02 7B 0A 0010_0110 0110_0110 0111_0100 0010_0100 0000_0010 0111_1011 0000_1010
60 66 75 FF FF 00 20 0110_0000 0110_0110 0111_0101 1111_1111 1111_1111 0000_0000 0010_0000
26 06 77 FF FF 00 20 0010_0110 0000_0110 0111_0111 1111_1111 1111_1111 0000_0000 0010_0000
60 FF 76 25 02 78 0A 0110_0000 1111_1111 0111_0110 0010_0101 0000_0010 0111_1000 0000_1010
The communication gives 4 sets of 7 bytes, then repeats. Now it was time to play with the heating and see which values changed...
Monday, July 15, 2013
DAoC - The middle man
We've already seen that the key generation isn't up to par, neither is the actual way how the RC4 encryption is used... but there's an even bigger issue. The game is susceptible to a man-in-the-middle attack (MITM).
The game client has no way of knowing if the traffic it receives is indeed coming from the official servers. Games like Guild Wars2 use Diffie-Hellman to exchange the encryption key, but they have the server part baked into the client binary. Therefor in a game like that, you can't impersonate the server without changing the client binary (unless they leak their server binary ofcourse *wink*).
Now, in Mythic's defense, the DAoC client does use RSA to transmit the RC4 session key to the server, which means a man in the middle attacker won't be able to decrypt this packet and sniff the encryption key (unless you found a solution for the factoring problem).
So... where's the problem then?
The issue is with the initial connection setup. The client connects to the server and sends a packet with it's info. The server then responds with the following packet:
0000: 22 01 31 01 0a 03
Which tells the client what version the server is running, but more importantly, tells the client to switch to encrypted communication mode. Yes, there's actually 2 modes the client can work in! Encrypted and non-encrypted mode.
This opens the possibility for a MITM attack. If we proxy the data between the client and the server and change the 01 into 00, we can trick the client to work in non-encrypted mode. To the server, we respond with an RSA encrypted RC4 key, which the proxy creates itself. From then on, it's just passing traffic while encrypting/decrypting the data between the 2.
Another big problem is that the communication protocol doesn't use anything like SRP to prevent people from sniffing and reusing the password. Therefor, the attacker will be able to grab the login and plain text password from the intercepted session.
As a proof of concept, I wrote a small proxy that did just that. It ran on a linux machine in between the client and the server and used the transparent proxying (TPROXY) feature of the linux kernel to redirect the traffic to the proxy program. Worked like a charm.
The game client has no way of knowing if the traffic it receives is indeed coming from the official servers. Games like Guild Wars2 use Diffie-Hellman to exchange the encryption key, but they have the server part baked into the client binary. Therefor in a game like that, you can't impersonate the server without changing the client binary (unless they leak their server binary ofcourse *wink*).
Now, in Mythic's defense, the DAoC client does use RSA to transmit the RC4 session key to the server, which means a man in the middle attacker won't be able to decrypt this packet and sniff the encryption key (unless you found a solution for the factoring problem).
So... where's the problem then?
The issue is with the initial connection setup. The client connects to the server and sends a packet with it's info. The server then responds with the following packet:
0000: 22 01 31 01 0a 03
Which tells the client what version the server is running, but more importantly, tells the client to switch to encrypted communication mode. Yes, there's actually 2 modes the client can work in! Encrypted and non-encrypted mode.
This opens the possibility for a MITM attack. If we proxy the data between the client and the server and change the 01 into 00, we can trick the client to work in non-encrypted mode. To the server, we respond with an RSA encrypted RC4 key, which the proxy creates itself. From then on, it's just passing traffic while encrypting/decrypting the data between the 2.
Another big problem is that the communication protocol doesn't use anything like SRP to prevent people from sniffing and reusing the password. Therefor, the attacker will be able to grab the login and plain text password from the intercepted session.
As a proof of concept, I wrote a small proxy that did just that. It ran on a linux machine in between the client and the server and used the transparent proxying (TPROXY) feature of the linux kernel to redirect the traffic to the proxy program. Worked like a charm.
Friday, May 24, 2013
DAoC Random function
As I mentioned before, the generation of the RC4 key in this game can easily be instrumented to generate the secret we want.
The pseudo code to generate the RC4 key looks something like this:
They are also feeding back the input into the RC4 state, by incrementing the j variable by the unencrypted input byte.
Another issue with just using the rdtsc instruction to generate random data, is that this instruction can be made priviledged by setting the TSD flag in CR4, ie. cause a system trap to occur when executed in userspace / ring3, which means there's full control over what this RC4 key generator produces without even having to alter the game binary or redirecting system APIs. Example code to do something like this, can be easily found, ie. here.
The pseudo code to generate the RC4 key looks something like this:
repeat 0x40 timesThis block is then RSA encrypted and exchanged with the server. From then on, all packets get encrypted with this RC4 key. One interesting thing also, is that the game doesn't use RC4 as a continuous stream cipher, instead each packet resets the RC4 cipher to the initial state. This stems from the fact that the game can use UDP for communication and therefor needs to handle the case where packetloss occurs, which would desync the state, but it also makes this less secure. I'm not an expert in cryptography, but I'm sure this enables some interesting crypto attacks to decipher the content. From what I've read, the first few bytes of RC4 are already less random than they should be, which is why it's suggested to advance the RC4 state a couple of bytes before actually using it on your data, which this game doesn't do. Couple that with knowledge of some of the payloads' fixed bytes and I'm sure a real cryptographer can decipher a stream without much effort. Now there's 1 thing they did to try and counter some of this. Instead of starting the packet encrypt from the first byte of the packet, they start it from the middle of the packet, which helps a bit with the known byte value issue.
use rdtsc to generate 1 byte
verify the resulting byte isn't 0
sleep 1
They are also feeding back the input into the RC4 state, by incrementing the j variable by the unencrypted input byte.
Another issue with just using the rdtsc instruction to generate random data, is that this instruction can be made priviledged by setting the TSD flag in CR4, ie. cause a system trap to occur when executed in userspace / ring3, which means there's full control over what this RC4 key generator produces without even having to alter the game binary or redirecting system APIs. Example code to do something like this, can be easily found, ie. here.
Tuesday, April 16, 2013
DAoC vulnerability update
So I got a mail back from the janitor at Mythic regarding my vulnerability report:
Oh boy... what can I say... FAIL!
Hello Karl,
Thank you for contacting Dark Age of Camelot Support.
With regard to your appeal, Ticket#: [XXXXX], we cannot field feedback or suggestions regarding how the game may be altered or improved. However, your opinions and thoughts are always valued!
To appropriately submit your suggestions and feedback regarding game content, mechanics, or design, please go to http://darkageofcamelot.com/contact. On this page, you will find a form which will allow you to submit your suggestions and opinions directly to our development team.
This email address is only for issues of a billing or technical nature, and not issues related to feedback or concerns regarding elements of the game.
Thank you for playing Dark Age of Camelot!
XXXX
Oh boy... what can I say... FAIL!
Monday, April 15, 2013
Hacking the central heating
The central heating I have installed in my home (Integra Zero F29e) doesn't have any network functionality or possibility to interface with a computer. It's using a 2 wire thermostat as a control. The thermostat is powered from the 2 wires it uses to communicate with the central unit.
As I was interested in a computer interface, I set out to investigate what my options were. After some googling around, I got up to speed on the types of interfaces that exist for these kinds of devices. It seems there are 2 major interfaces. One is called Ebus and the other OpenTherm. Both of these have been dissected by hobbyists and therefor there are devices / schematics available to make an interface.
When I started this endevour, I only had a multimeter available. Measuring the 2 wires, it gave a voltage around 20-24v, which led me to believe it was an Ebus interface. So I put something together to convert the data on the bus to TTL levels, since Ebus is just 9600bps serial communication. However, it didn't quite work out.
While researching all this stuff, I figured an oscilloscope would come in handy and since these days you can pick up a digital oscilloscope pretty cheap, I went ahead and ordered a cheap Rigol DS1052e. Once I had the scope, it quickly became apparent that this system wasn't Ebus based.
As I was already on a shopping spree, I also got myself an Open Workbench Logic Sniffer and some arduino's.
I figured it would be simpler to bypass the bus driving circuit, so I had a look at the PCB of the central unit. The PCB was quite simple, it's nothing more than a couple of relays controlled by a microprocessor, in this case an ST62T25.
Here the scope came in handy to check the pins on the MCU, which helped me to figure out which pins were used for the transmission and reception of data. With this knowledge, I could hook up the logic sniffer on those pins and get a dump of the data transmission. Here's how it looked:
For anyone with the same device, the data of the MCU pins are available from the topside of the PCB at points J1 (green wire) and J10 (white wire), the black wire is just a ground point.
With the logic dump available, my next step was to try and decode it. Which I'll explain in another post.
As I was interested in a computer interface, I set out to investigate what my options were. After some googling around, I got up to speed on the types of interfaces that exist for these kinds of devices. It seems there are 2 major interfaces. One is called Ebus and the other OpenTherm. Both of these have been dissected by hobbyists and therefor there are devices / schematics available to make an interface.
When I started this endevour, I only had a multimeter available. Measuring the 2 wires, it gave a voltage around 20-24v, which led me to believe it was an Ebus interface. So I put something together to convert the data on the bus to TTL levels, since Ebus is just 9600bps serial communication. However, it didn't quite work out.
While researching all this stuff, I figured an oscilloscope would come in handy and since these days you can pick up a digital oscilloscope pretty cheap, I went ahead and ordered a cheap Rigol DS1052e. Once I had the scope, it quickly became apparent that this system wasn't Ebus based.
As I was already on a shopping spree, I also got myself an Open Workbench Logic Sniffer and some arduino's.
I figured it would be simpler to bypass the bus driving circuit, so I had a look at the PCB of the central unit. The PCB was quite simple, it's nothing more than a couple of relays controlled by a microprocessor, in this case an ST62T25.
Here the scope came in handy to check the pins on the MCU, which helped me to figure out which pins were used for the transmission and reception of data. With this knowledge, I could hook up the logic sniffer on those pins and get a dump of the data transmission. Here's how it looked:
For anyone with the same device, the data of the MCU pins are available from the topside of the PCB at points J1 (green wire) and J10 (white wire), the black wire is just a ground point.
With the logic dump available, my next step was to try and decode it. Which I'll explain in another post.
Saturday, April 13, 2013
Blast from the past
Since I've been talking about game security the last couple of posts. I figured I revisit an old target I once investigated.
Many many moons ago I blogged about getting Dark Age of Camelot to run in wine. While reversing that game, I also had a look at how the actual game connection works, because that's something that always interests me, ie. the security aspect of it. In this case, there was an extra reason to have a look, since at one time early on in the game's life, a security issue was found and reported to them:
So fast forward 10 years, you'd think it would be pretty secure by now... unfortunately it appears it's still flawed in some way. The thing is, even after all these years, the game is still susceptible to a man-in-the-middle attack. It's perfectly possible to intercept / proxy a connection from the game without needing any details / account info from the player.
So how does the game connection work?
The communication is rather straight forward. There's only 1 connection maintained between the client and the server. The game supports both UDP or TCP for it's game session. This probably stems from the old days where most players actually used a dialup connection, where you don't want TCP retransmissions to cause issues.
Most of the game packets are known. There has been an emulator around for quite some time now and since it's open source, anyone can have a glimpse at how it all works.
The connection is encrypted with RC4. It generates a random session key which gets exchanged via RSA encryption. The generation of the RC4 key could also be improved, since how it currently is done, makes it extremely easy to intercept by using some virtualization techniques. This has as effect that one can get the game to generate the key you want, without having to make any patches to the game client, which is imho not a good thing.
But worse is the fact that this all doesn't matter, due to another vulnerability. But before explaining that one, I'll see if there's still anyone in charge of the game code (most players of the game, seem to think the janitor is the only guy left in the building.. so we'll see how it goes)
Anyway, let's hope the old Mythic gang @ City State Entertainment will have a better security track record if their Kickstarter project, Camelot Unchained, funds!
Many many moons ago I blogged about getting Dark Age of Camelot to run in wine. While reversing that game, I also had a look at how the actual game connection works, because that's something that always interests me, ie. the security aspect of it. In this case, there was an extra reason to have a look, since at one time early on in the game's life, a security issue was found and reported to them:
CVE-2004-1855
Dark Age of Camelot before 1.68 live patch does not sign the RSA public key, which could allow remote malicious servers to gain sensitive information via a man-in-the-middle attack.
A more detailed description is available at:
http://capnbry.net/daoc/advisory20031211/daoc-billinginfo-exploit.html
So fast forward 10 years, you'd think it would be pretty secure by now... unfortunately it appears it's still flawed in some way. The thing is, even after all these years, the game is still susceptible to a man-in-the-middle attack. It's perfectly possible to intercept / proxy a connection from the game without needing any details / account info from the player.
So how does the game connection work?
The communication is rather straight forward. There's only 1 connection maintained between the client and the server. The game supports both UDP or TCP for it's game session. This probably stems from the old days where most players actually used a dialup connection, where you don't want TCP retransmissions to cause issues.
Most of the game packets are known. There has been an emulator around for quite some time now and since it's open source, anyone can have a glimpse at how it all works.
The connection is encrypted with RC4. It generates a random session key which gets exchanged via RSA encryption. The generation of the RC4 key could also be improved, since how it currently is done, makes it extremely easy to intercept by using some virtualization techniques. This has as effect that one can get the game to generate the key you want, without having to make any patches to the game client, which is imho not a good thing.
But worse is the fact that this all doesn't matter, due to another vulnerability. But before explaining that one, I'll see if there's still anyone in charge of the game code (most players of the game, seem to think the janitor is the only guy left in the building.. so we'll see how it goes)
Anyway, let's hope the old Mythic gang @ City State Entertainment will have a better security track record if their Kickstarter project, Camelot Unchained, funds!
Monday, March 11, 2013
Portal Connection - update
Something I just noticed today when investigating an IMAP SSL connection issue (using openssl's s_client), is that the handshake packets looked quite similar to the SSL setup of the gw2 portal connection.
ie. what I originally had:
is actually:
ie. what I originally had:
0x14 = ack0x15 = server error0x16 = auth phase0x17 = game packet
is actually:
As shown in RFC5246 - The Transport Layer Security (TLS) Protocol, makes sense actually that they used a library for that instead of rolling their own TLS version.enum { change_cipher_spec(20), alert(21), handshake(22), application_data(23), (255) } ContentType;
Friday, March 8, 2013
Game connection
So last time I talked about the portal connection, now it's time to go over the security on the game connection.
The guildwars2 game connection is encrypted with RC4. Both the send and receive direction start from the same key.
The session key is randomly generated. The exchange of the session key is done using Diffie Hellman key exchange. The server's B value (gb mod p) is pre-computed and stored inside the game client, therefor isn't transmitted during the setup of the connection.
When the connection is established, the client will send a packet with version information and then send it's diffie hellman component to the server, ie. value A ( ga mod p). The value for g is fixed in all versions upto now and is always 4. The value p is changed on each new build of the game.
The actual session key is the computed diffie hellman shared secret xor'ed with the 20 bytes block the server sends at connection setup. However the RC4 initialization function uses a hash function on the key. I haven't been able to identify the hash function, so had to extract the one from the client to be able to initialize my RC4 routine. (search for "b3 98 b4 9f" and you'll find it)
After that, each byte send/received is just encrypted/decrypted with normal RC4.
As for the actual game packets. Every packet type has a predefined structure, which is handled by a MsgPack / Unpack function. Those functions use a table structure to define the types of fields. The actual msgtype numeric value for a packet can change between 2 revisions of the client, so hard coding those is a bad idea for anyone interested in writing an emulator. It is however fairly easy to extract the structure from the game client. While fooling around with it, I wrote a small program using libbfd to parse the executable and dump a header file with the structure of the packets, enabling me to decode a wireshark capture.
ie. example extract:
struct netFieldI serverMsgWvwCliObjectiveMgr_273[] = {
NETFIELD_MSGID(0x273, "serverMsgWvwCliObjectiveMgr_273"),
NETFIELD_BYTE(),
NETFIELD_END()
};
Since they still have that security issue I referred to a while ago, you don't need any hacks to decode the wireshark. I still haven't heard anything back from them, so I'll probably spill the beans about it one of these days.
Just to help anyone fooling around with it, here are the DH params for the current client (16974) :
const unsigned char p[] = {
0xe7, 0x6f, 0x21, 0x5a, 0x30, 0x4c, 0x56, 0x37, 0x83, 0x1b, 0x17, 0x9c, 0xde, 0x5d, 0xc7, 0x1e,
0x10, 0xec, 0xac, 0xbd, 0xd1, 0x96, 0x72, 0xe3, 0xd3, 0xcc, 0x73, 0x49, 0x0a, 0xfb, 0xb9, 0x97,
0x60, 0x49, 0x02, 0xe4, 0x96, 0xac, 0x4c, 0x8a, 0x39, 0xa7, 0xb2, 0xfa, 0xe4, 0x9d, 0x75, 0x98,
0xc6, 0x81, 0xd1, 0xa1, 0x28, 0x1a, 0x6a, 0x57, 0xb6, 0xf9, 0xa5, 0x1a, 0xf5, 0x11, 0x00, 0x89,
};
const unsigned char b[] = {
0x69, 0xa9, 0x48, 0xfe, 0x6b, 0xe4, 0x4e, 0xd4, 0xc3, 0x85, 0x8e, 0xdf, 0xc6, 0xc9, 0xd4, 0xd1,
0x82, 0x10, 0x9e, 0xce, 0x41, 0xcc, 0x34, 0x36, 0x9f, 0x13, 0xad, 0x37, 0x78, 0x05, 0x08, 0x59,
0xd5, 0x68, 0x2e, 0xe1, 0xf8, 0x34, 0xf3, 0x05, 0x9d, 0x12, 0x85, 0x85, 0x24, 0x7a, 0xa4, 0x69,
0xa9, 0x30, 0x98, 0xd4, 0x21, 0x22, 0xb6, 0xa0, 0x7c, 0x4f, 0xbf, 0x5e, 0x8d, 0x4b, 0x34, 0xe8,
};
g ofcourse is 4.
Another useful tip.. the protocol for this game connection is almost identical to how the GPLv3-licensed CyanWorlds.com Engine (Headspin/Plasma) functions. I'm actually fairly sure, they share a common origin, especially since some of the error messages and constant values of a certain template function are identical to this. The message pack/unpack is also similar, but that one isn't an exact copy.
The guildwars2 game connection is encrypted with RC4. Both the send and receive direction start from the same key.
The session key is randomly generated. The exchange of the session key is done using Diffie Hellman key exchange. The server's B value (gb mod p) is pre-computed and stored inside the game client, therefor isn't transmitted during the setup of the connection.
When the connection is established, the client will send a packet with version information and then send it's diffie hellman component to the server, ie. value A ( ga mod p). The value for g is fixed in all versions upto now and is always 4. The value p is changed on each new build of the game.
The actual session key is the computed diffie hellman shared secret xor'ed with the 20 bytes block the server sends at connection setup. However the RC4 initialization function uses a hash function on the key. I haven't been able to identify the hash function, so had to extract the one from the client to be able to initialize my RC4 routine. (search for "b3 98 b4 9f" and you'll find it)
After that, each byte send/received is just encrypted/decrypted with normal RC4.
As for the actual game packets. Every packet type has a predefined structure, which is handled by a MsgPack / Unpack function. Those functions use a table structure to define the types of fields. The actual msgtype numeric value for a packet can change between 2 revisions of the client, so hard coding those is a bad idea for anyone interested in writing an emulator. It is however fairly easy to extract the structure from the game client. While fooling around with it, I wrote a small program using libbfd to parse the executable and dump a header file with the structure of the packets, enabling me to decode a wireshark capture.
ie. example extract:
struct netFieldI serverMsgWvwCliObjectiveMgr_273[] = {
NETFIELD_MSGID(0x273, "serverMsgWvwCliObjectiveMgr_273"),
NETFIELD_BYTE(),
NETFIELD_END()
};
Since they still have that security issue I referred to a while ago, you don't need any hacks to decode the wireshark. I still haven't heard anything back from them, so I'll probably spill the beans about it one of these days.
Just to help anyone fooling around with it, here are the DH params for the current client (16974) :
const unsigned char p[] = {
0xe7, 0x6f, 0x21, 0x5a, 0x30, 0x4c, 0x56, 0x37, 0x83, 0x1b, 0x17, 0x9c, 0xde, 0x5d, 0xc7, 0x1e,
0x10, 0xec, 0xac, 0xbd, 0xd1, 0x96, 0x72, 0xe3, 0xd3, 0xcc, 0x73, 0x49, 0x0a, 0xfb, 0xb9, 0x97,
0x60, 0x49, 0x02, 0xe4, 0x96, 0xac, 0x4c, 0x8a, 0x39, 0xa7, 0xb2, 0xfa, 0xe4, 0x9d, 0x75, 0x98,
0xc6, 0x81, 0xd1, 0xa1, 0x28, 0x1a, 0x6a, 0x57, 0xb6, 0xf9, 0xa5, 0x1a, 0xf5, 0x11, 0x00, 0x89,
};
const unsigned char b[] = {
0x69, 0xa9, 0x48, 0xfe, 0x6b, 0xe4, 0x4e, 0xd4, 0xc3, 0x85, 0x8e, 0xdf, 0xc6, 0xc9, 0xd4, 0xd1,
0x82, 0x10, 0x9e, 0xce, 0x41, 0xcc, 0x34, 0x36, 0x9f, 0x13, 0xad, 0x37, 0x78, 0x05, 0x08, 0x59,
0xd5, 0x68, 0x2e, 0xe1, 0xf8, 0x34, 0xf3, 0x05, 0x9d, 0x12, 0x85, 0x85, 0x24, 0x7a, 0xa4, 0x69,
0xa9, 0x30, 0x98, 0xd4, 0x21, 0x22, 0xb6, 0xa0, 0x7c, 0x4f, 0xbf, 0x5e, 0x8d, 0x4b, 0x34, 0xe8,
};
g ofcourse is 4.
Another useful tip.. the protocol for this game connection is almost identical to how the GPLv3-licensed CyanWorlds.com Engine (Headspin/Plasma) functions. I'm actually fairly sure, they share a common origin, especially since some of the error messages and constant values of a certain template function are identical to this. The message pack/unpack is also similar, but that one isn't an exact copy.
Friday, December 21, 2012
Portal connection
Portal connection
Time to dig into the specifics of Guild Wars 2's connection...
The portal connection starts off in clear text. The game client will connect, then send a /Sts/Connect command which will include information about the game client.
Example:
P /Sts/Connect STS/1.0
l:252
<Connect>
<ConnType>400</ConnType>
<Address>192.168.1.1</Address>
<ProductType>0</ProductType>
<ProductName>gw2</ProductName>
<AppIndex>1</AppIndex>
<Epoch>999999999</Epoch>
<Program>101</Program>
<Build>1002</Build>
<Process>9999</Process>
</Connect>
P /Auth/StartTls STS/1.0
s:1
l:11
This looks similar to how HTTP requests work. Th
Example:
STS/1.0 400 Success s:1R l:46
<Error server="1001" module="2" line="1518"/>
The 's:1R' here, refers to the original client request. The
The client will begin by sending a buffer starting with:
16 03 03 xx xx
The first byte indicates what kind of packet this is:
14 = ack
15 = server error
16 = auth phase
17 = game packet
The 2 last bytes are the size of the sub buffer that follows.
So looking at the first response the client sends:
16 03 03 00 4e
01 00 00 4a 03 03 xx xx xx ...
Shows a subbuffer of size 0x4e (78 bytes). The first byte is the type of the buffer. If you look closely, it's apparent this buffer is also split up (ie. 0x00 0x4a is yet another size indicator of a sub part). I'm going to skip on some details, if you fire up wireshark you can more easily look at what's there.
There's 1 part that is important in this 0x01 sub buffer and that is a client seed that will be used further on. We need to save 0x20 bytes starting at xx as indicated above.
Also important, is that these sub buffers are used in the HMAC calculation, so we need to keep a sha256 hash of them, excluding the 0x14 sub buffer for digest1.
In code:
if (packet[0] != 0x14)
digest1.process(packet);
digest2.process(packet);
16 03 03 00 34
So we already know 00 34 is the size of the sub buffer, which contains:
02 00 00 30 03 03 xx xx xx
For what follows now, it's useful to read RFC5054 paragraph 2.2. and have a look at the SRP demo page.
The server follows up with a new large packet:
16 03 03 01 14
0c 00 01 10
00 80 xx xx xx .....
00 01 02
08 yy yy yy yy yy yy yy yy
00 80 zz zz zz .....
N = xx xx xx ...
g = 2
s = yy yy yy yy yy yy yy yy
B = zz zz zz ...
16 03 03 00 04
0e 00 00 00
16 03 03 00 86
10 00 00 82
00 80 xx xx xx xx
with A = xx xx xx ...
If you look at the SRP demo page (SRP-6a), you can see how all these values fit together. However GuildWars 2 uses a slightly different way to calculate value x, the RFC version uses:
x = H(salt || H(username||':'||password))
whereas Guild Wars 2 uses:
Then converts this passhash buffer using htonl() and hashes it to form the password field to use in the calculation:passhash = H(lowercase(unicode_pass||unicode_login))
x = H(salt || H(lowercase(username)||':'||H(passhash)))
With all these values, we're able to calculate the shared key S.
The client will now activate encryption by sending the packet:
14 03 03 00 01 01
From now on, the buffers will be encrypted, however the shared key S isn't used as-is for the encryption. First a master key is generated from this and then a key expansion function is used to generate a send and a receive key.
But that's for another post...
Wednesday, December 12, 2012
Hmm it's been far too long since I posted something here...
So a while ago I got interested in seeing how game security was, more specifically how games these days protect people from snooping the traffic. But I was also interested in what counter measures are present to prevent or detect tampering, since bots/cheats are a big issue these days and can potentially ruin a game.
Since I was planning on playing Guild Wars 2 for a bit, I figured it would be a nice target to investigate. The investigation was done on the beta client somewhere in march so my memory is already a bit fuzzy on some details. I've waited this long to post about it, since I didn't want to help bot makers, but I doubt it still matters today. A quick search on google will show there's already plenty of hacks out there, so anything posted here won't make much of a difference.
First thing I noticed was how much information was present in the binary. My initial thought was that this was due to it being a beta client, hence probably contained more debug info. Unfortunately a quick look at a recent binary shows this not to be the case.. there's still lots of useful information present.
For example, even just issuing strings gw2.exe is quite revealing:
Even today's binary (16247) still shows all this detail. Anyone who has ever reversed code will understand how valuable this is during the reversing process.
The game was written in C++ with RTTI enabled, which is also a great source for information. (See Igor Skochinsky's post Recon 2012: Compiler Internals)
Anyway I'll explain the network protocols used by GuildWars 2 on here, which might help some people that are interested in writing a gw2 server emulator. I'll probably spread this over a couple of posts.
While reversing the client, I also discovered a security issue, which to this day is still present. Therefor I've notified ArenaNet today. I'll refrain from explaining the issue for some time, or until ArenaNet resolves the issue. Whichever comes first.
On to the nitty gritty now.
GuildWars 2 uses 2 ports for network communication:
- port 6600 : portal connection
- port 6112 : game server connection
Actually, ports 80 and 443 are also required, but those aren't involved in actual gameplay and it's pretty known which protocol is used on those :-)
The portal connection starts as a clear text protocol, but immediately issues an AUTH TLS command, which initiates a secured connection. The actual data protocol used on this port is XML based. The game uses RapidXML to do the XML parsing.
Example XML piece:
The encryption used on this connection is AES in CBC mode. With a separate session key for incoming and outgoing traffic. An HMAC digest hash is also used, again one for incoming and one for outgoing communications.
The key exchange between the client and server is done via SRP (RFC5054, Secure Remote Password). Since SRP uses Diffie-Hellman, it won't prevent proxying this connection, which would allow people interested in writing cheats to get access to the communication on an external machine, without having to tamper with the actual client binary.
However this doesn't matter much as the game binary I investigated contained no security checks.
The game goes through some key expansion functions to generate the AES & HMAC keys.
NOTE: this is not vulnerable to MITM attacks, as one needs to know the password to be able to proxy the connection.
The connection to the game servers is over an RC4 encrypted connection. Again Diffie-Hellman is used as a key exchange, but in this case the server side packet is precomputed and stored in the game client, ie. the result of ga mod p has been precalculated and is stored in the game binary. Each release uses a new set of keys, so there's no point in trying to find the server key a (would take too long anyway).
The same key is used for transmitting and receiving data, but both paths use a separate state.
From what I heard, this is the same as how it was in GuildWars 1.
The actual data protocol used is a binary protocol with variable sized packets. The client has a MsgPack/Unpack function to (de)serialize the data to/from a C structure.
Again this is similar to how GuildWars 1 worked.
This is a quick overview of how the communication works, I'll go into greater detail in a following post.
GuildWars 2
So a while ago I got interested in seeing how game security was, more specifically how games these days protect people from snooping the traffic. But I was also interested in what counter measures are present to prevent or detect tampering, since bots/cheats are a big issue these days and can potentially ruin a game.
Since I was planning on playing Guild Wars 2 for a bit, I figured it would be a nice target to investigate. The investigation was done on the beta client somewhere in march so my memory is already a bit fuzzy on some details. I've waited this long to post about it, since I didn't want to help bot makers, but I doubt it still matters today. A quick search on google will show there's already plenty of hacks out there, so anything posted here won't make much of a difference.
A First look
First thing I noticed was how much information was present in the binary. My initial thought was that this was due to it being a beta client, hence probably contained more debug info. Unfortunately a quick look at a recent binary shows this not to be the case.. there's still lots of useful information present.
For example, even just issuing strings gw2.exe is quite revealing:
!((m_view == VIEW_GAMEPLAY) && !CharClientContext()->GetControlledCharacter())
!iterator.IsValid()
DNot supported in this configuration!
..\..\..\Game\View\Headless\VhdContext.cpp
N@onRendered
..\..\..\Game\View\Default\VdfRender.cpp
metric < arrsize(m_metrics)
..\..\..\Game\View\Default\VdfLoad.cpp
m_state == STATE_LOAD_MANIFEST
m_state == STATE_MODELS_STREAM
m_mapId == mapId
m_state == STATE_LOAD_CONTENT || m_state == STATE_LOAD_MANIFEST || m_state == STATE_SERVER_WAIT
mapContentLoaded
mapDef != NULL
m_state == STATE_LOAD_CONTENT
m_state == STATE_SERVER_WAIT
m_state == STATE_MAP_STREAM
Even today's binary (16247) still shows all this detail. Anyone who has ever reversed code will understand how valuable this is during the reversing process.
The game was written in C++ with RTTI enabled, which is also a great source for information. (See Igor Skochinsky's post Recon 2012: Compiler Internals)
Anyway I'll explain the network protocols used by GuildWars 2 on here, which might help some people that are interested in writing a gw2 server emulator. I'll probably spread this over a couple of posts.
While reversing the client, I also discovered a security issue, which to this day is still present. Therefor I've notified ArenaNet today. I'll refrain from explaining the issue for some time, or until ArenaNet resolves the issue. Whichever comes first.
On to the nitty gritty now.
The connections
GuildWars 2 uses 2 ports for network communication:
- port 6600 : portal connection
- port 6112 : game server connection
Actually, ports 80 and 443 are also required, but those aren't involved in actual gameplay and it's pretty known which protocol is used on those :-)
Portal Connection
The portal connection starts as a clear text protocol, but immediately issues an AUTH TLS command, which initiates a secured connection. The actual data protocol used on this port is XML based. The game uses RapidXML to do the XML parsing.
Example XML piece:
<Reply>
<UserId>99999999-9999-9999-9999-999999999999</UserId>
<UserCenter>1</UserCenter>
<HasPhone>0</HasPhone>
</Reply>
The encryption used on this connection is AES in CBC mode. With a separate session key for incoming and outgoing traffic. An HMAC digest hash is also used, again one for incoming and one for outgoing communications.
The key exchange between the client and server is done via SRP (RFC5054, Secure Remote Password). Since SRP uses Diffie-Hellman, it won't prevent proxying this connection, which would allow people interested in writing cheats to get access to the communication on an external machine, without having to tamper with the actual client binary.
However this doesn't matter much as the game binary I investigated contained no security checks.
The game goes through some key expansion functions to generate the AES & HMAC keys.
NOTE: this is not vulnerable to MITM attacks, as one needs to know the password to be able to proxy the connection.
Game server connection
The connection to the game servers is over an RC4 encrypted connection. Again Diffie-Hellman is used as a key exchange, but in this case the server side packet is precomputed and stored in the game client, ie. the result of ga mod p has been precalculated and is stored in the game binary. Each release uses a new set of keys, so there's no point in trying to find the server key a (would take too long anyway).
The same key is used for transmitting and receiving data, but both paths use a separate state.
From what I heard, this is the same as how it was in GuildWars 1.
The actual data protocol used is a binary protocol with variable sized packets. The client has a MsgPack/Unpack function to (de)serialize the data to/from a C structure.
Again this is similar to how GuildWars 1 worked.
This is a quick overview of how the communication works, I'll go into greater detail in a following post.
Subscribe to:
Posts (Atom)


