[GUIDE] Guide: Cheating games with the unreal engine

using the dumper from cake-san

A section for guides, manuals, and walkthroughs on how to use Cheat Engine functions and advanced features.


Post Reply
User avatar
Marc
Table Master
Table Master
Journeyman Hacker
Journeyman Hacker
Posts: 214
Joined: Sat Jul 23, 2022 2:08 am
Answers: 0
x 327

[GUIDE] Guide: Cheating games with the unreal engine

Post by Marc »

Hi all,

this guide is based on the tutorial video from kraqurjak (sadly deleted, but theres a version from Cheat the Game, see the end of the post) and own experience. Since I prefer to have written guides, I just try to deliver some of that on my own. Let me now how you like it :)

A game engine which is quite commonly used is the "unreal engine". Sometimes you can detect them on the unreal-logo, another hint is when the name of the exe-file ends with -unreal.exe.

Usually it would be quite a bit of work to dissect such a game (to be honest: I'd fail at it), but luckily for us the cheater Cake-san has created an absolute awesome table for us - a collection of scripts to almost automatically cheat unreal engine-games. If you don't have a fitting game at your hands, grab a copy of "Shadow Burglar" on steam, it uses the unreal engine and it's free.

Getting playerbase address
Run the game and load his table into Cheat Engine. Now activate his script called "Unreal Engine". This will take a few seconds, after that you will see among some other things a section "PlayerBase" with an address.

Now we select this PlayerBase-Entry and press F5 to see which code accesses this very address. Most likely we will get several codes, so checkout if our playerbase-address is the only one which is accessed by the found code(s). You will almost certainly find at least one code which only accesses the playerbase address.

In the case of "Shadow Burglar" I chose the code

Code: Select all

ShadowBurglar_Unreal-Win64-Shipping.exe.text+2973177: 4C 8B 0F              - mov r9,[rdi]

So, on this location we make a code injection to copy the playerbase address:

Code: Select all

[ENABLE]
aobscanmodule(pbase,ShadowBurglar_Unreal-Win64-Shipping.exe,4C 8B 0F 4C 8D 44 24 40 48 8B D0)
alloc(newmem,$1000,pbase)

label(code)
label(return)
label(playerbase)

newmem:
  mov [playerbase],rdi
code:
  mov r9,[rdi]
  lea r8,[rsp+40]
  jmp return

playerbase:
  dq 0

pbase:
  jmp newmem
  nop 3
return:
registersymbol(pbase playerbase)

[DISABLE]

pbase:
  db 4C 8B 0F 4C 8D 44 24 40

unregistersymbol(*)
dealloc(newmem)

So, now we have a script which successfully copies the correct address of the playerbase. Before you do something else: save your table!
Sometimes the scripts tend to crash Cheat Engine and we don't want to start over :)

Dissect the data playerbase address
Activate our newly created script. Of course you will not see any difference, but we now have a new variable called "playerbase" to our use.
So below our script, add another adress manually. Set it to be a pointer with base address PlayerBase and offset zero.

Here comes the real magic: activate from Cake-sans script collection the point "Enable UE Structure Lookup". This will integrate his scripts into the "dissect data" function (Ctrl-D).

Invoke the "dissect data" window, use [playerbase] as our address and let CE create a new structure. You will notice the name of the structure is not the common "new structure" but instead has a name like playerdata_C or something. And there are lots of useful values including a full descriptive name! Awesome!

Now, deactivate every single script except our own one, because we only want to keep the [playerbase] variable and save your table again, the risky part with chances of crashing is now over.

Create table entries using playerbase address
Walk through the entries of the "dissect data" window. At every entry which sounds interesting, select it and press "A" to add the entry into your address list.

What makes this way so awesome: every single entry in our address list will now automatically read "[playerbase]+xxxx". So if you are done with the dissect window, you can simply drag&drop the created entries below or script which gets the playerbase address and we're done.

Video from Cheat The Game:

The Next Level
There has been another video by Kraquarjak but it ist deleted, sadly. But happily, I've saved a copy on my NAS (really handy to have 10 TB free space sometimes). I like this guy, but he's no Chris Fayte, so I found this 1-hour-video somewhat hard to follow.

Doing as advised before, you'll end up with a table which uses an AOB Injection to get the current Playerbase Address, below the script there are the entries of interesting values with offset-addresses like +1a0. Now, in most cases these offsets will not change even when there's a new update to the game. But it can happen, depending on how much the developers are changing in the data structures. In these cases, it is worth the effort to use this way...

You' are abe to use the names instead of the offsets. Let's say you have a dissect table named player_c and there is as offset +150 the entry healthvalue. Using the "old"way described above you will get an address [playerbase]+150. Now you can change it into [playerbase}+player_c.healthvalue, Cheat Engine will look up the offset in the dissect data, find the +150 Offset and use it.

Now if the game changes and you would just update the dissect-data and ta-daaa, wour table is up-to-date again.

Of course you'd need to leave the dissect-data information in your table when releasing it. And/or you could add some code to your table alongside the dumper and populate the needed structures automatically, almost the same thing as in using the UE Dumper.

Code: Select all

  createThrad/(ue4createstruct('/Script/Engine.GameEngine', 'GameEngine',0)
  createThrad/(ue4createstruct('/Script/Engine.GameGameViewportClient', 'GameViewport',0)
  createThrad/(ue4createstruct('/Script/Engine.GameState', 'GameState',0)

have fun,
Marc


Tags:

User avatar
Marc
Table Master
Table Master
Journeyman Hacker
Journeyman Hacker
Posts: 214
Joined: Sat Jul 23, 2022 2:08 am
Answers: 0
x 327

Re: [GUIDE] Guide: Cheating games with the unreal engine

Post by Marc »

Since the tools from Cake-San are outdated (read: not supporting newer Unreal versions, especially not 5.x, you can use

Since the "UE Game Manager" does not work for me and the Guided Hacking-Version requires an older version of CE, I'll stick to the tool from bbfox :D

Last edited by Marc on Sun Jun 07, 2026 7:14 am, edited 1 time in total.

User avatar
Marc
Table Master
Table Master
Journeyman Hacker
Journeyman Hacker
Posts: 214
Joined: Sat Jul 23, 2022 2:08 am
Answers: 0
x 327

Re: [GUIDE] Guide: Cheating games with the unreal engine

Post by Marc »

Trying to update the guide a little. :)

Main problem is that you'll have a away to the values you are interested in. So you take your unreal-tool of choice and try to find what you need - usually you want to find the "LocalPlayer" address. One way is to start at the GWorld address and then dig your way.

For example, when cheating Gothic 1, I used the UE5 tool from bbfox. Pressing the "start at gworld" does exactly that and you'll the the right address of Gworld. Add this to the table, check out which code accesses this very address and make a code injection.
For example:

Code: Select all

[ENABLE]
aobscanmodule(get_gworld,G1R-Win64-Shipping.exe,C3 CC CC CC CC CC CC CC CC CC CC 40 53 48 83 EC 20 48 8B 01 48 8B D9 FF 90 88 01 00 00 48 85 C0 75 ** 48 83 C4 20 5B C3) // should be unique
alloc(newmem,$1000,get_gworld)

label(code)
label(return)
label(gworld)

newmem:
  mov [gworld],rcx
code:
  mov rax,[rcx]
  mov rbx,rcx
  jmp return

gworld:
  dq 0

get_gworld+11:
  jmp newmem
  nop
return:
registersymbol(get_gworld gworld)

[DISABLE]

get_gworld+11:
  db 48 8B 01 48 8B D9

unregistersymbol(*)
dealloc(newmem)

This thing just copies the current address of gworld into our own gworld-Adress (Variable, if you want to call it this way).
Below this script, make a new manual address entry called GWorld, check the "Pointer" checkbox. Enter "gworld" as an adress and let the "0" stay where it is (at the upper pointer). Now you have a table entry with the correct gworld address which will alway be right.

Now you have a good starting point which reliably brings you to this address.

Now, in the GUI of the UE5Dumper, use the green arrows to navigate down the tree. In our Case, the way to our goal turns out to be

Code: Select all

OwningWorld 
    -> OwningGameInstance
        -> LocalPlayers
            -> [0] for the first entry
                -> PlayerController

We can try to find a code which accesses the LocalPlayer or PlayerController address, but we are not forced to do so. Digging deeper from the PlayerController, we see

Code: Select all

"Pawn
    -> PlayerState
        -> AbilitySystemComponent

Below that we find some interesting names, containing Health. In this case we see some curly brackets {}, meaning there are several values, which of course are displayed when you click on the brackets. Now, as we have reached the final interesting value, we want cheat engine to use it. So click on the "Copy to CE XML" Button in the Dumper.

Switch to Cheat Engine, press Ctrl-V and you will get a new Cheat Entry with a complete Structure from Gworld down to your value. You can then just drag and drop 95% of this structure (all below the "GWorld" just below your own "Gworld" Entry from our code injection we made earlier and you're done.

Adding all other interesting value then is simple clickmonkey work :)


User avatar
bbfox
Table Master
Table Master
Journeyman Hacker
Journeyman Hacker
Posts: 368
Joined: Sat Jul 23, 2022 8:59 am
Answers: 0
x 783

Re: [GUIDE] Guide: Cheating games with the unreal engine

Post by bbfox »

Marc wrote: Sun Jun 07, 2026 2:44 am

Trying to update the guide a little. :)

Main problem is that you'll have a away to the values you are interested in. So you take your unreal-tool of choice and try to find what you need - usually you want to find the "LocalPlayer" address. One way is to start at the GWorld address and then dig your way.

For example, when cheating Gothic 1, I used the UE5 tool from bbfox. Pressing the "start at gworld" does exactly that and you'll the the right address of Gworld. Add this to the table, check out which code accesses this very address and make a code injection.

Alternative way, only if GWorld AOB is detected (and AOB checkbox only works if start from GWorld)
You just check AOB, then use Copy CE Field form single column (I do not change drilldown depth in options, so no drilldown)
Copy CE XML, Copy CE Field will copy CE-acceptable XML data into clipboard

螢幕擷取畫面 2026-06-07 180907.png
螢幕擷取畫面 2026-06-07 180907.png (279.05 KiB) Viewed 38 times

Paste into CE:

螢幕擷取畫面 2026-06-07 181052.png
螢幕擷取畫面 2026-06-07 181052.png (31.07 KiB) Viewed 38 times

Lua code for GWorld is generated

Code: Select all

[ENABLE]
{$lua}
if syntaxcheck then return end

if not AOBScanModule then
  function AOBScanModule(moduleName, signature)
    local baseAddr = nil
    local maxAddr = 0
    local modList
    synchronize(function()
      modList = enumModules()
    end)
    for _, mod in ipairs(modList) do
      if string.lower(mod.Name) == string.lower(moduleName) then
        baseAddr = mod.Address
        maxAddr = baseAddr + mod.Size
        break
      end
    end
    if not baseAddr then return nil end
    local ms = createMemScan()
    synchronize(function()
      ms.firstScan(soExactValue, vtByteArray, nil, signature,
        nil, baseAddr, maxAddr, '+X-C-W', fsmNotAligned, '1', true, true, false, false)
    end)
    ms.waitTillDone()
    local results = createFoundList(ms)
    results.initialize()
    local addr
    synchronize(function()
      if results.getCount() > 0 then
        addr = results[0]
      end
    end)
    results.destroy()
    ms.destroy()
    return addr
  end
end

if not closeLuaEngine then
  function closeLuaEngine()
    synchronize(function()
      getLuaEngine().Close()
    end)
  end
end
registerLuaFunctionHighlight('closeLuaEngine')

local AOBs = {
  {name='GWorld → gworld_addr_F397BF', aob='48 8B 05 ?? ?? ?? ?? 48 8D 95 F8 01 00 00 48 8B 48 18 48 89 4D 48 48 8D 4D 48 E8', pos=3, aoblen=7, symbol='gworld_addr_F397BF'},
}

local module_name = process

for _, entry in ipairs(AOBs) do
  local aob_addr_str = AOBScanModule(module_name, entry.aob)
  if aob_addr_str then
    local aob_addr_val = tonumber(aob_addr_str, 16)
    local offset_addr = aob_addr_val + entry.pos
    local relative_offset = readInteger(offset_addr, true)
    local final_addr = relative_offset + aob_addr_val + entry.aoblen
    synchronize(function()
      unregisterSymbol(entry.symbol)
      registerSymbol(entry.symbol, final_addr)
    end)
    print(string.format('[SymbolScanner] %s registered at: %X', entry.name, final_addr))
  else
    print(string.format('[SymbolScanner] WARNING: AOB scan failed for %s', entry.name))
  end
end

closeLuaEngine()
{$asm}

[DISABLE]
{$lua}
if syntaxcheck then return end
unregisterSymbol('gworld_addr_F397BF')
closeLuaEngine()
{$asm}

Table is free to use, but need to leave the author's name and source URL: https://opencheattables.com.
Table will not be up-to-date. Feel free to modify it, but leave credit to the source.
Tip me a coffee? https://ko-fi.com/bbfoxmodding


User avatar
Marc
Table Master
Table Master
Journeyman Hacker
Journeyman Hacker
Posts: 214
Joined: Sat Jul 23, 2022 2:08 am
Answers: 0
x 327

Re: [GUIDE] Guide: Cheating games with the unreal engine

Post by Marc »

Ah, even better. Still learning how to use your tool to it's full potential :)


Post Reply