Решил попробовать написать CE Lua скрипт, который прочесывает структуру и в Dissect data/structures окне создавал бы структуру только со смещениями, с которыми код работает, т.е. читает или пишет.
Например, мой персонаж прогуливается по городу, а каждые 200 мс ставится брейкпоинт на смещение +1 до гипотетической N границы структуры (например до 4096).
Я не успел сделать определение типа, но смещения внутри структуры получить я успел.
Итак, находим начало структуры любой. Запускаем Lua скрипт и просто что-то делаем в игре. Потом вылазит текст с дизассемблированными инструкциями и смещениями. Уже по этим логам можно определить вручную
к каким смещением было обращение (адреса по ним мы и будем менять или сравнивать структуры между собой позже)
по виду инструкции и соседнему смещению уже примерно можно определить тип данных и их размер
a3ea23e7-54e8-46c5-82a5-f3d2a73cc540-изображение.png
Осталось сделать определение типа, а это не так уж долго сделать и осталось взять код из предыдущих записей в блоге формирования структуры в окне dessect data. Так мы получим структуру только с активными смещениями, (а зачем нам пассивные?) и определим в них тип, я надеюсь определим правильно
Пример кода, который я использовал
addressStructure1 = 0x412E0200 --> адрес начала структуры в любой игре
sizeStructure = 100 --> гипототический размер структуры 100 для быстрых поисков, по умолчанию 4096
indexStructure = 0 --> индекс внутри структуры, который будет перемещаться вместе с breakPointAddress
breakPointAddress = 0 --> адрес, на который сейчас постален брейкпоинт
waitTimeTillBreak = 300 --> частота активности смещеиня
resultText = '' --> конкатенация частей текста в этой переменной
\-- Функция пытается поставить брейкпоинт на следующий байт в структуре
function TryNextSetBreakPointToAddress()
debug_removeBreakpoint(breakPointAddress)
indexStructure = indexStructure + 1
if indexStructure > sizeStructure then
debugTimer.Interval = 1000
debugTimer.Enabled = false
debugTimer.destroy()
debug_continueFromBreakpoint(co_run)
print(resultText) --> вывод результата с завершением отладки
return
end
breakPointAddress = addressStructure1 + indexStructure
debug_setBreakpoint(breakPointAddress, 1, bptAccess, bpmDebugRegister)
debug_continueFromBreakpoint(co_run)
end
\-- Любимая функция снятия отладочных данных
function debugger_onBreakpoint()
-- проверить обращение к структуре
prevAddress = getPreviousOpcode(RIP)
resultText = resultText..string.format('Offset: + %X : %s', indexStructure, disassemble(prevAddress)) .. '\r\n'
TryNextSetBreakPointToAddress()
return 1
end
\-- Простой таймер
debugTimer = createTimer(nil, false)
debugTimer.OnTimer = function(timer) TryNextSetBreakPointToAddress() end
debugTimer.Interval = waitTimeTillBreak
debugTimer.Enabled = true
breakPointAddress = addressStructure1 + indexStructure
debug_setBreakpoint(breakPointAddress, 1, bptAccess, bpmDebugRegister)