Quantcast
Channel: Gamehacking – Asbra.net
Viewing all 10 articles
Browse latest View live

Practical Gamehacking Tutorial: Dungeons of Dredmor (Part 1)

$
0
0

In this practical gamehacking tutorial we will take a look at the RPG / rogue-like game Dungeons of Dredmor.

Prerequisites (tools you will need)
- Memory scanner (I like Cheat Engine)
- Class/struct analyzer (I like ReClass 2011)

After you are done with this tutorial you will have made a ReClass-project. If you just want to grab the project now rather than later, Dungeons of Dredmor ReClass project

Alright, let’s start with the very basics gamehacking, unlimited health/mana, and so on. Then we will move on to more real reverse engineering of the game to see what we can come up with :)
To start this off, fire up the game and the tools. Make a new game, character and get ready.

gamehacking-tutorial-dungeons-of-dredmor-cheat-engineFirst we start by hacking our mana. In Cheat Engine set “Scan type” to “Exact Value”, set “Value type” to “4 bytes” and search for the amount of mana you now have (I have 37, so I search for 37).
Now cast a spell so your mana decreases. Enter the new value and click on “Next Scan”.
Repeat this until you only find one address.
Freeze it or change it so that you see that the change reflects in the game, that way you know you have found the correct address.

Now, right-click the value in your address list and run the “Find out what writes to this address”, then cast a spell (or something else that uses mana) in-game.
You will get this Dungeons of Dredmor.exe+128D10 - 29 06 - sub [esi],eax .. or similar

Now, we could simply place NOP on this instruction (right-click -> Replace with code that does nothing) to have unlimited mana, but we will soon delve deeper. Before we do so, take note that you can use pretty much the exact steps above to find your health, buff-duration and other things.

Instead we take a look around in this function the instruction is inside of ..

// called when casting a spell
00528CF9 - 8B 35 2C3C6000             - mov esi,[PHYSFS_utf8FromLatin1+A401C]
00528CFF - 8B 0D A0416000             - mov ecx,[PHYSFS_utf8FromLatin1+A4590]
00528D05 - 81 C6 30010000             - add esi,00000130
00528D0B - E8 00E1FEFF                - call 00516E10
00528D10 - 29 06                      - sub [esi],eax          ; this instruction removes mana
00528D12 - 8B 0D A0416000             - mov ecx,[PHYSFS_utf8FromLatin1+A4590]
00528D18 - 83 B9 B8000000 00          - cmp dword ptr [ecx+000000B8],00
00528D1F - 74 1D                      - je 00528D3E
00528D21 - A1 2C3C6000                - mov eax,[PHYSFS_utf8FromLatin1+A401C]
00528D26 - 8B 30                      - mov esi,[eax]

So let’s analyze this piece of code a bit. We see sub [esi],eax which means to subtract the value in EAX from the pointed-to value in ESI. “Pointed-to value”? Yes, the ESI register holds a memory-pointer (an address) to where the mana-value is stored.
Let’s go back/up a bit in the disassembly, we see mov esi,[PHYSFS_utf8FromLatin1+A401C], this is where the pointer to our mana value is loaded into the ESI register, after that we see add esi,00000130 which adds 0×130 to the pointer.
This means that the mana-value is 0×130 offsets into a data-structure, such as a class or a struct.

You still with me?

So what we know now is that at the line 00528CF9 - 8B 35 2C3C6000 - mov esi,[PHYSFS_utf8FromLatin1+A401C] a pointer is put into the ESI register. This pointer + 0×130 holds the value of our current mana.
What can we deduce from this?
- ESI holds a pointer to a data-structure with player values
- We can probably find more interesting values in that data-structure

Put a breakpoint on 00528D05 - 81 C6 30010000 - add esi,00000130 and check what value (pointer) is in the ESI register. You will have to cast a spell in the game or do something else that modifies your mana to make the breakpoint trigger. In my case it holds 0x0F48FAD8 (as you can see in the screenshot)

Dungeons of Dredmor Gamehacking Tutorial ReClassNow it is time to load up ReClass.

“Select” the process “Dungeons of Dredmor.exe”, create a New class, fill in the address we got from ESI (for me 0x0F48FAD8) as base of the class.

Add more offsets (Modify tab -> Add 1024) then scroll down to 0130
Click to mark the line then go to Modify tab and set as “Int 32″, name it something like “mana” if you want to.

This is how you start to reverse data-structures using ReClass.

ReClass gamehacking tutorial Dungeons of DredmorCheck out this screenshot and you see that I have filled out the mana variable at 0130. Now if we look right above the mana value we see an integral value of 23 .. Hmm, look back at the game and notice that my health ingame is 23. Coincidence? I think not!

We add the address of that value (0F48FC04) into Cheat Engine and change/freeze it, then we see that it really is the health value for the player. Let’s mark it as health in ReClass so we remember where that is at (012C).

Wonder what more is in this data-structure.. It would seem it holds player values, so let’s pull up our character sheet/stats and see if we can find some of those.

Now that we know what class we want to search in we can set the Memory Scan Options in Cheat Engine to Start where our class starts (in my case 0F48FAD8) and make up the value for Stop by adding a number higher than what we think the size of the class is, such as 0×00010000 since it is unlikely that the class is that big. This speeds up the scanning a bit as well as only gives us addresses in the range we want to scan in.

Gamehacking tutorial Cheat Engine 6My character has a “Coat of Tweed” that gives +1 Sagacity and some other stats. With the coat on she has 14 Sagacity, so let’s set up our memory scan range and search for 14.

Nice! Only 8 hits. Now I take the coat off and my Sagacity will decrease by 1, so we search for 13. Now I only got 1 address, which is good. If you got more than one just repeat by taking on the coat and searching for 14 and vice-versa.

The address I found was 0F48FD8C, so we take that and subtract the base address of our class (0F48FAD8), the result is 2B4. This means that Sagacity is stored at 2B4 in our class.

Dungeons of Dredmor ReClass Player ClassLet’s add that in ReClass.

After marking sagacity at 2B4 we can see that around that value are the other player stats (see screenshot) and a bit above them are what appears to be the maximum values for health and mana!

Keep looking around, changing values in ReClass and looking in-game for changes. See the screenshot and you see what I got by doing this for a few minutes. My ReClass project file will be available at the bottom of this post.

This concludes the first part of this tutorial. In the next part we look at the inventory-system.

You can download the complete Dungeons of Dredmor Player-class ReClass project

Got any questions or feedback? Leave a comment :)

Incoming search terms:

  • cheat engine 게임캐릭터 구조체
  • dungeons of dredmor cheat engine
  • cheat engine battleknight
  • cheat engine dungeons of dredmor
  • reclass 2011 tutorial

Read the post Practical Gamehacking Tutorial: Dungeons of Dredmor (Part 1) on Asbra.net.


Creating a browser game bot with PHP cURL – Part 01 (BattleKnight bot)

$
0
0

This will be a long article, the topic is creating a bot for playing browser games while you sleep, a friend asked me specifically for a BattleKnight bot which would play the game while he is in school or sleeping.

This type of games (browser games) are generally impossible to make a hack/cheat for. If you see any BattleKnight hack or BattleKnight cheat online, or another method that claim to give you gold or rubies it is surely fake and/or a virus, trojan or keylogger. Beware of such attempts to compromise your computer.

If you just want to get the finished script, click here: BattleKnight bot using PHP cURL

Prerequisites:

I suggest you read my first tutorial on how to use my cURL class to create a Facebook login bot first. It might be good to have attempted something else with cURL before starting this bot. :)

Creating a BattleKnight bot

First we start by analyzing the login page for BattleKnight. It does not matter which country you play as/with or which server, because all of them use the same structure.

Google Chrome Developer Console - Network InfoNow I will show you something I did not in the other tutorial. If you are using Google Chrome, while on the BattleKnight login page, press F12 or Ctrl+Shift+I or Ctrl+Shift+J on your keyboard. This will bring up the Developer Console, click on the Network tab. This will show you all the requests and replies that have been sent between your web browser and the BattleKnight web server. (see screenshot on the right)

Click the Clear button at the bottom to clear your console then click the button “Preserve Log upon Navigation” so it turns red. Then you enter your username/password and click Login-button on the website.

You will be taken to the main page for the game, and your network console will have filled up with lots of things. Scroll up to the very top and you should see two lines like these:
Chrome Network Console BattleKnight Login Log

The upper one we see is an AJAX request, this is sent by JavaScript and executed “in the background” of a website, they use it to confirm your login details before sending you to the main page of the game. Now, select the lines one-by-one, right-click and click on “Copy request headers”, paste into Notepad or somewhere temporarily, it should look like this:

GET /ajax/ajax/login/15/Rexxxxxxxx/7f2dfe557c3afbxxxxxxxxxxxxxxc97a?noCache=1362504866781 HTTP/1.1
Host: start.battleknight.de
Connection: keep-alive
Accept: application/json
X-Requested-With: XMLHttpRequest
X-Request: JSON
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.97 Safari/537.22
Referer: http://start.battleknight.de/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,sv;q=0.6
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: preferredServer=%7B%22de%22%3A15%7D
GET /main/login/Rexxxxxxxx/7f2dfe557c3afbxxxxxxxxxxxxxxc97a?kid=&servername=null&serverlanguage=null HTTP/1.1
Host: s15.battleknight.de
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.97 Safari/537.22
Referer: http://start.battleknight.de/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,sv;q=0.6
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: BattleKnightSession=jm7T0xxxxxxxxxxxXPk3Y3; BattleKnight=033b4943fe4xxxxxxxxxxxxxd943cba0%231162

(I have censored some of the information, don’t want my account banned just yet..)

Analyzing the first request

Let’s analyze the first one first. It is an AJAX request being sent when you click the Login button to confirm that your login details are correct before sending you to the next page. What is that in the request URL, /7f2dfe557c3afbxxxxxxxxxxxxxxc97a?kid=, that looks like a MD5 checksum.. I can tell you that it is an MD5 checksum of your password. How do I know this?

Bring up the source code of the page, search /js/ and follow your second hit, it should be similar to this var g_linkHelp = 'http://start.battleknight.de/main/help';</script><script type="text/javascript" src="http://start.battleknight.de/js/_cache-d3c846b9663e6f74cd4d22d584165570"></script>.

