 |
Cheat Engine The Official Site of Cheat Engine
|
| View previous topic :: View next topic |
| Author |
Message |
Gestalt Newbie cheater
Reputation: 0
Joined: 08 Sep 2011 Posts: 21
|
Posted: Thu Sep 05, 2013 1:31 am Post subject: Player Base and Entity Array - Saints Row IV |
|
|
Hi, i'm kind of new to game hacking and trying to make a trigger bot for the game, Saints Row IV. I sort of managed to do that. I found an address that is 0 when looking at world and something when looking at an entity. I then simulate a left mouse click.
I'm not satisfied though cause there are some problems.
1. I didn't seem to find the static address. So once in a while I need to update my addresses in the triggerbot.
2. I would love to find the Entity array or maybe only the current npc in the crosshair base address, in order to check HP and hopefully a flag like "hostile" or something.
What i seek is some guidelines or tips I could use in order to solve this. If you want any information just ask. Currently I'm using this:
SomeBase:"SaintsRowIV.exe"+061E0A90
PlayerBaseOffs1:6c8
PlayerBaseOffs2:2c
PlayerBaseOffs3:100
PlayerBaseOffs4:7c
HealthOffs:88
CrossHairID:240
and if I look at what writes to health I get this:
009B8627 - F3 0F11 86 101E0000 - movss [esi+00001E10],xmm0
(esi = 1E8BC000)
I really don't know much more and as I said the Addresses isn't static even though they work most of the time.
Thanks in advance.
|
|
| Back to top |
|
 |
Gniarf Grandmaster Cheater Supreme
Reputation: 43
Joined: 12 Mar 2012 Posts: 1285
|
Posted: Thu Sep 05, 2013 6:44 pm Post subject: Re: Player Base and Entity Array - Saints Row IV |
|
|
| Gestalt wrote: | | 1. I didn't seem to find the static address. So once in a while I need to update my addresses in the triggerbot. | If your triggerbot is made with cheat engine paste that in the main window: | Code: | <?xml version="1.0" encoding="utf-8"?>
<CheatTable>
<CheatEntries>
<CheatEntry>
<ID>12</ID>
<Description>"TargetLogger"</Description>
<Color>80000008</Color>
<VariableType>Auto Assembler Script</VariableType>
<AssemblerScript>[enable]
alloc(MyMemory,1024)
aobscanmodule(TargetLogger_aob,SaintsRowIV.exe,89 96 CC 1F 00 00 E8 ** ** ** ** 83 C4 04)
registersymbol(TargetLogger_aob)
//code
label(LogTarget)
//data
label(CurrentTarget)
registersymbol(CurrentTarget)
TargetLogger_aob-6:
call LogTarget
nop
MyMemory:
LogTarget:
mov dword [esi+00001FC8],eax //original code
mov dword [CurrentTarget],eax //store targeted entity ID (NOT a pointer)
retn
CurrentTarget:
dd 0
[disable]
dealloc(MyMemory)
unregistersymbol(TargetLogger_aob)
unregistersymbol(CurrentTarget)
TargetLogger_aob-6:
mov dword [esi+00001FC8],eax
</AssemblerScript>
<CheatEntries>
<CheatEntry>
<ID>13</ID>
<Description>"Current target ID"</Description>
<Color>80000008</Color>
<VariableType>4 Bytes</VariableType>
<Address>CurrentTarget</Address>
</CheatEntry>
</CheatEntries>
</CheatEntry>
</CheatEntries>
</CheatTable> | Basically it takes the piece of code that writes (what I presume to be) the ID of the entity under the crosshair and hooks it to store a copy of the target ID.
| Code: | SaintsRowIV.AK::Monitor::GetTimeStamp+39B0DB - 8D BE D01F0000 - lea edi,[esi+00001FD0]
SaintsRowIV.AK::Monitor::GetTimeStamp+39B0E1 - E8 7AB8FEFF - call SaintsRowIV.AK::Monitor::GetTimeStamp+386960
SaintsRowIV.AK::Monitor::GetTimeStamp+39B0E6 - 56 - push esi
SaintsRowIV.AK::Monitor::GetTimeStamp+39B0E7 - 89 86 C81F0000 - mov [esi+00001FC8],eax <- this eax is the target ID
SaintsRowIV.AK::Monitor::GetTimeStamp+39B0ED - 89 96 CC1F0000 - mov [esi+00001FCC],edx
SaintsRowIV.AK::Monitor::GetTimeStamp+39B0F3 - E8 08350000 - call SaintsRowIV.AK::Monitor::GetTimeStamp+39E600
SaintsRowIV.AK::Monitor::GetTimeStamp+39B0F8 - 83 C4 04 - add esp,04 |
| Gestalt wrote: | | 2. I would love to find the Entity array or maybe only the current npc in the crosshair base address, in order to check HP and hopefully a flag like "hostile" or something. | Look for a single byte that is:
0 when targeting the world
110 when targeting a saint
114 when targeting a neutral entity
121 when targeting an enemy
I haven't found a pointer to this one and simple code hooking won't work because the code that reads and writes it is shared.
_________________
DO NOT PM me if you want help on making/fixing/using a hack.
Last edited by Gniarf on Sun Sep 08, 2013 4:36 pm; edited 1 time in total |
|
| Back to top |
|
 |
