Skip to content

Commit

Permalink
fix PackList, add new B_Button Type
Browse files Browse the repository at this point in the history
  • Loading branch information
axhlzy committed Mar 29, 2024
1 parent fe27a9e commit 01acee8
Show file tree
Hide file tree
Showing 22 changed files with 1,811 additions and 44 deletions.
3 changes: 2 additions & 1 deletion Il2cppHook/agent/base/dynamic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ const packMethod = (method: Il2Cpp.Method) => {
return method
}

export const showParentClass = (handle: NativePointer | Il2Cpp.Class) => {
export const showParentClass = (handle: NativePointer | Il2Cpp.Class | string) => {
if (typeof handle === "string") handle = findClass(handle)
let clazz: Il2Cpp.Class | null = handle instanceof Il2Cpp.Class ? handle : new Il2Cpp.Class(checkCmdInput(handle))
let display: string = ""
while (clazz != null && !clazz.isNull()) {
Expand Down
4 changes: 4 additions & 0 deletions Il2cppHook/agent/base/valueResolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@ export class ValueResolve {
}
}

export function FakeCommonTypeObj(il2cppObject: Il2Cpp.Object):string {
return FakeCommonType(il2cppObject.class.type, il2cppObject.handle)
}

// 类型解析
export function FakeCommonType(type: Il2Cpp.Type, mPtr: NativePointer): string {
// LOGW(`FakeCommonType ${type.name} ${mPtr}`)
Expand Down
40 changes: 21 additions & 19 deletions Il2cppHook/agent/bridge/fix/packer/packList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,21 @@ export class PackList implements list_impl {
if (!doNotCheck) {
if (!this.class.name.includes('List`')) throw new Error('Input mPtr is not a list')
}
// _defaultCapacity 和 _emptyArray 不同unity版本可能不太一样
// _defaultCapacity 和 _emptyArray 不同 unity版本可能不太一样
try {
this._defaultCapacity = this.class.field('_defaultCapacity').value as number
this._defaultCapacity = this.object.field<number>('_defaultCapacity').value
} catch {
this._defaultCapacity = this.class.field('DefaultCapacity').value as number
this._defaultCapacity = this.object.tryField<number>('DefaultCapacity')!.value
}
try {
this._emptyArray = this.class.field('_emptyArray').value as NativePointer
this._emptyArray = this.object.field<NativePointer>('_emptyArray').value
} catch {
this._emptyArray = this.class.field('s_emptyArray').value as NativePointer
this._emptyArray = this.object.tryField<NativePointer>('s_emptyArray')!.value
}
this._items = this.class.field('_items').value as NativePointer
this._size = this.class.field('_size').value as number
this._version = this.class.field('_version').value as number
this._syncRoot = this.class.field('_syncRoot').value as NativePointer
this._items = this.object.tryField<NativePointer>('_items')!.value
this._size = this.object.tryField<number>('_size')!.value
this._version = this.object.tryField<number>('_version')!.value
this._syncRoot = this.object.tryField<NativePointer>('_syncRoot')!.value
} catch (error) { throw error }
}

Expand Down Expand Up @@ -115,43 +115,45 @@ export class PackList implements list_impl {

get_Item(index: number = 0): Il2Cpp.Object {
if (index > this.get_Count() - 1) throw new Error(`Index out of range: ${index}`)
return this.object.method('get_Item').invoke(index) as Il2Cpp.Object
const ret = new Il2Cpp.Object(this.object.method<NativePointer>('get_Item').invoke(index))
// LOGE(`${this.handle} | ${this.object.handle} | ${this.object.method<NativePointer>('get_Item')} | get_Item(${index}) -> ${ret} | ${ret.handle}`)
return ret
}

set_Item(index: number = 0, value: NativePointer): void {
return this.object.method('set_Item').invoke(index, value) as void
this.object.method('set_Item').invoke(index, value)
}

get_Capacity(): number {
return this.object.method('get_Capacity').invoke() as number
return this.object.method<number>('get_Capacity').invoke()
}

set_Capacity(newCapacity: number): void {
return this.object.method('set_Capacity').invoke(newCapacity) as void
this.object.method('set_Capacity').invoke(newCapacity)
}

get_Count(): number {
return this.object.method('get_Count').invoke() as number
return this.object.method<number>('get_Count').invoke()
}

RemoveAt(index: number = 0): void {
return this.object.method('RemoveAt').invoke(index) as void
this.object.method('RemoveAt').invoke(index)
}

Add(value: NativePointer): void {
return this.object.method('Add').invoke(value) as void
this.object.method('Add').invoke(value)
}

Contains(value: NativePointer): boolean {
return this.object.method('Contains').invoke(value) as boolean
return !this.object.method<NativePointer>('Contains').invoke(value).isNull()
}

Clear(): void {
return this.object.method('Clear').invoke() as void
this.object.method('Clear').invoke()
}

Reverse(): void {
return this.object.method('Reverse').invoke() as void
this.object.method('Reverse').invoke()
}

static localArray(mPtr: NativePointer): NativePointer {
Expand Down
52 changes: 29 additions & 23 deletions Il2cppHook/agent/bridge/fix/parseFields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,20 @@ export class FieldsParser {
}

fieldInstance(fieldName: string): Il2Cpp.Field | null {
if (this.mPtr.isNull()) return null
return this.mClass.field(fieldName)
if (this.mPtr.isNull() || this.mPtr == null) return null
let ret :Il2Cpp.Field | null
try {
ret = this.mClass.field(fieldName)
} catch (error) {
return null
}
return ret
}

fieldValue(fieldName: string): NativePointer {
if (this.mPtr.isNull()) return ptr(0)
if (this.mPtr.isNull() || this.mPtr == null) return ptr(0)
try {
let field: Il2Cpp.Field | null = this.fieldInstance(fieldName)
const field: Il2Cpp.Field | null = this.fieldInstance(fieldName)
if (field == null) return ptr(0)
if (field.isStatic) return fakeStaticField(field).readPointer()
return this.mPtr.add(this.fieldOffset(fieldName)).readPointer()
Expand All @@ -63,41 +69,41 @@ export class FieldsParser {
}

fieldOffset(fieldName: string): number {
let field: Il2Cpp.Field | null = this.fieldInstance(fieldName)
const field: Il2Cpp.Field | null = this.fieldInstance(fieldName)
if (field == null) return -1
return field.offset
}

toShow(retB: Boolean = false) {
if (this.mPtr.isNull()) return
newLine()
let titile = `Found ${this.mClass.fields.length} fields in class: ${this.mClass.name} (${this.mClass.handle})`
const titile = `Found ${this.mClass.fields.length} fields in class: ${this.mClass.name} (${this.mClass.handle})`
this.mClass.fields.length == 0 ? LOGE(titile) : LOGO(titile)
if (this.mClass.fields.length == 0) return newLine()
LOGO(getLine(50))
let countNum: number = -1
this.mClass.fields
.sort((f1: Il2Cpp.Field, f2: Il2Cpp.Field) => f1.offset - f2.offset)
.forEach((field: Il2Cpp.Field) => {
let index: string = FM.alignStr(`[${++countNum}]`, 6)
let offset: NativePointer = ptr(field.offset)
let modifier: string = getModifier(field.flags).trim()
let classDes: string = `${field.type.class.name} (${field.type.class.handle})`
let fieldName: string = field.name
LOGD(`${index} ${offset} ${modifier} ${classDes}\t${fieldName}`) // 字段通用信息打印
const index: string = FM.alignStr(`[${++countNum}]`, 6)
const offset: NativePointer = ptr(field.offset)
const modifier: string = getModifier(field.flags).trim()
const classDes: string = `${field.type.class.name} (${field.type.class.handle})`
const fieldName: string = field.name
LOGD(`${index} ${offset} ${modifier} ${classDes}\t${fieldName}`) // common info
let disp = dealWithSpecialType(field, this.mPtr)
let thisHandle: NativePointer = this.mPtr.add(field.offset)
let thisValue: NativePointer = thisHandle.readPointer()
let splitStr = " ---> "
LOGZ(`\t${thisHandle}${splitStr}${FM.alignStr(thisValue)}${String(disp).length == 0 ? "" : splitStr}${disp}`)
const thisHandle: NativePointer = this.mPtr.add(field.offset)
const thisValue: NativePointer = thisHandle.readPointer()
const splitStr = " ---> "
LOGZ(`\t${thisHandle}${splitStr}${FM.alignStr(thisValue)}${String(disp).length == 0 ? "" : splitStr}${disp}`) // value info
if (!retB) newLine()
})
LOGO(getLine(50))
}

toString(): string {
if (this.mPtr.isNull()) return ""
let retMap: Map<string, any> = new Map()
const retMap: Map<string, any> = new Map()
this.mClass.fields
.sort((f1: Il2Cpp.Field, f2: Il2Cpp.Field) => f1.offset - f2.offset)
.forEach((field: Il2Cpp.Field) => {
Expand All @@ -117,19 +123,19 @@ const dealWithSpecialType = (field: Il2Cpp.Field, thisValueP: NativePointer): st
return fakeStaticField(field).toString()
// 对枚举的解析
else if (field.type.class.isEnum) {
let value = thisValueP.add(field.offset)
const value = thisValueP.add(field.offset)
return `Enum : ${enumNumToName(value.readPointer().toInt32(), field.type.class.name, field.type.class.handle)}`
}

if (thisValueP.isNull()) return ""
let thisValue: NativePointer = thisValueP.add(field.offset).readPointer()
const thisValue: NativePointer = thisValueP.add(field.offset).readPointer()

return FakeCommonType(field.type, thisValue)
}

function fakeStaticField(field: Il2Cpp.Field): NativePointer {
try {
let tmpOut: NativePointer = alloc()
const tmpOut: NativePointer = alloc()
Il2Cpp.Api._fieldGetStaticValue(field.handle, tmpOut)
return tmpOut
} catch (error) {
Expand Down Expand Up @@ -164,10 +170,10 @@ globalThis.lfs = (mPtr: NativePointer, classHandle: NativePointer | string | obj

// 解析实例的 fields 以及 class 父级 fields (p means parents)
globalThis.lfp = (mPtr: NativePointer) => {
let classType: Array<mscorlib.Type> = (getTypeParent(mPtr) as Array<mscorlib.Type>).reverse().map((localType: mscorlib.Type) => {
let localT = new Il2Cpp.Class(localType.handle)
const classType: Array<mscorlib.Type> = (getTypeParent(mPtr) as Array<mscorlib.Type>).reverse().map((localType: mscorlib.Type) => {
const localT = new Il2Cpp.Class(localType.handle)
if (localT.isAbstract) {
let objT = Il2Cpp.Image.corlib.class("System.Object")
const objT = Il2Cpp.Image.corlib.class("System.Object")
return new mscorlib.Type(localT.inflate(objT).type.handle)
}
return localType
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import './api'
import './class'
import './enum'
import './export'
Loading

0 comments on commit 01acee8

Please sign in to comment.