Last active
January 9, 2019 06:38
-
-
Save fakuivan/61b3bb9e59d8ac724cedf1e8910de8e3 to your computer and use it in GitHub Desktop.
Use Cheat Engine's LUA engine to walk a struct to find offsets that match a given value and recursively walk potential structure pointers found within
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function scanTree(address, maxOffset, comparator, structValidator, maxDepth) | |
local offsetTree = {} | |
address = getAddress(address) | |
for currentOffset = 0, maxOffset, 1 do | |
local currentAddress = address + currentOffset | |
if comparator(currentAddress) then | |
offsetTree[currentOffset] = true | |
end | |
if maxDepth > 0 then | |
local nextNode = readPointer(currentAddress) | |
if structValidator(nextNode) then | |
-- If this is a valid offset, then we'll overwrite it | |
offsetTree[currentOffset] = scanTree(nextNode, | |
maxOffset, | |
comparator, | |
structValidator, | |
maxDepth - 1) | |
end | |
end | |
end | |
return offsetTree | |
end | |
function compareFloat(float1, float2, radius) | |
local lowerLimit = float2 - radius | |
local upperLimit = float2 + radius | |
return float1 <= upperLimit and float1 >= lowerLimit | |
end | |
function floatMemComparator(address, value, radius) | |
local toCompare = readFloat(address) | |
if not toCompare then return false else | |
return compareFloat(toCompare, value, radius) | |
end | |
end | |
function usableAddress(address) | |
--return not (address == 0 or address == nil) | |
return not (address == 0 or address == nil or readBytes(address, 1) == nil) | |
end | |
function formatOffset(symbol, offset, dontDereference) | |
dontDereference = (dontDereference or false) | |
local repr = string.format("%s+0x%X", symbol, offset) | |
if not dontDereference then | |
repr = string.format("[%s]", repr) | |
end | |
return repr | |
end | |
function printOffsets(currentOffsets, baseName, previusOffsets) | |
previusOffsets = previusOffsets or {} | |
for offset, structure in pairs(currentOffsets) do | |
if structure == true then | |
local offsetRepr = baseName | |
for _,previusOffset in ipairs(previusOffsets) do | |
offsetRepr = formatOffset(offsetRepr, previusOffset, false) | |
end | |
offsetRepr = formatOffset(offsetRepr, offset, true) | |
print(offsetRepr) | |
else | |
table.insert(previusOffsets, offset) | |
printOffsets(structure, baseName, previusOffsets) | |
table.remove(previusOffsets, #previusOffsets) | |
end | |
end | |
end | |
-- Example usage: | |
beginTime = os.time() | |
symbol = "[[[[[[[[PlayerBase]+10]+28]+338]+38]+28]+48]+148]" | |
maxOffset = 0x400 | |
comparator = function(address) return floatMemComparator(address, -133.9868927, 0.0001) end | |
depth = 3 | |
result = scanTree(getAddress(symbol), maxOffset, comparator, usableAddress, depth) | |
print("Finished") | |
printOffsets(result, symbol) | |
print("Finished") | |
print(string.format("Scan took %d second(s)", os.time() - beginTime)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment