Iniuria – An Analysis of the „Antileak“ System

Long time no see everyone, at least for those people that are used to #debuglog targeting payhacks (Yes, It’s that time again!). Today I’d like to talk a bit about something we did in the last couple of days. There are more and more cracks surfacing, which exploit the fact that common antileak systems in most cases suck balls; ranging from variants where the provided loader already includes the hack and has some credentials (mostly some form of a hardware id) hardcoded in the binary to hacks that are streamed form the server to the loader and then injected. The latter is used for the Iniuria antileak system as well – but at least with some degree of “protection”. So, let’s dive a bit into the server and client communication.

The Communication

iniuria_antileak

First of all, the antileak relevant communication is done with query.iniuria.us. That also means that we can route that address to localhost in the hosts file easily. Now, when you start the Iniuria client, it first requests the version.xml from the server (via http – important here because sloppy code ahead). The versions.xml contains the following:

<version>
 <number>129</number>
 <url>https://dl.dropboxusercontent.com/u/88120468/29_12_2014.exe</url>
</version>

As you can see it contains the current version number and a link to the binary of the client. For whatever reason this points to a file in a dropbox. You can try it yourself: http://query.iniuria.us/version.xml

Now, the client either updates itself and needs to be restarted or you are forwarded to the login screen. So, as the nice non paying person you are, you slam random characters into the fields and hit login. The next thing the client sends to the server is the following:

https://query.iniuria.us/login.php (yes, now we are using https)

payload:
Reason=Login&
Name=your_username&
PWD=your_password&
HWID=md5_of_hardwareid&
s=md5_of_request&
h=base64_encoded_hardware_info

Reason, Name and PWD are self-explanatory. HWID is the md5 checksum of the information that is used to identify your hardware (didn’t bother to look because it wasn’t necessary). The h field contains basic information about your hardware, probably used to identify account sharing and looks like this:

US (country code)
Windows 7 (your operating system)
Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz (name of the CPU)
Z97P-D3 (name of the mainboard)

And at last the s field contains the md5 checksum of the request, so tampering with the fields of the request is a bit harder. Now, you, as a smart user that doesn’t pay for stuff like hacks, will see the following:

<?xml version="1.0" encoding="UTF-8"?>
<information>
 <status>WrongLogin</status>
</information>

or

<?xml version="1.0" encoding="UTF-8"?>
<information>
 <status>WrongHardware</status>
</information>

If you actually have paid for an iniuria account (and I really hope you didn’t), you would get something like this as a response:

<?xml version="1.0" encoding="UTF-8"?>
<information>
 <status>Confirmed</status>
 <hackinformation>
  <entry_1>
   <product>Iniuria CS:GO Full</product>
   <type>9</type>
   <game>Counter-Strike: Global Offensive</game>
   <productinfo>Framework</productinfo>
   <detection>undetected</detection>
   <exe>csgo.exe</exe>
   <window>Counter-Strike: Global Offensive</window>
   <expires>27.12.2015</expires>
   <changelog>base64_of_html_changelog</changelog>
   <isclass>0</isclass>
  </entry_1>
 </hackinformation>
</information>

This output varies with the kind of subscription you have. In this case it’s just Counter-Strike: Global Offensive. Most of the datails displayed in the loader. is used to tell the loader in which game the hack should be injected. So, this is pretty straight-forward. If you don’t have the driver already loaded, the client will download it in the next step:

https://query.iniuria.us/login.php

Reason=Cartoon&
Name=your_username&
PWD=your_password&
HWID=md5_of_hardwareid&
k=true&
s=md5_of_request

I worked on a 64 bit machine. I’m not really sure what the „k“ field is used for but it could be a switch to tell the server what driver should be provided: 32Bit or 64Bit. The Server responds with this:

<?xml version="1.0" encoding="UTF-8"?>
<information>
 <status>CartoonOk</status>
 <size>161736</size>
 <cartoon>base64_of_driver_image</cartoon>
</information>

It sends the driver to the client. Just decode the content of the field and you are ready to go.

After the driver download/startup and the response from the server with the product details, you decide what hack you want to use. Select it and press load. The client will send this if you decided to play with the cs:go hack:

http://query.iniuria.us/login.php (HTTP, NOT HTTPS)

Reason=Tom&
Name=your_username&
PWD=your_password&
HWID=md5_of_hardwareid&
Type=9&
s=md5_of_request

Yeah.. for whatever reason he uses HTTP here and not HTTPS. Pretty cool if you want to snoop iniuria credentials at your local university/school/dorm. „Type“ indicates the product that should be streamed to the client. If everything went fine the server will respond as follows:

<?xml version="1.0" encoding="UTF-8"?>
<information>
 <status>InformationOk</status>
 <size>825856</size>
 <type>9</type>
 <isclass>0</isclass>
</information>

We get the confirmation that we are able to use this hack and receive the size of the hack.
You may ask why you get the size in this response. Don’t worry, I’ll explain it after the next request/response. So, after the confirmation and opening the game the client requests the actual hack:

https://query.iniuria.us/login.php (hooray for HTTPS again)

Reason=Cherry&
Name=your_username&
PWD=your_password&
HWID=md5_of_hardwareid&
xml=base64_of_xml_with_api_export_data&
j=base_address_of_hack_in_game&
Type=9&
s=md5_of_request

This is the last request. the xml field contains the base64 encoded xml data of all the exported apis of the kernel32.dll, user32.dll and advapi32.dll and their addresses. The j field contains the address where the client already allocated memory in the game. Remember the field of the last response? Yes, that was necessary so the client could already allocate enough space for the hack in the cs:go memory space. Now we inform the server where the hack will be in the game process. This address with the export data of the dlls is enough for the server to provide a fully prepared hack for the client by mapping the sections, fixing the imports with the provided export list (xml field) and fix relocations for the new base of the hack (the j field). If everything was fine the server will respond with:

<?xml version="1.0" encoding="UTF-8"?>
<information>
 <status>CherryOk</status>
 <file>base64_of_prepared_hack_image</file>
 <entry>address_of_entrypoint</entry>
</information>

Here it is, the fully prepared hack that now gets written to the allocated address (j field of the request). The field contains the entrypoint of the hack library. So, CreateThread on this address and the hack is up and running.

Breaking the System

Now, the observant eye might see a problem or two with the whole concept. If you don’t, don’t worry. Here is something that really makes you think: The server seems to use a valid ssl certificate.. but the client doesn’t validate ANYTHING. Replay attacks are EASILY possible. Just take the requests of a valid customer and send them again.. though you might want to do this from the same internet connection or you might get banned. The fun stuff starts when we want to emulate the whole iniuria server.

