ios-ue4-resource · discussions · github.com/shiedless

ios-ue4-re

reverse engineering and building read-only overlays for Unreal Engine 4 games on iOS (arm64 / arm64e)

engine platform scope license


Notes and a working example for reverse engineering and building overlays for Unreal Engine 4 games on iOS. This is the stuff I kept re-explaining to people, collected in one place, plus a small tweak that puts all of it together so you can see it actually run instead of just reading about it.

Read-only, analysis-and-visualization oriented. No memory writes into the game, no netcode tampering. If you want to learn how a UE4 iOS overlay is put together, start here.


the example

Reveal is a ~500-line skeleton ESP. It reads GWorld, walks the actors, pulls each character’s bone pose straight out of the skeletal mesh, projects the joints to screen and draws a figure. That is the whole thing — deliberately tiny so the data path is legible end to end, and the concrete version of every note below.

flowchart LR
    gw["GWorld"] --> actors["walk actors"]
    actors --> pose["bone pose<br/>from skeletal mesh"]
    pose --> proj["project joints<br/>to screen"]
    proj --> draw["draw the figure"]

    style gw fill:#C7192E,color:#fff
    style draw fill:#1f6feb,color:#fff

the notes

Read them in this order if you’re new — each one leans on the last.

flowchart TD
    n1["1 · ios-binary-re-notes<br/>decrypt · slice · load · read"]
    n2["2 · xor-string-deobf-notes<br/>break the string obfuscation"]
    n3["3 · arm64-ios-inline-hook-notes<br/>W^X · reloc · icache · PAC"]
    n4["4 · ue4-ios-gworld-gnames-notes<br/>the two globals + anti-tamper"]
    n5["5 · ue4-ios-fname-notes<br/>FName index -> string"]
    n6["6 · ue4-ios-processevent-notes<br/>the UFunction call funnel"]
    n7["7 · tencent-ace-anogs-notes<br/>ACE, and why naive attacks fail"]

    n1 --> n2 --> n4 --> n5 --> n6
    n3 -.->|needed to hook at all| n6
    n4 --> n7

    style n1 fill:#000,color:#fff
    style n4 fill:#C7192E,color:#fff
    style n7 fill:#222,color:#fff
# note what it covers
1 ios-binary-re-notes getting a decrypted binary, picking the right slice, loading it, and reading an iOS app at all — the groundwork
2 xor-string-deobf-notes breaking the XOR string obfuscation you hit the moment the app hides anything
3 arm64-ios-inline-hook-notes inline hooks by hand — W^X, instruction relocation, the icache, PAC — the four things that crash you
4 ue4-ios-gworld-gnames-notes finding the two globals everything hangs off, and the anti-tamper traps around them
5 ue4-ios-fname-notes turning an FName index into a string, which you need to match anything by name
6 ue4-ios-processevent-notes finding ProcessEvent, the funnel every UFunction call goes through
7 tencent-ace-anogs-notes how Tencent’s ACE anti-cheat is built and why the naive attacks on it fail — analysis, not a bypass

what you need

   
device a jailbroken iOS device (or a solid emulator/sim setup) to run and dump on
build Theos for building tweaks
static IDA, Ghidra or Binary Ninja
background a rough grip on ARM64 assembly and C/C++

None of the notes assume Windows-only tooling, which most UE RE guides quietly do.


how the pieces fit

The short version of the whole workflow:

Get a decrypted binary (ios-binary-re-notes). Load it, skim the Objective-C metadata and strings to map the surface. If the app hides its strings, break the XOR (xor-string-deobf-notes). Find GNames and GWorld (ue4-ios-gworld-gnames-notes), then you can resolve names (ue4-ios-fname-notes) and walk the live scene. From there an overlay is just reading the world and drawing it — which is what Reveal does. If you need to react to game events instead of just reading state, hook ProcessEvent (ue4-ios-processevent-notes), and if you need to hook code at all, do it without crashing (arm64-ios-inline-hook-notes). If the game has ACE, know what you’re walking into (tencent-ace-anogs-notes).

flowchart LR
    dec["decrypted binary"] --> map["map the surface<br/>objc metadata + strings"]
    map -->|hidden strings| xor["break XOR"]
    map --> glob["find GWorld / GNames"]
    xor --> glob
    glob --> name["resolve FName -> string"]
    name --> walk["walk the live scene"]
    walk --> overlay["read + draw<br/>(Reveal)"]
    walk -.->|react to events| pe["hook ProcessEvent"]
    pe -.->|hook safely| hook["inline hook: W^X · PAC"]

    style glob fill:#C7192E,color:#fff
    style overlay fill:#1f6feb,color:#fff

a note on intent

This is for learning how these systems work and building read-only tools on top of them. The anti-cheat writeup in particular stops at understanding on purpose. Do what you want with the knowledge, but the repos themselves don’t ship attacks.


beyond ue4

Same approach, other engines and tools:

repo what it covers
unity-il2cpp-esp-tutorial the unity il2cpp side — a native objc overlay from dump.cs to screen, plain uikit
roblox-ios-luau-vm-notes reversing roblox’s luau runtime on iOS: functions, anchors, lua_State layout
ios-messiah-re netease’s messiah engine: an ecs with no GWorld, a python gameplay layer, telemetry anti-cheat
ida-pro-guide getting around a binary in IDA — useful for every note above

questions and corrections

If the notes saved you time, a ⭐ on the repo helps other people find them.


license

MIT across the board.


— shiedless