AgentStack
SKILL verified Apache-2.0 Self-run

Unreal5

skill-as0ler-skills-unreal5 · by as0ler

Unreal Engine 5 internal structures and memory layouts for reverse engineering. Covers UObject hierarchy, FNamePool, FUObjectArray, FProperty system, UFunction, FField, GWorld, Large World Coordinates, and key UE5 global arrays. Use this when analyzing UE5 game binaries.

No reviews yet
0 installs
11 views
0.0% view→install

Install

$ agentstack add skill-as0ler-skills-unreal5

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Unreal5? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Unreal Engine 5 Structures

Comprehensive reference for UE5 internal data structures used during reverse engineering. All offsets are for 64-bit builds and should be verified per game build — custom engine modifications and compiler padding may shift fields.

> Scope: UE5.x only (5.0–5.5+). UE4 uses different structures (e.g., TNameEntryArray instead of FNamePool, UProperty instead of FProperty).


1. Core Object System

1.1 UObjectBase

The true root of the hierarchy. UObject inherits from UObjectBase.

struct UObjectBase {
    void **VTableObject;         // 0x00 — virtual function table pointer
    EObjectFlags ObjectFlags;    // 0x08 — object flags (RF_Public, RF_Transactional, etc.)
    int32_t InternalIndex;       // 0x0C — index in GUObjectArray (FUObjectArray)
    UClass *ClassPrivate;        // 0x10 — pointer to this object's UClass (reflection metadata)
    FName NamePrivate;           // 0x18 — object name as FName (8 bytes: ComparisonIndex + Number)
    UObject *OuterPrivate;       // 0x20 — outer/owner object (package, level, etc.)
};
// sizeof(UObjectBase) = 0x28

Key notes:

  • ClassPrivate at 0x10 is the most important field for RE — it gives access to all reflection data
  • NamePrivate at 0x18 can be resolved to a string via FNamePool
  • InternalIndex at 0x0C is the object's slot in GUObjectArray

1.2 UObject

struct UObject : UObjectBase {
    // UObject adds no new data fields in UE5 — it adds virtual functions only
    // sizeof(UObject) = 0x28 (same as UObjectBase)
};

1.3 EObjectFlags (bitmask)

enum EObjectFlags : uint32_t {
    RF_NoFlags                  = 0x00000000,
    RF_Public                   = 0x00000001,
    RF_Standalone               = 0x00000002,
    RF_MarkAsNative             = 0x00000004,
    RF_Transactional            = 0x00000008,
    RF_ClassDefaultObject       = 0x00000010,  // This is a CDO
    RF_ArchetypeObject          = 0x00000020,
    RF_Transient                = 0x00000040,
    RF_MarkAsRootSet            = 0x00000080,
    RF_TagGarbageTemp           = 0x00000100,
    RF_NeedInitialization       = 0x00000200,
    RF_NeedLoad                 = 0x00000400,
    RF_KeepForCooker            = 0x00000800,
    RF_NeedPostLoad             = 0x00001000,
    RF_NeedPostLoadSubobjects   = 0x00002000,
    RF_NewerVersionExists       = 0x00004000,
    RF_BeginDestroyed           = 0x00008000,
    RF_FinishDestroyed          = 0x00010000,
    RF_BeingRegenerated         = 0x00020000,
    RF_DefaultSubObject         = 0x00040000,
    RF_WasLoaded                = 0x00080000,
    RF_TextExportTransient      = 0x00100000,
    RF_LoadCompleted            = 0x00200000,
    RF_InheritableComponentTemplate = 0x00400000,
    RF_DuplicateTransient       = 0x00800000,
    RF_StrongRefOnFrame         = 0x01000000,
    RF_NonPIEDuplicateTransient = 0x02000000,
    RF_WillBeLoaded             = 0x20000000,
    RF_HasExternalPackage       = 0x40000000,
};

2. Name System (FNamePool)

UE5 replaced UE4's TNameEntryArray with a bucket-based FNamePool.

2.1 FName

struct FName {
    FNameEntryId ComparisonIndex;  // 0x00 — index into FNamePool
    int32_t Number;                // 0x04 — instance number (0 = no suffix, >0 = "_N-1")
};
// sizeof(FName) = 0x08

Usage: Number == 0 means the base name. Number == 3 means the name has suffix _2 (Number - 1).

2.2 FNameEntryId