The only thing that you have to do is replay every request the client does and save the result (all the xml responses). But there is one, quite annoying hurdle that you have to take: As stated above, the server does the „manual mapping“ stuff. You can’t use the reply with the hack since it only fits at a specific memory location with the kernel32.dll, user32.dll and advapi32.dll of a specific version loaded at specific addresses.

To fix that problem, we have to do several things:
1. we acquire two hack images with two different bases addresses and two lists with exported apis
2. Use the addresses of the exported apis list to search the the hack image and recognize all used apis and their offsets
3. diff both hack images to find differences so we can identify relocations
4. be able to patch one of the two „known“ hack images on a new request with a new export api list and new base

How to:
1.) No problem, just save two „Cherry“ requests with different bases and replay them.

2.) This is actually really easy. Just take the addresses from the fields and search through the hack images, save where you found the address and the name of the api. To make sure that everything went fine, do the same for the second hack image and check if both lists of [api_name, offset] are identical. If they are, the import fixing is not a problem anymore.

import_fix

3.) Finding the relocations is actually the hardest part in the server emulator. Since the hack images don’t contain a pe-header, we have to make educated guesses.. good educated guesses to make this work consistently. To make this work, we define a simple rule: for every ulong (4byte) we check, the lower half must be consistent with one of the
known images and the higher half can differ. Why you ask?

0x17FE 4337

When we talk about x86 memory allocation on windows, we know of the simple rule that all allocations will be a multiple of 0x10000. So, the only part that will vary is the higher part of the address (HIWORD). With this we can search for values that fit into this rule, substract the located address of the known module from the known base and save the offset and this delta like [offset, delta]. Now we can walk through the known library and write at those offsets the new_base + delta. With that we relocated the image to the requested address.

relocation_fix

4.) Just use the lists of the found imports and the relocations and write the data to a new instance of the known image. Encode it with base64, provide the entrypoint of the module ((known_entry – known_base) + new_base) and prepare the response.
done.

This is all it takes to emulate the iniuria server (and part of the client, actually).
Now, at this point we will not provide you with any binary, but since we want to educate people we provide a bit of code.

But first, here are the lessons learned from this from our point of view:
Even though the Pay to Cheat owners make way to much money out of blinded goons that seem to trust anyone as long they get a hack out of it, they don’t take anything serious. There are easy ways to make the job of people that want to break there systems waaaay harder, but that would require the coders to actually use their head and stop relying on the code of other people. I won’t give hints what to do here, obviously, but the amount of sloppy coding out there is depressing. The product quality of „commercial“ gamehacks can be compared with trojans, botnets and „hacking-tools“ you can from purchase in various scriptkiddy-forums.

Anyway, since the hardest part of the emulator is to fix the images, I’ll provide that code here. The communication part is easily done if you have basic skills in one scripting language.

https://openload.io/f/BmeUrf7IGQM/fix_image.py

Iniuria – An Analysis of the „Antileak“ System

Long time no see everyone, atleast for those people that are used to the Pay2Cheat targeting #debuglog. Today I’d like to talk a bit about something we did in the last couple of days. So, in the Pay to Cheat scene it seems that there are more and more cracks that utilizes the fact that the Antileak systems in most cases suck balls. Ranging from variants where the provided loader already includes the hack and has some credentials hardcoded in the binary to hacks that are streamed form the server to the loader and then injected. The latter is used for the Iniuria Antileak system as well, with a bit “protection”. So, let’s dive a bit into the server and client communication.

The Communication

iniuria_antileak

First of all, the antileak relevant communication is done with query.iniuria.us. That also means that we can route that address to localhost in the hosts file easily. Now, when you start the Iniuria Client,it first requests the version.xml from the server (via http – important here because slopping coding ahead). The versions.xml contains the following:

&lt;version&gt;
 &lt;number&gt;129&lt;/number&gt;
 &lt;url&gt;https://dl.dropboxusercontent.com/u/88120468/29_12_2014.exe&lt;/url&gt;
&lt;/version&gt;

As you can see it contains the current version number and a link to the binary of the client. For whatever reason this points to a file in a dropbox. You can try it yourself: http://query.iniuria.us/version.xml

Now, the client either updates itself and needs to be restarted or you are forwarded to the login screen. So, as the nice non paying person you are, you slam random characters into the fields and hit login. The next thing the client sends to the server is the following:

https://query.iniuria.us/login.php (yes, now we are using https)

payload:
Reason=Login&
Name=your_username&
PWD=your_password&
HWID=md5_of_hardwareid&
s=md5_of_request&
h=base64_encoded_hardware_info

Reason, Name and PWD are self-explanatory. HWID is the md5 checksumof the information that is used to identify your hardware (didn’t bother to look because it wasn’t necessary). The h field contains basic information about your hardware, probably used to identify account sharing and looks like this:

US (country code)
Windows 7 (your operating system)
Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz (name of the CPU)
Z97P-D3 (name of the mainboard)

And at last the s field contains the md5 checksum of the request so tempering with the fields of the request is a bit harder. Now, you, as a smart user that doesn’t pay for stuff like hacks, will see the following:

&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;information&gt;
 &lt;status&gt;WrongLogin&lt;/status&gt;
&lt;/information&gt;

or

&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;information&gt;
 &lt;status&gt;WrongHardware&lt;/status&gt;
&lt;/information&gt;

If you actually have paid for an iniuria account (and I really hope you didn’t), you would get something this as a response:

&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;information&gt;
 &lt;status&gt;Confirmed&lt;/status&gt;
 &lt;hackinformation&gt;
  &lt;entry_1&gt;
   &lt;product&gt;Iniuria CS:GO Full&lt;/product&gt;
   &lt;type&gt;9&lt;/type&gt;
   &lt;game&gt;Counter-Strike: Global Offensive&lt;/game&gt;
   &lt;productinfo&gt;Framework&lt;/productinfo&gt;
   &lt;detection&gt;undetected&lt;/detection&gt;
   &lt;exe&gt;csgo.exe&lt;/exe&gt;
   &lt;window&gt;Counter-Strike: Global Offensive&lt;/window&gt;
   &lt;expires&gt;27.12.2015&lt;/expires&gt;
   &lt;changelog&gt;base64_of_html_changelog&lt;/changelog&gt;
   &lt;isclass&gt;0&lt;/isclass&gt;
  &lt;/entry_1&gt;
 &lt;/hackinformation&gt;
&lt;/information&gt;

This output varies with the kind of subscription you have. In this case it’s just Counter-Strike: Global Offensive. Most of the datais displayed in the loader. is used to tell the loader in which game the hack should be injected. So, this is pretty straight-forward. If you don’t have the driver already loaded, the client will download it in the next step:

https://query.iniuria.us/login.php

Reason=Cartoon&
Name=your_username&
PWD=your_password&
HWID=md5_of_hardwareid&
k=true&
s=md5_of_request

I worked on a 64 bit machine. I’m not really sure what the „k“ field is used for but it could be a switch to tell the server what driver should be provided: 32Bit or 64Bit. The Server responds with this:

&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;information&gt;
&lt;status&gt;CartoonOk&lt;/status&gt;
&lt;size&gt;161736&lt;/size&gt;
&lt;cartoon&gt;base64_of_driver_image&lt;/cartoon&gt;
&lt;/information&gt;

It sends the driver to the client. Just decode the content of the field and you are ready to go.

After the driver download/startup and the response from the server with the product details, you decide what hack you want to use. Select it and press load. The client will send this if you decided to play with the cs:go hack:

http://query.iniuria.us/login.php (HTTP, NOT HTTPS)

Reason=Tom&
Name=your_username&
PWD=your_password&
HWID=md5_of_hardwareid&
Type=9&
s=md5_of_request

Yeah.. for whatever reason he uses HTTP here and not HTTPS. Pretty cool if you want to snoop iniuria credentials at your local university/school/dorm. „Type“ indicates the product that should be streamed to the client. If everything went fine the server will respond as follows:

&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;information&gt;
&lt;status&gt;InformationOk&lt;/status&gt;
&lt;size&gt;825856&lt;/size&gt;
&lt;type&gt;9&lt;/type&gt;
&lt;isclass&gt;0&lt;/isclass&gt;
&lt;/information&gt;

We get the confirmation that we are able to use this hack and receive the size of the hack.
You may ask why you get the size in this response. Don’t worry, I’ll explain it after the next request/response. So, after the confirmation and you opened the game the client requests the actual hack:

https://query.iniuria.us/login.php (hooray for HTTPS again)

Reason=Cherry&
Name=your_username&
PWD=your_password&
HWID=md5_of_hardwareid&
xml=base64_of_xml_with_api_export_data&
j=base_address_of_hack_in_game&
Type=9&
s=md5_of_request

This is the last request. the xml field contains the base64 encoded xml data of all the exported apis of the kernel32.dll, user32.dll and advapi32.dll and their addresses. The j field contains the address where the client already allocated memory in the game. Remember the field of the last response? Yes, that was necessary so the client could already allocate enough space for the hack in the cs:go memory space. Now we inform the server where the hack will be in the game process. This address with the export data of the dlls is enough for the server to provide a fully prepared hack for the client by mapping the sections, fixing the imports with the provided export list (xml field) and fix relocations for the new base of the hack (the j field). If everything was fine the server will respond with:

&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;information&gt;
&lt;status&gt;CherryOk&lt;/status&gt;
&lt;file&gt;base64_of_prepared_hack_image&lt;/file&gt;
&lt;entry&gt;address_of_entrypoint&lt;/entry&gt;
&lt;/information&gt;

Here it is, the fully prepared hack that now gets written to the allocated address (j field of the request). The field contains the entrypoint of the hack library. So, CreateThread on this address and the hack is up and running.

Breaking the System

Now, the observant eye might see a problem or two with the whole concept. If you don’t, don’t worry. Here is something that really makes you think: The server seems to use a valid ssl certificate.. but the client doesn’t validate ANYTHING. Replay attacks are EASILY possible. Just take the requests of a valid customer and send them again.. though you might want to do this from the same internet connection or you might get banned. The fun stuff starts when we want to emulate the whole iniuria server.

The only thing that you have to do is replay every request the client does and save the result (all the xml responses). But there is one, quite annoying hurdle that you have to take: As stated above, the server does the „manual mapping“ stuff. You can’t use the reply with the hack since it only fits at a specific memory location with the kernel32.dll, user32.dll and advapi32.dll of a specific version loaded at specific addresses.

To fix that problem, we have to do several things:
1. we acquire two hack images with two different bases addresses and two lists with exported apis
2. Use the addresses of the exported apis list to search the the hack image and recognize all used apis and their offsets
3. diff both hack images to find differences so we can identify relocations
4. be able to patch one of the two „known“ hack images on a new request with a new export api list and new base

How to:
1.) No problem, just save two „Cherry“ requests with different bases and replay them.

2.) This is actually really easy. Just take the addresses from the fields and search through the hack images, save where you found the address and the name of the api. To make sure that everything went fine, do the same for the second hack image and check if both lists of [api_name, offset] are identical. If they are, the import fixing is not a problem anymore.

import_fix

3.) Finding the relocations is actually the hardest part in the server emulator. Since the hack images don’t contain a pe-header, we have to make educated guesses.. good educated guesses to make this work consistently. To make this work, we define a simple rule: for every ulong (4byte) we check, the lower half must be consistent with one of the
known images and the higher half can differ. Why you ask?

0x17FE 4337

When we talk about memory allocation, we know of the simple rule that all allocations will be at least a multiple of 0x10000. So, the only part that will vary are the higher part of the address. With this we can search for values that fit into this rule, substract the located address of the known module from the known base and save the offset and this delta like [offset, delta]. Now we can walk through the known library and write at those offsets the new_base + delta. With that we relocated the image to the requested address.

relocation_fix

4.) Just use the lists of the found imports and the relocations and write the data to a new instance of the known image. Encode it with base64, provide the entrypoint of the module ((known_entry – known_base) + new_base) and prepare the response.
done.

This is all it takes to emulate the iniuria server (and part of the client, actually).
Now, at this point we will not provide you with any binary, but since we want to educate people we provide a bit of code.

But first, here are the lessons learned from this from our point of view:
Even though the Pay to Cheat owners make way to much money out of blinded goons that seem to trust anyone as long they get a hack out of it, they don’t take anything serious. There are easy ways to make the job of people that want to break there systems waaaay harder, but that would require the coders to actually user their head and stop relying on the coder of other people. I won’t give hints what to do here, obviously, but the amount of sloppy coding and thinking with this example is depressing.

Anyway, since the hardest part of the emulator is to fix the images you need to prepare, I’ll provide that code here. The communication part is easily done if you have basic skills in one scripting language.

https://openload.io/f/BmeUrf7IGQM/fix_image.py

Vague Concepts

You know what is totally useless? Vague concepts on how to implement security products. Whenever someone is vague about how his software works and is promising everyone the pie in the sky – we have no choice but to call bullshit.

While Game:ref does not fall one hundred percent in this category, it had many shortcomings, also because details of the implementation where omitted or simplified or scrubbed of as minor disadvantage. But at least there was a proof of concept and a technical outline of how it should work.
Expectedly this still wasn’t enough. The Game:ref kickstarter, which was planned to collect no less than 200.000$ of funds recently, died without a message from the author [1].

