UNPKG

frida-il2cpp-bridge-my

Version:

(my:Support IOS)Frida module to dump, manipulate and hijack any IL2CPP application at runtime with a high level of abstraction.

216 lines (215 loc) 9.36 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; Object.defineProperty(exports, "__esModule", { value: true }); exports._Il2CppMethod = void 0; const decorator_cache_getter_1 = require("decorator-cache-getter"); const accessor_1 = require("../../utils/accessor"); const console_1 = require("../../utils/console"); const api_1 = require("../api"); const decorators_1 = require("../decorators"); const native_struct_1 = require("../native-struct"); const variables_1 = require("../variables"); const utils_1 = require("../utils"); const class_1 = require("./class"); const object_1 = require("./object"); const type_1 = require("./type"); const parameter_1 = require("./parameter"); let _Il2CppMethod = class _Il2CppMethod extends native_struct_1.NativeStruct { get actualPointer() { return api_1.Api._methodGetPointer(this.handle); } get class() { return new class_1._Il2CppClass(api_1.Api._methodGetClass(this.handle)); } get isGeneric() { return api_1.Api._methodIsGeneric(this.handle); } get isInflated() { return api_1.Api._methodIsInflated(this.handle); } get isInstance() { return api_1.Api._methodIsInstance(this.handle); } get name() { return api_1.Api._methodGetName(this.handle); } get parameterCount() { return api_1.Api._methodGetParamCount(this.handle); } get parameters() { const iterator = Memory.alloc(Process.pointerSize); const accessor = new accessor_1.Accessor(); let handle; let parameter; while (!(handle = api_1.Api._methodGetParameters(this.handle, iterator)).isNull()) { parameter = new parameter_1._Il2CppParameter(handle); accessor[parameter.name] = parameter; } return accessor; } get relativePointerAsString() { return `0x${this.actualPointer.sub(variables_1.library.base).toString(16).padStart(8, "0")}`; } get returnType() { return new type_1._Il2CppType(api_1.Api._methodGetReturnType(this.handle)); } get nativeFunction() { const parametersTypesAliasesForFrida = Array(this.parameterCount).fill("pointer"); if (this.isInstance || variables_1.unityVersion.isLegacy) { parametersTypesAliasesForFrida.push("pointer"); } if (this.isInflated) { parametersTypesAliasesForFrida.push("pointer"); } return new NativeFunction(this.actualPointer, this.returnType.aliasForFrida, parametersTypesAliasesForFrida); } set implementation(callback) { Interceptor.revert(this.actualPointer); if (callback == null) return; if (this.actualPointer.isNull()) { console_1.raise(`Can't replace method ${this.name} from ${this.class.type.name}: pointer is NULL.`); } const parametersTypesAliasesForFrida = []; if (this.isInstance) { parametersTypesAliasesForFrida.push(this.class.type.aliasForFrida); } for (const parameterInfo of this.parameters) { parametersTypesAliasesForFrida.push(parameterInfo.type.aliasForFrida); } const methodInfo = this; const replaceCallback = function (...invocationArguments) { const instance = methodInfo.isInstance ? new object_1._Il2CppObject(invocationArguments[0]) : null; const startIndex = +methodInfo.isInstance | +variables_1.unityVersion.isLegacy; const args = methodInfo.parameters[accessor_1.filterAndMap](() => true, parameter => parameter.asHeld(invocationArguments, startIndex)); return callback.call(this, instance, args); }; const nativeCallback = new NativeCallback(replaceCallback, this.returnType.aliasForFrida, parametersTypesAliasesForFrida); Interceptor.replace(this.actualPointer, nativeCallback); Interceptor.flush(); } get parametersTypesAliasesForFrida() { const parametersTypesAliasesForFrida = new Array(this.parameterCount).fill("pointer"); if (this.isInstance || variables_1.unityVersion.isLegacy) { parametersTypesAliasesForFrida.push("pointer"); } if (this.isInflated) { parametersTypesAliasesForFrida.push("pointer"); } return parametersTypesAliasesForFrida; } invoke(...parameters) { return this._invoke(NULL, ...parameters); } intercept({ onEnter, onLeave }) { if (this.actualPointer.isNull()) { console_1.raise(`Can't intercept method ${this.name} from ${this.class.type.name}: pointer is NULL.`); } const interceptorCallbacks = {}; if (onEnter != undefined) { const methodInfo = this; interceptorCallbacks.onEnter = function (invocationArguments) { const instance = methodInfo.isInstance ? new object_1._Il2CppObject(invocationArguments[0]) : null; const startIndex = +methodInfo.isInstance | +variables_1.unityVersion.isLegacy; const args = methodInfo.parameters[accessor_1.filterAndMap](() => true, parameter => parameter.asHeld(invocationArguments, startIndex)); onEnter.call(this, instance, args); }; } if (onLeave != undefined) { const methodInfo = this; interceptorCallbacks.onLeave = function (invocationReturnValue) { onLeave.call(this, { valueHandle: invocationReturnValue.add(0), get value() { return utils_1.readRawValue(invocationReturnValue, methodInfo.returnType); }, set value(v) { invocationReturnValue.replace(utils_1.allocRawValue(v, methodInfo.returnType)); } }); }; } return Interceptor.attach(this.actualPointer, interceptorCallbacks); } trace() { if (this.actualPointer.isNull()) { console_1.warn(`Can't trace method ${this.name} from ${this.class.type.name}: pointer is NULL.`); } try { Interceptor.attach(this.actualPointer, () => console_1.inform(`${this.relativePointerAsString} ${this.name}`)); } catch (e) { console_1.warn(`Can't trace method ${this.name} from ${this.class.type.name}: ${e.message}.`); } } asHeld(holder) { const invoke = this._invoke.bind(this, holder); return { invoke(...parameters) { return invoke(...parameters); } }; } _invoke(instance, ...parameters) { if (this.parameterCount != parameters.length) { console_1.raise(`This method takes ${this.parameterCount} parameters, but ${parameters.length} were supplied.`); } const allocatedParameters = Array.from(this.parameters).map((parameter, i) => utils_1.allocRawValue(parameters[i], parameter.type)); if (this.isInstance || variables_1.unityVersion.isLegacy) allocatedParameters.unshift(instance); if (this.isInflated) allocatedParameters.push(this.handle); return utils_1.readRawValue(this.nativeFunction(...allocatedParameters), this.returnType); } }; __decorate([ decorator_cache_getter_1.cache ], _Il2CppMethod.prototype, "actualPointer", null); __decorate([ decorator_cache_getter_1.cache ], _Il2CppMethod.prototype, "class", null); __decorate([ decorator_cache_getter_1.cache ], _Il2CppMethod.prototype, "isGeneric", null); __decorate([ decorator_cache_getter_1.cache ], _Il2CppMethod.prototype, "isInflated", null); __decorate([ decorator_cache_getter_1.cache ], _Il2CppMethod.prototype, "isInstance", null); __decorate([ decorator_cache_getter_1.cache ], _Il2CppMethod.prototype, "name", null); __decorate([ decorator_cache_getter_1.cache ], _Il2CppMethod.prototype, "parameterCount", null); __decorate([ decorator_cache_getter_1.cache ], _Il2CppMethod.prototype, "parameters", null); __decorate([ decorator_cache_getter_1.cache ], _Il2CppMethod.prototype, "relativePointerAsString", null); __decorate([ decorator_cache_getter_1.cache ], _Il2CppMethod.prototype, "returnType", null); __decorate([ decorator_cache_getter_1.cache ], _Il2CppMethod.prototype, "nativeFunction", null); __decorate([ decorator_cache_getter_1.cache ], _Il2CppMethod.prototype, "parametersTypesAliasesForFrida", null); __decorate([ decorators_1.shouldBeInstance(false) ], _Il2CppMethod.prototype, "invoke", null); __decorate([ decorators_1.shouldBeInstance(true) ], _Il2CppMethod.prototype, "asHeld", null); _Il2CppMethod = __decorate([ decorators_1.nonNullHandle ], _Il2CppMethod); exports._Il2CppMethod = _Il2CppMethod;