struct FNameEntryId {
    uint32_t Value;
    // Encodes:  Block index (upper bits) + Offset within block (lower bits)
    // Block  = Value >> FNameBlockOffsetBits
    // Offset = Value & ((1 > 16
offset = FNameEntryId.Value & 0xFFFF

2.3 FNamePool

struct FNamePool {
    FRWLock Lock;                              // 0x00 — reader-writer lock (8 bytes)
    uint32_t CurrentBlock;                     // 0x08 — current active block index
    uint32_t CurrentByteCursor;                // 0x0C — write cursor within current block
    FNameEntryAllocator_Block Blocks[8192];    // 0x10 — array of block pointers
    // Each Blocks[i] is a pointer to a contiguous allocation
};

2.4 FNameEntry

struct FNameEntry {
    uint16_t Header;
    // Header layout:
    //   Bit 0:     bIsWide (0 = ANSI/UTF-8, 1 = UTF-16)
    //   Bits 1-5:  ProbeHashBits (for case-insensitive lookup)  [UE 5.1+: Len stored differently]
    //   Bits 6-15: Len (string length, max 1024)
    //
    // Followed immediately by string data (no null terminator):
    //   if bIsWide:  char16_t Data[Len]
    //   else:        char     Data[Len]  (ANSI, not full UTF-8)
};

Reading an FNameEntry:

len     = Header >> 6
isWide  = Header & 1
strData = &entry + 2  (immediately after the 2-byte header)

Stride: Entries in FNamePool are aligned to 2-byte boundaries. The stride for addressing within a block is 2 bytes per unit (i.e., offset * 2 gives the byte offset within the block).

2.5 FName Resolution Procedure

1. Extract ComparisonIndex.Value from FName
2. block  = Value >> 16
3. offset = Value & 0xFFFF
4. blockBase = FNamePool.Blocks[block]  (read pointer)
5. entryAddr = blockBase + (offset * 2)
6. header = read uint16 at entryAddr
7. len = header >> 6
8. isWide = header & 1
9. strData = entryAddr + 2
10. Read len bytes (ANSI) or len * 2 bytes (wide) from strData

> Encryption warning: Some UE5 titles XOR/rotate FNameEntry headers or string data. If step 7 yields garbage lengths, reverse the FName::ToString or FName::AppendString function to find the decryption logic — typically a compile-time XOR constant.


3. Object Array (FUObjectArray / GObjects)

3.1 FUObjectArray

struct FUObjectArray {
    int32_t ObjFirstGCIndex;                       // 0x00
    int32_t ObjLastNonGCIndex;                      // 0x04
    int32_t MaxObjectsNotConsideredByGC;            // 0x08
    bool OpenForDisregardForGC;                     // 0x0C
    FChunkedFixedUObjectArray ObjObjects;            // 0x10 — the actual object storage
};

3.2 FChunkedFixedUObjectArray

struct FChunkedFixedUObjectArray {
    FUObjectItem **Objects;      // 0x00 — array of chunk pointers
    FUObjectItem *PreAllocated;  // 0x08 — pre-allocated chunk (may be null)
    int32_t MaxElements;         // 0x10
    int32_t NumElements;         // 0x14 — total live objects count
    int32_t MaxChunks;           // 0x18
    int32_t NumChunks;           // 0x1C
};
// Elements per chunk = 65536 (0x10000)

3.3 FUObjectItem

struct FUObjectItem {
    UObject *Object;             // 0x00 — pointer to the UObject (or null if slot is empty)
    int32_t Flags;               // 0x08 — internal GC flags
    int32_t ClusterRootIndex;    // 0x0C
    int32_t SerialNumber;        // 0x10
    // padding to 0x18
};
// sizeof(FUObjectItem) = 0x18

3.4 GObjects Traversal Procedure

1. Locate GUObjectArray global (exported or found via xrefs)
2. Read ObjObjects at offset 0x10 from GUObjectArray base
3. numElements = ObjObjects.NumElements (at ObjObjects + 0x14)
4. chunksBase = ObjObjects.Objects (at ObjObjects + 0x00, pointer to pointer array)
5. For index i = 0..numElements-1:
     chunkIndex  = i / 65536
     withinChunk = i % 65536
     chunkPtr    = read pointer at (chunksBase + chunkIndex * pointerSize)
     itemAddr    = chunkPtr + (withinChunk * 0x18)
     objPtr      = read pointer at itemAddr
     if objPtr != null:
       ClassPrivate = read pointer at (objPtr + 0x10)
       NamePrivate  = read FName at (objPtr + 0x18)

4. Reflection System

4.1 UField (legacy base)

struct UField : UObject {
    UField *Next;            // 0x28 — next field in linked list (legacy, used for UFunctions)
};
// sizeof(UField) = 0x30

4.2 UStruct

struct UStruct : UField {
    UStruct *SuperStruct;          // 0x30 — parent class/struct (inheritance chain)
    UField *Children;              // 0x38 — linked list of UField children (UFunctions only in UE5)
    FField *ChildProperties;       // 0x40 — UE5: FProperty chain (replaces UProperty for data fields)
    int32_t PropertiesSize;        // 0x48 — total byte size of instances of this struct
    int32_t MinAlignment;          // 0x4C — minimum required alignment
    TArray Script;        // 0x50 — Blueprint bytecode (for BP classes)
    FProperty *PropertyLink;       // 0x68 — linked list for fast iteration over all properties
    FProperty *RefLink;            // 0x70 — reference property list (for GC)
    FProperty *DestructorLink;     // 0x78 — properties needing destruction
    FProperty *PostConstructLink;  // 0x80 — properties needing post-construct init
    TArray ScriptAndPropertyObjectReferences; // 0x88
    // ... additional fields
};
// sizeof(UStruct) varies — typically ~0xB0

Important for RE:

  • SuperStruct at 0x30 lets you walk the inheritance chain
  • ChildProperties at 0x40 is the FProperty linked list — this is how you enumerate struct/class fields in UE5
  • Children at 0x38 still holds UFunctions
  • PropertiesSize at 0x48 tells you the instance size

4.3 UClass

struct UClass : UStruct {
    // Offsets below are approximate — verify per build
    UObject* (*ClassConstructor)(...);           // class constructor function pointer
    UObject* (*ClassVTableHelperCtorCaller)(...);
    FUObjectCppClassStaticFunctions ClassStaticFunctions;
    void (*ClassAddReferencedObjects)(UObject*, FReferenceCollector&);
    uint32_t ClassUnique;
    EClassFlags ClassFlags;                      // CLASS_Abstract, CLASS_Native, etc.
    EClassCastFlags ClassCastFlags;              // quick type-checking bitmask
    UClass *ClassWithin;                         // required outer class
    UObject *ClassGeneratedBy;                   // Blueprint that generated this class (or null)
    FName ClassConfigName;                       // config file name
    TArray ClassReps;                // net replication info
    TArray NetFields;                   // network-relevant fields
    UObject *ClassDefaultObject;                 // CDO — the default template instance
    // ...
};

Key fields for RE:

  • ClassDefaultObject (CDO) — read default property values from here
  • ClassFlags — check for CLASS_Abstract, CLASS_Native, CLASS_Config
  • ClassCastFlags — fast IsA() check for common types (AActor, APawn, UActorComponent, etc.)

4.4 EClassCastFlags (bitmask — commonly checked types)

enum EClassCastFlags : uint64_t {
    CASTCLASS_None                  = 0x0000000000000000,
    CASTCLASS_UField                = 0x0000000000000001,
    CASTCLASS_FInt8Property         = 0x0000000000000002,
    CASTCLASS_UEnum                 = 0x0000000000000004,
    CASTCLASS_UStruct               = 0x0000000000000008,
    CASTCLASS_UScriptStruct         = 0x0000000000000010,
    CASTCLASS_UClass                = 0x0000000000000020,
    CASTCLASS_FByteProperty         = 0x0000000000000040,
    CASTCLASS_FIntProperty          = 0x0000000000000080,
    CASTCLASS_FFloatProperty        = 0x0000000000000100,
    CASTCLASS_FUInt64Property       = 0x0000000000000200,
    CASTCLASS_FClassProperty        = 0x0000000000000400,
    CASTCLASS_FUInt32Property       = 0x0000000000000800,
    CASTCLASS_FInterfaceProperty    = 0x0000000000001000,
    CASTCLASS_FNameProperty         = 0x0000000000002000,
    CASTCLASS_FStrProperty          = 0x0000000000004000,
    CASTCLASS_FProperty             = 0x0000000000008000,
    CASTCLASS_FObjectProperty       = 0x0000000000010000,
    CASTCLASS_FBoolProperty         = 0x0000000000020000,
    CASTCLASS_FUInt16Property       = 0x0000000000040000,
    CASTCLASS_UFunction             = 0x0000000000080000,
    CASTCLASS_FStructProperty       = 0x0000000000100000,
    CASTCLASS_FArrayProperty        = 0x0000000000200000,
    CASTCLASS_FInt64Property        = 0x0000000000400000,
    CASTCLASS_FDelegateProperty     = 0x0000000000800000,
    CASTCLASS_FNumericProperty      = 0x0000000001000000,
    CASTCLASS_FMulticastDelegateProperty = 0x0000000002000000,
    CASTCLASS_FObjectPropertyBase   = 0x0000000004000000,
    CASTCLASS_FWeakObjectProperty   = 0x0000000008000000,
    CASTCLASS_FLazyObjectProperty   = 0x0000000010000000,
    CASTCLASS_FSoftObjectProperty   = 0x0000000020000000,
    CASTCLASS_FTextProperty         = 0x0000000040000000,
    CASTCLASS_FInt16Property        = 0x0000000080000000,
    CASTCLASS_FDoubleProperty       = 0x0000000100000000,
    CASTCLASS_FSoftClassProperty    = 0x0000000200000000,
    CASTCLASS_UPackage              = 0x0000000400000000,
    CASTCLASS_ULevel                = 0x0000000800000000,
    CASTCLASS_AActor                = 0x0000001000000000,
    CASTCLASS_APlayerController     = 0x0000002000000000,
    CASTCLASS_APawn                 = 0x0000004000000000,
    CASTCLASS_USceneComponent       = 0x0000008000000000,
    CASTCLASS_UPrimitiveComponent   = 0x0000010000000000,
    CASTCLASS_USkinnedMeshComponent = 0x0000020000000000,
    CASTCLASS_USkeletalMeshComponent= 0x0000040000000000,
    CASTCLASS_UBlueprint            = 0x0000080000000000,
    CASTCLASS_UDelegateFunction     = 0x0000100000000000,
    CASTCLASS_UStaticMeshComponent  = 0x0000200000000000,
    CASTCLASS_FMapProperty          = 0x0000400000000000,
    CASTCLASS_FSetProperty          = 0x0000800000000000,
    CASTCLASS_FEnumProperty         = 0x0001000000000000,
    CASTCLASS_USparseDelegateFunction = 0x0002000000000000,
    CASTCLASS_FMulticastInlineDelegateProperty = 0x0004000000000000,
    CASTCLASS_FMulticastSparseDelegateProperty = 0x0008000000000000,
    CASTCLASS_FFieldPathProperty    = 0x0010000000000000,
    CASTCLASS_FObjectPtrProperty    = 0x0020000000000000,  // UE5: TObjectPtr
    CASTCLASS_FClassPtrProperty     = 0x0040000000000000,  // UE5: TClassPtr
    CASTCLASS_FLargeWorldCoordinatesRealProperty = 0x0080000000000000, // UE5 LWC
};

5. FField / FProperty System (UE5)

UE5 replaced UProperty (which was a full UObject) with lightweight FField/FProperty objects. These are not in GUObjectArray — they are allocated separately and linked from UStruct::ChildProperties.

5.1 FFieldClass

struct FFieldClass {
    FName Name;                      // 0x00 — type name (e.g., "StructProperty", "FloatProperty")
    uint64_t Id;                     // 0x08 — unique type ID
    uint64_t CastFlags;             // 0x10 — CASTCLASS_* bitmask for fast type checks
    EClassFlags ClassFlags;          // 0x18
    FFieldClass *SuperClass;         // 0x20 — parent FFieldClass
    // ...
};

5.2 FField

struct FField {
    void **VTableObject;             // 0x00 — vtable
    FFieldClass *ClassPrivate;       // 0x08 — type descriptor (FFieldClass)
    FFieldVariant Owner;             // 0x10 — union: owning UStruct* or FField*
                                     //         FFieldVariant = { void* Value; bool bIsUObject; }
                                     //         sizeof = 0x10 (pointer + bool + padding)
    FField *Next;                    // 0x20 — next in linked list
    FName NamePrivate;               // 0x28 — property name
    EObjectFlags FlagsPrivate;       // 0x30
};
// sizeof(FField) = 0x38

5.3 FProperty

struct FProperty : FField {
    int32_t ArrayDim;                // 0x38 — static array dimension (usually 1)
    int32_t ElementSize;             // 0x3C — size of a single element
    EPropertyFlags PropertyFlags;    // 0x40 — CPF_* flags (uint64_t)
    uint16_t RepIndex;               // 0x48 — replication index
    uint16_t BlueprintReplicationCondition; // 0x4A
    int32_t Offset_Internal;         // 0x4C — byte offset of this property within the owning struct instance
    FName RepNotifyFunc;             // 0x50 — name of OnRep function (if replicated)
    FProperty *PropertyLinkNext;     // 0x58 — next in UStruct::PropertyLink chain
    FProperty *NextRef;              // 0x60 — next

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [as0ler](https://github.com/as0ler)
- **Source:** [as0ler/skills](https://github.com/as0ler/skills)
- **License:** Apache-2.0

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.