> For the complete documentation index, see [llms.txt](https://0x29a.gitbook.io/0x29a-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://0x29a.gitbook.io/0x29a-docs/memory-and-analysis/mem.md).

# mem

**memory · SEH-guarded · global: `mem`**

Reading, writing and scanning the target process's memory. Every address is an `integer` (Lua number). Access failures never crash the process — read functions return `0`/`nil`/an empty string depending on the case, and write functions return `false`.

## Reading

### `mem.read(addr, size) -> string`

Reads `size` raw bytes from `addr` and returns them as a binary string.

### `mem.read_u8(addr) -> integer`

### `mem.read_u16(addr) -> integer`

### `mem.read_u32(addr) -> integer`

### `mem.read_u64(addr) -> integer`

### `mem.read_i32(addr) -> integer`

### `mem.read_f32(addr) -> number`

### `mem.read_f64(addr) -> number`

### `mem.read_ptr(addr) -> integer`

Reads a pointer (8 bytes on x64).

These eight are the **hot path**: they use `Memory::ReadFast`, with no `VirtualQuery` call, meant for per-frame reads (bones, position, HP). On a page fault they return `0` instead of propagating an error.

### `mem.read_vec3(addr) -> x, y, z`

Reads 3 consecutive floats in a single native call — avoids 3 round trips across the Lua↔C boundary when reading a whole `Vector`.

```lua
local x, y, z = mem.read_vec3(entity + 0x14)
```

### `mem.read_str(addr [, maxlen=256]) -> string`

Reads a NUL-terminated ASCII string, up to `maxlen` bytes.

### `mem.read_wstr(addr [, maxlen=256]) -> string`

Reads a NUL-terminated UTF-16LE string and converts it to UTF-8.

## Writing

### `mem.write(addr, bytes) -> bool`

Writes the binary string `bytes` at `addr`.

### `mem.write_u8(addr, v) -> bool`

### `mem.write_u16(addr, v) -> bool`

### `mem.write_u32(addr, v) -> bool`

### `mem.write_u64(addr, v) -> bool`

### `mem.write_i32(addr, v) -> bool`

### `mem.write_f32(addr, v) -> bool`

### `mem.write_f64(addr, v) -> bool`

### `mem.write_str(addr, str [, with_null=true]) -> bool`

Writes `str` at `addr`; by default also writes the NUL terminator right after.

### `mem.write_wstr(addr, str) -> bool`

Converts `str` (UTF-8) to UTF-16LE and writes it, including the NUL.

## Pointers & buffers

### `mem.deref(base, off1 [, off2, ...]) -> addr | nil`

Follows a pointer chain: reads `*(base+off1)`, uses the result as the base for `off2`, and so on. Returns `nil` at the first step that fails to read.

```lua
local hp_addr = mem.deref(local_player, 0xF0, 0x334)
```

### `mem.copy(dst, src, n) -> bool`

Copies `n` bytes from `src` to `dst` (reads then writes — not atomic).

### `mem.fill(addr, byte, n) -> bool`

Fills `n` bytes starting at `addr` with `byte` (0–255).

### `mem.compare(a, b, n) -> bool`

Compares `n` bytes at `a` and `b`; `true` if they're identical.

### `mem.is_readable(addr [, size=1]) -> bool`

Checks whether the region is readable before attempting a more expensive read.

## Allocation & protection

### `mem.alloc(size [, protect=mem.EXECUTE_READWRITE]) -> addr`

Allocates `size` bytes in the target process with `VirtualAlloc`.

### `mem.free(addr)`

Frees memory allocated with `mem.alloc`.

### `mem.protect(addr, size, prot) -> old_protect | nil`

Calls `VirtualProtect`; returns the previous protection, handy for restoring it later.

Protection constants are available as `mem.NOACCESS`, `mem.READONLY`, `mem.READWRITE`, `mem.EXECUTE`, `mem.EXECUTE_READ`, `mem.EXECUTE_READWRITE`.

## Calling native functions

### `mem.call(addr, a1, a2, ... ) -> result | (nil, "fault")`

Invokes a native function at `addr` using the Microsoft x64 calling convention, with up to **12 arguments**. Dispatches by arity and is SEH-guarded — a bad address or wrong signature returns `nil, "fault"` instead of killing the process.

Lua → native argument conversion:

| Lua type  | Becomes                                                   |
| --------- | --------------------------------------------------------- |
| `number`  | `uint64` (address/integer)                                |
| `string`  | pointer to a NUL-terminated copy, kept alive for the call |
| `boolean` | `0`/`1`                                                   |
| `nil`     | `0`                                                       |

```lua
local ret, err = mem.call(some_func_addr, this_ptr, 1, "hello")
if not ret then print("call failed:", err) end
```

{% hint style="warning" %}
Every argument is passed as a 64-bit integer/pointer — there's no support for a `float`/`double` argument, nor for non-integer (SSE) calling conventions. For functions with floating-point arguments, prefer a hook (see [hook](/0x29a-docs/runtime/hook.md)) instead of `mem.call`.
{% endhint %}

## Memory introspection

### `mem.hex(addr, size) -> string`

Returns the bytes at `addr` as a hex string (`"48 8B 05 ..."`).

### `mem.modules() -> [{name, base, size}]`

Lists every module loaded in the process.

### `mem.module(name_or_nil) -> {name, base, size} | nil`

Looks up a module by name. `nil` or `""` returns the main executable.

```lua
local m = mem.module(nil)       -- main .exe
local u = mem.module("user32.dll")
```

### `mem.query(addr) -> {base, size, state, type, protect}`

Mirrors `VirtualQuery` — useful before scanning an unknown region.

### `mem.scan_value(value, type_str [, start, size]) -> [addr]`

Scans for an exact value. `type_str` is one of `"u8" "u16" "u32" "u64" "i32" "f32" "f64"`. Without `start`/`size`, scans every loaded module.

```lua
local hits = mem.scan_value(100, "i32")   -- e.g. looking for "100 HP"
```

### `mem.strings(addr, size [, minlen=4]) -> [{addr, str}]`

Finds printable ASCII strings inside the region, at least `minlen` characters long.

## Structs

### `mem.struct(addr, layout) -> table`

Reads multiple fields of a native struct in a single call, from a declarative description.

```lua
local player = mem.struct(entity_addr, {
    { "health",  "i32", 0x100 },
    { "team",    "u8",  0x104 },
    { "name",    "str", 0x110, 32 },   -- 4th element = max length (str/wstr)
})

print(player.health, player.team, player.name)
```

Supported types: `u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 ptr bool str wstr`. The 4th element of each field (length) is only used by `str`/`wstr` (default 64).

***

See also [disasm](/0x29a-docs/memory-and-analysis/disasm.md) and [sig](/0x29a-docs/memory-and-analysis/sig.md) to locate the addresses these functions will read/write.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://0x29a.gitbook.io/0x29a-docs/memory-and-analysis/mem.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