Open up that document and search for login/, it should bring you to this line: function handleLoginRequest(username,password,server){var oneRequest=new Request.JSON({url:g_base_request+'login/'+server+'/'+username+'/'+hex_md5(password),noCache:true,onRequest:function()

The interesting thing here is url:g_base_request+'login/'+server+'/'+username+'/'+hex_md5(password)

This matches up nicely with the request above, start.battleknight.de/ajax/ajax/login/15/Rexxxxxxxx/7f2dfe557c3afbxxxxxxxxxxxxxxc97a?noCache=1362504866781

Analyzing the second request

Ok, so now look at the second request. That is executed after they have confirmed your login details via AJAX. However they must surely check the login details again on the server-side, so let’s skip the AJAX request and head straight for this one.

What’s important to notice here is that it is run to s15.battleknight.de, not to start.battleknight.de (remember to change s15 for your servers number!)

Writing the bot

Let’s write it up in PHP:

<?php // I will omit this in the future, but don't forget it!
require 'curl.class.php';
$curl = new cURL();

$baseUrl = 'http://s15.battleknight.de/'; // Replace .de with the TLD of the BattleKnight version you play and s15 with the number of the server you play on

$username = 'Your_BattleKnight_Username';
$password = md5( 'Your_BattleKnight_Password' );

$url = $baseUrl . "/main/login/$username/$password?kid=&servername=null&serverlanguage=null";

$data = $curl->get( $url, $baseUrl );

echo $data; // Output the response so we can see what happens

Run this code either in CLI (command line) or in your webbrowser and see what happens!

..

Yay, we get logged in to the game! :)

Next we will look at what we can do after we are logged in. But first, let’s start by structuring up our code a bit.
Create two .php files, call them cron.php and functions.php

cron.php

<?php
require 'curl.class.php';
$curl = new cURL();

require 'functions.php';

$username = 'Your_BattleKnight_Username';
$password = md5( 'Your_BattleKnight_Password' );
$server   = 15;

$baseUrl = 'http://s' . $server . '.battleknight.de/';

if( !login( $username, $password ) )
{
  echo 'Failed to log in!';
  echo $curl->data; // Output the data from the last cURL request
  exit;
}

functions.php

<?php
function login( $username, $password )
{
  global $baseUrl;

  $url = $baseUrl . "/main/login/$username/$password?kid=&servername=null&serverlanguage=null";

  $data = $curl->get( $url, $baseUrl );

  if( strstr( $data, '<form id="loginForm"' ) ) // If the login form is on the page, we know that we failed to log in
  {
    return false; // Login failed :( 
  }

  return true; // Login successful!
}

BattleKnight mission bot

Alright, now we have the basic structure of our bot ready and it looks great! Now let’s see how to make our bot do missions.

Hover the “Mission” link under “World” in the left sidebar, or right-click on it and copy the address. http://s15.battleknight.de/world/location. This next step is not always completely necessary, depending on the coding of the website/game, but it is a always nice to try and keep under the radar.

Send a GET request to that page, add the following at the end of cron.php $data = $curl->get( $baseUrl . 'world/location' ); you can also add a echo $data; if you want to see the output.

Why do we send a GET request to the page you may ask. Because what we are going to do next is to tell the webserver we want to start a mission, and if we are on the main page of the game and not on the mission page this might look very suspicious! Some games check for behavior like that, some do not. I like to be more safe than sorry, so I do like that. There are plenty of other ways some browser games check for bots; if you load all resources (images, scripts, etc.) on the website, adding extra fields to forms through JavaScript, tracking your mouse movements with JavaScript etc.
However, many techniques relying on JavaScript can be unreliable, and the developers know this.

BattleKnight.de mission pageNow we are on the mission page (screenshot on the right). Open up the Developer Console on the Network tab again (if you closed it before), clear it and set Preserve Log upon Navigation. Click on one of the missions and choose a size, so that the mission is performed, you will be redirected to another page. Now scroll up in the log to the top and find the POST request to location/. Right-click it and Copy all as HAR, paste this into Notepad.

Now find the request and the POST data for the location/ request by searching for world/location/, it should look similar to this:

          "postData": {
            "mimeType": "application/x-www-form-urlencoded",
            "text": "chooseMission=Cave&missionArt=small&missionKarma=Good&buyRubies=0",
            "params": [
              {
                "name": "chooseMission",
                "value": "Cave"
              },
              {
                "name": "missionArt",
                "value": "small"
              },
              {
                "name": "missionKarma",
                "value": "Good"
              },
              {
                "name": "buyRubies",
                "value": "0"
              }
            ]
          }

But what do these mean? Hmm..

Click on one of the missions to open up the dialog box. In here, right-click on one of the options (such as Small: 20 MP) and select Inspect element.
The developer console will open up and show you the HTML of the webpage, similar to the following:
BattleKnight Bot Chrome HTML Inspector

Notice the onclick="chooseMission('small', 'BanditLair', 'Good', this);"?
Now take the medium of the same and you should see onclick="chooseMission('medium', 'BanditLair', 'Good', this);" and so on.

Go through the missions that are available on the page to you, for me (on the first map) I get; BanditLair, Cave, StoneCircle, Coast. So those are the chooseMission
For the field missionArt there is the size; small, medium, large
Finally the missionKarma can be Good or Evil

Let’s write up some code and try it out, add this to the bottom of your BattleKinght bot in cron.php

$url = $baseUrl . 'world/location';

$curl->get( $url );

$data = array( 'chooseMission' => 'BanditLair', // 'BandirLair', 'Cave', 'StoneCircle' or 'Coast'
               'missionArt'    => 'small', // 'small', 'medium' or 'large'
               'missionKarma'  => 'Good', // 'Good' or 'Evil'
               'buyRubies'     => '0', // I don't want to spend Rubies
);

echo $curl->post( $url, $data, $url );

Now run it in your web browser, the result should look similar to this:
BattleKnight mission result page
Great, it works perfectly!

Next up, since there is a waiting time after each mission we need to read the timer before trying to start a new mission. Let’s see how to do that.
Execute your bot again now and you should get to the cooldown page, similar to this:
BattleKnight cooldown page

Open up the source, search for cooldown and you find this line <div id="mainContent" class="cooldownFight">
Now what we can do is add a string search to check if class="cooldownFight" exists on the page. If it does, kill the script.

So add this piece of code in right before starting the new mission of your BattleKnight bot

if( strstr( $curl->data, 'class="cooldownFight"' ) )
{
  echo "Cooldown!";
  exit; // You can add code here to just wait instead of killing script..
}

Try it out! Works great, right?

Now take that code and move into a new function in functions.php that we name “mission”, this way we keep a nice structure of our code.

Here is the full script that we have so far:

cron.php

<?php
/*
 * @author  Johan / Asbra
 * @date    2013-03-05
 */
require 'curl.class.php';
$curl = new cURL();

require 'functions.php';

$username = 'Your_BattleKnight_Username';
$password = md5( 'Your_BattleKnight_Password' );
$server   = 15;

$baseUrl = 'http://s' . $server . '.battleknight.de/';

if( !login( $username, $password ) )
{
  echo 'Failed to log in!';
  echo $curl->data;
  exit;
}

mission();

functions.php

<?php
/* 
 * @author  Johan / Asbra
 * @date    2013-03-05
 */
function login( $username, $password )
{
  global $curl, $baseUrl;

  $url = $baseUrl . "/main/login/$username/$password?kid=&servername=null&serverlanguage=null";

  $curl->get( $url, $baseUrl );

  if( strstr( $curl->data, '<form id="loginForm"' ) ) // If the login form is on the page, we know that we failed to log in
  {
    return false;
  }

  return true;
}

function mission()
{
  $url = $baseUrl . 'world/location';

  $curl->get( $url );

  if( strstr( $curl->data, 'class="cooldownFight"' ) )
  {
    echo 'Cooldown!';
    exit;
  }

  $data = array( 'chooseMission' => 'BanditLair', // 'BanditLair', 'Cave', 'StoneCircle' or 'Coast'
                 'missionArt'    => 'small', // 'small', 'medium' or 'large'
                 'missionKarma'  => 'Good', // 'Good' or 'Evil'
                 'buyRubies'     => '0', // I don't want to spend Rubies
  );

  $curl->post( $url, $data, $url );
}

You can also grab the files here: BattleKnight bot

Alright, that is all for now. Try making your own functions for other things in-game, post your questions and feedback in the comments. There might be a part 2 of this BattleKnight bot in the future :)

Read Part 2 of this tutorial Here!

Incoming search terms:

  • create bot for browser using PHP
  • run php bot in battleknight
  • old version battleknight
  • battleknight bot auto mission
  • write a bot using curl
  • script php browser game
  • old battleknight version
  • how to write bot game with php
  • google chrome battleknight
  • creating-a-browser-game-bot-with-php-curl-part-01-battleknight-bot

Read the post Creating a browser game bot with PHP cURL – Part 01 (BattleKnight bot) on Asbra.net.

Creating a browser game bot with PHP cURL – Part 02 (BattleKnight bot)

$
0
0

You should read How to create a BattleKnight bot – Part 01 before you start with this part of the tutorial.

Reading stats

Knowing how much health, silver, experience, etc. can be very useful, for example to determine which action to take (drink a potion, do a quest, work ..)

To make our bot read out your stats from the site, go to any BattleKnight page (after you are logged in), right-click anywhere on the page and choose “View Source”.
Then search for one of the values you have, for example my character has 277 silver, so I search (Ctrl+F in Chrome) for 277
Here is what I find:
BattleKnight bot reading your stats

Now, the easiest way for us to read the silver count into a PHP variable is to use a regular expression. If you do not have previous experience with regex (abbreviation for Regular Expressions) do not worry! I have a solution without using regex aswell.

With regex we can do like this:

preg_match( '/id="silverCount">([^<]+)<\/span>/s', $curl->data, $matches );
$silver = intval( trim( $matches[1] ) );

Without using regex we can do this:

$start = strpos( $curl->data, 'id="silverCount">' );
$end   = strpos( $curl->data, '</span>', $start + 1 );
$tmp   = substr( $curl->data, $start, ( $end - 1 ) - $start );

$silver = intval( trim( $tmp ) );

If you are going to do this without regex, you should write that into a function. Here is the function I use in these applications:

function strbetween( $string, $str1, $str2 )
{
  if( $str1 == '' )
  {
    $pos = 0;
  }
  else
  {
    $pos = strpos( $string, $str1 );

    if( $pos === false )
    {
      return false;
    }
  }

  $end = strpos( $string, $str2, ( $pos + 1 ) );

  return substr( $string, $pos + strlen( $str1 ), ( $end - $pos ) - strlen( $str1 ) );
}

To use this function with the example above, it would be:

$silver = intval( trim( strbetween( $curl->data, 'id="silverCount">', '</span>' ) ) );

Alright, so now we have got silver in a variable, let’s do the rest of the values we might need as well. If you look around where we found silver you will also see the value for health, experience, level and rubies. So let’s add those:

$health = intval( trim( strbetween( $curl->data, 'id="lifeCount">', '</span>' ) ) );
$silver = intval( trim( strbetween( $curl->data, 'id="silverCount">', '</span>' ) ) );
$exp = intval( trim( strbetween( $curl->data, 'id="levelCount">', '</span>' ) ) );
$level = intval( strip_tags( trim( strbetween( $curl->data, 'id="userLevel">', '</span>' ) ) ) );
$rubies = intval( trim( strbetween( $curl->data, 'id="rubyCount">', '</span>' ) ) );

You see that I added strip_tags function when fetching our character level? It is because the markup looks like this:

                    <div id="userLevel">
                        <span>
                        	5                        </span>
                        <!-- end #userLevel -->
                    </div>

What the strip_tags function does is to remove HTML tags from the string passed to it. With my strbetween function I get the content between <div id="userLevel"> and </span> which means that it would give us <span> 5 and we only want the 5 so we use strip_tags to remove the span tag.

trim function removes whitespace at the start/end of a string.
intval makes sure that the string is a number. If it is not a number it will return 0. You can read more about it here: php.net intval

BattleKnight bot – healing

So, our bot already knows how to perform missions, that is good. But what to do when we are low on health? We would not want to go on a quest then.. Instead, we should use a healing potion!
I will show you how to make the bot go through your inventory, how you can read out what is in your current inventory, and to use that information to find your health potions. Then we will tell the game to use one potion to heal our character.

(If you don’t have a healing potion, buy one)
Open up the Character screen. The URL of this page should be user/ at the end.
Right-click, “View page source”
Search for “PotionRed” (assuming it’s a red potion, if it’s yellow search “PotionYellow”)
BattleKnight bot use potions

This might look confusing to you, this is part of JSON data. Scroll up a bit and you can see that we are in an argument to the JavaScript function g_dragFunctions.storeAttributes. In this case we see that the first argument is 'inventory', if we look for other calls to g_dragFunctions.storeAttributes we find that the first argument differs. This function call is placed for each item in your inventory, if it is an equipped gear item, the first argument will be 'character'.
The last argument in the call is the one that contains our potion, here is the entire argument:

{"item_id":"3761265","quest_id":"0","item_level":"0","item_karma":"0","item_pic":"PotionRed50","item_own":"33xxx2","item_inventory":"1","item_info":{"posX":0,"posY":0},"item_width":"1","item_depth":"1","item_set":"0","item_name":"_db178","item_add":"0","item_magic_level":"white","item_value":"50","item_use":"0","item_slot":"0","item_rune1":"0","item_rune2":"0","item_rune3":"0","item_str":"0","item_dex":"0","item_end":"0","item_luck":"0","item_weapon":"0","item_shield":"0","item_ride":"0","item_critical":"0","item_speed":"0","item_off":"0","item_def":"0","item_damage":"0","item_damage2":"0","item_armour":"0","item_fire":"0","item_fire_res":"0","item_ice":"0","item_ice_res":"0","item_shock":"0","item_shock_res":"0","item_poison":"0","item_poison_res":"0","item_special_ability":[],"item_timestamp":"2013-03-09 12:03:50","clue_item":null,"clue_level":null,"clue_status":null,"clue_data":null,"item_manor_seconds":null,"item_fullName":"50 HP Healing Potion","item_ruby":0}

This is a JSON structure with item-data. What we want from this is probably the item_id.

Let’s write some code to grab all those function calls and filter so we only have the ‘inventory’ ones, and to parse out the last argument into a JSON object.

$item_id = 0; // This variable will hold the item_id of the red potion we find (if any)

$data = explode( 'g_dragFunctions.storeAttributes(', $curl->data );

foreach( $data as $temp )
{
  if( substr( $temp, 0, 11 ) != "'inventory'" ) // Check if first argument is 'inventory'
  {
    continue; // If it is Not, then we skip it
  }

  // Use the strbetween function from before to get the last argument of the call (the JSON item-data)
  $json_data = '{' . strbetween( $tmp, 'false,{', ');' );

  // json_decode function converts pure JSON data into a PHP object
  $json = json_decode( $json_data );

  if( substr( $json->item_pic, 0, 9 ) == 'PotionRed' ) // Check that it is a red potion
  {
    $item_id = intval( $json->item_id ); // Get the item ID

    break; // We have found a red potion, we do not need to continue parsing the inventory
  }
}

Now we want to use the potion.

Open the Network tab in the Developer Console of Chrome/Opera (or Tamper Data if you use Firefox)
Drag a potion to your character so that it is used
Copy the URL that the GET request was sent to, it should be similar to this:
http://s7.battleknight.co.uk/ajax/ajax/usePotion/?noCache=1360006512229&id=37xxx52&merchant=false&table=user

Now we can craft our own request and send to the server to use the potion. After the code above, add the following:

$url = $baseUrl . 'ajax/ajax/usePotion/?noCache=1&id=' . $item_id . '&merchant=false&table=user';

$curl->get( $url, $baseUrl . 'user/' );

Now our bot can use a potion! Put this into a function to keep everything nice & tidy.

function heal()
{
  $curl->get( $baseUrl . 'user/', $baseUrl ); // Open the character page

  $item_id = 0; // This variable will hold the item_id of the red potion we find (if any)

  $data = explode( 'g_dragFunctions.storeAttributes(', $curl->data );

  foreach( $data as $temp )
  {
    if( substr( $temp, 0, 11 ) != "'inventory'" ) // Check if first argument is 'inventory'
    {
      continue; // If it is Not, then we skip it
    }

    // Use the strbetween function from before to get the last argument of the call (the JSON item-data)
    $json_data = '{' . strbetween( $tmp, 'false,{', ');' );

    // json_decode function converts pure JSON data into a PHP object
    $json = json_decode( $json_data );

    if( substr( $json->item_pic, 0, 9 ) == 'PotionRed' ) // Check that it is a red potion
    {
      $item_id = intval( $json->item_id ); // Get the item ID

      break; // We have found a red potion, we do not need to continue parsing the inventory
    }
  }

  $url = $baseUrl . 'ajax/ajax/usePotion/?noCache=1&id=' . $item_id . '&merchant=false&table=user';

  $curl->get( $url, $baseUrl . 'user/' );
}

Now we can add in the cron.php of our BattleKnight bot, right before we call mission(); a check to see if we are in good health. For example:

if( $health < 100 )
{
  heal();
}

Pretty simple, right?

Here is the complete code right now:

cron.php

<?php
/*
 * @author  Johan / Asbra <johan@asbra.net>
 * @version 1.0.130309
 * @date    2013-03-05
 */
require 'curl.class.php';
$curl = new cURL();

require 'functions.php';

$username = 'Your_BattleKnight_Username';
$password = md5( 'Your_BattleKnight_Password' );
$server   = 15;

$baseUrl = 'http://s' . $server . '.battleknight.de/';

if( !login( $username, $password ) )
{
  echo 'Failed to log in!';
  echo $curl->data;
  exit;
}

if( $health < 100 )
{
  heal();
}

mission();

functions.php

<?php
/*
 * @author  Johan / Asbra
 * @version 1.0.130309
 * @date    2013-03-05
 */
function login( $username, $password )
{
  global $curl, $baseUrl;

  $url = $baseUrl . "/main/login/$username/$password?kid=&servername=null&serverlanguage=null";

  $data = $curl->get( $url, $baseUrl );

  if( strstr( $data, '<form id="loginForm"' ) ) // If the login form is on the page, we know that we failed to log in
  {
    return false;
  }

  return true;
}

function mission()
{
  global $curl, $baseUrl;

  $url = $baseUrl . 'world/location';

  $curl->get( $url );

  if( strstr( $curl->data, 'class="cooldownFight"' ) )
  {
    echo "Cooldown!";
    return false;
  }

  $data = array( 'chooseMission' => 'BanditLair', // 'BanditLair', 'Cave', 'StoneCircle' or 'Coast'
                 'missionArt'    => 'small', // 'small', 'medium' or 'large'
                 'missionKarma'  => 'Good', // 'Good' or 'Evil'
                 'buyRubies'     => '0', // I don't want to spend Rubies
  );

  $curl->post( $url, $data, $url );
  return true;
}

function heal()
{
  $curl->get( $baseUrl . 'user/', $baseUrl ); // Open the character page

  $item_id = 0; // This variable will hold the item_id of the red potion we find (if any)

  $data = explode( 'g_dragFunctions.storeAttributes(', $curl->data );

  foreach( $data as $temp )
  {
    if( substr( $temp, 0, 11 ) != "'inventory'" ) // Check if first argument is 'inventory'
    {
      continue; // If it is Not, then we skip it
    }

    // Use the strbetween function from before to get the last argument of the call (the JSON item-data)
    $json_data = '{' . strbetween( $tmp, 'false,{', ');' );

    // json_decode function converts pure JSON data into a PHP object
    $json = json_decode( $json_data );

    if( substr( $json->item_pic, 0, 9 ) == 'PotionRed' ) // Check that it is a red potion
    {
      $item_id = intval( $json->item_id ); // Get the item ID

      break; // We have found a red potion, we do not need to continue parsing the inventory
    }
  }

  $url = $baseUrl . 'ajax/ajax/usePotion/?noCache=1&id=' . $item_id . '&merchant=false&table=user';

  $curl->get( $url, $baseUrl . 'user/' );
}

I think this is enough for this time, stay tuned for the next part :)

Read the post Creating a browser game bot with PHP cURL – Part 02 (BattleKnight bot) on Asbra.net.

How To Cheat in Facebook Games: Candy Crush Saga

$
0
0

Very straight-forward Cheat Engine tutorial for hacking Facebook games; how to cheat Candy Crush Saga.

Using the method described here you can create a Candy Crush Saga cheat with unlimited moves, if you try other things you can get massive score, unlimited boosters, and more :)

Requirements:

Using Cheat Engine with Chrome

In Google Chrome press Shift and Esc, this will bring up the Task Manager in Chrome.

Now in the Task Manager, find Plugin: Shockwave Flash.
Chrome Task Manager
What you want to focus on here is the Process ID, as you can see in the screenshot, for me it’s 6416 now.

Open up CE (Cheat Engine).

In CE click the button in top-left corner to get the process list. In the list you see many chrome.exe processes, one of those is the Flash process. CE shows the process ID’s as hexadecimal so we have to convert the process ID we got from Chrome (6416) to hexadecimal which is 0×1910.
Cheat Engine process list
So we select the proper chrome.exe process and open it.

Using Cheat Engine with Firefox

If you are using Firefox, open plugin-container.exe in Cheat Engine.

Unlimited moves in Candy Crush Saga

Now that we have the browsers Flash process open in CE, let’s make unlimited moves.

Open a level in Candy Crush Saga where you start with a number of moves. For example, Level 19:
Candy Crush Saga Level 19

Here you see I start with 35 moves. So I open up CE, enter value 35 and press First Scan
Cheat Engine with Candy Crush Saga
I got 1,528 results. Now make a move in the game so we have one less, and search for that value (34 for me).

Now you should only have 2 results left in the list. Add both of them to your table (double-click them or click them then click the red arrow).

Try changing one of them to anything (for example 99), if the value changes inside the game then set the value back and remove it from the table. Because that one is only the “visual” value, not the real value.
So now we only have one left, try setting this one to 99 and then use all your moves ingame. You will see that you go down to a negative amount of moves and can still play :)
Candy Crush Saga cheat unlimited moves

Finishing your Candy Crush Saga cheat

Now we have the memory address where your amount of moves is stored, this is fine we can set this to what we want.
Problem is we need to search for this value again each time we change level! DMA (Dynamic Memory Allocation), let’s fix it with a better method :)

Now in CE, right-click on the address with the moves in your table and choose Find out what writes to this address. This will open a new window that has set a hardware breakpoint on the value and will log when some opcode in the software changes your moves value.

Make a move in the game and you will see a line pops up in that window:
Cheat Engine find out what writes to this address
Select the line and click the button Show disassembler

This probably looks very confusing to you unless you have experience with Assembler.
Candy Crush Saga Cheat Engine
Right-click on the line and select Add to code list.
Click OK
Enter a name, Unlimited Moves and press OK
Now in the CE main window, in bottom-left corner click Advanced options
Right-click your unlimited moves and choose replace with code that does nothing
Candy Crush Saga Unlimited Moves Hack
Now you will have unlimited moves.

ASM dump, in case images disappear..

07FCB7E9 - 8B 45 10                   - mov eax,[ebp+10]
07FCB7EC - 8B 10                      - mov edx,[eax]
07FCB7EE - 8B 48 04                   - mov ecx,[eax+04]
07FCB7F1 - B8 04000000                - mov eax,00000004
07FCB7F6 - 89 4A 10                   - mov [edx+10],ecx        ; set number of moves
07FCB7F9 - 8B 4D F0                   - mov ecx,[ebp-10]
07FCB7FC - 89 0D 50500D03             - mov [030D5050],ecx
07FCB802 - 8B E5                      - mov esp,ebp
07FCB804 - 5D                         - pop ebp
07FCB805 - C3                         - ret 
07FCB806 - CC                         - int 3 

Enjoy :)

Incoming search terms:

  • candy crush saga cheat engine
  • cheat engine for facebook games candy
  • candy crush boosters with cheat engine
  • candy crush cheat engine
  • candy crush booster hack on google chrome
  • candy crush google chrome cheat
  • cheat engine candy crush
  • cheat engine candy crush table
  • cheat engine unlimited boosters
  • facebook game cheat candy crush

Read the post How To Cheat in Facebook Games: Candy Crush Saga on Asbra.net.

The War Z hack source code – ESP, screenshot cleaner/blocker

$
0
0

Working as of 2013-05-20

Update 2013-05-21
- Fixed memory leak
- Fixed race-condition
- Added unhooking/ejecting (F9)
- “Fixed” player ESP crash

Download WarZ hack source code

You can download the entire WarZ hack project here or check it out over at my BitBucket. Project is written in C++ using Visual Studio 2010.
The only thing I have not included is text rendering. I did not want to publicize the font library I’m using, so you will have to find an alternative if you need it :)
I apologize beforehand for the mixed notation. Some parts are documented, other parts.. not so much.

If the game is updated classes might change. It is unlikely that I will keep them maintained. For the latest updated classes, see this thread on UC.

Features

  • Basic box ESP
  • Player ESP – shows player name, health, distance
  • Zombie ESP – shows zombie distance
  • Item ESP shows item name, ammunition, weight, amount of money, etc.
  • Screenshot cleaner
  • Basic crosshair

Will I get banned for using this?

Currently they only check screenshots on client side, and this contains a screenshot cleaner that will make all your screenshots look like you don’t have any hack. However in the future they might add more advanced anti-cheat techniques to for example detect the way that I am hooking the D3D-functions, at that point it will be a different thing altogether ;)

Thanks to

Geecko and Freeheadshot for getting me into War Inc. hacking in the first place.
s0beit for the r3dRenderLayer pattern used.
Samzor, lowHertz, daemonium and DarkLinuxz for being good people :D

WarZ ESP zombies

Screenshot of zombie ESP

Since the War Z source code was leaked a lot changed. I have renamed all my classes and reworked some things to fit the actual names from the source code. Up to that point they had been based on string references and guessing (as so often in RE).

I might write some things here later, on what you can do to improve/modify this base, etc. :)

The most “important” files are main.cpp and hooks.h

main.cpp holds the entry point for the DLL, and is where all patterns are found & pointers set..

/* 
 * @file	main.cpp
 * @author  Nov/Asbra.net <johan@asbra.net>
 * @version	1.0.130520
 * 
 * @section	LICENSE
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details at
 * http://www.gnu.org/copyleft/gpl.html
 */
#include "main.h"

DWORD MainThread( LPVOID lpArgs )
{
    Log->Write( "MainThread" );

	// First we need to find r3dRenderLayer so we can get the Direct3D device pointer

    DWORD dwRenderAddress = 0;
    while( dwRenderAddress == 0 )
        dwRenderAddress = FindPattern( hGameBase, 0x128000, ( BYTE* )"\xA1\x00\x00\x00\x00\x68\x02\x04\x00\x40\xE8", "x????xxxxxx" );
    Log->Write( "dwRenderAddress %p", dwRenderAddress );

    dwRenderAddress = *( DWORD* )( dwRenderAddress + 1 );
    Log->Write( "dwRenderAddress %p", dwRenderAddress );

    while( *( DWORD* )dwRenderAddress == NULL );
    Log->Write( "*(DWORD*)dwRenderAddress %p", *( DWORD* )dwRenderAddress );

    pRenderer = ( r3dRenderLayer* ) * ( DWORD* )dwRenderAddress;

    while( pRenderer->pD3DDevice == NULL || *( DWORD* )pRenderer->pD3DDevice == NULL );
    Log->Write( "pDevice %p", pRenderer->pD3DDevice );
    Log->Write( "*(DWORD*)pDevice %p", *( DWORD* )pRenderer->pD3DDevice );


	// Then let's find the ClientGameLogic pointer.
	// It holds local player pointer among other things.

	// 75 ?? E8 ?? ?? ?? ?? 05
    DWORD pGetGame = 0;
    while( pGetGame == 0 )
        pGetGame = FindPattern( hGameBase, 0, ( BYTE* )"\x75\x00\xE8\x00\x00\x00\x00\x05", "x?x????x", 3 );
    Log->Write( "pGetGame %p", pGetGame );

	// See cgame_localplayer.txt for more information about the following
    DWORD tmp = 0;
    BYTE tmpb = 0;

    tmp = pGetGame + 5; // 05 254A0000    ADD EAX,4A25
    offLocalPlayer = *( DWORD* )( tmp );

    tmp = pGetGame + 25; // 8070 03 13     XOR BYTE PTR DS:[EAX+3],13
    tmpb = *( BYTE* )( tmp );
    xorLocalPlayer = tmpb;

    tmp = pGetGame + 17; // 8070 02 B7     XOR BYTE PTR DS:[EAX+2],0B7
    tmpb = *( BYTE* )( tmp );
    xorLocalPlayer = ( xorLocalPlayer << 8 ) | tmpb;

    tmp = pGetGame + 21; // 8070 01 B1     XOR BYTE PTR DS:[EAX+1],0B1
    tmpb = *( BYTE* )( tmp );
    xorLocalPlayer = ( xorLocalPlayer << 8 ) | tmpb;

    tmp = pGetGame + 13; // 8030 DF        XOR BYTE PTR DS:[EAX],0DF
    tmpb = *( BYTE* )( tmp );
    xorLocalPlayer = ( xorLocalPlayer << 8 ) | tmpb;

    Log->Write( "offLocalPlayer %p", ( DWORD )offLocalPlayer );
	Log->Write( "xorLocalPlayer %p", xorLocalPlayer );
	// ------------------------------------------------------------------

    GetGame = ( tGetGame )( *( DWORD* )pGetGame + pGetGame + 4 );

    pGame = GetGame();
    Log->Write( "pGame %p", pGame );


	// And now for ObjectManager pointer.

	// E8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 8B ?? ?? 68 ?? ?? ?? ?? E8
    DWORD pGetGameWorld = 0;
    while( pGetGameWorld == 0 )
    {
        pGetGameWorld = FindPattern( hGameBase, 0, ( BYTE* )"\xE8\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x8B\x00\x00\x68\x00\x00\x00\x00\xE8", "x????x????x??x????x", 1 );
        Log->Write( "pGetGameWorld %p", pGetGameWorld );
    }
    pGetGameWorld = ( *( DWORD* )pGetGameWorld + pGetGameWorld + 4 );
    Log->Write( "pGetGameWorld %p", pGetGameWorld );

    GetGameWorld = ( tGetGameWorld )( ( DWORD )pGetGameWorld );

    pGameWorld = GetGameWorld();
    Log->Write( "pGameWorld %p", pGameWorld );

	// E8 ?? ?? ?? ?? 8B ?? ?? FF 0F 84 ?? 00 00 00 8D
    while( pGetFirstObject == 0 )
    {
        pGetFirstObject = FindPattern( hGameBase, 0, ( BYTE* )"\xE8\x00\x00\x00\x00\x8B\x00\x00\xFF\x0F\x84\x00\x00\x00\x00\x8D", "x????x??xxx?xxxx", 1 );
        Log->Write( "pGetFirstObject %p", pGetFirstObject );
    }
    pGetFirstObject = ( *( DWORD* )pGetFirstObject + pGetFirstObject + 4 );
    Log->Write( "pGetFirstObject %p", pGetFirstObject );

	// E8 ?? ?? ?? ?? 8B ?? ?? FF 0F 85 ?? FF FF FF
    while( pGetNextObject == 0 )
    {
        pGetNextObject = FindPattern( hGameBase, 0, ( BYTE* )"\xE8\x00\x00\x00\x00\x8B\x00\x00\xFF\x0F\x85\x00\xFF\xFF\xFF", "x????x??xxx?xxx", 1 );
        Log->Write( "pGetNextObject %p", pGetNextObject );
    }
    pGetNextObject = ( *( DWORD* )pGetNextObject + pGetNextObject + 4 );
    Log->Write( "pGetNextObject %p", pGetNextObject );

    // CC 83 EC 08 8B 0D ?? ?? ?? ?? 8D
    WeaponArmory__getConfig = ( tWeaponArmory__getConfig )FindPattern( hGameBase, 0, ( BYTE* )"\xCC\x83\xEC\x08\x8B\x0D\x00\x00\x00\x00\x8D", "xxxxxx????x", 1 );
    Log->Write( "WeaponArmory__getConfig %p", ( DWORD )WeaponArmory__getConfig );


	// Now let's hook some Direct3D functions.

    oGetRenderTargetData = ( tGetRenderTargetData )VTableHook( *( DWORD* )pRenderer->pD3DDevice, 32, ( DWORD )&hGetRenderTargetData );
    Log->Write( "oGetRenderTargetData %p", oGetRenderTargetData );

    oEndScene = ( tEndScene )VTableHook( *( DWORD* )pRenderer->pD3DDevice, 42, ( DWORD )&hEndScene );
    Log->Write( "oEndScene %p", oEndScene );

	while( !quit )
	{
		Sleep( 100 );

		VTableHook( *( DWORD* )pRenderer->pD3DDevice, 32, ( DWORD )&hGetRenderTargetData );
		VTableHook( *( DWORD* )pRenderer->pD3DDevice, 42, ( DWORD )&hEndScene );
	}

	Sleep( 100 );

	// Remove our hooks
	VTableHook( *( DWORD* )pRenderer->pD3DDevice, 32, ( DWORD )oGetRenderTargetData );
	VTableHook( *( DWORD* )pRenderer->pD3DDevice, 42, ( DWORD )oEndScene );

	Log->~Logging();

    return 0;
}

BOOL APIENTRY DllMain( HMODULE hModule, DWORD dwReason, LPVOID lpReserved )
{
    if( dwReason == DLL_PROCESS_ATTACH )
    {
        Log = new Logging( hModule );

        hHackModule = hModule;
        hGameBase = GetModuleHandleA( "WarZ.exe" );
        Log->Write( "hGameBase %p", hGameBase );

        CreateThread( NULL, NULL, ( LPTHREAD_START_ROUTINE )MainThread, NULL, NULL, NULL );
    }
    else if( dwReason == DLL_PROCESS_DETACH )
    {
        quit = true;
    }

    return TRUE;
}

hooks.h is where you find the 2 hooks this hack has implemented, hooking IDirect3DDevice9::EndScene and IDirect3DDevice9::GetRenderTargetData

/* 
 * @file	hooks.h
 * @author  Nov/Asbra.net <johan@asbra.net>
 * @version	1.0.130520
 * 
 */
HRESULT __stdcall hGetRenderTargetData( LPDIRECT3DDEVICE9 pDevice, IDirect3DSurface9* pRenderTarget, IDirect3DSurface9* pDestSurface )
{
    if( pCleanFrame == NULL || pBackBuffer == NULL )
    {
        // If we don't have a clean screenshot, return so it's black.
        return D3D_OK;
    }
    else if( pRenderTarget == pBackBuffer )
    {
        // Now load our clean screenshot onto the requested surface
        D3DXLoadSurfaceFromSurface( pDestSurface, NULL, NULL, pCleanFrame, NULL, NULL, D3DX_FILTER_NONE, 0 );
        D3DXLoadSurfaceFromSurface( pRenderTarget, NULL, NULL, pCleanFrame, NULL, NULL, D3DX_FILTER_NONE, 0 );

        return D3D_OK;
    }

    return oGetRenderTargetData( pDevice, pRenderTarget, pDestSurface );
}

bool getCleanFrame = false;
int lastFrameId = 0;

HRESULT __stdcall hEndScene( LPDIRECT3DDEVICE9 pDevice )
{
    gpDevice = pDevice;

    static bool firstCall = true;
    if( firstCall == true )
    {
		// Create line so we can draw
        D3DXCreateLine( pDevice, &pLine );

		LPDIRECT3DSURFACE9 renderTarget = NULL;
		D3DSURFACE_DESC desc;

		pDevice->GetRenderTarget( 0, &renderTarget );
		renderTarget->GetDesc( &desc );
		renderTarget->Release();

		pDevice->CreateOffscreenPlainSurface( desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &pCleanFrame, NULL );

        firstCall = false;
    }

    // Get the games pointer to the back buffer. This is useful to check if they are requesting a screenshot.
    static DWORD pBackBufferAddr = 0;
    if( pBackBufferAddr == 0 )
    {
        pBackBufferAddr = FindPattern( hGameBase, 0, ( BYTE* )"\x50\xFF\xD2\x89\x1D\x00\x00\x00\x00\x8B\x35", "xxxxx????xx", 11 ); // 50FFD2891D????????8B35
    }
    if( pBackBufferAddr != 0 &&
        ** ( DWORD** )pBackBufferAddr != NULL &&
        *( DWORD* )( **( DWORD** )( pBackBufferAddr ) + 0xAC628 ) != NULL )
    {
        pBackBuffer = *( IDirect3DSurface9** )( **( DWORD** )( pBackBufferAddr ) + 0xAC628 );
        static IDirect3DSurface9* pOldBackBuffer = NULL;

        if( pOldBackBuffer != pBackBuffer )
        {
            Log->Write( "pBackBuffer %p", pBackBuffer );
            pOldBackBuffer = pBackBuffer;
        }
    }

    // Make sure to wait for new frame before we take screenshot
    // this way we take our clean frame immedietly in a new frame
    // before we've had a chance to draw anything ourselves.
    if( getCleanFrame && pGameWorld->m_FrameId != lastFrameId )
    {
		// GetRenderTargetData copies back buffer data to our buffer
        oGetRenderTargetData( pDevice, pBackBuffer, pCleanFrame );
        getCleanFrame = false;
    }
    lastFrameId = pGameWorld->m_FrameId;

    static DWORD endTick = 500;
    if( GetTickCount() >= endTick )
    {
        getCleanFrame = true;
        endTick = GetTickCount() + 5000; // Take new clean frame every 5 seconds
    }

	pDevice->GetViewport( &viewport );

    static DWORD renderState = 0;
    pDevice->GetRenderState( D3DRS_ZFUNC, &renderState );
    pDevice->SetRenderState( D3DRS_ZFUNC, D3DCMP_ALWAYS );

	// Get pointer to local player class
	localPlayer = pGame->getLocalPlayer();

	// Check if we are spawned inside a server
    if( localPlayer && pGameWorld && pGameWorld->bInited )
	{
		D3DXMATRIX matTmp = *( D3DXMATRIX* )( ( DWORD )pRenderer + 0x220 );
		if( matTmp.m[3][3] != 1.f )
		{
			matProj = matTmp;
			matView = *( D3DXMATRIX* )( ( DWORD )pRenderer + 0x1A0 );
		}

        static char espText[1024] = {0}, name[64] = {0};

		// Get the first object from the object manager
        GameObject* object = pGameWorld->GetFirstObject();

        do
        {
            if( object == NULL || object == ( GameObject* )localPlayer )
                continue;

            EGameObjectType objectType = object->getObjType();

            if( !( objectType & OBJTYPE_Human ) &&		// Is it a player?
                !( objectType & OBJTYPE_Zombie ) &&		// Is it a zombie?
                !( objectType & OBJTYPE_GameplayItem ) )// Is it loot?
                continue;								// Nope

            D3DXVECTOR3 screen, box, screenHead;
            D3DCOLOR color = white;

            memset( espText, 0, 1024 );

			// Get distance to the object
			D3DXVECTOR3 vecDist = localPlayer->vPos - object->vPos;
			float distance = D3DXVec3Length( &vecDist );

            if( objectType & OBJTYPE_Human )
            {
				// The object is a player
                obj_Player* player = ( obj_Player* )object;

				// If the player is dead, skip it
                if( !player->isAlive() )
                    continue;

				// You will have to figure out visibility check on your own ;) 
                bool visible = true; // IsVisible( myCameraPosition, playerVec );

				// If visible show ESP in red, otherwise orange
                color = ( visible ? red : orange );

				// Get screen coordinates from world position
                if( WorldToScreen( player->vPos, &screen ) )
                {
                    D3DXVECTOR3 headVec = D3DXVECTOR3( player->vPos.x, player->vPos.y + 1.75f/*approx. better to use bones*/, player->vPos.z );

					// Get screen coordinates of the players head from world position
                    if( WorldToScreen( headVec, &screenHead ) )
                    {
                        box.y = ( ( screen.y - screenHead.y ) > 1.f ) ? screen.y - screenHead.y : 1.f;
                        box.x = box.y / 2.75f;

                        drawLine( screen.x - ( box.x / 2 ),			screen.y - box.y,			screen.x - ( box.x / 2 ) + box.x,	screen.y - box.y,			1,	color );
                        drawLine( screen.x - ( box.x / 2 ) + box.x,	screen.y - box.y,			screen.x - ( box.x / 2 ) + box.x,	screen.y - box.y + box.y,	1,	color );
                        drawLine( screen.x - ( box.x / 2 ) + box.x,	screen.y - box.y + box.y,	screen.x - ( box.x / 2 ),			screen.y - box.y + box.y,	1,	color );
                        drawLine( screen.x - ( box.x / 2 ),			screen.y - box.y + box.y,	screen.x - ( box.x / 2 ),			screen.y - box.y,			1,	color );
                    }

					// Add player name to our ESP text
                    if( player->getPlayerName( name ) )
                        sprintf_s( espText, "%s %s", espText, name );

					// Add player health to our ESP text
                    sprintf_s( espText, "%s %d%%", espText, player->getHealth() );

					// Add distance to our ESP text
                    sprintf_s( espText, "%s %dm", espText, ( int )( distance + .5f ) );
                }
            }
            else if( objectType & OBJTYPE_Zombie )
			{
				// The object is a zombie
                obj_Zombie* zombie = ( obj_Zombie* )object;

				// If the zombie is dead, skip it
                if( zombie->getZombieState() == ZState_Dead )
                    continue;

				// You will have to figure out visibility check on your own ;) 
                bool visible = true; // IsVisible( myCameraPosition, zombieVec );

				// If visible show ESP in lime, otherwise green
                color = visible ? lime : green_dark;

				// Get screen coordinates from world position
                if( WorldToScreen( zombie->vPos, &screen ) )
                {
                    D3DXVECTOR3 headVec = D3DXVECTOR3( zombie->vPos.x, zombie->vPos.y + 1.75f/*approx. better to use bones*/, zombie->vPos.z );

					// Get screen coordinates of the zombies head from world position
                    if( WorldToScreen( headVec, &screenHead ) )
                    {
                        box.y = ( ( screen.y - screenHead.y ) > 1.f ) ? screen.y - screenHead.y : 1.f;
                        box.x = box.y / 2.75f;

                        drawLine( screen.x - ( box.x / 2 ),			screen.y - box.y,			screen.x - ( box.x / 2 ) + box.x,	screen.y - box.y,			1,	color );
                        drawLine( screen.x - ( box.x / 2 ) + box.x,	screen.y - box.y,			screen.x - ( box.x / 2 ) + box.x,	screen.y - box.y + box.y,	1,	color );
                        drawLine( screen.x - ( box.x / 2 ) + box.x,	screen.y - box.y + box.y,	screen.x - ( box.x / 2 ),			screen.y - box.y + box.y,	1,	color );
                        drawLine( screen.x - ( box.x / 2 ),			screen.y - box.y + box.y,	screen.x - ( box.x / 2 ),			screen.y - box.y,			1,	color );
                    }

					// Add distance to our ESP text
                    sprintf_s( espText, "%dm", ( int )( distance + .5f ) );
                }
            }
            else if( objectType & OBJTYPE_GameplayItem )
			{
				// The object is a loot item
                obj_DroppedItem* item = ( obj_DroppedItem* )object;

				// Don't bother with items that are further than 1000m away
                if( ( uint )( distance + .5f ) > 1000 )
                    continue;

				// Get screen coordinates from world position
                if( WorldToScreen( item->vPos, &screen ) )
				{
					wiInventoryItem* inventoryItem = item->getInventoryItem();
                    int itemID = inventoryItem->itemID;

                    if( itemID == 1196379204 )
                    {
						// The item is money
						// 
						// Add the amount of money to our ESP text
                        sprintf_s( espText, "$%d", inventoryItem->quantity );

						// If further away than 30m, add distance to ESP
                        if( ( int )( distance + .5f ) > 30 )
                            sprintf_s( espText, "%s %dm", espText, ( int )( distance + .5f ) );
                    }
                    else
                    {
						// Get item information from the marketplace data
                        BaseItemConfig* itemConfig = WeaponArmory__getConfig( itemID );

                        if( itemConfig )
                        {
                            if( itemConfig->m_StoreName )
							{
								// Add item name to ESP text
                                sprintf_s( espText, "%s %s", espText, itemConfig->m_StoreName );

								if( itemConfig->category == storecat_ASR ||	// Assault rifle
									itemConfig->category == storecat_SNP ||	// Sniper rifle
									itemConfig->category == storecat_SHTG ||// Shotgun
									itemConfig->category == storecat_MG ||	// Machine gun
									itemConfig->category == storecat_HG ||	// Handgun
									itemConfig->category == storecat_SMG )	// Sub machine gun
								{
									// Don't show empty weapons on ESP
                                    if( inventoryItem->ammo == 0 )
                                        continue;

									// Add ammunition to ESP text
									if( inventoryItem->ammo < 0 )
										sprintf_s( espText, "%s FULL", espText );
									else
										sprintf_s( espText, "%s x%d", espText, inventoryItem->ammo );

									// Add item weight to ESP text
                                    sprintf_s( espText, "%s %gkg", espText, itemConfig->m_Weight );
                                }
                            }
                            else
                                sprintf_s( espText, "%s %p", espText, itemID );

							// If further away than 30m, add distance to ESP
                            if( ( int )( distance + .5f ) > 30 )
                                sprintf_s( espText, "%s %dm", espText, ( int )( distance + .5f ) );
						}
						else
							sprintf_s( espText, "%s %p", espText, itemID );
                    }
                }
            }

            if( espText[0] != 0 )
                drawOutlinedText( color, screen.x, screen.y, true, espText );
        }
        while( object = pGameWorld->GetNextObject( object ) );
    }

    // Draw a crosshair
    static uint center_x = ( pRenderer->BackBufferWidth / 2 );
    static uint center_y = ( pRenderer->BackBufferHeight / 2 );
    drawRect( center_x - 5,	center_y - 1,	11,	3,	black );
    drawRect( center_x - 1,	center_y - 5,	3,	11,	black );
    drawLine( center_x - 4,	center_y,		center_x + 5,	center_y,		1,	white );
    drawLine( center_x,		center_y - 4,	center_x,		center_y + 5,	1,	white );

    pDevice->SetRenderState( D3DRS_ZFUNC, renderState );

    return oEndScene( pDevice );
}

With a little bit of work you could turn this basehook into a full-good WarZ hack, like this:

Full WarZ hack with ESP, zombie shield, aimbot, etc.
WarZ aimbot

Incoming search terms:

  • asbra net WarZ public
  • asbra net_warz_public_[www unknowncheats me]
  • source code the warz

Read the post The War Z hack source code – ESP, screenshot cleaner/blocker on Asbra.net.

PointBlank / Project Blackout – How to start reversing / hacking it

$
0
0

I recently started looking into this game briefly for a friend. Since this game still seems rather popular I figured I might write something about it.
Since the engine is divided in multiple DLL-files, it makes finding out how stuff works very easy, even for the beginner at reverse-engineering.

I’ve got PointBlank Thailand (since I live there), there are multiple versions for different regions, the core engine is the same but offsets might vary.

We start by checking out the games Wikipedia page Point Blank (2008 video game) – Wikipedia
PointBlank Wikipedia
“Engine: ICube” .. never heard of this before.

Let’s start by looking at what files there are in the game folder
PointBlank files

The DLL files starting with “i3″ belong to this engine, i3D or whatever. “i3DGfxDx” sounds very interesting, let’s open it up in IDA Pro

In IDA we go to Imports and we see this interesting function
PointBlank Direct3DCreate9

Double-click that, then mark the function name Direct3DCreate9, right-click it and Jump to xref to operand or press X
PointBlank D3D9 imports
In the popup dialog that appears click OK

Now we land here
PointBlank i3RenderContext::Create

.text:10033492                 call    Direct3DCreate9
.text:10033497                 mov     [esi+5364h], eax

Here it calls Direct3DCreate9 to create an instance of IDirect3D9, and puts the pointer in +5364h of the i3RenderContext class. For more information on Direct3DCreate9, take a look at MSDN; Direct3DCreate9 function definition.

Now it would be very nice to have an pointer to the i3RenderContext class the game uses. Let’s analyze other modules and see what we can find.. Here is a little play-by-play:

i3SceneDx.dll
PointBlank i3SceneDx
PointBlank i3RenderContext::isReady
PointBlank i3RenderContext* g_pRenderContext

Hey, that’s cool, now we’ve found the static pointer g_pRenderContext to i3RenderContext!

Before we move on, let’s look up the i3RenderContext::isReady(void) function in i3GfxDx.dll, we can use that later in our hack to determine if D3D is initialized yet. So open the DLL back up in IDA again, find the function and it looks like this:
PointBlank i3GfxDx i3RenderContext::isReady(void)
We can see all it does is return the value of this+28h, so we know that at 0×28 into the i3RenderContext class is the boolean value for “isReady”. This way we can check if the renderer is ready or not before trying to hook it. :)

What we know so far?

class i3RenderContext
{
public:
	char _0x0000[40];
	__int32 isReady; //0x0028 
	char _0x002C[21304];
	IDirect3D9* pD3D; //0x5364 
	IDirect3DDevice9* pD3DDevice; //0x5368 
};

Now let’s use this knowledge to start building a PointBlank D3D hack.

First we need to build a byte pattern/signature to find the i3RenderContext* g_pRenderContext easily. Here is a memory dump:

04C8CFCF   CC               INT3
04C8CFD0   83EC 60          SUB ESP,60
04C8CFD3   A1 54EDDF04      MOV EAX,DWORD PTR DS:[4DFED54]
04C8CFD8   33C4             XOR EAX,ESP
04C8CFDA   894424 5C        MOV DWORD PTR SS:[ESP+5C],EAX
04C8CFDE   A1 BC98D504      MOV EAX,DWORD PTR DS:[4D598BC]           ; i3RenderContext * g_pRenderContext
04C8CFE3   53               PUSH EBX
04C8CFE4   8B5C24 6C        MOV EBX,DWORD PTR SS:[ESP+6C]
04C8CFE8   55               PUSH EBP
04C8CFE9   8B6C24 6C        MOV EBP,DWORD PTR SS:[ESP+6C]
04C8CFED   56               PUSH ESI
04C8CFEE   8BF1             MOV ESI,ECX
04C8CFF0   8B08             MOV ECX,DWORD PTR DS:[EAX]
04C8CFF2   FF15 9496D504    CALL DWORD PTR DS:[4D59694]              ; i3RenderContext::IsReady(void)

And here is a decent pattern for it A1 ?? ?? ?? ?? 53 8B 5C 24 ?? 55

// Define our byte pattern
BYTE patRenderContext[] = "\xA1\x00\x00\x00\x00\x53\x8B\x5C\x24\x6C\x55";
char maskRenderContext[] = "x????xxxx?x";

UINT Stride = 0;

// Our DrawIndexedPrimitive hook, this is where chams, wallhack, etc. go
typedef HRESULT ( __stdcall* tDrawIndexedPrimitive )( LPDIRECT3DDEVICE9 pDevice, D3DPRIMITIVETYPE Type, INT BaseVertexIndex, UINT MinVertexIndex, UINT NumVertices, UINT StartIndex, UINT PrimitiveCount );
tDrawIndexedPrimitive oDrawIndexedPrimitive = NULL;
HRESULT __stdcall hDrawIndexedPrimitive( LPDIRECT3DDEVICE9 pDevice, D3DPRIMITIVETYPE Type, INT BaseVertexIndex, UINT MinVertexIndex, UINT NumVertices, UINT StartIndex, UINT PrimitiveCount )
{
	if( pDevice->GetStreamSource(0, &Stream_Data, &Offset, &Stride) == D3D_OK )
		Stream_Data->Release();

	if( Stride == 40 || Stride == 44 || Stride == 52 )
	{
		// Draw chams/wallhack
	}

	return oDrawIndexedPrimitive( pDevice, Type, BaseVertexIndex, MinVertexIndex, NumVertices, StartIndex, PrimitiveCount );
}

// Function for the thread
DWORD MainThread( LPVOID lpArgs )
{
	// Wait for 'i3GfxDx.dll' to load
	while( i3GfxDx == NULL )
		i3GfxDx = GetModuleHandleA( "i3GfxDx" );
	Log->Write( "i3GfxDx %p", i3GfxDx );

	// Wait for 'i3SceneDx.dll' to load
	while( i3SceneDx == NULL )
		i3SceneDx = GetModuleHandleA( "i3SceneDx" );
	Log->Write( "i3SceneDx %p", i3SceneDx );

	// Both DLL's are loaded, let's find the static i3RenderContext pointer
	DWORD addrRenderContext = FindPattern( i3SceneDx, 0, patRenderContext, maskRenderContext, 1 ); // 1 is for +1
#ifdef DEBUG
	Log->Write( "addrRenderContext %p", addrRenderContext );
#endif

	// Wait while game initializes renderer
	while( (i3RenderContext*)addrRenderContext == NULL ||
		*(i3RenderContext**)addrRenderContext == NULL ||
		**(i3RenderContext***)addrRenderContext == NULL ||
		***(i3RenderContext****)addrRenderContext == NULL )
		Sleep(10);

	pRenderContext = ***(i3RenderContext****)addrRenderContext;
	Log->Write( "pRenderContext %p", pRenderContext );

	// The isReady function/variable we found earlier is very useful now :) 
	while( pRenderContext->isReady == 0 )
		Sleep( 10 );
	Log->Write( "pRenderContext->isReady %d", pRenderContext->isReady );

	// And finally hook the device table, virtual functions table, midfunction hook, or whatever you use.

	// Hooking the vtable of the Direct3D9 Device is detected so I feel ok showing that:
	oDrawIndexedPrimitive = (tDrawIndexedPrimitive)VTableHook( *( DWORD* )pRenderContext->pD3DDevice, 42, ( DWORD )&hDrawIndexedPrimitive );
	Log->Write( "oDrawIndexedPrimitive %p", oDrawIndexedPrimitive );
}

// DLL entry point
BOOL APIENTRY DllMain( HMODULE hModule, DWORD dwReason, LPVOID lpReserved )
{
	if( dwReason == DLL_PROCESS_ATTACH )
	{
		CreateThread( NULL, NULL, ( LPTHREAD_START_ROUTINE )MainThread, NULL, NULL, NULL );
	}
	else if( dwReason == DLL_PROCESS_DETACH )
	{
	}

	return TRUE;
}

Change the vtable hook to an undetected hooking method, or add an HackShield bypass, then you should have a working D3D PointBlank hack. :)

Incoming search terms:

  • hook pointblank

Read the post PointBlank / Project Blackout – How to start reversing / hacking it on Asbra.net.

Forces of War utilities (userscript/bot)

$
0
0

UPDATE June 1st, 2014
Full version of my Forces of War bot is now available free! » Forces of War bot w/ boss sniping «


.. so I wrote a bot for the Facebook game Forces of War.

The game is created by Uken Games and all of their text-based browser MMO games (Forces of War, Age of Legends, Villains, etc.) build on the same engine, share the same code base, etc. so this script will work on those as well with minor modifications.

I’ve decided to release a “lite” version of my bot right now, it contains:

  • Collect bot (automatically collects money when available)
  • Battle (PvP) bot (automatically performs battles for you when above X stamina)
  • Heal bot (automatically heals you when below X health)

The PvP bot tries to find the weakest possible target it can (lower level, has lost alot of battles).

My full Forces of War script/bot also has:

  • Invasion bot (automatically finds and camps invasion boss, attempts to get the killing blow always)
  • Mission bot (automatically performs selected mission(s) for you)

The script available at the bottom of this post and in a Gist on GitHub. I will post it on userscripts.org at a later time since it’s down right now. :)

Prerequisites

To run this you will need to get the browser extension Tampermonkey (or Greasemonkey if you use Firefox)

Forces of War bot script cheat

When activated, the script adds controls to the header of the game page.

Script details

The script makes use of the existing JavaScript variables that Uken provides, such as U_HEALTH and U_STAMINA. If you are interested in what other variables are available, start by looking for those two in the files loaded on page.

If you are interested in programming/scripting, repeated_checks() contains the meat of the script, it is where values are checked and appropriate actions taken. It runs indefinitely until any action is available.

The Forces of War script

To install this in Tampermonkey/Greasemonkey, make a new script, paste the entire script from here, save it. Enjoy.

Edit: Now I also uploaded it to userscripts.org, follow the link and click the Install button, that should take care of it. http://userscripts.org/scripts/show/464408

Script has been removed from my webserver due to request from Uken
You can still get the script on userscripts.org or Github.

Incoming search terms:

  • forces of war bot
  • forces of war hack
  • cheat forces of war invasions
  • forces of war script
  • uken games cheats
  • forces of war
  • uken bots
  • uken games hack
  • cheats for forces of war
  • how to cheat uken villains dwarf invasion

Read the post Forces of War utilities (userscript/bot) on Asbra.net.

Forces of War bot with boss sniping (invasion bot)

$
0
0

Better late than never! ..right?

Full version of my bot for the Facebook game Forces of War.

The game is created by Uken Games and all of their text-based browser MMO games (Forces of War, Age of Legends, Villains, etc.) build on the same engine, share the same code base, etc. so this script will work on those as well with minor modifications.

Features

  • Invasion bot (automatically finds and camps invasion boss, attempts to get the killing blow always)
  • Mission bot (automatically performs selected mission(s) for you)
  • Collect bot (automatically collects money when available)
  • Battle (PvP) bot (automatically performs battles for you when above X stamina)
  • Heal bot (automatically heals you when below X health)

The PvP bot tries to find the weakest possible target it can (lower level, has lost alot of battles).

Prerequisites

To run this you will need to get the Google Chrome extension Tampermonkey

Forces of War bot

When activated, the script adds controls to the header of the game page.

Script details

The script makes use of the existing JavaScript variables that Uken provides, such as U_HEALTH and U_STAMINA. If you are interested in what other variables are available, start by looking for those two in the files loaded on page.

If you are interested in programming/scripting, repeated_checks() contains the meat of the script, it is where values are checked and appropriate actions taken. It runs indefinitely until any action is available.

The Forces of War script

You can install it from GitHub Gists by going here: Forces of War bot then click on Raw (direct link) and Tampermonkey should ask to install it :)

To install this in Tampermonkey, make a new script, paste the entire script from here, save it. Enjoy.

Script has been removed from my webserver due to request from Uken
You can still get the script on userscripts.org or Github.

Incoming search terms:

  • crime inc facebook bot
  • forces of war invasion bot
  • bot forcesofwar
  • cheat crime inc uken
  • fb sniper facebook bot
  • Forces of war bot download
  • fow bot
  • how do you do boss missions on mobile game forces of war?

Read the post Forces of War bot with boss sniping (invasion bot) on Asbra.net.


How to create a Zoom Hack for Banished

$
0
0

Banished without zoom hack

Banished without zoom hack

Hello!

In this tutorial we will create a zoom hack for the game Banished. By default the game is quite limiting in its’ zoom options, you can zoom in & pan the camera around a bit, but I like to get up real close and see what’s going on down there :)

What you learn in this tutorial can be applied to other games as well, useful in some strategy games. So how is zoom hack achieved?

Cheat_Engine_6.3_2014-06-25_19-28-32 Let’s start by opening up the game and our trusty old pal Cheat Engine. Now in most situations like these there will be a float value with the amount you are zoomed/panned, so let’s start looking for that.

Now what you want to do is go in-game and either zoom in or zoom out, then you go back to Cheat Engine and search for either “Increased value” or “Decreased value”. Which is which? You will find out :)
Keep zooming in/out in-game and searching increased/decreased in Cheat Engine. Once in a while don’t zoom in game just move the camera around or other things, then search “Unchanged value”. That will weed out the “bad” values that are unrelated to zoom.

Eventually you will find a value that is 20 when max zoomed in and 130 when max zoomed out.

So what do we do now?

Right-click on it in the cheat table and “Find out what writes to this address” then zoom in in-game to the limit and keep pushing the zoom in button, then do the same thing with zooming out. You will find two instructions that set maximum/minimum value to the zoom when trying to go above/below it.

Digging into the code

Here’s a ASM dump of that

Application-steam-x64.exe+ED970 - F3 0F10 0D 6CED0700   - movss xmm1,[Application-steam-x64.exe+16C6E4]
Application-steam-x64.exe+ED978 - 85 DB                 - test ebx,ebx
Application-steam-x64.exe+ED97A - 74 3C                 - je Application-steam-x64.exe+ED9B8
Application-steam-x64.exe+ED97C - F3 0F10 47 3C         - movss xmm0,[rdi+3C]
Application-steam-x64.exe+ED981 - 7E 0A                 - jle Application-steam-x64.exe+ED98D
Application-steam-x64.exe+ED983 - F3 0F5C 05 2DED0700   - subss xmm0,[Application-steam-x64.exe+16C6B8]
Application-steam-x64.exe+ED98B - EB 08                 - jmp Application-steam-x64.exe+ED995
Application-steam-x64.exe+ED98D - F3 0F58 05 23ED0700   - addss xmm0,[Application-steam-x64.exe+16C6B8]
Application-steam-x64.exe+ED995 - 0F2F C8               - comiss xmm1,xmm0
Application-steam-x64.exe+ED998 - F3 0F11 47 3C         - movss [rdi+3C],xmm0
Application-steam-x64.exe+ED99D - 76 09                 - jna Application-steam-x64.exe+ED9A8
Application-steam-x64.exe+ED99F - C7 47 3C 0000A041     - mov [rdi+3C],41A00000
Application-steam-x64.exe+ED9A6 - EB 10                 - jmp Application-steam-x64.exe+ED9B8
Application-steam-x64.exe+ED9A8 - 0F2F 05 89ED0700      - comiss xmm0,[Application-steam-x64.exe+16C738]
Application-steam-x64.exe+ED9AF - 76 07                 - jna Application-steam-x64.exe+ED9B8
Application-steam-x64.exe+ED9B1 - C7 47 3C 00000243     - mov [rdi+3C],43020000
Application-steam-x64.exe+ED9B8 - F3 0F10 57 44         - movss xmm2,[rdi+44]

