Page 1 of 1

Aquaria 1.1.2

Posted: Fri Jun 08, 2018 2:51 am
by Lord Blade
[b]Game Name:[/b] Aquaria

[b]Game Engine:[/b] Indie

[b]Game Version:[/b] 1.1.2

[b]Options Required:[/b] Health, Food amount, racing time

[b]Game/Steam Website:[/b] [URL]https://store.steampowered.com/app/24420/[/URL]

[b]Other Info:[/b] 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.

Aquaria 1.1.2

Posted: Fri Jun 08, 2018 6:19 am
by Slade
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.

Aquaria 1.1.2

Posted: Fri Jun 08, 2018 8:42 am
by Lord Blade
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

Aquaria 1.1.2

Posted: Fri Jun 08, 2018 9:10 am
by Slade
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[/CODE]





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[/code]



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.

[/code]





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 :)

Aquaria 1.1.2

Posted: Fri Jun 08, 2018 9:44 pm
by Lord Blade
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

Aquaria 1.1.2

Posted: Fri Jun 08, 2018 10:23 pm
by Slade
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.

Aquaria 1.1.2

Posted: Fri Jun 08, 2018 10:38 pm
by SunBeam
Want my old trainer source? :p



[code]

#include "stdafx.h"

#include "Resource.h"

#include

#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
"

"Powered by extaLibâ„¢
";



//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;

}[/code]





BR,

Sun

Aquaria 1.1.2

Posted: Sat Jun 09, 2018 12:00 am
by Lord Blade
So, the food bit works fine. Eat a food item and I get max of them.

The ingredient one won't activate though.

Aquaria 1.1.2

Posted: Sat Jun 09, 2018 12:20 am
by Slade
[QUOTE="Lord Blade, post: 48669, member: 911"]So, the food bit works fine. Eat a food item and I get max of them.

The ingredient one won't activate though.[/QUOTE]



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.

Aquaria 1.1.2

Posted: Sat Jun 09, 2018 12:25 am
by Lord Blade
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

Aquaria 1.1.2

Posted: Sat Jun 09, 2018 12:33 am
by SunBeam
[USER=3704]@Slade[/USER]: You should know by know you're to use the [B]VEH Debugger[/B] (not the standard Windows one). Also, make use of hardware breakpoints, not software ones. That's why you see CC.

Aquaria 1.1.2

Posted: Sat Jun 09, 2018 12:49 am
by Slade
[USER=12587]@SunBeam[/USER], 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.



[USER=911]@Lord Blade[/USER]... 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.