Вызов функций Warcraft 3, через mix (dll)
постараюсь объяснить максимально просто,без теории (совсем без теории).
Во первых нам понадобиться c++ (или аналог)
- Создаем новый проект, динамичная dll библиотека.
будет что-то на подобии этого:
#include "stdafx.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
Чтобы работать с jass`вскими функциями варика, во первых нужно узнать, хендл либы game.dll
добавляем 2 строчки:
глобальную переменную DWORD GameDll; и получение аддрес game.dll в памяти: GameDll = (DWORD) GetModuleHandle("Game.dll");
#include "stdafx.h"
DWORD GameDll = 0;
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
GameDll = (DWORD) GetModuleHandle("Game.dll");
break;
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
- Шаг - добавление функций.
SetPlayerTechMaxAllowed (Hplayer;II)V 0x3c9660
Где 0x3c9660 адресс этой функции. (Hplayer;II) - переменные Hplayer и 2 integer.
Где 0x3c9660 адресс этой функции. (Hplayer;II) - переменные Hplayer и 2 integer.
Пишем вызов функции, это будет выглядеть вот так:
__declspec(naked) void __cdecl SetPlayerTechMaxAllowed(Hplayer WhichPlayer, int TechId, int Maximum)
{
_asm
{
mov eax, GameDll
add eax, 0x3C9660
jmp eax
}
}
к регистру eax присваиваем адресс game.dll и добавляем адресс, тот который нашли ранее. Не забываем добавить тип "Hplayer"
typedef DWORD Hplayer;
Нам так-же понадобиться функция "Player(0)", делаем тоже самое, что и с SetPlayerTechMaxAllowed
declspec(naked) Hplayer cdecl Player(int number)
{
_asm
{
mov eax, GameDll
add eax, 0x3BBB30
jmp eax
}
}
{
_asm
{
mov eax, GameDll
add eax, 0x3BBB30
jmp eax
}
}
- Вызов, к примеру по нажатие на клавишу end. ничего писать не буду, просто кину финальный код.
#include "stdafx.h"
#define IS_KD(lParam) ((lParam & ((DWORD)1<<30)) == 0 && (lParam & ((DWORD)1<<31)) == 0)
DWORD GameDll = 0;
typedef DWORD Hplayer;
HHOOK KHook = NULL;
__declspec(naked) Hplayer __cdecl Player(int number)
{
_asm
{
mov eax, GameDll
add eax, 0x3BBB30
jmp eax
}
}
__declspec(naked) void __cdecl SetPlayerTechMaxAllowed(Hplayer WhichPlayer, int TechId, int Maximum)
{
_asm
{
mov eax, GameDll
add eax, 0x3C9660
jmp eax
}
}
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (IS_KD(lParam) )
{
SetPlayerTechMaxAllowed(Player(15), 4,28);
}
return CallNextHookEx(KHook, nCode, wParam, lParam);
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
GameDll = (DWORD) GetModuleHandle("Game.dll");
KHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, hModule, GetCurrentThreadId());
break;
}
case DLL_PROCESS_DETACH:
{
UnhookWindowsHookEx(KHook);
break;
}
break;
}
return TRUE;
}
принципе пока все, в след статье расскажу про хуки, и как вызвать из под варика функции нашей библиотеки (но без теории не обойтись).
Ред. Vitalik8
Ред. kaganec
GameDll = (DWORD)GetModuleHandle("Game.dll");
Как её можно исправить?
*(BYTE*) (GameDll + 0x2de2a0+ 0x0) = 0xE8;
*(DWORD*) (GameDll + 0x2de2a0+ 0x1) = (DWORD)hookCHS - (dwGameBaseAddress + 0x2de2a0+ 0x5);
*(BYTE*) (GameDll + 0x2de2a0+ 0x5) = 0xC3;
Тут что два одинаковых адреса в разных переменных? В GameDll и в dwGameBaseAddress?