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

May 20, 2013 by Johan — 10 Comments

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:

  • box esp source code
  • sourcecodecleaner

Johan

Posts Twitter Facebook

Blogging out of many years of experience with gamehacking, programming and reverse-engineering. Currently freelancing in webprogramming.

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

  1. Could you give a tutorial how use this hack?

  2. LPD3DXFONT m_font;
    void drawText(uint color, float x, float y, bool center,varchar* text )
    {
    RECT rct = {x- 120, y, x+ 120, y + 15};
    m_font->DrawText(NULL, text, -1, &rct, DT_NOCLIP, red);
    }

    Why this text dont work?

  3. How can i get pGameWolrd ? I wanna use this in one emulator ?? can u show me way ?? thank you!

  4. How to update GetGameWorld?

  5. same trouble : getgameworld = 000000000

Leave a Reply