В видео я рассказывал про таблицу виртуальных функций (VTable). Что это такое, по сути?
Создаётся некий объект MyObj, который умеет две функции - Init() и Destroy():
class MyObj
{
virtual void Init() {}
virtual void Destroy() {}
}
var myObj = new MyObj();
Как только создаётся такой объект, с ним в памяти ассоциируется таблица функций, в дизассемблированном виде выглядящая как:
...
jmp init
...
...
jmp destroy
...
Если смотреть на это с точки зрения Direct3D, то все реализации (код) функций лежат в dll с именем d3d.dll, а когда создаётся новый объект d3d - получается вот такая картина:
Игровой код:
call [d3d+0x123]
vTable:
0x123: jmp init
d3d.dll:
0x456: init
Т.е. созданный объект стучится в присвоенную ему vTable, находит там (по смещению от начала) нужную функцию, а уже она указывает на конкретную реализацию в библиотеке.
Помните смещение из видео? [ECX+0AC]? 0xAC = 172 в десятичной системе счисления. 172/4 = 43. Почему делим на 4? Потому что все указатели (а vTable - это таблица указателей) занимают ровно 4 байта. Отнимаем ещё 4 байта (первые 4 - указатель на саму таблицу) - получаем, что Clear() находится на 42-й позиции в vTable. И это всегда так (для данной версии DirectX). Приятность тут в том, что это не зависит от игры. Никак. Если 20 игр используют эту версию библиотеки - во всех играх эта функция будет находиться по этому смещению в vTable.
Нам остаётся только как-то найти всё это дело, не вмешиваясь особо в код игры.
Создаётся некий объект MyObj, который умеет две функции - Init() и Destroy():
class MyObj
{
virtual void Init() {}
virtual void Destroy() {}
}
var myObj = new MyObj();
Как только создаётся такой объект, с ним в памяти ассоциируется таблица функций, в дизассемблированном виде выглядящая как:
...
jmp init
...
...
jmp destroy
...
Если смотреть на это с точки зрения Direct3D, то все реализации (код) функций лежат в dll с именем d3d.dll, а когда создаётся новый объект d3d - получается вот такая картина:
Игровой код:
call [d3d+0x123]
vTable:
0x123: jmp init
d3d.dll:
0x456: init
Т.е. созданный объект стучится в присвоенную ему vTable, находит там (по смещению от начала) нужную функцию, а уже она указывает на конкретную реализацию в библиотеке.
Помните смещение из видео? [ECX+0AC]? 0xAC = 172 в десятичной системе счисления. 172/4 = 43. Почему делим на 4? Потому что все указатели (а vTable - это таблица указателей) занимают ровно 4 байта. Отнимаем ещё 4 байта (первые 4 - указатель на саму таблицу) - получаем, что Clear() находится на 42-й позиции в vTable. И это всегда так (для данной версии DirectX). Приятность тут в том, что это не зависит от игры. Никак. Если 20 игр используют эту версию библиотеки - во всех играх эта функция будет находиться по этому смещению в vTable.
Нам остаётся только как-то найти всё это дело, не вмешиваясь особо в код игры.
Комментариев нет:
Отправить комментарий
Не люблю мат и низкий уровень грамотности. Чем конкретнее поставите свой вопрос и чем лучше он будет выглядеть - тем большая вероятность на мой ответ. :)