Wymagana jest znajomość obiektowego C++
Poradniki
#1 CInvoke - HookZacznijmy od podstaw - czym jest hook? Otóż Hook jest to doczepienie się do funkcji silnika. Pytanie po co? Dajmy przykład:
Mam funkcję sprawdzającą czy hero ma wyciągniętą broń dystansową. Podczas tego chciałbym mieć printa. Teraz mam dwa wyjścia:
A)Napisać szereg warunków i wywołać funkcję co klatkę
B)Zrobić Hook'a dzięki czemu oszczędzę sobie zbędnych warunków.
Wersja A:
Wersja B:
Chyba widać, że Hook jest krótszy. Teraz trzeba opisać co każdy element oznacza:
Zacznijmy od pustej funkcji:
int __fastcall _BowMode(
oCAIHuman*,
void*, int);
Pierwszy
int wziął się stąd, że oryginalna funkcja BowMode zawraca Int'a.
0x00695F00 protected: int __thiscall oCAIHuman::BowMode(int)
__fastcall - Funkcja musi zostać wywołana szybciej niż oryginalna, więc rejestry idą w ruch.
_BowMode - Nazwa funkcji. Chyba nie trzeba wyjaśniać.
oCAIHuman* - Jest to klasa z której pochodzi metoda. W Ikarusie uznawana jako zmienna ECX.
void* - Zawsze po zastosowaniu __fastcall, o ile hookowana funkcja miała typ __thiscall, po klasie jest "virtual table" oznaczany zmienną void* nie jest wykorzystany, ale MUSI BYĆ!
int - Argument z oryginalnej funkcji - w Ikarusie był odczytywany za pomocą MEM_ReadInt(ESP + ...);
Przeanalizuj, i spróbuj zrozumieć co się dzieje - do skutku!
Wykonałeś punkt o myśleniu? Nie? To analizuj, bo nic nie zrozumiesz...
Teraz opiszę Hook'a. Do dzieła.
CInvoke<
int(
__thiscall*)(
oCAIHuman*,
int)>
pBowMode(
0x00695F00,
_BowMode,
IVK_AUTO);
CInvoke - Szablon stworzony wewnątrz AST, służy do Hookowania.
int - zawsze na początku
CInvokemusimy podać co oryginalna funkcja zawraca. Tutaj zawracała Int'a, lecz jeżeli zawracała by
void dalibyśmy
void, jeżeli zawracałaby
zCView*, dalibyśmy
zCView* etc.
__thiscall* - funkcja była typu
__thiscall, czyli musimy tu umieścić
__thiscall*.
oCAIHuman* - Funkcja była metodą klasy, więc musimy podać wskaźnik do ów klasy.
int - Jej argumentem był tylko
int, jeżeli miałaby więcej argumentów podawalibyśmy je w kolejności po przecinku. Co ciekawe - w
CInvoke nigdy, nie podajemy
void*, co ma sens, ponieważ tylko w
__fastcall, musi być
void* po klasie i to tylko pod warunkiem, że hookowana funkcja była typu
__thiscall - jeżeli to wiedziałeś to dobrze zapamiętałeś pierwszy punkt o "Pustej funkcji"
pBowMode - Oryginalna funkcja, która posiada przed argumentami dodatkowy jeden argument którą jest klasa - w tym wypadku tym argumentem będzie
oCAIHuman*.
0x00695F00 - adres do oryginalnej funkcji możemy go dostać na kilka sposobów.
Sposób 1: Używając IDA szukamy adresu.
Sposób 2: Tabela z WoG'a - niestety nie mam linku.
Sposób 3: W AST 003 mamy plik G2_Names - są tam wszystkie adresy z gry.
_BowMode - wskaźnik do funkcji w której będą przechowane informacje o Hooku. Tak samo jak w Ikarusie HookEngine(adres, Len, funkcja);
IVK_AUTO - Polecam używać tego, gdyż niektóre funkcje były użyte w AST.dll - po prostu zapobiega błędom.
Trzeci punkt to rozbudowa funkcji
_BowMode. Jednak to już zostawiam wam. Możecie robić tam co chcecie. Dodam tylko od siebie - jeżeli nie damy w roboczej funkcji
pBowMode(_this, arg);Oryginalna funkcja nie wywoła się nigdy i nie będzie działać tak jak należy. Jeżeli w tym przykładzie zabrałbym
pBowMode(_this, arg); to bohater nie mógłby strzelać z łuku, chować broni długodystansowej etc.
Tak więc spróbujcie zrobić kilka przykładów dla utrwalenia. Więcej przykładów pojawi się wkrótce - piszę to szybko, ponieważ boję się o utratę prądu
Pozdrawiam Siemekk