frida-il2cpp-bridge
Version:
A Frida module to dump, trace or hijack any Il2Cpp application at runtime, without needing the global-metadata.dat file.
1,056 lines • 55.5 kB
TypeScript
declare namespace Il2Cpp {
/** */
const application: {
/**
* Gets the data path name of the current application, e.g.
* `/data/emulated/0/Android/data/com.example.application/files`
* on Android.
*
* **This information is not guaranteed to exist.**
*
* ```ts
* Il2Cpp.perform(() => {
* // prints /data/emulated/0/Android/data/com.example.application/files
* console.log(Il2Cpp.application.dataPath);
* });
* ```
*/
readonly dataPath: string | null;
/**
* Gets the identifier name of the current application, e.g.
* `com.example.application` on Android.
*
* In case the identifier cannot be retrieved, the main module name is
* returned instead, which typically is the process name.
*
* ```ts
* Il2Cpp.perform(() => {
* // prints com.example.application
* console.log(Il2Cpp.application.identifier);
* });
* ```
*/
readonly identifier: string;
/**
* Gets the version name of the current application, e.g. `4.12.8`.
*
* In case the version cannot be retrieved, an hash of the IL2CPP
* module is returned instead.
*
* ```ts
* Il2Cpp.perform(() => {
* // prints 4.12.8
* console.log(Il2Cpp.application.version);
* });
* ```
*/
readonly version: string;
};
/**
* Gets the Unity version of the current application.
*
* **It is possible to override or manually set its value using
* {@link Il2Cpp.$config.unityVersion}:**
* ```ts
* Il2Cpp.$config.unityVersion = "5.3.5f1";
*
* Il2Cpp.perform(() => {
* // prints 5.3.5f1
* console.log(Il2Cpp.unityVersion);
* });
* ```
*
* When overriding its value, the user has to make sure to set a valid
* value so that it gets matched by the following regular expression:
* ```
* (20\d{2}|\d)\.(\d)\.(\d{1,2})(?:[abcfp]|rc){0,2}\d?
* ```
*/
const unityVersion: string;
}
declare namespace Il2Cpp {
/** Create a boxed primitive */
function boxed<T extends boolean | number | Int64 | UInt64 | NativePointer>(value: T, type?: T extends number ? "int8" | "uint8" | "int16" | "uint16" | "int32" | "uint32" | "int64" | "uint64" | "char" : T extends NativePointer ? "intptr" | "uintptr" : never): Il2Cpp.Object;
}
declare namespace Il2Cpp {
/**
* Set of configurations users can override. It is for advanced use cases,
* when certain values cannot be detected automatically. \
* For reference, see:
* - {@link Il2Cpp.module};
* - {@link Il2Cpp.unityVersion};
* - {@link Il2Cpp.exports};
*/
const $config: {
moduleName?: string;
unityVersion?: string;
exports?: Record<`il2cpp_${string}`, () => NativePointer>;
};
}
declare namespace Il2Cpp {
/**
* @deprecated
* Dumps the application, i.e. it creates a dummy `.cs` file that contains
* all the class, field and method declarations.
*
* The dump is very useful when it comes to inspecting the application as
* you can easily search for succulent members using a simple text search,
* hence this is typically the very first thing it should be done when
* working with a new application. \
* Keep in mind the dump is version, platform and arch dependentend, so
* it has to be re-genereated if any of these changes.
*
* The file is generated in the **target** device, so you might need to
* pull it to the host device afterwards.
*
* Dumping *may* require a file name and a directory path (a place where the
* application can write to). If not provided, the target path is generated
* automatically using the information from {@link Il2Cpp.application}.
*
* ```ts
* Il2Cpp.perform(() => {
* Il2Cpp.dump();
* });
* ```
*
* For instance, the dump resembles the following:
* ```
* class Mono.DataConverter.PackContext : System.Object
* {
* System.Byte[] buffer; // 0x10
* System.Int32 next; // 0x18
* System.String description; // 0x20
* System.Int32 i; // 0x28
* Mono.DataConverter conv; // 0x30
* System.Int32 repeat; // 0x38
* System.Int32 align; // 0x3c
*
* System.Void Add(System.Byte[] group); // 0x012ef4f0
* System.Byte[] Get(); // 0x012ef6ec
* System.Void .ctor(); // 0x012ef78c
* }
* ```
*/
function dump(fileName?: string, path?: string): void;
/**
* @deprecated
* Just like {@link Il2Cpp.dump}, but a `.cs` file per assembly is
* generated instead of having a single big `.cs` file. For instance, all
* classes within `System.Core` and `System.Runtime.CompilerServices.Unsafe`
* are dumped into `System/Core.cs` and
* `System/Runtime/CompilerServices/Unsafe.cs`, respectively.
*
* ```ts
* Il2Cpp.perform(() => {
* Il2Cpp.dumpTree();
* });
* ```
*/
function dumpTree(path?: string, ignoreAlreadyExistingDirectory?: boolean): void;
}
declare namespace Il2Cpp {
/**
* Installs a listener to track any thrown (unrecoverable) C# exception. \
* This may be useful when incurring in `abort was called` errors.
*
* By default, it only tracks exceptions that were thrown by the *caller*
* thread.
*
* **It may not work for every platform.**
*
* ```ts
* Il2Cpp.perform(() => {
* Il2Cpp.installExceptionListener("all");
*
* // rest of the code
* });
* ```
*
* For instance, it may print something along:
* ```
* System.NullReferenceException: Object reference not set to an instance of an object.
* at AddressableLoadWrapper+<LoadGameObject>d__3[T].MoveNext () [0x00000] in <00000000000000000000000000000000>:0
* at UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) [0x00000] in <00000000000000000000000000000000>:0
* ```
*/
function installExceptionListener(targetThread?: "current" | "all"): InvocationListener;
}
declare namespace Il2Cpp {
/**
* The **core** object where all the necessary IL2CPP native functions are
* held. \
* `frida-il2cpp-bridge` is built around this object by providing an
* easy-to-use abstraction layer: the user isn't expected to use it directly,
* but it can in case of advanced use cases.
*
* The exports depends on the Unity version, hence some of them may be
* unavailable; moreover, they are searched by **name** (e.g.
* `il2cpp_class_from_name`) hence they might get stripped, hidden or
* renamed by a nasty obfuscator.
*
* However, it is possible to override or set the handle of any of the
* exports using {@link Il2Cpp.$config.exports}:
* ```ts
* Il2Cpp.$config.exports = {
* il2cpp_image_get_class: () => Il2Cpp.module.base.add(0x1204c),
* il2cpp_class_get_parent: () => {
* return Memory.scanSync(Il2Cpp.module.base, Il2Cpp.module.size, "2f 10 ee 10 34 a8")[0].address;
* },
* };
*
* Il2Cpp.perform(() => {
* // ...
* });
* ```
*/
const exports: {
readonly alloc: NativeFunction<NativePointer, [number | UInt64]>;
readonly arrayGetLength: NativeFunction<number, [NativePointerValue]>;
readonly arrayNew: NativeFunction<NativePointer, [NativePointerValue, number]>;
readonly assemblyGetImage: NativeFunction<NativePointer, [NativePointerValue]>;
readonly classForEach: NativeFunction<void, [NativePointerValue, NativePointerValue]>;
readonly classFromName: NativeFunction<NativePointer, [NativePointerValue, NativePointerValue, NativePointerValue]>;
readonly classFromObject: NativeFunction<NativePointer, [NativePointerValue]>;
readonly classGetArrayClass: NativeFunction<NativePointer, [NativePointerValue, number]>;
readonly classGetArrayElementSize: NativeFunction<number, [NativePointerValue]>;
readonly classGetAssemblyName: NativeFunction<NativePointer, [NativePointerValue]>;
readonly classGetBaseType: NativeFunction<NativePointer, [NativePointerValue]>;
readonly classGetDeclaringType: NativeFunction<NativePointer, [NativePointerValue]>;
readonly classGetElementClass: NativeFunction<NativePointer, [NativePointerValue]>;
readonly classGetFieldFromName: NativeFunction<NativePointer, [NativePointerValue, NativePointerValue]>;
readonly classGetFields: NativeFunction<NativePointer, [NativePointerValue, NativePointerValue]>;
readonly classGetFlags: NativeFunction<number, [NativePointerValue]>;
readonly classGetImage: NativeFunction<NativePointer, [NativePointerValue]>;
readonly classGetInstanceSize: NativeFunction<number, [NativePointerValue]>;
readonly classGetInterfaces: NativeFunction<NativePointer, [NativePointerValue, NativePointerValue]>;
readonly classGetMethodFromName: NativeFunction<NativePointer, [NativePointerValue, NativePointerValue, number]>;
readonly classGetMethods: NativeFunction<NativePointer, [NativePointerValue, NativePointerValue]>;
readonly classGetName: NativeFunction<NativePointer, [NativePointerValue]>;
readonly classGetNamespace: NativeFunction<NativePointer, [NativePointerValue]>;
readonly classGetNestedClasses: NativeFunction<NativePointer, [NativePointerValue, NativePointerValue]>;
readonly classGetParent: NativeFunction<NativePointer, [NativePointerValue]>;
readonly classGetStaticFieldData: NativeFunction<NativePointer, [NativePointerValue]>;
readonly classGetValueTypeSize: NativeFunction<number, [NativePointerValue, NativePointerValue]>;
readonly classGetType: NativeFunction<NativePointer, [NativePointerValue]>;
readonly classHasReferences: NativeFunction<number, [NativePointerValue]>;
readonly classInitialize: NativeFunction<void, [NativePointerValue]>;
readonly classIsAbstract: NativeFunction<number, [NativePointerValue]>;
readonly classIsAssignableFrom: NativeFunction<number, [NativePointerValue, NativePointerValue]>;
readonly classIsBlittable: NativeFunction<number, [NativePointerValue]>;
readonly classIsEnum: NativeFunction<number, [NativePointerValue]>;
readonly classIsGeneric: NativeFunction<number, [NativePointerValue]>;
readonly classIsInflated: NativeFunction<number, [NativePointerValue]>;
readonly classIsInterface: NativeFunction<number, [NativePointerValue]>;
readonly classIsSubclassOf: NativeFunction<number, [NativePointerValue, NativePointerValue, number]>;
readonly classIsValueType: NativeFunction<number, [NativePointerValue]>;
readonly domainGetAssemblyFromName: NativeFunction<NativePointer, [NativePointerValue, NativePointerValue]>;
readonly domainGet: NativeFunction<NativePointer, []>;
readonly domainGetAssemblies: NativeFunction<NativePointer, [NativePointerValue, NativePointerValue]>;
readonly fieldGetClass: NativeFunction<NativePointer, [NativePointerValue]>;
readonly fieldGetFlags: NativeFunction<number, [NativePointerValue]>;
readonly fieldGetName: NativeFunction<NativePointer, [NativePointerValue]>;
readonly fieldGetOffset: NativeFunction<number, [NativePointerValue]>;
readonly fieldGetStaticValue: NativeFunction<void, [NativePointerValue, NativePointerValue]>;
readonly fieldGetType: NativeFunction<NativePointer, [NativePointerValue]>;
readonly fieldSetStaticValue: NativeFunction<void, [NativePointerValue, NativePointerValue]>;
readonly free: NativeFunction<void, [NativePointerValue]>;
readonly gcCollect: NativeFunction<void, [number]>;
readonly gcCollectALittle: NativeFunction<void, []>;
readonly gcDisable: NativeFunction<void, []>;
readonly gcEnable: NativeFunction<void, []>;
readonly gcGetHeapSize: NativeFunction<Int64, []>;
readonly gcGetMaxTimeSlice: NativeFunction<Int64, []>;
readonly gcGetUsedSize: NativeFunction<Int64, []>;
readonly gcHandleGetTarget: NativeFunction<NativePointer, [number]>;
readonly gcHandleFree: NativeFunction<void, [number]>;
readonly gcHandleNew: NativeFunction<number, [NativePointerValue, number]>;
readonly gcHandleNewWeakRef: NativeFunction<number, [NativePointerValue, number]>;
readonly gcIsDisabled: NativeFunction<number, []>;
readonly gcIsIncremental: NativeFunction<number, []>;
readonly gcSetMaxTimeSlice: NativeFunction<void, [number | Int64]>;
readonly gcStartIncrementalCollection: NativeFunction<void, []>;
readonly gcStartWorld: NativeFunction<void, []>;
readonly gcStopWorld: NativeFunction<void, []>;
readonly getCorlib: NativeFunction<NativePointer, []>;
readonly imageGetAssembly: NativeFunction<NativePointer, [NativePointerValue]>;
readonly imageGetClass: NativeFunction<NativePointer, [NativePointerValue, number]>;
readonly imageGetClassCount: NativeFunction<number, [NativePointerValue]>;
readonly imageGetName: NativeFunction<NativePointer, [NativePointerValue]>;
readonly initialize: NativeFunction<void, [NativePointerValue]>;
readonly livenessAllocateStruct: NativeFunction<NativePointer, [NativePointerValue, number, NativePointerValue, NativePointerValue, NativePointerValue]>;
readonly livenessCalculationBegin: NativeFunction<NativePointer, [NativePointerValue, number, NativePointerValue, NativePointerValue, NativePointerValue, NativePointerValue]>;
readonly livenessCalculationEnd: NativeFunction<void, [NativePointerValue]>;
readonly livenessCalculationFromStatics: NativeFunction<void, [NativePointerValue]>;
readonly livenessFinalize: NativeFunction<void, [NativePointerValue]>;
readonly livenessFreeStruct: NativeFunction<void, [NativePointerValue]>;
readonly memorySnapshotCapture: NativeFunction<NativePointer, []>;
readonly memorySnapshotFree: NativeFunction<void, [NativePointerValue]>;
readonly memorySnapshotGetClasses: NativeFunction<NativePointer, [NativePointerValue, NativePointerValue]>;
readonly memorySnapshotGetObjects: NativeFunction<NativePointer, [NativePointerValue, NativePointerValue]>;
readonly methodGetClass: NativeFunction<NativePointer, [NativePointerValue]>;
readonly methodGetFlags: NativeFunction<number, [NativePointerValue, NativePointerValue]>;
readonly methodGetName: NativeFunction<NativePointer, [NativePointerValue]>;
readonly methodGetObject: NativeFunction<NativePointer, [NativePointerValue, NativePointerValue]>;
readonly methodGetParameterCount: NativeFunction<number, [NativePointerValue]>;
readonly methodGetParameterName: NativeFunction<NativePointer, [NativePointerValue, number]>;
readonly methodGetParameters: NativeFunction<NativePointer, [NativePointerValue, NativePointerValue]>;
readonly methodGetParameterType: NativeFunction<NativePointer, [NativePointerValue, number]>;
readonly methodGetReturnType: NativeFunction<NativePointer, [NativePointerValue]>;
readonly methodIsGeneric: NativeFunction<number, [NativePointerValue]>;
readonly methodIsInflated: NativeFunction<number, [NativePointerValue]>;
readonly methodIsInstance: NativeFunction<number, [NativePointerValue]>;
readonly monitorEnter: NativeFunction<void, [NativePointerValue]>;
readonly monitorExit: NativeFunction<void, [NativePointerValue]>;
readonly monitorPulse: NativeFunction<void, [NativePointerValue]>;
readonly monitorPulseAll: NativeFunction<void, [NativePointerValue]>;
readonly monitorTryEnter: NativeFunction<number, [NativePointerValue, number]>;
readonly monitorTryWait: NativeFunction<number, [NativePointerValue, number]>;
readonly monitorWait: NativeFunction<void, [NativePointerValue]>;
readonly objectGetClass: NativeFunction<NativePointer, [NativePointerValue]>;
readonly objectGetVirtualMethod: NativeFunction<NativePointer, [NativePointerValue, NativePointerValue]>;
readonly objectInitialize: NativeFunction<void, [NativePointerValue, NativePointerValue]>;
readonly objectNew: NativeFunction<NativePointer, [NativePointerValue]>;
readonly objectGetSize: NativeFunction<number, [NativePointerValue]>;
readonly objectUnbox: NativeFunction<NativePointer, [NativePointerValue]>;
readonly resolveInternalCall: NativeFunction<NativePointer, [NativePointerValue]>;
readonly stringGetChars: NativeFunction<NativePointer, [NativePointerValue]>;
readonly stringGetLength: NativeFunction<number, [NativePointerValue]>;
readonly stringNew: NativeFunction<NativePointer, [NativePointerValue]>;
readonly valueTypeBox: NativeFunction<NativePointer, [NativePointerValue, NativePointerValue]>;
readonly threadAttach: NativeFunction<NativePointer, [NativePointerValue]>;
readonly threadDetach: NativeFunction<void, [NativePointerValue]>;
readonly threadGetAttachedThreads: NativeFunction<NativePointer, [NativePointerValue]>;
readonly threadGetCurrent: NativeFunction<NativePointer, []>;
readonly threadIsVm: NativeFunction<number, [NativePointerValue]>;
readonly typeEquals: NativeFunction<number, [NativePointerValue, NativePointerValue]>;
readonly typeGetClass: NativeFunction<NativePointer, [NativePointerValue]>;
readonly typeGetName: NativeFunction<NativePointer, [NativePointerValue]>;
readonly typeGetObject: NativeFunction<NativePointer, [NativePointerValue]>;
readonly typeGetTypeEnum: NativeFunction<number, [NativePointerValue]>;
};
}
declare namespace Il2Cpp {
/**
* Creates a filter to include elements whose type can be assigned to a
* variable of the given class. \
* It relies on {@link Il2Cpp.Class.isAssignableFrom}.
*
* ```ts
* const IComparable = Il2Cpp.corlib.class("System.IComparable");
*
* const objects = [
* Il2Cpp.corlib.class("System.Object").new(),
* Il2Cpp.corlib.class("System.String").new()
* ];
*
* const comparables = objects.filter(Il2Cpp.is(IComparable));
* ```
*/
function is<T extends Il2Cpp.Class | Il2Cpp.Object | Il2Cpp.Type>(klass: Il2Cpp.Class): (element: T) => boolean;
/**
* Creates a filter to include elements whose type can be corresponds to
* the given class. \
* It compares the native handle of the element classes.
*
* ```ts
* const String = Il2Cpp.corlib.class("System.String");
*
* const objects = [
* Il2Cpp.corlib.class("System.Object").new(),
* Il2Cpp.corlib.class("System.String").new()
* ];
*
* const strings = objects.filter(Il2Cpp.isExactly(String));
* ```
*/
function isExactly<T extends Il2Cpp.Class | Il2Cpp.Object | Il2Cpp.Type>(klass: Il2Cpp.Class): (element: T) => boolean;
}
declare namespace Il2Cpp {
/**
* The object literal to interacts with the garbage collector.
*/
const gc: {
/**
* Gets the heap size in bytes.
*/
readonly heapSize: Int64;
/**
* Determines whether the garbage collector is enabled.
*/
isEnabled: boolean;
/**
* Determines whether the garbage collector is incremental
* ([source](https://docs.unity3d.com/Manual/performance-incremental-garbage-collection.html)).
*/
readonly isIncremental: boolean;
/**
* Gets the number of nanoseconds the garbage collector can spend in a
* collection step.
*/
get maxTimeSlice(): Int64;
/**
* Sets the number of nanoseconds the garbage collector can spend in
* a collection step.
*/
set maxTimeSlice(nanoseconds: number | Int64);
/**
* Gets the used heap size in bytes.
*/
readonly usedHeapSize: Int64;
/**
* Returns the heap allocated objects of the specified class. \
* This variant reads GC descriptors.
*/
choose(klass: Il2Cpp.Class): Il2Cpp.Object[];
/**
* Forces a garbage collection of the specified generation.
*/
collect(generation: 0 | 1 | 2): void;
/**
* Forces a garbage collection.
*/
collectALittle(): void;
/**
* Resumes all the previously stopped threads.
*/
startWorld(): void;
/**
* Performs an incremental garbage collection.
*/
startIncrementalCollection(): void;
/**
* Stops all threads which may access the garbage collected heap, other
* than the caller.
*/
stopWorld(): void;
};
}
/** Scaffold class. */
declare class NativeStruct implements ObjectWrapper {
readonly handle: NativePointer;
constructor(handleOrWrapper: NativePointerValue);
equals(other: NativeStruct): boolean;
isNull(): boolean;
asNullable(): this | null;
}
declare namespace Il2Cpp {
/**
* Allocates the given amount of bytes - it's equivalent to C's `malloc`. \
* The allocated memory should be freed manually.
*/
function alloc(size?: number | UInt64): NativePointer;
/**
* Frees a previously allocated memory using {@link Il2Cpp.alloc} - it's
* equivalent to C's `free`..
*
* ```ts
* const handle = Il2Cpp.alloc(64);
*
* // ...
*
* Il2Cpp.free(handle);
* ```
*/
function free(pointer: NativePointerValue): void;
}
declare namespace Il2Cpp {
/**
* Gets the IL2CPP module (a *native library*), that is where the IL2CPP
* exports will be searched for (see {@link Il2Cpp.exports}).
*
* The module is located by its name:
* - Android: `libil2cpp.so`
* - Linux: `GameAssembly.so`
* - Windows: `GameAssembly.dll`
* - iOS: `UnityFramework`
* - macOS: `GameAssembly.dylib`
*
* On iOS and macOS, IL2CPP exports may be located within a module having
* a different name.
*
* In any case, it is possible to override or set the IL2CPP module name
* using {@link Il2Cpp.$config.moduleName}:
* ```ts
* Il2Cpp.$config.moduleName = "CustomName.dylib";
*
* Il2Cpp.perform(() => {
* // ...
* });
* ```
*/
const module: Module;
}
declare namespace Il2Cpp {
/** Attaches the caller thread to Il2Cpp domain and executes the given block. */
function perform<T>(block: () => T | Promise<T>, flag?: "free" | "bind" | "leak" | "main"): Promise<T>;
}
declare namespace Il2Cpp {
class Tracer {
#private;
constructor(applier: Il2Cpp.Tracer.Apply);
/** */
thread(thread: Il2Cpp.Thread): Pick<Il2Cpp.Tracer, "verbose"> & Il2Cpp.Tracer.ChooseTargets;
/** Determines whether print duplicate logs. */
verbose(value: boolean): Il2Cpp.Tracer.ChooseTargets;
/** Sets the application domain as the place where to find the target methods. */
domain(): Il2Cpp.Tracer.FilterAssemblies;
/** Sets the passed `assemblies` as the place where to find the target methods. */
assemblies(...assemblies: Il2Cpp.Assembly[]): Il2Cpp.Tracer.FilterClasses;
/** Sets the passed `classes` as the place where to find the target methods. */
classes(...classes: Il2Cpp.Class[]): Il2Cpp.Tracer.FilterMethods;
/** Sets the passed `methods` as the target methods. */
methods(...methods: Il2Cpp.Method[]): Il2Cpp.Tracer.FilterParameters;
/** Filters the assemblies where to find the target methods. */
filterAssemblies(filter: (assembly: Il2Cpp.Assembly) => boolean): Il2Cpp.Tracer.FilterClasses;
/** Filters the classes where to find the target methods. */
filterClasses(filter: (klass: Il2Cpp.Class) => boolean): Il2Cpp.Tracer.FilterMethods;
/** Filters the target methods. */
filterMethods(filter: (method: Il2Cpp.Method) => boolean): Il2Cpp.Tracer.FilterParameters;
/** Filters the target methods. */
filterParameters(filter: (parameter: Il2Cpp.Parameter) => boolean): Pick<Il2Cpp.Tracer, "and">;
/** Commits the current changes by finding the target methods. */
and(): Il2Cpp.Tracer.ChooseTargets & Pick<Il2Cpp.Tracer, "attach">;
/** Starts tracing. */
attach(): void;
}
namespace Tracer {
type Configure = Pick<Il2Cpp.Tracer, "thread" | "verbose"> & Il2Cpp.Tracer.ChooseTargets;
type ChooseTargets = Pick<Il2Cpp.Tracer, "domain" | "assemblies" | "classes" | "methods">;
type FilterAssemblies = FilterClasses & Pick<Il2Cpp.Tracer, "filterAssemblies">;
type FilterClasses = FilterMethods & Pick<Il2Cpp.Tracer, "filterClasses">;
type FilterMethods = FilterParameters & Pick<Il2Cpp.Tracer, "filterMethods">;
type FilterParameters = Pick<Il2Cpp.Tracer, "and"> & Pick<Il2Cpp.Tracer, "filterParameters">;
interface State {
depth: number;
buffer: string[];
history: Set<number>;
flush: () => void;
}
type Apply = (method: Il2Cpp.Method, state: Il2Cpp.Tracer.State, threadId: number) => void;
}
/** */
function trace(parameters?: boolean): Il2Cpp.Tracer.Configure;
/** */
function backtrace(mode?: Backtracer): Il2Cpp.Tracer.Configure;
}
declare namespace Il2Cpp {
class Array<T extends Il2Cpp.Field.Type = Il2Cpp.Field.Type> extends NativeStruct implements Iterable<T> {
/** Gets the Il2CppArray struct size, possibly equal to `Process.pointerSize * 4`. */
static get headerSize(): number;
/** Gets the size of the object encompassed by the current array. */
get elementSize(): number;
/** Gets the type of the object encompassed by the current array. */
get elementType(): Il2Cpp.Type;
/** Gets the total number of elements in all the dimensions of the current array. */
get length(): number;
/** Gets the encompassing object of the current array. */
get object(): Il2Cpp.Object;
/** Gets the element at the specified index of the current array. */
get(index: number): T;
/** Sets the element at the specified index of the current array. */
set(index: number, value: T): void;
/** */
toString(): string;
/** Iterable. */
[Symbol.iterator](): IterableIterator<T>;
}
/** Creates a new empty array of the given length. */
function array<T extends Il2Cpp.Field.Type>(klass: Il2Cpp.Class, length: number): Il2Cpp.Array<T>;
/** Creates a new array with the given elements. */
function array<T extends Il2Cpp.Field.Type>(klass: Il2Cpp.Class, elements: T[]): Il2Cpp.Array<T>;
}
declare namespace Il2Cpp {
class Assembly extends NativeStruct {
/** Gets the image of this assembly. */
get image(): Il2Cpp.Image;
/** Gets the name of this assembly. */
get name(): string;
/** Gets the encompassing object of the current assembly. */
get object(): Il2Cpp.Object;
}
}
declare namespace Il2Cpp {
class Class extends NativeStruct {
/** Gets the actual size of the instance of the current class. */
get actualInstanceSize(): number;
/** Gets the array class which encompass the current class. */
get arrayClass(): Il2Cpp.Class;
/** Gets the size of the object encompassed by the current array class. */
get arrayElementSize(): number;
/** Gets the name of the assembly in which the current class is defined. */
get assemblyName(): string;
/** Gets the class that declares the current nested class. */
get declaringClass(): Il2Cpp.Class | null;
/** Gets the encompassed type of this array, reference, pointer or enum type. */
get baseType(): Il2Cpp.Type | null;
/** Gets the class of the object encompassed or referred to by the current array, pointer or reference class. */
get elementClass(): Il2Cpp.Class | null;
/** Gets the fields of the current class. */
get fields(): Il2Cpp.Field[];
/** Gets the flags of the current class. */
get flags(): number;
/** Gets the full name (namespace + name) of the current class. */
get fullName(): string;
/** Gets the generic class of the current class if the current class is inflated. */
get genericClass(): Il2Cpp.Class | null;
/** Gets the generics parameters of this generic class. */
get generics(): Il2Cpp.Class[];
/** Determines whether the GC has tracking references to the current class instances. */
get hasReferences(): boolean;
/** Determines whether ther current class has a valid static constructor. */
get hasStaticConstructor(): boolean;
/** Gets the image in which the current class is defined. */
get image(): Il2Cpp.Image;
/** Gets the size of the instance of the current class. */
get instanceSize(): number;
/** Determines whether the current class is abstract. */
get isAbstract(): boolean;
/** Determines whether the current class is blittable. */
get isBlittable(): boolean;
/** Determines whether the current class is an enumeration. */
get isEnum(): boolean;
/** Determines whether the current class is a generic one. */
get isGeneric(): boolean;
/** Determines whether the current class is inflated. */
get isInflated(): boolean;
/** Determines whether the current class is an interface. */
get isInterface(): boolean;
/** Determines whether the current class is a struct. */
get isStruct(): boolean;
/** Determines whether the current class is a value type. */
get isValueType(): boolean;
/** Gets the interfaces implemented or inherited by the current class. */
get interfaces(): Il2Cpp.Class[];
/** Gets the methods implemented by the current class. */
get methods(): Il2Cpp.Method[];
/** Gets the name of the current class. */
get name(): string;
/** Gets the namespace of the current class. */
get namespace(): string | undefined;
/** Gets the classes nested inside the current class. */
get nestedClasses(): Il2Cpp.Class[];
/** Gets the class from which the current class directly inherits. */
get parent(): Il2Cpp.Class | null;
/** Gets the pointer class of the current class. */
get pointerClass(): Il2Cpp.Class;
/** Gets the rank (number of dimensions) of the current array class. */
get rank(): number;
/** Gets a pointer to the static fields of the current class. */
get staticFieldsData(): NativePointer;
/** Gets the size of the instance - as a value type - of the current class. */
get valueTypeSize(): number;
/** Gets the type of the current class. */
get type(): Il2Cpp.Type;
/** Allocates a new object of the current class. */
alloc(): Il2Cpp.Object;
/** Gets the field identified by the given name. */
field<T extends Il2Cpp.Field.Type>(name: string): Il2Cpp.Field<T>;
/** Gets the hierarchy of the current class. */
hierarchy(options?: {
includeCurrent?: boolean;
}): Generator<Il2Cpp.Class>;
/** Builds a generic instance of the current generic class. */
inflate(...classes: Il2Cpp.Class[]): Il2Cpp.Class;
/** Calls the static constructor of the current class. */
initialize(): Il2Cpp.Class;
/** Determines whether an instance of `other` class can be assigned to a variable of the current type. */
isAssignableFrom(other: Il2Cpp.Class): boolean;
/** Determines whether the current class derives from `other` class. */
isSubclassOf(other: Il2Cpp.Class, checkInterfaces: boolean): boolean;
/** Gets the method identified by the given name and parameter count. */
method<T extends Il2Cpp.Method.ReturnType>(name: string, parameterCount?: number): Il2Cpp.Method<T>;
/** Gets the nested class with the given name. */
nested(name: string): Il2Cpp.Class;
/** Allocates a new object of the current class and calls its default constructor. */
new(): Il2Cpp.Object;
/** Gets the field with the given name. */
tryField<T extends Il2Cpp.Field.Type>(name: string): Il2Cpp.Field<T> | null;
/** Gets the method with the given name and parameter count. */
tryMethod<T extends Il2Cpp.Method.ReturnType>(name: string, parameterCount?: number): Il2Cpp.Method<T> | null;
/** Gets the nested class with the given name. */
tryNested(name: string): Il2Cpp.Class | undefined;
/** */
toString(): string;
/** Executes a callback for every defined class. */
static enumerate(block: (klass: Il2Cpp.Class) => void): void;
}
}
declare namespace Il2Cpp {
/** Creates a delegate object of the given delegate class. */
function delegate<P extends Il2Cpp.Parameter.Type[], R extends Il2Cpp.Method.ReturnType>(klass: Il2Cpp.Class, block: (...args: P) => R): Il2Cpp.Object;
}
declare namespace Il2Cpp {
class Domain extends NativeStruct {
/** Gets the assemblies that have been loaded into the execution context of the application domain. */
get assemblies(): Il2Cpp.Assembly[];
/** Gets the encompassing object of the application domain. */
get object(): Il2Cpp.Object;
/** Opens and loads the assembly with the given name. */
assembly(name: string): Il2Cpp.Assembly;
/** Attached a new thread to the application domain. */
attach(): Il2Cpp.Thread;
/** Opens and loads the assembly with the given name. */
tryAssembly(name: string): Il2Cpp.Assembly | null;
}
/** Gets the application domain. */
const domain: Il2Cpp.Domain;
}
declare namespace Il2Cpp {
class Field<T extends Il2Cpp.Field.Type = Il2Cpp.Field.Type> extends NativeStruct {
/** Gets the class in which this field is defined. */
get class(): Il2Cpp.Class;
/** Gets the flags of the current field. */
get flags(): number;
/** Determines whether this field value is known at compile time. */
get isLiteral(): boolean;
/** Determines whether this field is static. */
get isStatic(): boolean;
/** Determines whether this field is thread static. */
get isThreadStatic(): boolean;
/** Gets the access modifier of this field. */
get modifier(): string | undefined;
/** Gets the name of this field. */
get name(): string;
/** Gets the offset of this field, calculated as the difference with its owner virtual address. */
get offset(): number;
/** Gets the type of this field. */
get type(): Il2Cpp.Type;
/** Gets the value of this field. */
get value(): T;
/** Sets the value of this field. Thread static or literal values cannot be altered yet. */
set value(value: T);
/** */
toString(): string;
}
/**
* A {@link Il2Cpp.Field} bound to a {@link Il2Cpp.Object} or a
* {@link Il2Cpp.ValueType} (also known as *instances*).
* ```ts
* const object: Il2Cpp.Object = Il2Cpp.string("Hello, world!").object;
* const m_length: Il2Cpp.BoundField<number> = object.field<number>("m_length");
* const length = m_length.value; // 13
* ```
* Of course, binding a static field does not make sense and may cause
* unwanted behaviors.
*
* Binding can be done manually with:
* ```ts
* const SystemString = Il2Cpp.corlib.class("System.String");
* const m_length: Il2Cpp.Field<number> = SystemString.field<number>("m_length");
*
* const object: Il2Cpp.Object = Il2Cpp.string("Hello, world!").object;
* // @ts-ignore
* const m_length_bound: Il2Cpp.BoundField<number> = m_length.bind(object);
* ```
*/
interface BoundField<T extends Il2Cpp.Field.Type = Il2Cpp.Field.Type> extends Field<T> {
}
namespace Field {
type Type = boolean | number | Int64 | UInt64 | NativePointer | Il2Cpp.Pointer | Il2Cpp.ValueType | Il2Cpp.Object | Il2Cpp.String | Il2Cpp.Array;
const enum Attributes {
FieldAccessMask = 7,
PrivateScope = 0,
Private = 1,
FamilyAndAssembly = 2,
Assembly = 3,
Family = 4,
FamilyOrAssembly = 5,
Public = 6,
Static = 16,
InitOnly = 32,
Literal = 64,
NotSerialized = 128,
SpecialName = 512,
PinvokeImpl = 8192,
ReservedMask = 38144,
RTSpecialName = 1024,
HasFieldMarshal = 4096,
HasDefault = 32768,
HasFieldRVA = 256
}
}
}
declare namespace Il2Cpp {
class GCHandle {
readonly handle: number;
/** Gets the object associated to this handle. */
get target(): Il2Cpp.Object | null;
/** Frees this handle. */
free(): void;
}
}
declare namespace Il2Cpp {
class Image extends NativeStruct {
/** Gets the assembly in which the current image is defined. */
get assembly(): Il2Cpp.Assembly;
/** Gets the amount of classes defined in this image. */
get classCount(): number;
/** Gets the classes defined in this image. */
get classes(): Il2Cpp.Class[];
/** Gets the name of this image. */
get name(): string;
/** Gets the class with the specified name defined in this image. */
class(name: string): Il2Cpp.Class;
/** Gets the class with the specified name defined in this image. */
tryClass(name: string): Il2Cpp.Class | null;
}
/** Gets the COR library. */
const corlib: Il2Cpp.Image;
}
declare namespace Il2Cpp {
class MemorySnapshot extends NativeStruct {
/** Captures a memory snapshot. */
static capture(): Il2Cpp.MemorySnapshot;
/** Creates a memory snapshot with the given handle. */
constructor(handle?: NativePointer);
/** Gets any initialized class. */
get classes(): Il2Cpp.Class[];
/** Gets the objects tracked by this memory snapshot. */
get objects(): Il2Cpp.Object[];
/** Frees this memory snapshot. */
free(): void;
}
/** */
function memorySnapshot<T>(block: (memorySnapshot: Omit<Il2Cpp.MemorySnapshot, "free">) => T): T;
}
declare namespace Il2Cpp {
class Method<T extends Il2Cpp.Method.ReturnType = Il2Cpp.Method.ReturnType> extends NativeStruct {
/** Gets the class in which this method is defined. */
get class(): Il2Cpp.Class;
/** Gets the flags of the current method. */
get flags(): number;
/** Gets the implementation flags of the current method. */
get implementationFlags(): number;
/** */
get fridaSignature(): NativeCallbackArgumentType[];
/** Gets the generic parameters of this generic method. */
get generics(): Il2Cpp.Class[];
/** Determines whether this method is external. */
get isExternal(): boolean;
/** Determines whether this method is generic. */
get isGeneric(): boolean;
/** Determines whether this method is inflated (generic with a concrete type parameter). */
get isInflated(): boolean;
/** Determines whether this method is static. */
get isStatic(): boolean;
/** Determines whether this method is synchronized. */
get isSynchronized(): boolean;
/** Gets the access modifier of this method. */
get modifier(): string | undefined;
/** Gets the name of this method. */
get name(): string;
/** Gets the encompassing object of the current method. */
get object(): Il2Cpp.Object;
/** Gets the amount of parameters of this method. */
get parameterCount(): number;
/** Gets the parameters of this method. */
get parameters(): Il2Cpp.Parameter[];
/** Gets the relative virtual address (RVA) of this method. */
get relativeVirtualAddress(): NativePointer;
/** Gets the return type of this method. */
get returnType(): Il2Cpp.Type;
/** Gets the virtual address (VA) of this method. */
get virtualAddress(): NativePointer;
/** Replaces the body of this method. */
set implementation(block: (this: Il2Cpp.Class | Il2Cpp.Object | Il2Cpp.ValueType, ...parameters: Il2Cpp.Parameter.Type[]) => T);
/** Creates a generic instance of the current generic method. */
inflate<R extends Il2Cpp.Method.ReturnType = T>(...classes: Il2Cpp.Class[]): Il2Cpp.Method<R>;
/** Invokes this method. */
invoke(...parameters: Il2Cpp.Parameter.Type[]): T;
/** Gets the overloaded method with the given parameter types. */
overload(...typeNamesOrClasses: (string | Il2Cpp.Class)[]): Il2Cpp.Method<T>;
/** Gets the parameter with the given name. */
parameter(name: string): Il2Cpp.Parameter;
/** Restore the original method implementation. */
revert(): void;
/** Gets the overloaded method with the given parameter types. */
tryOverload<U extends Il2Cpp.Method.ReturnType = T>(...typeNamesOrClasses: (string | Il2Cpp.Class)[]): Il2Cpp.Method<U> | undefined;
/** Gets the parameter with the given name. */
tryParameter(name: string): Il2Cpp.Parameter | undefined;
/** */
toString(): string;
}
/**
* A {@link Il2Cpp.Method} bound to a {@link Il2Cpp.Object} or a
* {@link Il2Cpp.ValueType} (also known as *instances*). \
* Invoking bound methods will pass the assigned instance as `this`.
* ```ts
* const object: Il2Cpp.Object = Il2Cpp.string("Hello, world!").object;
* const GetLength: Il2Cpp.BoundMethod<number> = object.method<number>("GetLength");
* // There is no need to pass the object when invoking GetLength!
* const length = GetLength.invoke(); // 13
* ```
* Of course, binding a static method does not make sense and may cause
* unwanted behaviors. \
*
* Binding can be done manually with:
* ```ts
* const SystemString = Il2Cpp.corlib.class("System.String");
* const GetLength: Il2Cpp.Method<number> = SystemString.method<number>("GetLength");
*
* const object: Il2Cpp.Object = Il2Cpp.string("Hello, world!").object;
* // @ts-ignore
* const GetLengthBound: Il2Cpp.BoundMethod<number> = GetLength.bind(object);
* ```
*/
interface BoundMethod<T extends Il2Cpp.Method.ReturnType = Il2Cpp.Method.ReturnType> extends Method<T> {
}
namespace Method {
type ReturnType = void | Il2Cpp.Field.Type | Il2Cpp.Reference;
const enum Attributes {
MemberAccessMask = 7,
PrivateScope = 0,
Private = 1,
FamilyAndAssembly = 2,
Assembly = 3,
Family = 4,
FamilyOrAssembly = 5,
Public = 6,
Static = 16,
Final = 32,
Virtual = 64,
HideBySig = 128,
CheckAccessOnOverride = 512,
VtableLayoutMask = 256,
ReuseSlot = 0,
NewSlot = 256,
Abstract = 1024,
SpecialName = 2048,
PinvokeImpl = 8192,
UnmanagedExport = 8,
RTSpecialName = 4096,
ReservedMask = 53248,
HasSecurity = 16384,
RequireSecObject = 32768
}
const enum ImplementationAttribute {
CodeTypeMask = 3,
IntermediateLanguage = 0,
Native = 1,
OptimizedIntermediateLanguage = 2,
Runtime = 3,
ManagedMask = 4,
Unmanaged = 4,
Managed = 0,
ForwardRef = 16,
PreserveSig = 128,
InternalCall = 4096,
Synchronized = 32,
NoInlining = 8,
AggressiveInlining = 256,
NoOptimization = 64,
SecurityMitigations = 1024,
MaxMethodImplVal = 65535
}
}
}
declare namespace Il2Cpp {
class Object extends NativeStruct {
/** Gets the Il2CppObject struct size, possibly equal to `Process.pointerSize * 2`. */
static get headerSize(): number;
/**
* Returns the same object, but having its parent class as class.
* It basically is the C# `base` keyword, so that parent members can be
* accessed.
*
* **Example** \
* Consider the following classes:
* ```csharp
* class Foo
* {
* int foo()
* {
* return 1;
* }
* }
* class Bar : Foo
* {
* new int foo()
* {
* return 2;
* }
* }
* ```
* then:
* ```ts
* const Bar: Il2Cpp.Class = ...;
* const bar = Bar.new();
*
* console.log(bar.foo()); // 2
* console.log(bar.base.foo()); // 1
* ```
*/
get base(): Il2Cpp.Object;
/** Gets the class of this object. */
get class(): Il2Cpp.Class;
/** Returns a monitor for this object. */
get monitor(): Il2Cpp.Object.Monitor;
/** Gets the size of the current object. */
get size(): number;
/** Gets the non-static field with the given name of the current class hierarchy. */
field<T extends Il2Cpp.Field.Type>(name: string): Il2Cpp.BoundField<T>;
/** Gets the non-static method with the given name (and optionally parameter count) of the current class hierarchy. */
method<T extends Il2Cpp.Method.ReturnType>(name: string, parameterCount?: number): Il2Cpp.BoundMethod<T>;
/** Creates a reference to this object. */
ref(pin: boolean): Il2Cpp.GCHandle;
/** Gets the correct virtual method from the given virtual method. */
virtualMethod<T extends Il2Cpp.Method.ReturnType>(method: Il2Cpp.Method): Il2Cpp.BoundMethod<T>;
/** Gets the non-static field with the given name of the current class hierarchy, if it exists. */
tryField<T extends Il2Cpp.Field.Type>(name: string): Il2Cpp.BoundField<T> | undefined;
/** Gets the non-static method with the given name (and optionally parameter count) of the current class hierarchy, if it exists. */
tryMethod<T extends Il2Cpp.Method.ReturnType>(name: string, parameterCount?: number): Il2Cpp.BoundMethod<T> | undefined;
/** */
toString(): string;
/** Unboxes the value type (either a primitive, a struct or an enum) out of this object. */
unbox(): Il2Cpp.ValueType;
/** Creates a weak reference to this object. */
weakRef(trackResurrection: boolean): Il2Cpp.GCHandle;
}
namespace Object {
class Monitor {
/** Acquires an exclusive lock on the current object. */
enter(): void;
/** Release an exclusive lock on the current object. */
exit(): void;
/** Notifies a thread in the waiting queue of a change in the locked object's state. */
pulse(): void;
/** Notifies all waiting threads of a change in the object's state. */
pulseAll(): void;
/** Attempts to acquire an exclusive lock on the current object. */
tryEnter(timeout: number): boolean;
/** Releases the lock on an object and attempts to block the current thread until it reacquires the lock. */
tryWait(timeout: number): boolean;
/** Releases the lock on an object and blocks the current thread until it reacquires the lock. */
wait(): void;
}
}
}
declare namespace Il2Cpp {
class Parameter {
/** Name of this parameter. */
readonly name: string;
/** Position of this parameter. */
readonly position: number;
/** Type of this parameter. */
readonly type: Il2Cpp.Type;
constructor(name: string, position: number, type: Il2Cpp.Type);
/** */
toString(): string;
}
namespace Parameter {
type Type = Il2Cpp.Field.Type | Il2Cpp.Reference;
}
}
declare namespace Il2Cpp {
class Pointer<T extends Il2Cpp.Field.Type = Il2Cpp.Field.Type> extends NativeStruct {
readonly type: Il2Cpp.Type;
constructor(handle: NativePointer, type: Il2Cpp.Type);
/** Gets the element at the given index. */
get(index: number): T;
/** Reads the given amount of elements starting at the given offset. */
read(length: number, offset?: number): T[];
/** Sets the given element at the given index */
set(index: number, value: T): void;
/** */
toString(): string;
/** Writes the given elements starting