Skip to content

Commit

Permalink
Update Module
Browse files Browse the repository at this point in the history
The code has been optimized. Now the code is adapted to the Lua plugin for VS Code. Added a raw version of storing search results.
  • Loading branch information
kruvcraft21 committed Jun 28, 2022
1 parent f2fb1f2 commit 7b20720
Show file tree
Hide file tree
Showing 2 changed files with 180 additions and 71 deletions.
174 changes: 108 additions & 66 deletions Il2cppApi.lua
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ function getAlfUtf16()
return Utf16
end

--- Is a function that was created to patch the desired address. The first argument should be an offset, and the subsequent ones should be constructs.
---@param StartAddress number
function addresspath(StartAddress, ...)
local args, patch = {...}, {}
for i = 1,#args do
Expand All @@ -60,39 +62,6 @@ function CheckSupportType(index, typeIndex)
return Il2cpp.GlobalMetadataApi:GetClassName(index)
end

function ChooseIl2cppVersion(version)
version = (version <= 24 and version > 0) and 24 or ((version > 24 and version <= 27) and 27 or 0)
if (Il2cppApi[version]) then
local api = Il2cppApi[version]

Il2cpp.FieldApi.Offset = api.FieldApiOffset
Il2cpp.FieldApi.Type = api.FieldApiType
Il2cpp.FieldApi.ClassOffset = api.FieldApiClassOffset

Il2cpp.ClassApi.NameOffset = api.ClassApiNameOffset
Il2cpp.ClassApi.MethodsStep = api.ClassApiMethodsStep
Il2cpp.ClassApi.CountMethods = api.ClassApiCountMethods
Il2cpp.ClassApi.MethodsLink = api.ClassApiMethodsLink
Il2cpp.ClassApi.FieldsLink = api.ClassApiFieldsLink
Il2cpp.ClassApi.FieldsStep = api.ClassApiFieldsStep
Il2cpp.ClassApi.CountFields = api.ClassApiCountFields

Il2cpp.MethodsApi.ClassOffset = api.MethodsApiClassOffset
Il2cpp.MethodsApi.NameOffset = api.MethodsApiNameOffset
Il2cpp.MethodsApi.ParamCount = api.MethodsApiParamCount
Il2cpp.MethodsApi.ReturnType = api.MethodsApiReturnType

Il2cpp.GlobalMetadataApi.typeDefinitionsSize = api.typeDefinitionsSize
Il2cpp.GlobalMetadataApi.typeDefinitionsOffset = api.typeDefinitionsOffset
Il2cpp.GlobalMetadataApi.stringOffset = api.stringOffset
Il2cpp.GlobalMetadataApi.version = version

Il2cpp.TypeApi.Type = api.TypeApiType
else
error('Not support this il2cpp version')
end
end

Il2cppApi = {
[24] = {
FieldApiOffset = platform and 0x18 or 0xC,
Expand Down Expand Up @@ -133,14 +102,61 @@ Il2cppApi = {
typeDefinitionsOffset = 0xA0,
stringOffset = 0x18,
TypeApiType = platform and 0xA or 0x6,
}
},
ChooseIl2cppVersion = function(self, version)
version = (version <= 24 and version > 0) and 24 or ((version > 24 and version <= 27) and 27 or 0)
if (self[version]) then
local api = self[version]

Il2cpp.FieldApi.Offset = api.FieldApiOffset
Il2cpp.FieldApi.Type = api.FieldApiType
Il2cpp.FieldApi.ClassOffset = api.FieldApiClassOffset

Il2cpp.ClassApi.NameOffset = api.ClassApiNameOffset
Il2cpp.ClassApi.MethodsStep = api.ClassApiMethodsStep
Il2cpp.ClassApi.CountMethods = api.ClassApiCountMethods
Il2cpp.ClassApi.MethodsLink = api.ClassApiMethodsLink
Il2cpp.ClassApi.FieldsLink = api.ClassApiFieldsLink
Il2cpp.ClassApi.FieldsStep = api.ClassApiFieldsStep
Il2cpp.ClassApi.CountFields = api.ClassApiCountFields

Il2cpp.MethodsApi.ClassOffset = api.MethodsApiClassOffset
Il2cpp.MethodsApi.NameOffset = api.MethodsApiNameOffset
Il2cpp.MethodsApi.ParamCount = api.MethodsApiParamCount
Il2cpp.MethodsApi.ReturnType = api.MethodsApiReturnType

Il2cpp.GlobalMetadataApi.typeDefinitionsSize = api.typeDefinitionsSize
Il2cpp.GlobalMetadataApi.typeDefinitionsOffset = api.typeDefinitionsOffset
Il2cpp.GlobalMetadataApi.stringOffset = api.stringOffset
Il2cpp.GlobalMetadataApi.version = version

Il2cpp.TypeApi.Type = api.TypeApiType
else
error('Not support this il2cpp version')
end
end
}

-- Memorizing Il2cpp Search Result
Il2cppMemory = {
Methods = {}
}