Let’s dig into it!

movss xmm1,[Application-steam-x64.exe+16C6E4] - 20.0 float (minimum zoom)

Loads the minimum zoom value into xmm1 register

movss xmm0,[rdi+3C]

Load current zoom value into xmm0 register

subss xmm0,[Application-steam-x64.exe+16C6B8]

Decrease zoom by 5.0, this is for when we zoom in

addss xmm0,[Application-steam-x64.exe+16C6B8]

Increase zoom by 5.0, this is for when we zoom out

comiss xmm1,xmm0

Compare current zoom value to the minimum allowed zoom

movss [rdi+3C],xmm0

Set the new zoom value

jna Application-steam-x64.exe+ED9A8

JNA (Jump if Not Above)
If the current zoom value is above the minimum allowed zoom value, jump away. Otherwise run the next instruction:

mov [rdi+3C],41A00000
jmp Application-steam-x64.exe+ED9B8

Sets zoom to minimal value (20 float) and then jumps away.
0xA041 is 20 in float value.

comiss xmm0,[Application-steam-x64.exe+16C738]

Compares current zoom value to the maximum allowed zoom value (130)

jna Application-steam-x64.exe+ED9B8

If the current zoom value is not above the maximum allowed zoom value, jump away. Otherwise run the next instruction:

mov [rdi+3C],43020000

Set zoom to maximum value (130 float)
0×0243 is 130 in float value.

This teaches us that zoom factor/value is at 0x3C into some class. This can be a good start for reversing that class (probably a camera class where you can find FOV, camera position etc.) if you are interested in that.

So! Now how do we make it so we can zoom in as close as we want to or as far away as we want? There are many different solutions to this. Let’s look at a couple.

First method for unlimited zoom hack

First of all we could eliminate the two operations that force the zoom value, namely these two

mov [rdi+3C],41A00000
mov [rdi+3C],43020000

NOP those out (‘Replace with code that does nothing’ in Cheat Engine) and that will do the trick.

Second method for unlimited zoom hack

More interestingly would be to patch one of the jumps to avoid the checks altogether.

76 09                 - jna Application-steam-x64.exe+ED9A8
C7 47 3C 0000A041     - mov [rdi+3C],41A00000
EB 10                 - jmp Application-steam-x64.exe+ED9B8
0F2F 05 89ED0700      - comiss xmm0,[Application-steam-x64.exe+16C738]
76 07                 - jna Application-steam-x64.exe+ED9B8
C7 47 3C 00000243     - mov [rdi+3C],43020000
F3 0F10 57 44         - movss xmm2,[rdi+44]

If we would change the first JNA to a JMP and change it to go all the way down to the movss, then it would avoid the checks :)
Current the JNA has the bytes 76 09, 76 is the instruction JNA (short). The instruction JMP (short) is EB, so we start by changing the bytes to EB 09.

Now we have a jump instruction that looks like this
EB 09 - jmp Application-steam-x64.exe+ED9A8

Hmm, that’s no good tho, it will jump to before the next check! So let’s change the distance too.. how can we do that?
The second byte of the instruction is 09. It is the distance in bytes of how far the jump should be! We want our jump to go down to the movss so we need to jump an additional 0×10. Hence we change the 09 to 19!

Now the complete instruction is EB 19 instead of the original 76 09
EB 19 - jmp Application-steam-x64.exe+ED9B8

Now our jump goes all the way down to the movss instruction, skipping the code that would have limited our zoom. Our zoom hack is ready! :)

Hacking camera panning

Now, as an added bonus; if we scroll up a little bit in the code we find this area:

FF 15 F3BD0500        - call qword ptr [Application-steam-x64.exe+149730]
84 C0                 - test al,al
74 12                 - je Application-steam-x64.exe+ED953
F3 0F10 47 44         - movss xmm0,[rdi+44]
F3 0F5C 05 BEEC0700   - subss xmm0,[Application-steam-x64.exe+16C60C]
F3 0F11 47 44         - movss [rdi+44],xmm0
44 0F2F 5F 44         - comiss xmm11,[rdi+44]
76 04                 - jna Application-steam-x64.exe+ED95E
44 89 67 44           - mov [rdi+44],r12d
F3 0F10 47 44         - movss xmm0,[rdi+44]
41 0F2F C4            - comiss xmm0,xmm4
76 07                 - jna Application-steam-x64.exe+ED970
C7 47 44 0000803F     - mov [rdi+44],3F800000
F3 0F10 0D 6CED0700   - movss xmm1,[Application-steam-x64.exe+16C6E4]
85 DB                 - test ebx,ebx
74 3C                 - je Application-steam-x64.exe+ED9B8
F3 0F10 47 3C         - movss xmm0,[rdi+3C]
7E 0A                 - jle Application-steam-x64.exe+ED98D
F3 0F5C 05 2DED0700   - subss xmm0,[Application-steam-x64.exe+16C6B8]

This is where the game limits the camera panning.

As an exercise I suggest you figure out how that works and how you can patch it to achieve unlimited camera panning too! ;)

Now we can finally see their tiny, pixelated faces up close and personal

I especially like that boy with mutton chops in the background..

I especially like that boy with mutton chops in the background..

Incoming search terms:

  • candy crush engineers

Read the post How to create a Zoom Hack for Banished on Asbra.net.

Counter-Strike Source Radar Hack Tutorial

$
0
0

This is a re-post from my old blog, ilsken.net
This tutorial explains how to make all players shown on the radar, always. The technique shown in this tutorial is also applicable to other games.

You will need 2 tools:
– Memory scanner (I use Cheat Engine)
– Debugger (I use OllyDbg and x64dbg)

  1. Start a local game
  2. Join a team
  3. Add a bot in opposite team
  4. Set sv_cheats 1 and bot_stop 1
  5. Walk up to the bot so you see it on your radar
  6. Search for value 1 as type 1 byte
  7. Turn around or walk a bit so the bot doesn’t show on radar anymore
  8. Next search for 0
  9. Repeat steps 5 to 8 until you have a few values left

Then try freezing some of them, walk away from the bot and it should stay visible on the radar.
Do that until you have 1 value left.

Alright, now I open debugger, go to the address that I found earlier.
Right-click it, Breakpoint -> Memory Breakpoint, Access

And it hits on an instruction that looks like this:
14C41803 |> 8A8437 1D0D0000 MOV AL,BYTE PTR DS:[EDI+ESI+D1D]

Remove your memory breakpoint and put a regular breakpoint on it.

Add a few more bots & add the addresses right after the one you found as 1 byte also, if you found eg. 12345030, then you add 12345031 12345032 12345033 12345034 etc.
Try freeze them all to 1 and you should see all enemies on radar all the time.

Alright, now take a look at what’s in EDI and ESI.

If we run/break a few times we see that EDI moves similiar to this:
EDI 00000002
EDI 00000003
EDI 00000006

It’s obvious that it’s player index in the array.

ESI 20A428A8
ESI 2725AE10

ESI should look similar to this (addresses vary ofc. depending on allocation base of the modules)

In your memory-scanner (CE) search for the first ESI value, 20A428A8 as 4 bytes (remember to tick the Hex box).

We find it in a bunch of places.
Disconnect your server & make a new one.

Now when we break on
14C41803 |> 8A8437 1D0D0000 MOV AL,BYTE PTR DS:[EDI+ESI+D1D]
check the value of ESI (our pointer) and look in CE if some of the addresses we found before holds the new ESI.

I found 2 static places for this:
client.dll+4CE070
client.dll+4D4BA4

So now we know that:
*(client.dll+4CE070) = ESI
*(ESI + index + D1D) set to 1 to show on radar

To be sure of finding things on next update I search for the address of client.dll+4CE070 and find that it’s found static at:
14B02E70 /$ A1 70E0F614 MOV EAX,DWORD PTR DS:[14F6E070]
14B02E75 |. 85C0 TEST EAX,EAX
14B02E77 |. 74 06 JE SHORT client.14B02E7F
14B02E79 |. 05 A8040000 ADD EAX,4A8
14B02E7E |. C3 RETN
14B02E7F |> 33C0 XOR EAX,EAX
14B02E81 \. C3 RETN

So we make a byte-signature for this so we easily can find it:
A1 ?? ?? ?? ?? 85 C0 74 06 05

Alright, now let’s code this up in C++

//Asbra.net
#include <Windows.h>

// FindPattern & DataCompare by dom1n1k
BOOL DataCompare( BYTE* pData, BYTE* bMask, char * szMask )
{
	for( ; *szMask; ++szMask, ++pData, ++bMask )
		if( *szMask == 'x' && *pData != *bMask )
			return FALSE;

	return ( *szMask == NULL );
}

DWORD FindPattern( DWORD dwAddress, DWORD dwLen, BYTE *bMask, char * szMask )
{
	for( DWORD i = 0; i < dwLen; i++ )
		if( DataCompare( (BYTE*)( dwAddress + i ), bMask, szMask ) )
			return (DWORD)( dwAddress + i );

	return 0;
}

DWORD MainThread( LPVOID lpArgs )
{
	HMODULE hClient = GetModuleHandleA( "client.dll" );
	while(hClient == NULL) { hClient = GetModuleHandleA( "client.dll" ); }

	DWORD dwDrawOnRadar = FindPattern((DWORD)hClient, 0x005E5000, (BYTE*)"\xA1\x00\x00\x00\x00\x85\xC0\x74\x06\x05", "x????xxxxx") + 1;
	dwDrawOnRadar = *(DWORD*)dwDrawOnRadar;

	while(1)
	{
		for(int i = 0;i < 0x4F;i++) // at 0x50 seems to be start of clan name
		{
			BYTE* pDrawOnRadar = (BYTE*)((*(DWORD*)dwDrawOnRadar) + 0xD1D + i);
			*pDrawOnRadar = 1;
		}

	}

	return 0;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
{
	if(dwReason == DLL_PROCESS_ATTACH)
	{
		DWORD dwThreadID = 0;
		HANDLE hThread = CreateThread( NULL, NULL, (LPTHREAD_START_ROUTINE)MainThread, NULL, NULL, &dwThreadID );
	}

	return TRUE;
}

Can easily be done externally using WriteProcessMemory if you want to do that.

Anyhow, enjoy.

Read the post Counter-Strike Source Radar Hack Tutorial on Asbra.net.

Viewing all 10 articles
Browse latest View live