-
Notifications
You must be signed in to change notification settings - Fork 49
Code snippets
Kruvcraft edited this page Apr 29, 2023
·
2 revisions
A live example of using the module.
All tests are carried out on the example of 1.apk. You can download it in the test
folder
Class for the test:
using UnityEngine;
using TMPro;
using System;
using ForTwoClass;
public class TestClass : TestVirtual
{
public int Field1;
public float Field2;
public static int Field3;
private const int field6 = 679;
private const float field7 = 23.345f;
private const string field8 = "Isn't Const";
private const uint field9 = 414141412;
private const bool field10 = true;
private const int field11 = -12414;
private const int field12 = 5;
public TestStruct Field13 = new TestStruct(2345, 1234);
private ForTwoClass.TestClass field14 = new ForTwoClass.TestClass(1);
private TestGenericClass<int> field15 = new TestGenericClass<int>();
public string Field16;
private System.Random random = new System.Random(DateTime.UtcNow.GetHashCode());
private GameObject[] textFields;
private GameObject[] textFieldsMethods;
private void Start()
{
Field1 = 1;
Field2 = 2;
Field3 = 3;
Field16 = "For String api";
textFields = GameObject.FindGameObjectsWithTag("Field");
textFieldsMethods = GameObject.FindGameObjectsWithTag("FieldMethod");
UpdateTextField();
}
public int GetField4()
{
return random.Next(0, 30) + GetOne() + GetTwo();
}
private static int GetTwo()
{
return TestClass.field12;
}
public override int GetOne()
{
return 100;
}
public int GetField5()
{
return (int)TestEnum.var4;
}
public string GetField13()
{
return this.Field13.ToString();
}
public void UpdateTextField()
{
Debug.Log(textFields.Length);
Type testClass = GetType();
foreach(GameObject textField in textFields)
{
string nameField = textField.name;
Debug.Log(nameField);
textField.GetComponent<TextMeshProUGUI>().text = String.Format("{0} = {1}", nameField, testClass.GetField(nameField).GetValue(this));
}
foreach (GameObject textField in textFieldsMethods)
{
string nameField = textField.name;
Debug.Log(nameField);
textField.GetComponent<TextMeshProUGUI>().text = String.Format("{0} = {1}", nameField, testClass.GetMethod("Get" + nameField).Invoke((object)this, null));
}
}
}
public enum TestEnum:int
{
var1,
var2,
var3,
var4,
}
public struct TestStruct
{
private int field1;
private float field2;
private string field3;
public TestStruct(
int Field1,
float Field2)
{
this.field1 = Field1;
this.field2 = Field2;
this.field3 = "Test String";
}
public override string ToString()
{
return $"[{this.field1}, {this.field2}, {this.field3}]";
}
}
namespace ForTwoClass
{
public class TestClass
{
private int field1;
public TestClass(int Field1)
{
field1 = Field1;
}
}
public class TestVirtual : MonoBehaviour
{
public virtual int GetOne()
{
return 1;
}
}
}
public abstract class TestAbstractClass<T>
{
public abstract T GetValue();
public abstract void TestAbstractMethod();
private void SetValue()
{
return;
}
}
public class TestGenericClass<T> : TestAbstractClass<T>
{
public override T GetValue()
{
return default(T);
}
public override void TestAbstractMethod()
{
return;
}
}
By pressing the Update
button, the application updates the text on the screen.
My code for changing class fields :
io.open('il2cppapi.lua',"w+"):write(gg.makeRequest("https://raw.githubusercontent.com/kruvcraft21/GGIl2cpp/master/build/Il2cppApi.lua").content):close()
require('il2cppapi')
os.remove('il2cppapi.lua')
Il2cpp()
---@type ClassConfig
local TestClassConfig = {}
TestClassConfig.Class = "TestClass"
TestClassConfig.FieldsDump = true
local TestClasses = Il2cpp.FindClass({TestClassConfig})[1]
local ChangeTestClasses = {}
print(TestClasses)
for k,v in ipairs(TestClasses) do
local TestClassObject = Il2cpp.FindObject({tonumber(v.ClassAddress, 16)})[1]
if v.Parent and v.Parent.ClassName ~= "ValueType" and #v.ClassNameSpace == 0 then
for i = 1, #TestClassObject do
ChangeTestClasses[#ChangeTestClasses + 1] = {
address = TestClassObject[i].address + tonumber(v:GetFieldWithName("Field1").Offset, 16),
flags = gg.TYPE_DWORD,
value = 40
}
ChangeTestClasses[#ChangeTestClasses + 1] = {
address = TestClassObject[i].address + tonumber(v:GetFieldWithName("Field2").Offset, 16),
flags = gg.TYPE_FLOAT,
value = 33
}
end
ChangeTestClasses[#ChangeTestClasses + 1] = {
address = v.StaticFieldData + tonumber(v:GetFieldWithName("Field3").Offset, 16),
flags = gg.TYPE_DWORD,
value = 12
}
end
end
gg.setValues(ChangeTestClasses)
Result of code execution:
Скрипт завершен:
{ -- table(245dc4)
[1] = { -- table(da5d4ad)
['ClassAddress'] = '79A5C56290',
['ClassName'] = 'TestClass',
['ClassNameSpace'] = '',
['Fields'] = { -- table(13673e2)
[1] = { -- table(e4a6373)
['Access'] = '',
['ClassAddress'] = '0',
['ClassName'] = 'TestClass',
['FieldName'] = '',
['IsConst'] = false,
['IsStatic'] = false,
['Offset'] = '0',
['Type'] = '(not support type -> 0x0)',
},
},
['ImageName'] = 'UnityEngine.CoreModule.dll',
['InstanceSize'] = 20,
['IsEnum'] = false,
['Parent'] = { -- table(deb9230)
['ClassAddress'] = '79A5BF0710',
['ClassName'] = 'ValueType',
},
['Token'] = '0x20000D1',
['TypeMetadataHandle'] = 516749687788,
},
[2] = { -- table(4f80ea9)
['ClassAddress'] = '79A5C61C10',
['ClassName'] = 'TestClass',
['ClassNameSpace'] = '',
['Fields'] = { -- table(1cbec2e)
[ 1] = { -- table(f5dc3cf)
['Access'] = 'public',
['ClassAddress'] = '79A5C61C10',
['ClassName'] = 'TestClass',
['FieldName'] = 'Field1',
['IsConst'] = false,
['IsStatic'] = false,
['Offset'] = '18',
['Type'] = 'int',
},
[ 2] = { -- table(dafa15c)
['Access'] = 'public',
['ClassAddress'] = '79A5C61C10',
['ClassName'] = 'TestClass',
['FieldName'] = 'Field2',
['IsConst'] = false,
['IsStatic'] = false,
['Offset'] = '1C',
['Type'] = 'float',
},
[ 3] = { -- table(19ec65)
['Access'] = 'public',
['ClassAddress'] = '79A5C61C10',
['ClassName'] = 'TestClass',
['FieldName'] = 'Field3',
['IsConst'] = false,
['IsStatic'] = true,
['Offset'] = '0',
['Type'] = 'int',
},
[ 4] = { -- table(c2e9d3a)
['Access'] = 'private',
['ClassAddress'] = '79A5C61C10',
['ClassName'] = 'TestClass',
['FieldName'] = 'field6',
['IsConst'] = true,
['IsStatic'] = false,
['Offset'] = '0',
['Type'] = 'int',
},
[ 5] = { -- table(89ccdeb)
['Access'] = 'private',
['ClassAddress'] = '79A5C61C10',
['ClassName'] = 'TestClass',
['FieldName'] = 'field7',
['IsConst'] = true,
['IsStatic'] = false,
['Offset'] = '0',
['Type'] = 'float',
},
[ 6] = { -- table(437748)
['Access'] = 'private',
['ClassAddress'] = '79A5C61C10',
['ClassName'] = 'TestClass',
['FieldName'] = 'field8',
['IsConst'] = true,
['IsStatic'] = false,
['Offset'] = '0',
['Type'] = 'string',
},
[ 7] = { -- table(4c1e9e1)
['Access'] = 'private',
['ClassAddress'] = '79A5C61C10',
['ClassName'] = 'TestClass',
['FieldName'] = 'field9',
['IsConst'] = true,
['IsStatic'] = false,
['Offset'] = '0',
['Type'] = 'uint',
},
[ 8] = { -- table(d95306)
['Access'] = 'private',
['ClassAddress'] = '79A5C61C10',
['ClassName'] = 'TestClass',
['FieldName'] = 'field10',
['IsConst'] = true,
['IsStatic'] = false,
['Offset'] = '0',
['Type'] = 'bool',
},
[ 9] = { -- table(785dc7)
['Access'] = 'private',
['ClassAddress'] = '79A5C61C10',
['ClassName'] = 'TestClass',
['FieldName'] = 'field11',
['IsConst'] = true,
['IsStatic'] = false,
['Offset'] = '0',
['Type'] = 'int',
},
[10] = { -- table(ebcbff4)
['Access'] = 'private',
['ClassAddress'] = '79A5C61C10',
['ClassName'] = 'TestClass',
['FieldName'] = 'field12',
['IsConst'] = true,
['IsStatic'] = false,
['Offset'] = '0',
['Type'] = 'int',
},
[11] = { -- table(392431d)
['Access'] = 'public',
['ClassAddress'] = '79A5C61C10',
['ClassName'] = 'TestClass',
['FieldName'] = 'Field13',
['IsConst'] = false,
['IsStatic'] = false,
['Offset'] = '20',
['Type'] = 'TestStruct',
},
[12] = { -- table(b279992)
['Access'] = 'private',
['ClassAddress'] = '79A5C61C10',
['ClassName'] = 'TestClass',
['FieldName'] = 'field14',
['IsConst'] = false,
['IsStatic'] = false,
['Offset'] = '30',
['Type'] = 'TestClass',
},
[13] = { -- table(9930f63)
['Access'] = 'private',
['ClassAddress'] = '79A5C61C10',
['ClassName'] = 'TestClass',
['FieldName'] = 'field15',
['IsConst'] = false,
['IsStatic'] = false,
['Offset'] = '38',
['Type'] = 'TestGenericClass`1',
},
[14] = { -- table(bdfe760)
['Access'] = 'public',
['ClassAddress'] = '79A5C61C10',
['ClassName'] = 'TestClass',
['FieldName'] = 'Field16',
['IsConst'] = false,
['IsStatic'] = false,
['Offset'] = '40',
['Type'] = 'string',
},
[15] = { -- table(b14f419)
['Access'] = 'private',
['ClassAddress'] = '79A5C61C10',
['ClassName'] = 'TestClass',
['FieldName'] = 'random',
['IsConst'] = false,
['IsStatic'] = false,
['Offset'] = '48',
['Type'] = 'Random',
},
[16] = { -- table(ea1bcde)
['Access'] = 'private',
['ClassAddress'] = '79A5C61C10',
['ClassName'] = 'TestClass',
['FieldName'] = 'textFields',
['IsConst'] = false,
['IsStatic'] = false,
['Offset'] = '50',
['Type'] = 'GameObject[]',
},
[17] = { -- table(41d3ebf)
['Access'] = 'private',
['ClassAddress'] = '79A5C61C10',
['ClassName'] = 'TestClass',
['FieldName'] = 'textFieldsMethods',
['IsConst'] = false,
['IsStatic'] = false,
['Offset'] = '58',
['Type'] = 'GameObject[]',
},
},
['ImageName'] = 'Assembly-CSharp.dll',
['InstanceSize'] = 96,
['IsEnum'] = false,
['Parent'] = { -- table(4c198c)
['ClassAddress'] = '79A5C5E250',
['ClassName'] = 'TestVirtual',
},
['StaticFieldData'] = 518487849712,
['Token'] = '0x2000002',
['TypeMetadataHandle'] = 516749753700,
},
[3] = { -- table(e77b8d5)
['ClassAddress'] = '79A5C8C310',
['ClassName'] = 'TestClass',
['ClassNameSpace'] = 'ForTwoClass',
['Fields'] = { -- table(d08c8ea)
[1] = { -- table(8f107db)
['Access'] = 'private',
['ClassAddress'] = '79A5C8C310',
['ClassName'] = 'TestClass',
['FieldName'] = 'field1',
['IsConst'] = false,
['IsStatic'] = false,
['Offset'] = '10',
['Type'] = 'int',
},
},
['ImageName'] = 'Assembly-CSharp.dll',
['InstanceSize'] = 24,
['IsEnum'] = false,
['Parent'] = { -- table(d674278)
['ClassAddress'] = '79A5BEF590',
['ClassName'] = 'Object',
},
['Token'] = '0x2000047',
['TypeMetadataHandle'] = 516749759772,
},
}
Завершено.
Скрипт записал 130 КБ в 2 файлов.