[COMPLETED] Aquaria 1.1.2

Lord Blade

Expert Cheater
Mar 9, 2017
385
1
18
#1
Game Name: Aquaria
Game Engine: Indie
Game Version: 1.1.2
Options Required: Health, Food amount, racing time
Game/Steam Website: https://store.steampowered.com/app/24420/
Other Info: Looking for infinite health (one that doesn't also affect enemies).
Also a food cheat (to let you edit amounts or just not use them up) would be awesome.
And something to help with the seahorse races (which can be a pain) would be nice.
 

Slade

Expert Cheater
Apr 29, 2017
97
5
8
#2
I had a look at this a long time ago and didn't succeed. I have a little bit more knowledge now, so I'll take another look. No promises though.

Edit: Now I know why. The game closes when it detects the debugger.

If someone has a way of making CE "stealth", I'd be happy to know about it.

edit 2: Health is stored as a float with an initial value of 5.

Edit 3: I changed debuggers in CE and now the game doesn't go "pop" when I attach the debugger. So I have a working health cheat. I'll have to play the game to get further to figure out the rest.
 
Last edited:

Lord Blade

Expert Cheater
Mar 9, 2017
385
1
18
#3
Just getting the health value was beyond me. :p
I work much better with straight displayed numbers. lol

Of course I also suck at making working tables that I can use for more than the one session. :p
 

Slade

Expert Cheater
Apr 29, 2017
97
5
8
#4
I'm happy to provide you with some help if you want to learn. It's not as hard as you'd think.
Non displayed values are a bit of a pain, but you can learn a few tricks that might help.

Often in these cases, the health is stored as a float, not an integer. So that helps narrow down the search. That's my usual starting point, floats, then doubles, then 4 byte integers. Just keep getting hurt and do a decrease, then find health and do an increase, until you narrow it down to a few results. Then freeze them and see what happens.

Once you've found the location, attach the debugger (new window opens), get hit and select the code in the new window, choose disassemble and stuff like below is shown. The "fsub dword ptr [esp+28]" is interesting, and using "Replace with code that does nothing" on it (right click the instruction) means you don't die - but neither does the enemy.


Code:
"Aquaria.exe"+B710D: EB 0C                 -  jmp Aquaria.exe+B711B
"Aquaria.exe"+B710F: DD D8                 -  fstp st(0)
"Aquaria.exe"+B7111: D9 86 E4 1A 00 00     -  fld dword ptr [esi+00001AE4]
// ---------- INJECTING HERE ----------
"Aquaria.exe"+B7117: D8 64 24 28           -  fsub dword ptr [esp+28]
"Aquaria.exe"+B711B: D9 9E E4 1A 00 00     -  fstp dword ptr [esi+00001AE4]
// ---------- DONE INJECTING  ----------
"Aquaria.exe"+B7121: D8 9E E4 1A 00 00     -  fcomp dword ptr [esi+00001AE4]
"Aquaria.exe"+B7127: DF E0                 -  fnstsw ax
"Aquaria.exe"+B7129: F6 C4 01              -  test ah,01

So restore the code, use the "Find out what addresses this instruction access" menu item (right click) and shoot / get hit - I usually freeze my health so I can't die. A bunch of addresses will show in the new window that opened. Select 3-4 including your own health, and use the data dissector and click OK on all the options. Scroll through that looking for something unique to the player. In this case it's the players name. Using that we can filter out the player hits against the enemies every time.

So instead of our code being this:

Code:
  code:
  fsub dword ptr [esp+28]              // take one health off the player or enemy
  fstp dword ptr [esi+00001AE4] // write the health back to the memory location
  jmp return
We can add:

Code:
newmem:
  cmp dword ptr [esi+1994], 'Naij' //compare the location at esi + 1944 with the characters name
  jne code                                         //if not correct, jump to the code portion
  fstp dword ptr [esi+00001AE4] //otherwise write the health back to the memory location (skipping the fsub dword ptr [esp+28], thus not reducing our health)
  jmp return                                    //return back the the original code in the game.

I know it isn't much, but it gives you some insight as to how the cheats are written.

I'll keep working on the table now. Health is working, food is working too, both ingredients and full recipes :)
 
Last edited:

Lord Blade

Expert Cheater
Mar 9, 2017
385
1
18
#5
Can you share the table you've put together so far?

I've tried the whole debugger thing and most times end up breaking the game. lol
 

Slade

Expert Cheater
Apr 29, 2017
97
5
8
#6
Here ya go.
I will admit, I'm not enjoying the game that much. It's so directionless, and I feel like I'm wandering aimlessly around this vast cavern with f/all to do. I haven't found these sea horse races yet. I will try to persevere with it over the coming days, but I almost fell asleep last night playing.

As for crashing the game, that happens to everyone. It's really easy to crash most games. I do it all the time, but there's usually a way around it. I do often just walk away from some games, because they're not worth the effort.
 

Attachments

  • Aquaria.CT

    [Steam] Health, Food, Ingredients

    8.4 KB Views: 7

SunBeam

RCE Fanatics
Talents
Fearless Donors
Feb 4, 2018
681
347
63
#7
Want my old trainer source? :p

Code:
#include "stdafx.h"
#include "Resource.h"
#include <shellapi.h>
#include "cMemory.h"
#include "cProcess.h"
#include "cSigScan.h"

#define _WIN32_WINNT    0x0501
#include "commctrl.h"
#pragma comment(lib,"comctl32.lib")
#pragma comment(lib,"extaLib.lib")

using namespace cMemory;
using namespace cProcess;
using namespace cSigScan;

cMemory Mem;
cProcess Proc;
cSigScan Sig;

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK IdProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);