Gestalt Newbie cheater
Reputation: 0
Joined: 08 Sep 2011 Posts: 21
|
Posted: Fri Sep 06, 2013 5:38 pm Post subject: |
|
|
Nice, thank you. You did a lot of work. Smart trick with getting the address.
Also the flags would be very useful if I could find out the pointers. How did you get the values, by just look for changed values?
Last time I ran a pointer scan on this game (level 7,offset 4096 ) my hard drive ran out of space (over 1.40 TB) I'm going to raid my other drive and get another TB and see if I can get this one.
Maybe I should use less levels or offset value. Is there a good recommendation?
Side note: I make my cheats in C++ currently. I'm kinda new to that too but I do have many years of experience with C# so it's not that hard to understand. I guess I need to learn AoB scans in C++ then, fun! I'm not that much in it for the cheats, I just like to challenge myself.
Thanks for the quick, very helpful answer. Hope you have a nice evening!
|
|
| Back to top |
|
 |
Dark Byte Site Admin
Reputation: 471
Joined: 09 May 2003 Posts: 25819 Location: The netherlands
|
Posted: Fri Sep 06, 2013 7:14 pm Post subject: |
|
|
This pointerscan would need a structsize of 8192
Anyhow, have you tried some of the new option in 6.3. E.g limiting the number of elements by node can greatly decrease number of results, but still return quite useful paths. (It's like a variable structsize during the scan)
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Like my help? Join me on Patreon so i can keep helping |
|
| Back to top |
|
 |
Gestalt Newbie cheater
Reputation: 0
Joined: 08 Sep 2011 Posts: 21
|
Posted: Sat Sep 07, 2013 4:28 am Post subject: |
|
|
| Dark Byte wrote: | | Anyhow, have you tried some of the new option in 6.3. |
No I haven't. I'll try them. I don't fully get though what the settings mean. Is there any documentation?
I will probably run it tonight. Thanks!
|
|
| Back to top |
|
 |
Dark Byte Site Admin
Reputation: 471
Joined: 09 May 2003 Posts: 25819 Location: The netherlands
|
Posted: Sat Sep 07, 2013 5:03 am Post subject: |
|
|
The documentation is basically just a repeat of the function name
Here's a few more detailed explenations:
First element must point to module:
If it is an object oriented programmed game, objects tend to have a vtable as first element of their structure.
A vtable is basically a pointer to memory describing the class properties. The memory is usually located in static memory (module memory)
So, if you do a scan with this, you only find real objects, instead of getting offsets that point halfway into another object
No looping pointers:
This remove pointerpaths that would enter an infinite loop, including it's children
e.g a->b->c->d->a->b->c->d....
Max different offsets per node:
Normally the pointerscan will take every offset there is in the current node
Worst case scenario: 0, 4, 8, c, ... ff8, ffc, ...
Usually more like: 4, 48, 12c, 480, ff8, ffc
With max offsets per node set to 3, it will only enter the first 3 paths it encounters (4, 48, 12c, and skip 480-)
As you may guess, there is a chance you may lose some valid pointerpaths, but this will reduce the amount of paths tremendously and you can do very big level scans.
And it's not completely useless, as it is able to find high value structure elements, and it's usually recommended to pick the path with the smallest offsets anyhow
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Like my help? Join me on Patreon so i can keep helping |
|
| Back to top |
|
 |
Gestalt Newbie cheater
Reputation: 0
Joined: 08 Sep 2011 Posts: 21
|
Posted: Sat Sep 07, 2013 5:42 am Post subject: |
|
|
| Nice, thank you I get it now. If I find anything useful I'll post what I find here so others may use it.
|
|
| Back to top |
|
 |
Gniarf Grandmaster Cheater Supreme
Reputation: 43
Joined: 12 Mar 2012 Posts: 1285
|
Posted: Sun Sep 08, 2013 4:35 pm Post subject: |
|
|
| Gestalt wrote: | | Also the flags would be very useful if I could find out the pointers. How did you get the values, by just look for changed values? | Yep, changed, unchanged, and patience. I think I did an exact value 0 when looking at the world in the late stages.
| Gestalt wrote: | | I guess I need to learn AoB scans in C++ then, fun!! | You don't need the aobscan in your c++ app, it's a safety I take when publishing hacks incase we wouldn't have exactly the same version of the game. You can look for the byte pattern yourself and then hardcode the resulting address in your bot. You'll just have to update your bot each time the game gets patched.
OK So I finally got a way to access the target flags. I found a pointer that works each time I start the game (but dies when I reload a save): ["SaintsRowIV.exe"+06BF23A0]+4
Then found what read it, and got a function that accesses stuff 4 bytes before the target flags each time your cross hair goes over a target.
| Code: | <?xml version="1.0" encoding="utf-8"?>
<CheatTable>
<CheatEntries>
<CheatEntry>
<ID>8</ID>
<Description>"Get target flags"</Description>
<Color>80000008</Color>
<VariableType>Auto Assembler Script</VariableType>
<AssemblerScript>[ENABLE]
alloc(MyMem,1024)
//use this define if you don't want to use (de)alloc (VirtualAlloc in c++)
//define(MyMem,SaintsRowIV.CreateAudioInputSourceParams+1311DA)
aobscanmodule(TargetFlagHook_aob,SaintsRowIV.exe,50 e8 * * * * 8B F8 83 C4 08 85 FF 74 * 8b cb)
registersymbol(TargetFlagHook_aob)
registersymbol(TargetFlagAddr)
//code
label(TargetFlagHook)
label(TargetFlagHook_Return)
//data
label(TargetFlagAddr)
TargetFlagHook_aob+6: //should be = SaintsRowIV.ares_parse_a_reply+2100C3
jmp TargetFlagHook
TargetFlagHook_Return:
MyMem:
TargetFlagHook:
mov dword [TargetFlagAddr],eax //flags are at [eax+4]
mov edi,eax //original code
add esp,08 //original code
jmp TargetFlagHook_Return
//SaintsRowIV.exe+4DE2FFC: //uncomment if you don't use (de)alloc
TargetFlagAddr:
dd 0
[DISABLE]
dealloc(MyMem)
unregistersymbol(TargetFlagHook_aob)
unregistersymbol(TargetFlagAddr)
TargetFlagHook_aob+6:
mov edi,eax
add esp,08
</AssemblerScript>
<CheatEntries>
<CheatEntry>
<ID>9</ID>
<Description>"target flag"</Description>
<Color>80000008</Color>
<VariableType>Byte</VariableType>
<Address>[TargetFlagAddr]+4</Address>
</CheatEntry>
</CheatEntries>
</CheatEntry>
</CheatEntries>
</CheatTable>
| Note that it take a bit of time for CE to update the address of an entry, so it might take some time before the target flag line becomes valid.
| Code: | SaintsRowIV.ares_parse_a_reply+2100B8 - 2B C2 - sub eax,edx
SaintsRowIV.ares_parse_a_reply+2100BA - 40 - inc eax
SaintsRowIV.ares_parse_a_reply+2100BB - 50 - push eax
SaintsRowIV.ares_parse_a_reply+2100BC - 8B CE - mov ecx,esi
SaintsRowIV.ares_parse_a_reply+2100BE - E8 1D896FFF - call SaintsRowIV.GDS_value_decode_values+17CAA0
SaintsRowIV.ares_parse_a_reply+2100C3 - 50 - push eax <-target flags are at [eax+4]
SaintsRowIV.ares_parse_a_reply+2100C4 - E8 67E7FFFF - call SaintsRowIV.ares_parse_a_reply+20E830
SaintsRowIV.ares_parse_a_reply+2100C9 - 8B F8 - mov edi,eax <-same eax here
SaintsRowIV.ares_parse_a_reply+2100CB - 83 C4 08 - add esp,08
SaintsRowIV.ares_parse_a_reply+2100CE - 85 FF - test edi,edi |
_________________
DO NOT PM me if you want help on making/fixing/using a hack. |
|
| Back to top |
|
 |
Gestalt Newbie cheater
Reputation: 0
Joined: 08 Sep 2011 Posts: 21
|
Posted: Mon Sep 09, 2013 9:41 am Post subject: |
|
|
Thank you so much. I came up with nothing solid. I've learned much by this, now it's up to programming it.
Do I need to make a code cave in c++? I've never done that. All I try fail. I think external hacks are more practical but dll injection works too. I have tried booth, the only time something happened was when I crashed the game, lol. Actually the hacks I done in the past (in C++) only involve reading and writing values to addresses. This is all new.
As I see it, failing is a part of learning. I'm gonna keep try, sooner or later I will get it. Thanks for all help!
|
|
| Back to top |
|
 |
Gniarf Grandmaster Cheater Supreme
Reputation: 43
Joined: 12 Mar 2012 Posts: 1285
|
Posted: Mon Sep 09, 2013 12:10 pm Post subject: |
|
|
| Gestalt wrote: | | the only time something happened was when I crashed the game | I don't know what you did exactly, but perhaps you forgot to call VirtualProtect before attempting to write on the game's code, causing WriteProcessMemory to fail, or perhaps you forgot to update my code before injecting it (the address of the jumps, or the address where you want to store TargetFlagAddr). Remember that jumps are relative so when you inject "jmp SomeAddress" you must write 0xE9,{SomeAddress-JMPAddress-5 over 4 bytes}.
| Gestalt wrote: | | Do I need to make a code cave in c++? | No. Almost all programs have an huge cave at the end of the .code/.text section that you can use. In the present case it's at SaintsRowIV.exe+DE290A = SaintsRowIV.CreateAudioInputSourceParams+1311DA .
Cheat engine's alloc function/VirtualAlloc allows to create a cave without worrying much about code size and memory access permissions but it's not required for this hack.
BTW: if your bot simply clicks when TargetFlags=121 it might be easier to find the boolean that holds bMouseLButtonDown and overwrite it from the CE hack.
If you use a cracked exe (or one with a static base and no crc checks), the variant below should be hardcodable in the .exe (use file->open FILE, browse to the.exe, activate the hack, close CE).
| Code: | [ENABLE]
aobscan(CodeCave,ff 15 * * * * C9 C2 08 00 00)
//aobscan(TargetFlagHook_aob,50 e8 * * * * 8B F8 83 C4 08 85 FF 74 * 8b cb)
aobscan(TargetFlagHook_aob,85 FF 74 20 8B CB E8) //this signature is slightly better than the one above because
//the modified bytes are not covered by the signature.
registersymbol(TargetFlagHook_aob)
//code
label(TargetFlagHook)
label(TargetFlagHook_Return)
//data
define(TargetFlagAddr,51E2FFC) //51E2FFC is a virtual address (=address in ram in a running process)
//label(TargetFlagAddr) //so we can't put a label at that address in a file
//TargetFlagHook_aob+6:
TargetFlagHook_aob-5: //because I changed the signature; it shoud be = SaintsRowIV.exe+B28C1E
jmp TargetFlagHook //jumps are reltative so we can use labels for jump targets in hardcoded hacks
TargetFlagHook_Return:
CodeCave+b:
TargetFlagHook:
mov dword [TargetFlagAddr],eax //flags are at [eax+4]
mov edi,eax //original code
add esp,08 //original code
jmp TargetFlagHook_Return
[DISABLE]
unregistersymbol(TargetFlagHook_aob)
TargetFlagHook_aob-5:
mov edi,eax
add esp,08 | After that just read [51E2FFC]+4 in your bot.
_________________
DO NOT PM me if you want help on making/fixing/using a hack. |
|
| Back to top |
|
 |
Gestalt Newbie cheater
Reputation: 0
Joined: 08 Sep 2011 Posts: 21
|
Posted: Mon Sep 09, 2013 12:44 pm Post subject: |
|
|
I use the Steam version of the game, legal. What I tried most now is dll injection. This is my short test cpp:
| Code: | #include <Windows.h>
#include <Tlhelp32.h>
#define F6_KEY 0x75
#define RIGHT_MOUSE 0x02
#define JMP(from,to) (((int)to-(int)from)-5)
const DWORD dw_CodeCaveAddy = 0xF32419;
DWORD AddressForFlag = 0x0;
__declspec(naked) void /*__stdcall*/ MyCodeCaveHack()
{
__asm
{
mov [AddressForFlag],eax
mov edi,eax
add esp,0x08
jmp dword ptr ds:[dw_CodeCaveAddy+5]
}
}
struct MyPlayer_t
{
BYTE flag;
void ReadInformation()
{
flag = *(BYTE*)(AddressForFlag + 4);
}
}MyPlayer;
DWORD WINAPI dwMainThread(LPVOID)
{
*(BYTE*) dw_CodeCaveAddy = 0xe9;
*(DWORD*)(dw_CodeCaveAddy+1) = JMP(dw_CodeCaveAddy,MyCodeCaveHack);
while (!GetAsyncKeyState(F6_KEY))
{
MyPlayer.ReadInformation();
}
return 0;
}
BOOL WINAPI DllMain ( HMODULE hDll, DWORD dwReason, LPVOID lpReserved )
{
DisableThreadLibraryCalls(hDll);
if ( dwReason == DLL_PROCESS_ATTACH )
{
CreateThread(NULL, NULL, dwMainThread, NULL, NULL, NULL);
}
return TRUE;
} |
What I don't really can figure out is if the code is wrong or the addresses. I took your AoB scan bytes and searched for them in CE. I ended up on address F32413 (not the latest ones though, the ones before)
I will try what you suggested though, just that I would love to understand what I do wrong.
|
|
| Back to top |
|
 |
Gniarf Grandmaster Cheater Supreme
Reputation: 43
Joined: 12 Mar 2012 Posts: 1285
|
Posted: Mon Sep 09, 2013 1:57 pm Post subject: |
|
|
You were missing the VirtualProtects, a null check in ReadInformation(), and "jmp dword ptr ds:[dw_CodeCaveAddy+5]" means read what is at (&dw_CodeCaveAddy)+5, interpret it as an address and jump there.
Also I recommend getting some sleep in the while(GetAsyncKeyState(...)) loop.
Nice one for the __declspec(naked), I didn't know that trick.
| Code: | #include <Windows.h>
#include <Tlhelp32.h>
#include <stdio.h> //for sprintf
//#define F6_KEY 0x75 //use the VK_** defines from winuser.h instead
#define RIGHT_MOUSE 0x02
#define JMP(from,to) (((int)to-(int)from)-5)
const DWORD dw_CodeToHook = 0xF3241e-5; //aob 85 FF 74 20 8B CB E8
const DWORD dw_HookReturnAddress= dw_CodeToHook+5;
DWORD AddressForFlag = 0x0;
__declspec(naked) void /*__stdcall*/ MyCodeCaveHack()
{
__asm
{
mov [AddressForFlag],eax
mov edi,eax
add esp,0x08
jmp dword ptr [dw_HookReturnAddress]
}
}
class Player //could use being in a separate file
{
public:
BYTE flag;
void ReadInformation()
{
if (AddressForFlag) //null check incase AddressForFlag wouldn't be set yet
{
flag = *(BYTE*)(AddressForFlag + 4);
}
}
};
DWORD WINAPI dwMainThread(LPVOID)
{
Player MyPlayer;
DWORD OldProtect;
DWORD Dummy; //to keep the 2nd VirtualProtect happy
//allow ourselves to overwrite the game's code
VirtualProtect(reinterpret_cast<LPVOID>(dw_CodeToHook),5,PAGE_EXECUTE_READWRITE,&OldProtect);
//write the code
*(BYTE*) dw_CodeToHook = 0xe9;
*(DWORD*)(dw_CodeToHook+1) = JMP(dw_CodeToHook,MyCodeCaveHack);
//restore the original protection
VirtualProtect(reinterpret_cast<LPVOID>(dw_CodeToHook),5,OldProtect,&Dummy);
while (!GetAsyncKeyState(VK_F6))
{
if (GetAsyncKeyState(VK_F7))
{
MyPlayer.ReadInformation();
char Message[50];
sprintf(Message,"target flag=%d",MyPlayer.flag);
MessageBox(NULL,Message,"Flags",MB_OK);
}
Sleep(200); //No need to burn 100% cpu resources
}
return 0;
}
BOOL WINAPI DllMain ( HMODULE hDll, DWORD dwReason, LPVOID lpReserved )
{
DisableThreadLibraryCalls(hDll);
if ( dwReason == DLL_PROCESS_ATTACH )
{
CreateThread(NULL, NULL, dwMainThread, NULL, NULL, NULL);
}
return TRUE;
} |
_________________
DO NOT PM me if you want help on making/fixing/using a hack. |
|
| Back to top |
|
 |
Gestalt Newbie cheater
Reputation: 0
Joined: 08 Sep 2011 Posts: 21
|
Posted: Mon Sep 09, 2013 2:23 pm Post subject: |
|
|
| Thanks, this works. And I tried hardcoding the exe as you said and that worked perfect. Suddenly I have 2 working triggerbots lol. This has been very educational. Thanks again!
|
|
| Back to top |
|
 |
Gniarf Grandmaster Cheater Supreme
Reputation: 43
Joined: 12 Mar 2012 Posts: 1285
|
Posted: Mon Sep 09, 2013 5:01 pm Post subject: |
|
|
Lol now we've got too many working bots. Well, if you don't mind there is a question that's been bugging me for a while: for me shooting is part of the fun so, what do you want to do with a triggerbot ? Throw your mouse sideway and clear a room?
_________________
DO NOT PM me if you want help on making/fixing/using a hack. |
|
| Back to top |
|
 |
Gestalt Newbie cheater
Reputation: 0
Joined: 08 Sep 2011 Posts: 21
|
Posted: Mon Sep 09, 2013 5:58 pm Post subject: |
|
|
Actually I finished the game on harcore without any kind of cheats. I just wanted to make a triggerbot and I was currently playing this game. I think most cheats takes away the fun in games. There is a lot of work put in to make a game challenging and rewarding. With cheats I just can't feel that I get rewarded.
However I really do love programming and now game hacking got my interest. I will probably try and use what I've learned on a few other games just to see if I can. It's the developing that is interesting to me.
By the way, since Saints Row: The Third is practically the same engine the:
| Code: | | 50 e8 * * * * 8B F8 83 C4 08 85 FF 74 * 8b cb |
Aobscan will work on that too. I tried.
[EDIT] nvm the flag hangs at 121 in Saints Row: The Third. I'm shooting everyone now. Well I don't think I'm gonna put down time on it though, have newer games to try.
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You can download files in this forum
|
|