Ajouter Home
118
Home.md
Normal file
118
Home.md
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
# Finding offsets opcode access signature
|
||||||
|
|
||||||
|
As soon as we have generated a SDK with Dumper-7, we have to open the Basic.hpp file generated in order to get the offsets.
|
||||||
|
They look like this :
|
||||||
|
```
|
||||||
|
namespace Offsets
|
||||||
|
|
||||||
|
{
|
||||||
|
constexpr int32 GObjects = 0x092F8D70;
|
||||||
|
constexpr int32 AppendString = 0x01273B00;
|
||||||
|
constexpr int32 GNames = 0x092155C0;
|
||||||
|
constexpr int32 GWorld = 0x090C7008;
|
||||||
|
constexpr int32 ProcessEvent = 0x0149DC80;
|
||||||
|
constexpr int32 ProcessEventIdx = 0x0000004F;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
These offsets will vary with game' updates and thus can't be used as static in our code because SDK functions call will make the game to **crash** sooner or later.
|
||||||
|
|
||||||
|
So the workaround here is to search for opcode that access them (load the address pointed by the offset).
|
||||||
|
Typical opcode address loading by offset looks like these :
|
||||||
|
`lea rax,["HellIsUs-Win64-Shipping.exe"+92155C0]`
|
||||||
|
`mov rax, ["HellIsUs-Win64-Shipping.exe"+92155C0]`
|
||||||
|
`mov eax, ["HellIsUs-Win64-Shipping.exe"+92155C0]`
|
||||||
|
|
||||||
|
We will need a Cheat Engine lua script in order to find an opcode accessing the offset.
|
||||||
|
`local MODNAME = "HellIsUs-Win64-Shipping.exe"` has to be modified with the game executable name
|
||||||
|
`local OFFSET_HEX` has to be modified with the Unreal Engine offset we look for found in Basic.hpp
|
||||||
|
As soon as the script has pointed an address with the opcode accessing the offset, we can generate a unique AOB signature.
|
||||||
|
For code to be used see below :
|
||||||
|
```
|
||||||
|
-- Lua script for Cheat Engine
|
||||||
|
-- Scanne plusieurs patterns RIP-relative et ajoute "GNames_ptr" si le match correspond
|
||||||
|
|
||||||
|
local MODNAME = "HellIsUs-Win64-Shipping.exe"
|
||||||
|
local OFFSET_HEX = 0x92155C0
|
||||||
|
local SIG_SCAN_FLAGS = "+X-C-W" -- sections exécutables uniquement
|
||||||
|
local SIGNATURES = {
|
||||||
|
{pattern="48 8D 05 ?? ?? ?? ??", dispOffset=3, instrLen=7}, -- lea rax,[rip+disp32]
|
||||||
|
{pattern="48 8B 05 ?? ?? ?? ??", dispOffset=3, instrLen=7}, -- mov rax,[rip+disp32]
|
||||||
|
{pattern="8B 05 ?? ?? ?? ??", dispOffset=2, instrLen=6}, -- mov eax,[rip+disp32]
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Helper: lit un int32 little-endian safe
|
||||||
|
local function safeReadInt32(addr)
|
||||||
|
local ok, b = pcall(readBytes, addr, 4, true)
|
||||||
|
if not ok or not b or #b < 4 then return nil end
|
||||||
|
local val = b[1] | (b[2] << 8) | (b[3] << 16) | (b[4] << 24)
|
||||||
|
if val >= 0x80000000 then val = val - 0x100000000 end
|
||||||
|
return val
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Helper: trouve module
|
||||||
|
local function findModule(name)
|
||||||
|
local mods = enumModules()
|
||||||
|
if not mods then return nil end
|
||||||
|
for i, m in ipairs(mods) do
|
||||||
|
if m.Name == name then
|
||||||
|
return {base = m.Address, size = m.Size}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Récup module
|
||||||
|
local mod = findModule(MODNAME)
|
||||||
|
if not mod then
|
||||||
|
print("Module non trouvé : " .. MODNAME)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local moduleBase = mod.base
|
||||||
|
local targetAddr = moduleBase + OFFSET_HEX
|
||||||
|
print(string.format("Module trouvé: %s base=0x%X size=0x%X", MODNAME, moduleBase, mod.size))
|
||||||
|
print(string.format("Recherche offset cible = 0x%X", targetAddr))
|
||||||
|
|
||||||
|
local found = false
|
||||||
|
|
||||||
|
for _, sig in ipairs(SIGNATURES) do
|
||||||
|
local matches = AOBScan(sig.pattern, SIG_SCAN_FLAGS)
|
||||||
|
if matches then
|
||||||
|
for i=0, matches.Count-1 do
|
||||||
|
local addr = tonumber(matches[i],16)
|
||||||
|
if addr then
|
||||||
|
local disp32 = safeReadInt32(addr + sig.dispOffset)
|
||||||
|
if disp32 then
|
||||||
|
local resolved = (addr + sig.instrLen) + disp32
|
||||||
|
if resolved == targetAddr then
|
||||||
|
found = true
|
||||||
|
print(string.format("Match trouvé à 0x%X -> résolu = 0x%X", addr, resolved))
|
||||||
|
|
||||||
|
-- Ajoute à la table
|
||||||
|
local al = getAddressList()
|
||||||
|
local mr = al.createMemoryRecord()
|
||||||
|
mr.Description = "Offset pointer"
|
||||||
|
mr.Address = string.format("%X", resolved)
|
||||||
|
mr.Type = vtQword
|
||||||
|
mr.Active = true
|
||||||
|
|
||||||
|
-- Enregistre symbole pour Auto Assembler
|
||||||
|
pcall(function() registerSymbol("Offset pointer", resolved, true) end)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
matches.destroy()
|
||||||
|
if found then break end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not found then
|
||||||
|
print("Aucun match valide trouvé pour Offset pointer.")
|
||||||
|
else
|
||||||
|
print("Adresse ajoutée sous le nom 'Offset pointer'.")
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
Reference in New Issue
Block a user