Skip to content

Code Features

Gabriel edited this page Sep 26, 2023 · 2 revisions

Table of contents

Memory

Reading

The following functions are exposed for reading from a memory address;

char[] Read(IntPtr address, IntPtr count);

T Read<T>(long address) where T : unmanaged
T Read<T>(IntPtr address) where T : unmanaged

Examples

// Read a float value from the specified memory location and output it to the console.
Console.WriteLine(Read<float>(myLocation));

Writing

The following functions are exposed for writing to a memory address;

void Write<T>(long address, T data) where T : unmanaged
void Write<T>(long address, params T[] data) where T : unmanaged

// Use WriteProtected for writing data to protected memory pages.
void WriteProtected<T>(long address, T data) where T : unmanaged
void WriteProtected<T>(long address, params T[] data) where T : unmanaged

Examples

// Write a 64-bit integer with the value of 1337 at the specified memory location.
Write<long>(myLocation, 1337); // Implicit
Write(myLocation, 1337L);      // Explicit

// Write a byte with the value of 5 at the specified memory location.
Write<byte>(myLocation, 5); // Implicit
Write(myLocation, (byte)5); // Explicit

// Write an array of bytes at the specified memory location.
Write<byte>(myLocation, new byte[] { 1, 3, 3, 7 }); // Implicit
Write(myLocation, new byte[] { 1, 3, 3, 7 });       // Explicit

Assembly injection

Codes have functions for assembling x86-64 code at runtime and injecting it.

The following functions are used for hooking assembly code;

// instructions:         The instructions to assemble.
// address:              The address to insert the hook at.
// behavior (optional):  The behavior of the hooked code (see HookBehavior enum below).
// parameter (optional): The execution mode of the hooked code (see HookParameter enum below).
void WriteAsmHook(string instructions, long address, HookBehavior behavior, HookParameter parameter);
void WriteAsmHook(long address, HookBehavior behavior, params string[] instructions);

// HookBehavior.Before:  Write a jump/call to the custom code before the original code is done.
// HookBehavior.After:   Write a jump/call to the custom code after the original code is done (default).
// HookBehavior.Replace: Write a jump/call over the original code, replacing it entirely (recommended if the original code contains jumps and calls).
public enum HookBehavior
{
    Before, After, Replace
}

// HookParameter.Jump: Jump to the custom code (default).
// HookParameter.Call: Call the custom code as its own function.
public enum HookParameter
{
    Jump, Call
}

A hook will replace an instruction at the starting address with a jmp/call instruction (depending on HookParameter) to the custom code in memory. Please be wary of the length of this instruction when using hooks to ensure the original code will still be valid once jumped back into.

  • 32-bit jmp is 5 bytes.
  • 64-bit jmp is 14 bytes.

Examples

// Writes a mid-asm hook at the specified address that replaces the original code.
WriteAsmHook
(
    @"
        mov eax, eax
        xor eax, eax
    ",

    myHookLocation,

    HookBehavior.Replace
);

// Writes a mid-asm hook at the specified address that executes after the original code.
WriteAsmHook(myHookLocation, HookBehavior.After, "mov eax, eax", "xor eax, eax");

Signature scanning

Codes have support for scanning memory for code-style patterns (added in v1.2).

The following functions are available;

// Pattern length must be equal to mask length.
IntPtr ScanSignature(byte[] pattern, string mask);
long ScanSignature(string pattern, string mask);

Examples

// Write a NOP instruction where the pattern matches.
WriteNop(ScanSignature("\xAA\xBB\xCC\x00\xDD\xEE", "xxx?xx"), 1);

Preprocessor

Codes use extended preprocessor features that aren't part of the C# language model.

These must be placed at the beginning of your code.

Importing assemblies

You can import a new assembly if it hasn't already been loaded with the base assemblies for the codes.

Examples

// Loads the System.Numerics assembly.
#load "System.Numerics.dll"

using System.Numerics;

Macros

You can create macros just as you would in C/C++ to compact necessary chunks of code into a single line.

Examples

#define MY_CONSTANT 1
#define PRINT(in_str) Console.WriteLine(in_str)
#define PRINT_MULTI(in_str, in_count) \
    for (int i = 0; i < in_count; i++) \
        Console.WriteLine(in_str);

Code "Example Code"
PRINT(MY_CONSTANT); // Writes 1 to the console.
PRINT_MULTI("Hello world!", 10) // Writes "Hello world!" 10 times to the console.
Clone this wiki locally