Il2cpp = {
il2cppStart = 0,
il2cppEnd = 0,
globalMetadataStart = 0,
globalMetadataEnd = 0,
--- Patch `Bytescodes` to `add`
---
--- Example:
--- arm64:
--- `mov w0,#0x1`
--- `ret`
---
--- `Il2cpp.PatchesAddress(0x100, "\x20\x00\x80\x52\xc0\x03\x5f\xd6")`
---@param add number
---@param Bytescodes string
PatchesAddress = function(add, Bytescodes)
local patch = {}
for code in string.gmatch(Bytescodes, '.') do
Expand All @@ -152,15 +168,32 @@ Il2cpp = {
end
gg.setValues(patch)
end,
--- Searches for a method, or rather information on the method, by name or by offset, you can also send an address in memory to it.
---
--- Return table with information about methods.
---@param searchArgs table
---@return table
FindMethods = function(searchArgs)
local MethodsMemory = Il2cppMemory.Methods
for i = 1, #searchArgs do
searchArgs[i] = Il2cpp.MethodsApi.Find(Il2cpp.MethodsApi, searchArgs[i])
if MethodsMemory[searchArgs[i]] then
searchArgs[i] = MethodsMemory[searchArgs[i]]
else
local searchResult = Il2cpp.MethodsApi:Find(searchArgs[i])
MethodsMemory[searchArgs[i]] = searchResult
searchArgs[i] = searchResult
end
end
return searchArgs
end,
--- Searches for a class, by name, or by address in memory.
---
--- Return table with information about class.
---@param searchArgs table
---@return table
FindClass = function(searchArgs)
for i = 1, #searchArgs do
searchArgs[i] = Il2cpp.ClassApi.Find(Il2cpp.ClassApi, searchArgs[i])
for i = 1, #searchArgs do
searchArgs[i] = Il2cpp.ClassApi:Find(searchArgs[i])
end
return searchArgs
end,
Expand Down Expand Up @@ -427,18 +460,20 @@ Il2cpp = {
if (#ResultTable == 0) then error('nothing was found for this address 0x' .. string.format("%X", ClassAddress)) end
return ResultTable
end,
FindArgsCheck = {
['number'] = function (self, _class)
return Protect:Call(self.FindClassWithAddressInMemory, self, _class)
end,
['string'] = function (self, _class)
return Protect:Call(self.FindClassWithName, self, _class)
end,
['default'] = function()
return {Error = 'Invalid search criteria'}
end
},
Find = function (self, class)
local ClassInfo = switch(type(class.Class), {
['number'] = function (self, _class)
return Protect:Call(self.FindClassWithAddressInMemory, self, _class)
end,
['string'] = function (self, _class)
return Protect:Call(self.FindClassWithName, self, _class)
end,
}, {Error = 'Invalid search criteria'},self, class.Class)
if (#ClassInfo == 0) then
ClassInfo = {ClassInfo}
else
local ClassInfo = (self.FindArgsCheck[type(class.Class)] or self.FindArgsCheck['default'])(self, class.Class)
if #ClassInfo ~= 0 then
for k = 1, #ClassInfo do
ClassInfo[k] = self:UnpackClassInfo(ClassInfo[k], {FieldsDump = class.FieldsDump, MethodsDump = class.MethodsDump})
end
Expand Down Expand Up @@ -568,22 +603,24 @@ Il2cpp = {
ClassName = MethodInfo.ClassName,
}
end,
FindArgsCheck = {
['number'] = function(self, method)
if (method > Il2cpp.il2cppStart and method < Il2cpp.il2cppEnd) then
return Protect:Call(self.FindMethodWithAddressInMemory, self, method)
else
return Protect:Call(self.FindMethodWithOffset, self, method)
end
end,
['string'] = function(self, method)
return Protect:Call(self.FindMethodWithName, self, method)
end,
['default'] = function()
return {Error = 'Invalid search criteria'}
end
},
Find = function (self, method)
local _MethodsInfo = switch(type(method), {
['number'] = function (self, method)
if (method > Il2cpp.il2cppStart and method < Il2cpp.il2cppEnd) then
return Protect:Call(self.FindMethodWithAddressInMemory, self, method)
else
return Protect:Call(self.FindMethodWithOffset, self, method)
end
end,
['string'] = function (self, method)
return Protect:Call(self.FindMethodWithName, self, method)
end,
}, 'Invalid search criteria',self, method)
if (#_MethodsInfo == 0) then
_MethodsInfo = {_MethodsInfo}
else
local _MethodsInfo = (self.FindArgsCheck[type(method)] or self.FindArgsCheck['default'])(self, method)
if (#_MethodsInfo ~= 0) then
local MethodsInfo = {}
for k = 1, #_MethodsInfo do
local MethodInfo
Expand All @@ -593,6 +630,7 @@ Il2cpp = {
MethodsInfo = gg.getValues(MethodsInfo)
self:DecodeMethodsInfo(_MethodsInfo, MethodsInfo)
end

return _MethodsInfo
end
}
Expand Down Expand Up @@ -662,9 +700,13 @@ Il2cpp = setmetatable(Il2cpp, {
end

if args[3] then
ChooseIl2cppVersion(args[3])
Il2cppApi:ChooseIl2cppVersion(args[3])
else
ChooseIl2cppVersion(gg.getValues({{address = self.globalMetadataStart + 0x4, flags = gg.TYPE_DWORD}})[1].value)
Il2cppApi:ChooseIl2cppVersion(gg.getValues({{address = self.globalMetadataStart + 0x4, flags = gg.TYPE_DWORD}})[1].value)
end

Il2cppMemory.Methods = {}
end
})
})

return Il2cpp
77 changes: 72 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
# Il2cpp Module for GameGuardian

## About script
This script is only needed to make it easier to work with Il2cpp. This script works through the program [GameGuardian](https://gameguardian.net). With the help of the module, you can get information about the method or class that interests you.
This script is only needed to make it easier to work with Il2cpp. This script works through the program [GameGuardian](https://gameguardian.net). With the help of the module, you can get information about the method or class that interests you.

The module has support for the [Lua](https://marketplace.visualstudio.com/items?itemName=yinfei.luahelper) plugin for `VS Code`, that is, some functions have a description that this plugin can display.


## About Module

This Module has 4 functions
This Module has 5 functions

```lua
Il2cpp()
Il2cpp.FindMethods()
Il2cpp.FindClass()
Il2cpp.PatchesAddress()
addresspath()
```


* "Il2cpp()" - This function takes from 0 to 2 arguments, it is needed to indicate the beginning of global-metadata and libil2cpp. Without it, the function located in the Il2cpp table will not work.
* "Il2cpp.FindMethods()" - Searches for a method, or rather information on the method, by name or by offset, you can also send an address in memory to it.
* "Il2cpp.FindClass()" - Searches for a class, or rather information on a method, by name or by address in memory.
* "Il2cpp.FindClass()" - Searches for a class, by name, or by address in memory.
* "Il2cpp.PatchesAddress()" - Patch `Bytescodes` to `add`
* "addresspath()" - is a function that was created to patch the desired address. The first argument should be an offset, and the subsequent ones should be constructs.

## How to use
Expand Down Expand Up @@ -159,7 +163,7 @@ print(Il2cpp.FindClass({{Class = 'MyClass', MethodsDump = true, FieldsDump = tru
]]

local Method1 = Il2cpp.FindMethods({'Method1'})[1]
for k,v in pairs(Method1) do
for k,v in ipairs(Method1) do
if v.Class == 'MyClass' then
addresspath(tonumber(v.AddressInMemory,16),"\x20\x00\x80\x52","\xc0\x03\x5f\xd6")
end
Expand All @@ -175,6 +179,26 @@ arm64:
51235003 C0035FD6 ret
]]

local Method1 = Il2cpp.FindMethods({'Method1'})[1]
for k,v in ipairs(Method1) do
if v.Class == 'MyClass' then
Il2cpp.PatchesAddress(tonumber(v.AddressInMemory,16),"\x20\x00\x80\x52\xc0\x03\x5f\xd6")
end
end

--output
--[[
this code changes will change the method "Method1", so that it constantly returns 1
arm64:
51234FFF 20008052 mov w0,#0x1
51235003 C0035FD6 ret
]]


```
Without the `Il2cpp()` function, some functions will not work, since this function remembers or finds the location `libil2cpp.so` and `global-metadata.dat`. You can also specify the version of `Il2cpp`, this will be required in cases where the module cannot determine the version itself.

Expand All @@ -192,4 +216,47 @@ local globalmetadata = {start = 0x9888, ['end'] = 0x14888}
Il2cpp(libil2cpp, globalmetadata) -- in this case, "Il2cpp()" and will remember the location "libil2cpp.so " and "global-metadata.dat", which was passed to him.

Il2cpp(nil, nil, 27) -- in this case , the method will find "libil2cpp.so" and "global-metadata.dat" and will remember the "Il2cpp" version
```
```

It is worth talking about processing the results of the module.

If the search fails, the functions will return a table with an error. Therefore, I recommend using `ipairs` to work with search results, but `pairs` can also be used, only you will have to check the key coming for processing. Otherwise, you may get a missing field error.

Example:
```Lua
local searchResult = Il2cpp.FindMethods({'Method2', 'Method1', 'method does not exist'})

for k,v in ipairs(searchResult[1]) do
print(v.ClassName)
end

-- output
--[[
MyClass
]]

for k,v in pairs(searchResult[2]) do
if k ~= 'Error' then print(v.ClassName) end
end

-- output
--[[
MyClass
]]

for k,v in pairs(searchResult[3]) do
print(v.ClassName)
end

-- output
--[[
nil
]]

```

## Memorizing Il2cpp Search Result

`Memorizing Il2cpp Search Result` is a special simple system to speed up the module. It remembers the search results, so far it only works with `Il2cpp.FindMethods`, since for `Il2cpp.FindClass` it is necessary to do a lot of checks, which may lead to the module not being effective. But in the future, this system will be improved to work with all types of search.

It is worth noting that any call to the `Il2cpp()` function will reset this system.

0 comments on commit 7b20720

Please sign in to comment.