Sadly this does not hold people off from announcing the holy grail of Anticheat with a big wall of text almost without any useful information.
Worse than that: There isn’t even a tiny shred of verifiable information given to us.
I am talking about this:
http://www.reddit.com/r/GlobalOffensive/comments/36bpgs/we_are_developing_an_anticheat_that_is_better_in/

So the very first thing which comes to mind is to question the motives of the post. Why post a big wall of text, promising to be „an anti-cheat that is better in every single way than any that exist„, when giving no information about the concept?

The first clue is in the questionare at the end of the post. The first two questions already start with „Would you pay..“.
Ha! Is it seriously that shallow and transparent? I am not even the slightest bit surprised. This is the same banter you get from payhack-developers, who promise undetectable, stable, cheap, and feature-rich hacks, when in reality the customer gets buggy, unstable hacks with unimpressive features (which every old free open source OGC hack trumped more than a decade ago) with expensive monthly fees and DRM mechanisms.

Now let’s work through important parts of the post bit by bit. Some of these comments are nothing more than poking in the dark, because – as i said – we have no real verifiable information to go on.

My background is in development.
I run a design, consulting and development company. I am self-taught, but also attended school in order to see if I was missing anything. I wasn’t, in some cases, I taught my professors things. I know PHP, Java, Python, Ruby, (among HTML, CSS and tons of random web/LAMP based languages) and have recently been learning C++.

I connected with a friend who specializes in Javascript and Python, and he was able to connect me to his friend who is an expert in all variations of C, among many other low/high level development languages.

There were some good answers to this on reddit already. All he does is a block of tooting in his own horn, establishing credentials, making him more believable.
He clearly is deceiving himself, overestimating his self-importance and skills. The whole „i taught my professor things“ is simply a meaningless fallacy. Have you ever configured a mixminion remailer on OpenBSD? You didn’t? I must be smarter than you, then.

While all these remarks are true – i simply call irrelevance. I don’t care. Just show me what you got. What is you concept? Let me verify it, please. For the love of god, just let me try to hack it.

Let’s continue to read his tale.

We got onto a server together (not competitive), and started firing up various cheats, some before we started CS:GO, some after, in many iterations.

In some cases before they were even toggled on, or in basic terms, while it was gathering information in order to prepare the cheat to be toggled on, our anti-cheat detected successfully 12/16 cheats that we were testing.

One of the other four was detected in less than five minutes, two within fifteen minutes, while one cheat evaded us completely. Come to find out, the final cheat was not even working, thus why we did not detect it.

That’s a 15/15 score, with one non-operational cheat (which, doesn’t matter) not being detected.

What can we gather from this? They tested 16 cheats. One of them was unfunctional.
We don’t know which ones. We don’t know how these cheats work, what features they have, how intrusive they are, what mechanisms they exploit, nothing.

Next we get the information that some of the cheats were detected immediately, while others took minutes to detect. Knowing nothing about the anticheats architecture this would mean that the Anticheat processes data that takes minutes on modern systems to sift through and analyze. I am just taking a guess here: Maybe it just walks the whole physical memory and looks for x86/x64 assembly patterns that access and process internal structures of the game process. It wouldn’t be a bad approach, the heuristics might be a bit difficult, you would have false positives, false negatives and the usual problems, but why not.
Maybe this AC even uses techniques like PIN tracing or dynamic recompilation [2]…

I can take guesses all day, but let’s face it: A testable and verifiable concept encompasses much much more than just the vague mentioning of a method like this and the reddit post didn’t even do that. It leaves us with nothing than just anecdotes. And everybody knows that anecdotal evidence is poor and unreliable [3][4].
Moving on.

After we decompiled them, we anonymously sent many of them to various dev teams over the last month or so in order for them to better detect them. We even highlighted routines they should pay attention to.

Really? You decompiled all hacks and send them to Valve? Or do you mean just disassembled? Which is just a software job. Or did you really decompile every hack manually back to C or C++? Which would take years.

I think the most plausible explanation is: They pseudo-decompiled all hacks with a pirated copy of Hexrays [5] and maybe commented some structures and functions here and there …

Anyway: Here is another clue for my pattern-scanning on accessing gamestructures  hypothesis. They highlighted routines to pay attention to. What routines you ask? Routines that probably access and or process often used offsets, addresses and constants of internal game structures.
Another reason why these cheats and routines might have been detected so easily, is because the sphere of payhacks is mostly just a big sad pile of publicly copypasted ressources, that are openly accessible [6].
But this also means: Everyone knowledgable enough would be able to obfuscate these easy to distinguish patterns into unrecognizable oblivion – even when tracing and emulating through it yourself, because you can almost always make execution dependable on input the emulator doesn’t have, unless the emulator paradoxically emulates the whole system with himself in it (much like the infinity computer that emulates the universe with itself in it) [7].

We plan over upcoming weeks to acquire many cheats, both public and private, both „detected“ and „not detected“ by VAC/ESEA, and decompile them to learn more about what makes some of these programs more special than others.

The fallacy in this approach is easily detectable, isn’t it? What would you say to an engineer of an operating system, that hasn’t been released, if he boasts: „I have tested all known exploits against my operating system and it still stands.
That is not how it works. You need to put the anticheat openly to the test. Every client in the future will have access to the whole part of the anticheat that is running on his system. As such it will be open for scrutiny for every hacker. Let them be the judge. Be greatful for every hacker that will analyse your anticheat and openly release what he found. That is penetration testing [8] free of charge.
Your hidden tests on hacks that are not designed to bypass your unknown anticheat with your unknown detection method are of no value whatsoever.

No, I won’t post screenshots of the anti-cheat, and no I won’t post any of the code/share decompiled code from the cheats we have.

Why not? Releasing information about the hacks (or your AC for that matter) would advance public knowledge in general, on how those hacks work and on how to defend against them, analogous to Kerckhoffs princinple [9]. If you are really concerned about advances against online gaming cheats, you would release the information you have.

But you are not. You are not interested in the advancement of knowledge. Half of your post reveals nothing but economic interests and i am not surprised.

„because we need to patent and protect whatever we can“
„Hopefully, through this partnership, our software can notify Valve/ESEA or whatever companies partner“
„Would you pay $X/month for a 99% clean cheat environment?“
„Would you pay a monthly fee to Valve to see it added into matchmaking instead?“

Last but not least a confused remark on my side. This question just boggled my mind:

Does the intrusiveness level of an anti-cheat make you less likely to want to use it?

How on earth would i know how intrusive your anticheat is? You gave absolutely no information on what information the Anticheat collects, processes and sends out.
How can anybody possibly answer this question?
With this i end this tale on how bad and useless „vague concepts“ are. They are mostly nothing more than a sales pitch.

[1] https://www.kickstarter.com/projects/1094040691/game-ref-the-worlds-first-hardware-anti-cheat-devi
[2] https://medium.com/@oleavr/anatomy-of-a-code-tracer-b081aadb0df8
[3] http://blog.minitab.com/blog/adventures-in-statistics/why-anecdotal-evidence-is-unreliable
[4] http://scienceblogs.com/insolence/2012/04/16/a-homeopath-lectures-scientists-about-an/
[5] https://www.hex-rays.com
[6] http://www.unknowncheats.me/forum/counterstrike-global-offensive/103220-global-offensive-structs-offsets.html
[7] http://rationalwiki.org/wiki/Simulation_argument#Computing_complexity
[8] http://en.wikipedia.org/wiki/Penetration_test
[9] http://en.wikipedia.org/wiki/Kerckhoffs%27s_principle

Let’s talk about Game:ref

Recently David Titarenco presented the idea of a hardware anticheat device, focused on mouse input control of the player [1].

It is basically a black box (or should be, more on this later) with USB in+out and ethernet. The player plugs in his mouse into the device and another cable from the device into his computer.
The device also needs access to the internet, therefore a seperate ethernet interface.

The device then communicates with a anticheat server and reports the users mouse data (while also relaying the mouse signal to the computer), which in turn can be compared with the game servers input logs of the players viewangles.
In theory they should match up, but as the author notes, there are several issues with this. Talking about comparing mouse y-input graphs, the author notes:

Obviously, the two don’t “line up” perfectly and unfortunately, the two will never be isomorphic. Windows (and OSX/Linux) tends to provide various mouse features that consist of smoothing, acceleration, deceleration, interpolation, etc.

Finally he resorts to just logging the x and y directions for each time slice, for x or y being: -1, 0 or 1.
This interestingly has very important ramifications, i will talk about at the end.

So this promises to be an aimbot-detecting hardware-anticheat (not aiming to detect and/or prevent other non-input kind of hacks like Wallhacks or ESPs).

Let’s talk about some things.

Anticheat-concept: Input Control

Input control is not really a new idea, albeit not really used that much and not usually realized with hardware devices.

Demo analysis:
Demo-Analysers (like FPS-Death) check a recording for input plausability, for example perfect bunnyhopping timings.
It is also possible to detect certain kinds of silent aimbots or in general hack features where client/server angles are desynched on purpose or as a side-effect of the hack.
Demo analysis can of course be easily thwarted by keeping client recordings plausible.

Heuristic server plugins:
David also briefly touched on this in his article and called it „stochastic“ method to detect hacks.
The idea is – again – to check for plausible input and determine if reaction, precision, timing and „imperfect information based actions“ (like hitting someone behind a wall pretty often) are humanly possible. The biggest problem is to determine the tresholds. What reactions, precisions, timings and actions based on imperfect information are too implausible to be only human input?
This is not an easy question to answer – there might even be crossovers. Humans who cheat and keep being below the treshold and very good players who break the treshold.
This will possibly generate false positives and negatives.

Monitor-Drivers:
Monitor Drivers do just that – they monitor input directly as a HID filter driver and compare them with client or server data.
Davids device could in theory be completely modelled and implemented as a driver with an interesting advantage. It could weed out some of the adjustments to the mouse movement done by the operating system, being more comparable to the angle-differences the client engine processes and reports to the game server. It would also be thinkable to calculate in the engines mouse processing to match it even further.
The main disadvantage of course is the shifted attack surface, which David mainly had in mind. Cheat developers can more easily distribute only-software hacks and with lower prices.
David of course hopes that hardware manipulation or extra devices will be necessary to aimbot, costing the hacker knowledge, ressources and distribution problems.
On the other hand some well known anticheat drivers have a pretty good track record to show for and serious attacks have largely been just propaganda by payhack-sellers.

Blackbox requirements

The first thing that comes to mind: Can’t we just emulate that whole thing?
We just contact the anticheat-server ourselves with our hack and splice our aimbot-data to it, pretending it to be genuine mouse data.
And if the data/traffic is encrypted/encoded in a way we can’t inspect over sniffing the network, let’s just dump the software from the device and reverse engineer it. Afterall this is a user-friendly Arduino, isn’t it?
In the worst case we just fizzle out Flash or EEPROM and read it out on our own device.

Now these thoughts tell us something about the security implications and requirements such a project should have.
David briefly touches on this saying:

I need to implement HMAC (or a variation of it) to make sure that the device itself is tamper-proof

… which would be far from complete. Having a static HMAC secret is also very dangerous, making timing side-channel-attacks very easy. And once the static secret is recovered, it is game over. Harder – but not impossible – would be TLS with mutual authentication, having ephemeral session keys, even rolling out new keys on the fly maybe.
Cryptography-wise there is a lot to say and consider when developing devices the potential adversary comes in contact with. Which is the exact situation we have.
To not blow this blog post out of proportion, more on this here [2].

There is also pure operational security at play here. The device must defend its secrets also physically to prevent someone to just carefully solder out memory chips, reading out the contents in order to reverse engineer and remodel the entire device in software.

To counter this many agencies and the military (in case of stolen devices) use some sort of anti-tamper coating of crucial cryptograhic chips containing secrets [3].

Hardware – man in the middle

The most obvious point of failure of course is:
How can the device ever confirm that the device plugged in its USB slot is actually a real mouse? Maybe its another arduino plugged into the pc with the hack running, feeding fake input data.
Or it is a cable from a USB Device Controller controlled by the PC – and the software controlling the fake HID is the hack itself. The possibilities are almost endless.
David does acknowledge this in the comments and says that the goal of the device is to at least eliminate all aimbots solely based on software.

Restriced direction aimbot (aim assistance)

At the beginning we touched a bit on the fact that the input graphs (when comparing raw mouse input on the device and the server viewangle data) will not match up and have several error margins.
His solution is testing for correct X/Y directions per time-slice, with -1 moving in the negative X/Y direction, 1 moving in the positive X/Y direction and 0 not moving in that X/Y direction at all.
As a player we can be in the following situations with our mouse movement:

X: -1 (left) 1 (right) 0 (still)
Y: -1 (down) 1 (up) 0 (still)

X   Y
====
-1 -1
-1  0  // neither moving up nor downwards
-1  1
0 -1 // neither moving right nor left
0  0  // mouse not moving at all
0  1 // neither moving right nor left
1 -1
1  0 // neither moving up nor downwards
1  1

