UE4SS-RE / RE-UE4SS

Injectable LUA scripting system, SDK generator, live property editor and other dumping utilities for UE4/5 games
http://docs.ue4ss.com/
MIT License
1.36k stars 185 forks source link

How do I get GMalloc using x64dbg? #665

Open Betterlin opened 2 months ago

Betterlin commented 2 months ago

Branch or Release zDEV-UE4SS v3.0.1

Game and Engine Version UE4SSTestDemo- UE v5.3.2

Describe the bug How do I get GMalloc using x64dbg? I don't know how to search for it, better have a screenshot demo. please

Mods directory

To Reproduce

Expected behavior

Screenshots, UE4SS Log, and .dmp file UE4SS.log

Desktop (please complete the following information):

Additional context Add any other context about the problem here.

TimeMaster18 commented 1 month ago

I have to agree, the 6.1 Section of the Guide is extremely hard to follow.

It seems like it expects you to know a lot of things to even understand what you need to do.

narknon commented 1 month ago

It requires reverse engineering knowledge. It's not something for which we can just make an encompassing guide. There are docs for 64dbg.

TimeMaster18 commented 1 month ago

It requires reverse engineering knowledge. It's not something for which we can just make an encompassing guide. There are docs for 64dbg.

That's obvious now, but not stated there:

For this guide you'll need to know what a root directory and working directory is. A root directory is always the directory that contains ue4ss.dll. A working directory is either the directory that contains ue4ss.dll OR a game specific directory, for example /SatisfactoryEarlyAccess

I'm a software engineer and familiar with modding (just not this specific type) and the listed "general steps" are quite unfortunate in my humble opinion.

But I won't be another annoying user that only complaining about a tool made voluntarily and open-source for the community. So here goes my best try at helping out:

Make a blank shipped game in your game's UE version, with PDBs This alone already involves several steps:

  1. Get your game UE version. UE4SS detects it. But it can also be checked by using right-click on the .exe in Binaries, opening properties and checking on the details tab. In this case 5.3.2.0
  2. Create an Epic Games account
  3. Download Epic Games Launcher
  4. In the launcher at the left side, go to Unreal Engine, Library tab at the top and Install engine version 5.3.2
  5. Once installed Launch Unreal Engine 5.3.2. Games tab -> Select Blank -> Uncheck Starter Content (Optional to set a Project Name / change location) -> Create
  6. (Assuming Windows OS) Press Platforms button on the top bar -> Packaging Settings -> Check "Include Debug Files in Shipping Builds
  7. Press Platforms button on the top bar ->Windows -> Select "Shipping" (or the one that applies to your game build) -> Package Project and select a folder
  8. Check that the newly packaged blank project contains a .exe along with a .pdb in Binaries in the selected folder

Read game's memory using x64dbg

  1. Install https://[x64dbg](https://x64dbg.com/).com/
  2. Run the .exe at the root folder of the newly packaged blank project (Running the .exe in Binaries might throw an error, running from root works too either way)
  3. Open x64dbg -> File -> Attach -> Select the newly packaged blank project .exe (The one with the path at Binaries)

Look for the signature you need - those can be found below

  1. (Optional but recommended) Connect Epic Games with Github. Login in the Epic Games Website -> Manage Account -> Apps and Accounts -> Github -> Once done, check email and accept invitation to the UE project
  2. (Optional but recommended) Check the source code for the function that is intended to be found in memory. In this case here: https://github.com/EpicGames/UnrealEngine/blob/5.3.2-release/Engine/Source/Runtime/Core/Public/HAL/FMemory.inl#L142
  3. In x64dbg go to Symbols tab -> In the left window select the .exe -> Under the right window search for the function (in this case "FMemory::Free") -> Double click the found Function in the right window
  4. You should be now back at the CPU tab with the address in memory of the start of the selected function

Grab a copy of the bytes from that function, sometimes the header is enough. If it is not, it may be better to grab a call to the function and if it's not a virtual function, you can grab the RIP address there

  1. (Optional but recommended) Install Baymax ToOls plugin for x64dbg
  2. Select some (This is where it is not the same for every game and required magic/"knowledge" starts) address lines -> Right Click -> Copy -> Selection or Selection (Bytes only)
  3. If Baymax ToOls installed, while selecting all the addresses lines composing the function -> Right Click -> Baymax ToOls -> Copy Signature.
  4. Might want to copy both selection types and save them in a file for comparison and reference.

Some context and definitions:

In this context, a Signature refers to a unique sequence or pattern of bytes used to identify a function or piece of code within a binary, such as specific instructions or constants that are unlikely to appear elsewhere. It serves as a recognizable "fingerprint" to locate a particular routine during reverse engineering or patching.

In contrast, a Block of Bytes is simply a contiguous sequence of raw data or instructions without any specific identification purpose. A block of bytes may or may not represent anything meaningful or unique, whereas a signature is carefully chosen to reliably distinguish a particular function or code segment.

RIP (Instruction Pointer Register) is a register in x86-64 architecture that holds the address of the next instruction to be executed. It plays a key role in managing program flow, enabling the CPU to keep track of where it is in the program code.

Open your game's memory in x64dbg and search it for the same block of bytes If you find it, you can use the swiss army knife tool to extract the AOB for it which you can use in a simple script such as example here

  1. Open the game you want to mod
  2. Attach x64dbg as seen before with the blank project
  3. Search for the saved block of bytes found in the last step
  4. (If nothing found) Search for the pattern from Baymax ToOls
  5. (If nothing found) Try searching parts of the block of bytes (or signature from Baymax ToOls) and compare the addresses block with the one from the blank project.
  6. If nothing found, I don't know. It's beyond my knowledge for now
  7. If found a good match -> Create the lua script to retrieve the address of the function/variable required. -> Put it in UE4SS_Signatures folder in the Binaries of your game folder where UE4SS was installed.
  8. Run the game and UE4SS hopefully works now (Spoiler: In my case it doesn't and gives no error, so no clue what happens)

In my case GMalloc.lua:

function Register()
    return "48 8B D9 48 8B 0D ?? ?? ?? ?? 48 85 C9 75 0C E8 ?? ?? ?? ??"
end

function OnMatchFound(MatchAddress)
    -- Address of the first mov instruction that loads GMalloc
    local MovInstr = MatchAddress + 0x03  -- Offset to the mov instruction with GMalloc

    -- Offset value is encoded after the instruction opcode (3 bytes after the start of the mov)
    local Offset = DerefToInt32(MovInstr + 0x3)

    -- Calculate the address of GMalloc using RIP-relative addressing
    local RIP = MovInstr + 0x7  -- Address of the next instruction
    local GMallocAddress = RIP + Offset

    return GMallocAddress
end

I even did an extra step as debug to go back to running the blank project and attaching x64dbg and calculating manually the Address wanted from the signature used in Lua for the game to mod. (Calculated manually the GMalloc address from the Free function) Then setting the address in GMalloc.lua for the blank project and checking that the Address found is the same as the one auto-detected from UE4SS when running it in the blank project. And it was a match!

Note: It's my first time using x64dbg, reverse engineering the game attached and first time using lua. Note2: My solution doesn't work for me, I have no clue why. UE4SS gives no useful error so far (it did show other errors when I messed up the lua script or other issues though). Note3: ChatGPT was quite useful in most of the steps, specially with the Lua script and explaining some terms.

Buckminsterfullerene02 commented 1 week ago

We would really appreciate it if you could make a PR for the docs and add all this useful information yourself! If you don't want to bother (no problemo), could we add it in ourselves? Cheers

Also, can this issue be closed?