void KeyCheck();

HINSTANCE mInst;
HWND tDlg;
HWND hMsgBox;
HICON Icon;
WNDPROC OldIdProc;
HCURSOR hIdCursor = LoadCursor(NULL,IDC_HAND);

char* TrainerTitle = "Extalia presents..";
char* game = "aquaria.exe";
char* About =
"Aquaria v1.0.3 - Trainer +5\n"
"Powered by extaLib™\n";

//God Mode
DWORD dwGodCave = NULL;
BYTE bGodMod[]    = { 0x3B, 0x05, 0x0C, 0xBA, 0x5E, 0x00, 0x75, 0x0E, 0x53,
                    0x8B, 0x98, 0x3C, 0x1C, 0x00, 0x00, 0x89, 0x98, 0x38,
                    0x1C, 0x00, 0x00, 0x5B, 0xD9, 0x80, 0x38, 0x1C, 0x00,
                    0x00};
BYTE bGodOrig[] = { 0xD9, 0x80, 0x38, 0x1C, 0x00, 0x00 };

//Inventory Items
BYTE bInvOrig[] = { 0x83, 0x40, 0x3C, 0xFF };

/*//Speed
DWORD dwSpdCave = NULL;
BYTE bSpdMod[]  = { 0x3B, 0x35, 0x0C, 0xBA, 0x5E, 0x00, 0x75, 0x0E,
                    0xB8, 0xD0, 0x07, 0x00, 0x00, 0xEB, 0x15, 0x80,
                    0x3D, 0x14, 0xBA, 0x5E, 0x00, 0x01, 0x75, 0x09,
                    0xB8, 0x00, 0x00, 0x00, 0x00, 0x89, 0x86, 0xC4,
                    0x44, 0x00, 0x00 };
BYTE bSpdOrig[] = { 0x89, 0x86, 0xC4, 0x44, 0x00, 0x00 };

//Save Position
DWORD dwSvCave    = NULL;
BYTE bSvMod[]    = {  };
BYTE bSvOrig    = {  };

//Load Position


//Magnify Naija*/




BOOL CheckProc()
{
    DWORD dwProcId = NULL;
    dwProcId = cProcess::ProcIdByProcName( game );
    if( dwProcId == 0 )
    {
        MessageBox( tDlg, "Game is not running!", "Error", MB_OK );
        return FALSE;
    }
    else
        return TRUE;
}

void KeyCheck()
{
    static BOOL b1Enabled = FALSE;
    static BOOL b2Enabled = FALSE;
/*    static BOOL b3Enabled = FALSE;
    static BOOL b4Enabled = FALSE;
    static BOOL b5Enabled = FALSE;
    static BOOL b6Enabled = FALSE;*/

    BYTE* pBaseAddress = NULL;

    if (GetAsyncKeyState(VK_F1))
    {
        if( !CheckProc() ) return;

        if( !b1Enabled )
        {
            //Mem.GetModBase( game, &pBaseAddress );
            //dwGodCave = Mem.MakeJump( (pBaseAddress+0xF5316), 1, &bGodMod, sizeof(bGodMod) );
           
            dwGodCave = cMemory::MakeJump(
                cProcess::ProcIdByProcName(game),
                (cProcess::ModBaseFromProcName( game, module ) + 0xF5316),
                1,
                &bGodMod,
                sizeof(bGodMod) );

            SetDlgItemText( tDlg, IDC_F1, "ON" );
        }
       
        else
        {
            Mem.GetModBase( game, &pBaseAddress );
            Mem.WriteMem( (pBaseAddress+0xF5316), &bGodOrig, sizeof(bGodOrig) );
            Mem.DeleteCave( (BYTE *)dwGodCave, sizeof(bGodMod) );

            SetDlgItemText( tDlg, IDC_F1, "OFF" );
        }

        b1Enabled = !b1Enabled;
    }

    if (GetAsyncKeyState(VK_F2))
    {
        if( !CheckProc() ) return;

        if( !b2Enabled )
        {    
            Mem.GetModBase( game, &pBaseAddress );
            Mem.WriteNops( (pBaseAddress+0xBF390), 4 );
           
            SetDlgItemText( tDlg, IDC_F2, "ON" );
        }

        else
        {    
            Mem.GetModBase( game, &pBaseAddress );
            Mem.WriteMem( (pBaseAddress+0xBF390), &bInvOrig, sizeof(bInvOrig) );

            SetDlgItemText( tDlg, IDC_F2, "OFF" );
        }

        b2Enabled = !b2Enabled;
    }

/*    if (GetAsyncKeyState(VK_F3))
    {
        if( !CheckProc() ) return;

        if( !b3Enabled )
        {    
            Mem.GetModBase( game, &pBaseAddress );
            dwSpdCave = Mem.MakeJump( (pBaseAddress+0xAB734), 1, &bSpdMod, sizeof(bSpdMod) );

            SetDlgItemText( tDlg, IDC_F3, "ON" );
        }

        else
        {    
            Mem.GetModBase( game, &pBaseAddress );
            Mem.WriteMem( (pBaseAddress+0xAB734), &bSpdOrig, sizeof(bSpdOrig) );
            Mem.DeleteCave( (BYTE *)dwSpdCave, sizeof(bSpdMod) );

            SetDlgItemText( tDlg, IDC_F3, "OFF" );
        }

        b3Enabled = !b3Enabled;
    }

    if (GetAsyncKeyState(VK_F4))
    {
        if( !CheckProc() ) return;

        if( !b4Enabled )
        {    
            Mem.GetModBase( game, &pBaseAddress );
            Mem.WriteMem( (pBaseAddress+0x2B9E5), &bInvisMod, sizeof(bInvisMod) );

//            SetDlgItemText( tDlg, IDC_INVIS, "ON");
        }

        else
        {    
            Mem.GetModBase( game, &pBaseAddress );
            Mem.WriteMem( (pBaseAddress+0x2B9E5), &bInvisOrig, sizeof(bInvisOrig) );
           
//            SetDlgItemText( tDlg, IDC_INVIS, "OFF");
        }

        b4Enabled = !b4Enabled;
    }

    if( GetAsyncKeyState(VK_F5) )
    {
        if( !CheckProc() ) return;

        if( !b5Enabled )
        {
            Mem.GetModBase( game, &pBaseAddress );
            dwSpeedCaveAddr = Mem.MakeCave( &pSpeedCave, sizeof(pSpeedCave) );
            Mem.WriteMem( (pBaseAddress+0x14BCBB), &bSpeedChange, sizeof(bSpeedChange) );
            Mem.WriteMem( (pBaseAddress+0x14BCBC), &dwSpeedCaveAddr, 4 );

//            SetDlgItemText( tDlg, IDC_SPEED, "ON");
        }
       
        else
        {
            Mem.GetModBase( game, &pBaseAddress );
            Mem.WriteMem( (pBaseAddress+0x14BCBA), &bSpeedOrig, sizeof(bSpeedOrig) );
            Mem.DeleteCave( (PBYTE)dwSpeedCaveAddr, sizeof(pSpeedCave) );

//            SetDlgItemText( tDlg, IDC_SPEED, "OFF");
        }

        b5Enabled = !b5Enabled;
    }

    if (GetAsyncKeyState(VK_F6))
    {
        if( !CheckProc() ) return;

        if( !b6Enabled )
        {    
            Mem.GetModBase( game, &pBaseAddress );
            Mem.WriteMem( (pBaseAddress+0x447924), &szJumpModEnabled, sizeof(szJumpModEnabled) );

//            SetDlgItemText( tDlg, IDC_JUMP, "ON");
        }

        else
        {    
            Mem.GetModBase( game, &pBaseAddress );
            Mem.WriteMem( (PBYTE)(pBaseAddress+0x447924), &szJumpModDisabled, sizeof(szJumpModDisabled) );

//            SetDlgItemText( tDlg, IDC_JUMP, "OFF");
        }

        b6Enabled = !b6Enabled;
    }*/

    Proc.CloseProc();
}


BOOL CALLBACK DialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
    switch(uMsg){
         
    case WM_INITDIALOG:
        tDlg = hwndDlg;
        SetWindowSubclass(GetDlgItem(hwndDlg,IDC_LOGO), IdProc, 0, 0);
        SetWindowSubclass(GetDlgItem(hwndDlg,IDC_ABOUT), IdProc, 0, 0);
        SetWindowSubclass(GetDlgItem(hwndDlg,IDC_EXIT), IdProc, 0, 0);
        SetWindowText(hwndDlg,TrainerTitle);
        SendMessage(hwndDlg, WM_SETICON,ICON_BIG,(LPARAM)Icon);
        SetTimer(hwndDlg,1,255,0);
        return FALSE;

    case WM_CLOSE:
        KillTimer(hwndDlg,1);
        EndDialog(hwndDlg,0);
        return TRUE;

    case WM_TIMER:
        KeyCheck();
        return TRUE;
   
    case WM_COMMAND:
        switch (wParam){
            case IDC_LOGO:
                ShellExecute(0,"open","http://www.extalia.com",NULL,NULL,SW_SHOWNORMAL);
                return TRUE;

            case IDC_ABOUT:
                MessageBoxA(tDlg, About, "About", MB_ICONINFORMATION);
                return true;

            case IDC_EXIT:
                KillTimer(hwndDlg,1);
                EndDialog(hwndDlg,0);
                return true;
        }
        return TRUE;
    }
    return FALSE;
}


LRESULT CALLBACK IdProc(HWND hWnd, UINT uMsg,WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass,DWORD_PTR dwRefData)
{
    switch(uMsg){

    case WM_SETCURSOR:
        SetCursor(hIdCursor);
        return TRUE;

    default:
        return DefSubclassProc(hWnd, uMsg, wParam, lParam);
    }
    return FALSE;
}



int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
    Icon = (HICON)LoadImage(hInstance,(LPCSTR)IDI_ICON,IMAGE_ICON,0,0,LR_DEFAULTCOLOR);
   
    mInst = hInstance;
    DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_DIALOG),0,DLGPROC(DialogProc),0);
    return 0;
}

BR,
Sun
 

Lord Blade

Expert Cheater
Mar 9, 2017
385
1
18
#8
So, the food bit works fine. Eat a food item and I get max of them.
The ingredient one won't activate though.
 

Slade

Expert Cheater
Apr 29, 2017
97
5
8
#9
So, the food bit works fine. Eat a food item and I get max of them.
The ingredient one won't activate though.
Yeah, I know, sorry. I have an issue with CE. Often instead of the first byte of the aobscan being the correct byte, it throws in CC instead. No idea why, but it's caused quite a few crashes in games for me. I should remember to check, but I don't.

I've just loaded the game and noticed the issue as well.

Here's a fixed table.
 

Attachments

  • Aquaria.CT

    Fixed Max ingredients

    8.4 KB Views: 8

Lord Blade

Expert Cheater
Mar 9, 2017
385
1
18
#10
Thanks.

Also, the game starts off a bit slow, giving you the slow, relaxing exploration stuff to do. Just swim about and get a feel for the area. But once you get your energy form (the black look you have during the one quick story bit), things start to pick up. Plus there's a bunch of forms and abilities you'll get as you progress, standard Metroidvania style really.

And the story for the game is pretty cool, though it gets pretty damn dark in places. :p
 

SunBeam

RCE Fanatics
Talents
Fearless Donors
Feb 4, 2018
681
347
63
#11
@Slade: You should know by know you're to use the VEH Debugger (not the standard Windows one). Also, make use of hardware breakpoints, not software ones. That's why you see CC.
 

Slade

Expert Cheater
Apr 29, 2017
97
5
8
#12
@SunBeam, you sir, are a genius ! Thank you.

I had to swap the VEH debugger, the standard windows one causes the game to close (not sure why I swapped to that in the first place). I was using software breakpoints because at one stage I was watching more than 4 locations at the same time, and CE had a big cry about it. That was ... a while ago. I never remembered to swap it back.

@Lord Blade... I've unlocked both forms, and am now slowly boring my way through the Kelp fields. I just crashed the game and will have to reload. It's still stupidly slow. Lots of enemies that seem to soak up those bullets, and I just swim through empty cave after cave.
 
Top Bottom