Some movement pairs are really rare. Try to move your mouse in a straight line up/downwards or left/right without even going one pixel in the perpendicular direction. Try it in MS Paint: Do one straight line without using any tools and see if you can do it. 🙂

Being completely still (0,0)  does happen more often, though. For the kind of aimbot presented here, this is slightly disadvantageous; just something to keep in mind or to at least compensate through readily move the mouse at the right moment.

So most of the time the mouse is moving in one of the following ways: left and down, left and up, right and down, right and up.

Being in a fight and trying to aim at an enemy, MOST of the time as a player, one starts to aim at least in the direction of the enemy player.
So if the head is left and above the crosshair, the first reaction is to move towards it, in this case (-1, 1: left and up).
The problem is: One overshoots the correct destination or stops to soon or changes direction in an unfavorable way. But the general aiming trend, the rough direction is indeed correct (-1,1).
This is where the aimbot kicks in. It locks the movement of the mouse with the speed and precise direction (more than just the trend) while the correct trend direction is being administred by the players real mouse.
If it so happens that the player moves his mouse in an unfavorable direction trend, the aimbot moves the mouse just as slow as possible in the wrong direction.

In a way (helping out the player keeping the trend of correctly aiming) works like aim assisting features mostly found in console games.
A picture to illustrate:

In conclusion and as it stands now (i know this is yet just a prototype):
– The basic idea of mouse input control and matching isn’t that revolutionary or new
– Davids claim that software aimbots are completely eliminated and ruled out with his device is untrue
– The problem of man-in-the-middling hardware can’t be realistically mitigated and stands as disadvantage
– Many cryptographic and physical security concerns are yet unadressed
– In some sense the same thing can be implemented (with better input-matching) with drivers and in combination with combatting other types of cheats (like wallhacks, ESPs)
– the costs (ressources, management, shipping) for the device may be disproportional to its real advantages

These are just my first thoughts. This article does not touch upon further operational questions that are important to handle (like intentional disruption of the network connection, also known as „fakelagging“ or or being able to update the devices firmware for the clients using it, while at the same time fully limiting access to the device for hackers) and the problems and hacking advantages that come with these problems.
Seeing that this project is barely in a workable phase, i’ll leave it at that and maybe follow up on this when things have developed more.
Also: This article provides some critical thoughts possible investors should consider before putting money into this project.

[5/2/2015] Update: Another good analysis of the device:
http://www.reddit.com/r/GlobalOffensive/comments/34l05k/im_emozilla_long_time_developer_and_member_of_the/

[1] http://dvt.name/2015/finishing-what-intel-started-building-the-first-hardware-anti-cheat/
[2] https://www.era.lib.ed.ac.uk/bitstream/handle/1842/860/Spadavecchia_thesis.pdf
[3] https://siliconpr0n.org/wiki/doku.php?id=physical_protection

NetShark: Attack Vectors

As already stated Valve uses Public-key-cryptography to exchange the ICE-Key to encrypt its game traffic on its own servers. The community servers use a key that just depends on the client build number.

The method used is RSAES-OAEP according to the PKCS#1 v1.5 standard. While this has some weaknesses we must remember that our attack has to be feasible within seconds or minutes during game session. It wouldn’t matter if we retrieve secrets even hours after the game took place. We need them instantaneously to gain any advantage.

NetShark was strong because it was non-intrusive and out of scope of anticheat technology. We have encountered a blow to this mechanism.

But what if we make a little compromise. What if we just quickly steal the ICE Key from memory (through any means), save it to a file, move it to the PC where NetShark runs and do the same as we did before.
It is a compromise because we could still be caught by stealing the key. But other than reading 128 Bit from memory (4 DWORDs) we keep being clean for the rest of the time.

I updated NetShark to use the IceKey from the file „icekey“ in the same folder.
How you get the IceKey is described below.

Getting the ICE-Key from Memory

Hint: All addresses are rebased.You will have to find everything yourself or calculate base differences.

The whole encryption and decryption of game traffic is done in the „engine“ module of the game. Carefully following breakpoints put on recv() we end up in a function with some string references, one of which is:
„NET_ReceiveDatagram: receiving voice from %s (%d bytes)“

This helps us finding the function more quickly the next time. Following the usage of the network buffer, we manage to find the decryption loop:

.text:1013183A                 xor     esi, esi                       // initialize loop counter
.text:1013183C                 mov     ebx, esp                  // temp variable
.text:1013183E                 cmp     [edi+40h], esi          // size of buffer
.text:10131841                 jle     short loc_10131869
.text:10131843                 mov     eax, [edi+18h]         // pointer to buffer with encrypted data
.text:10131846                 lea     ecx, [ebp+var_18]     // IceKey-Instance class pointer
.text:10131849                 push    ebx                          // push plaintext temp buffer
.text:1013184A                 add     eax, esi
.text:1013184C                 push    eax                         // push ciphertext buffer
.text:1013184D                 call    sub_101C2DE0       // IceKey::decrypt (look in SDK)
.text:10131852                 mov     eax, [ebp+var_205C]
.text:10131858                 movq    xmm0, qword ptr [ebx]
.text:1013185C                 movq    qword ptr [eax+esi], xmm0
.text:10131861                 add     esi, 8                       // block cipher, 8 bytes for every block
.text:10131864                 cmp     esi, [edi+40h]        // are we done yet?
.text:10131867                 jl     short loc_10131843   // end of  loop

Those who encountered ICE before will recognize it, because it has a blocklength of 8 bytes.
Let’s look in the SDK.

https://github.com/ValveSoftware/source-sdk-2013/blob/56accfdb9c4abd32ae1dc26b2e4cc87898cf4dc1/sp/src/mathlib/IceKey.cpp

https://github.com/ValveSoftware/source-sdk-2013/blob/56accfdb9c4abd32ae1dc26b2e4cc87898cf4dc1/sp/src/public/mathlib/IceKey.H

Before anything can be decrypted, the IceKey class has to be initialized and the key has to be set.
Let’s look for more calls of the class instance [ebp+var_18]. Right above we’ll find:

.text:101317D9                 call    sub_10130260           // FindNetChannel(…,
.text:101317DE                 test    eax, eax
.text:101317E0                 jz      loc_10131AD2
.text:101317E6                 mov     edx, [eax]
.text:101317E8                 mov     ecx, eax
.text:101317EA                 call    dword ptr [edx+134h]  // GetChannelEncryptionKey
.text:101317F0                 mov     esi, eax
.text:101317F2                 test    esi, esi
.text:101317F4                 jz      loc_101318B7
.text:101317FA                 push    2
.text:101317FC                 lea     ecx, [ebp+var_18]
.text:101317FF                 call    sub_101C2B50         // IceKey::IceKey(2)
.text:10131804                 push    esi                           // push encryption key
.text:10131805                 lea     ecx, [ebp+var_18]
.text:10131808                 call    sub_101C3080         //IceKey::set(char* key)

Now we know where to look for our key.  We also know it must be 128 bit in size.
64 bit is the standard key length and the constructor is called with n=2, doubling it.

The engine has support for several logical communication channels. Usually only one channel is used, but file transfers for example are delivered over a second allocated channel object.
So apparently every channel instance stores it’s own encryption key, probably in one of its members.
This means we need to get the pointer to the main channel instance first and then access the encryption key member afterwards.

So let’s look into FindNetChannel(…) to find the main channel.
.text:101302B0                 mov     eax, dword_106A0818
.text:101302B5                 mov     ebx, [eax+esi*4]

dword_106A0818 has our channel list and the main channel is – for all cases we are aware of – the first element. This is all we need to know.

Now let’s look into GetChannelEncryptionKey(), which was at vtable+134h.

sub_10127020    proc near               ; DATA XREF: .rdata:103BE594o
.text:10127020                 mov     eax, dword_106F5058
.text:10127025                 test    al, 1
.text:10127027                 jnz     short loc_1012703F
.text:10127029                 mov     edx, dword_106C2AB4
.text:1012702F                 or      eax, 1
.text:10127032                 mov     dword_106F5058, eax
.text:10127037                 mov     dword_106F505C, edx
.text:1012703D                 jmp     short loc_10127045
.text:1012703F loc_1012703F:                          
.text:1012703F                 mov     edx, dword_106F505C
.text:10127045 loc_10127045:                          
.text:10127045                 test    al, 2
.text:10127047                 jnz     short loc_101270C4
.text:10127049                 or      eax, 2
.text:1012704C                 mov     byte ptr word_10430FDC, dl
.text:10127052                 mov     dword_106F5058, eax
.text:10127057                 mov     eax, edx
<snip—snip–snip> // build static key and store
.text:101270C4 loc_101270C4:                          
.text:101270C4                 cmp     dword ptr [ecx+4288h], 0 // are we on a valve server?
.text:101270CB                 jz      short loc_101270D4
.text:101270CD                 mov     eax, [ecx+4284h] // return dynamic session key (valve servers)
.text:101270D3                 retn
.text:101270D4 loc_101270D4:                          
.text:101270D4                 mov     eax, offset unk_10430FD8 // return static key (community servers)
.text:101270D9                 retn
.text:101270D9 sub_10127020    endp

Upon examination we discover several things. First: What we actually get as a key, depends on dword ptr [ecx+4288h]. Testing reveals: This is NULL on community servers, and we find our key (after it was built together) at unk_10430FD8. It is the same key every time and it depends on the build number.

On Valves servers (Matchmaking, etc.) the key is retrieved from the channel class member [ecx+4284h].

So this is all we need. We retrieve the first member of the channel list. (dword_106A0818): (CNetchan**)engine.dll+0x7C0818 and from this we retrieve the key
(ICE_KEY*)(DWORD*)CNetChan+0x4284.

If no icekey file is found, NetSharkGO.exe uses a static ICE-Key for the community servers. This might break on the next update. So use this tutorial and put the new key into
an icekey file.
FindIceKey.exe might break also, because it uses static offsets.

We can now retrieve the icekey, share it with the netshark computer and cheat as we are used to.
While this is a compromise and we have to read memory, other memory-hacks need to read constantly and run cheat code. We just need to read something quickly and we can fuck off completely. If done right, this is still an advantage.

Warning: FindIceKey.exe is only a demonstration application. If Valve decides to blacklist this process, it will get you banned. Be creative when accessing and reading out memory.

Download: NetSharkGO, small resolution, FindIceKey.exe —>
http://uptobox.com/7nbouge7xco7 (update 14.01, wrong community icekey)

Update 15.01:
New Community-IceKey: http://pastebin.com/yhqCimU9

Valve uses PKI Infrastructure

I am happy to inform you that from a perspective as a game security researcher, NetShark GO has been a success.

After the recent update of CS Global Offensive Valve decided to use good crypto for their Matchmaking Servers (their own PKI infrastructure with asymmetric crypto and digitial server certificates).

Remember that free publishing hackers are not your enemy, but your friends that push developers to implement secure and solid code.
This technique (reading game traffic over the network) has been around in the dark for a very long time and game developers are often oblivious to these kind of attacks, because in their minds what you can not see, does not exist. A very naive security approach.

But keep in mind that this might not be the last word on this and research must continue. The next step should be a crypto audit of their implementation to find possible weaknesses.

NetShark GO

:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-::-::-::-::-::-::-::-::-::-::-:
:-:                                                                                   :-:
:-:                                                                                   :-:
:-: _\ \\ \__    /\ \        /\ \                     /\_ \                           :-:
:-:/\__  _  _\   \_\ \     __\ \ \____  __  __     __ \//\ \     ___      __          :-:
:-:\/_L\ \\ \L_  /'_` \  /'__`\ \ '__`\/\ \/\ \  /'_ `\ \ \ \   / __`\  /'_ `\        :-:
:-:  /\_   _  _\/\ \L\ \/\  __/\ \ \L\ \ \ \_\ \/\ \L\ \ \_\ \_/\ \L\ \/\ \L\ \       :-:
:-:  \/_/\_\\_\/\ \___,_\ \____\\ \_,__/\ \____/\ \____ \/\____\ \____/\ \____ \      :-:
:-:     \/_//_/  \/__,_ /\/____/ \/___/  \/___/  \/___L\ \/____/\/___/  \/___L\ \     :-:
:-:                                                /\____/                /\____/     :-:
:-:                                                \_/__/                 \_/__/      :-:
:-:                                                                                   :-:
:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-::-::-::-::-::-::-::-::-::-::-:
:-:                                                                                   :-:
:-: [ Releaser        ] ..... irc.rizon.net - #debuglog, #debuglog.public             :-:
:-: [ Coder           ] ..... DeepBlueSea                                             :-:
:-:                                                                                   :-:
:-: [ App - Name      ] ..... NetShark GO for Counter-Strike: Global Offensive        :-:
:-: [ App - Version   ] ..... last modification: 13.01.2015                           :-:
:-: [ Release Date    ] ..... 06.12.2014                                              :-:
:-:                                                                                   :-:
:-:                                                                                   :-:
:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-::-::-::-::-::-::-::-::-::-::-:
:-:                                                                                   :-:
:-: [ Description    ]                                                                :-:
:-:  NetShark Go reads the game server traffic and parses out the position of         :-:
:-:  every player. You can run NetShark on another computer which routes the game     :-:
:-:  traffic and you are therefore immune to every Anticheat out there by default.    :-:
:-:                                                                                   :-:
:-:  To update the ICE key (MM or community) look at the tutorial on                  :-:
:-:  https://debuglog.wordpress.com/2015/01/13/netshark-attack-vectors/               :-:
:-:                                                                                   :-:
:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-::-::-::-::-::-::-::-::-::-::-:
:-:                                                                                   :-:
:-: [ Release Usage   ]                                                               :-:
:-: -2  - Retrieve ICE-Key from Memory (Tutorial or FindIceKey.exe (DANGEROUS!))      :-:
:-: -1. - (optional) setup 2 PCs and route traffic through PC 1                       :-:
:-:  0. - Copy "\SteamLibrary\SteamApps\common\Counter-Strike Global Offensive\csgo\  :-:
:-:             resource\overviews" into "OverviewData"                               :-: 
:-:  1. - install WinPCAP (on PC 1) (http://www.winpcap.org/)                         :-:
:-:  2- - install C++ Redistributable Packages for Visual Studio 2013 (on PC 1)       :-:
:-:  3. - start NetShark GO (on PC 1)                                                 :-:
:-:  4. - choose your network adapter, which routes game traffic (internet unsually)  :-:
:-:  5. - type server port and map (or autodetect)                                    :-:
:-:  6. - join Server (on PC 2)                                                       :-:
:-:                                                                                   :-:
:-:                                                                                   :-:
:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-::-::-::-::-::-::-::-::-::-::-:
:-:                                                                                   :-:
:-: [ Known Issues    ]                                                               :-:
:-: I.  ) team detection sucks (only at round start and sometimes incomplete )        :-:
:-: II. ) sometimes no origin updates on round start                                  :-:
:-: III.) map autodetection works only before connecting to the server                :-:
:-: IV. ) sometimes laggy                                                             :-:
:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-::-::-::-::-::-::-::-::-::-::-:
:-: [ Changelog       ]                                                               :-:
:-: 1. fixed Crash on network bridges                                                 :-:
:-: 2. click on playericon to change team                                             :-:
:-: 3. Valve-Update: packet decoding                                                  :-:
:-: 4. Valve-Update: Valve changed keys                                               :-:
:-: 5. Valve-Update: Key-Change (09.01.2015)                                          :-:
:-: 6. ICE Key in file "icekey" (13.01.2015)                                          :-:
:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-::-::-::-::-::-::-::-::-::-::-:
:-:                               _=-[ #debuglog ]=-_                                 :-:
:-:                                                                                   :-:
:-:                                  DeepBlueSea                                      :-:
:-:                                                                                   :-:
:-:                                        |                                          :-:
:-:                                     _` |                                          :-:
:-:                                    (   |                                          :-:
:-:                                   \__,_|                                          :-:
:-:                                                                                   :-:
:-:                                                                                   :-:
:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-::-::-::-::-::-::-::-::-::-::-:

Demo-Video: http://webmshare.com/play/0gyWg

Download: http://uptobox.com/7nbouge7xco7
(Binary for small resolutions inside)

Notice: Valve-Servers (MM, Casual,…) have dynamic key, which will need to be retrieved from memory and stored in „icekey“ file.

NetShark for Counter-Strike 1.6

:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-::-::-::-::-::-::-::-::-::-::-:
:-:                                                                                   :-:
:-:                                                                                   :-:
:-: _\ \\ \__    /\ \        /\ \                     /\_ \                           :-:
:-:/\__  _  _\   \_\ \     __\ \ \____  __  __     __ \//\ \     ___      __          :-: 
:-:\/_L\ \\ \L_  /'_` \  /'__`\ \ '__`\/\ \/\ \  /'_ `\ \ \ \   / __`\  /'_ `\        :-: 
:-:  /\_   _  _\/\ \L\ \/\  __/\ \ \L\ \ \ \_\ \/\ \L\ \ \_\ \_/\ \L\ \/\ \L\ \       :-:
:-:  \/_/\_\\_\/\ \___,_\ \____\\ \_,__/\ \____/\ \____ \/\____\ \____/\ \____ \      :-:
:-:     \/_//_/  \/__,_ /\/____/ \/___/  \/___/  \/___L\ \/____/\/___/  \/___L\ \     :-:
:-:                                                /\____/                /\____/     :-:
:-:                                                \_/__/                 \_/__/      :-:
:-:                                                                                   :-:
:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-::-::-::-::-::-::-::-::-::-::-:
:-:                                                                                   :-:
:-: [ Releaser        ] ..... irc.rizon.net - #debuglog, #debuglog.public             :-:
:-: [ Coder           ] ..... XEPT, DeepBlueSea                                       :-:
:-:                                                                                   :-:
:-: [ App - Name      ] ..... NetShark CS 1.6                                         :-:
:-: [ App - Version   ] ..... 0.2                                                     :-:
:-: [ Release Date    ] ..... 30.05.2012                                              :-:
:-:                                                                                   :-:
:-:                                                                                   :-:
:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-::-::-::-::-::-::-::-::-::-::-:
:-:                                                                                   :-:
:-: [ Release Usage   ]                                                               :-:
:-: -1. - (optional) setup 2 PCs and route traffic through PC 1                       :-:
:-:  0. - install WinPCAP (on PC 1) (http://www.winpcap.org/)                         :-:
:-:  1. - start NetShark (on PC 1)                                                    :-:
:-:  2. - Choose your network adapter, which routes game traffic (on PC 1)            :-:
:-:  3. - join Server (on PC 2)                                                       :-:
:-:  4. - if overview doesn't get loaded automatically, enter mapname and force       :-:
:-:                                                                                   :-:
:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-::-::-::-::-::-::-::-::-::-::-:
:-:                                                                                   :-:
:-: [ Known Bugs      ]                                                               :-:
:-: I.  ) sometimes false team detection                                              :-:
:-: II. ) short-lived ghost entities                                                  :-:
:-: III.) local player inivisble (Hit F10)                                            :-:
:-: IV. ) wrong angles on far entities                                                :-:
:-:                                                                                   :-:
:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-::-::-::-::-::-::-::-::-::-::-:
:-:                                                                                   :-:
:-:                               _=-[ #debuglog ]=-_                                 :-:
:-:                                                                                   :-:
:-:                                  DeepBlueSea                                      :-:
:-:                                                                                   :-:
:-:                                        |                                          :-:
:-:                   XEPT              _` |           Inliferty                      :-:
:-:                                    (   |                                          :-:
:-:                                   \__,_|                                          :-:
:-:                                                                                   :-:
:-:                                                                                   :-:
:-:                                                                                   :-:
:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-::-::-::-::-::-::-::-::-::-::-:

Download Link:

Download

Video: