Код
LIBRARY Test;
{!INFO
MODULENAME = 'Test'
VERSION = '0.1'
AUTHOR = 'sag'
}
USES Win, Utils, SysUtils, VPUtils;
//PROCEDURE HookCode(P: POINTER; NewAddr: POINTER; UseCall: BOOLEAN); external 'angel' name 'HookCode';
CONST
(* HookCode constants *)
C_HOOKTYPE_JUMP = FALSE;
C_HOOKTYPE_CALL = TRUE;
C_OPCODE_JUMP = $E9;
C_OPCODE_CALL = $E8;
C_UNIHOOK_SIZE = 5;
TYPE
(* Çàïèñü, íåîáõîäèìàÿ äëÿ ðàáîòû ñ ôóíêöèÿìè ïàò÷èíãà *)
THookRec = RECORD
Opcode: BYTE;
Ofs: INTEGER;
END; // .record THookRec
VAR
Temp: INTEGER; // Óíèâåðñàëüíàÿ âðåìåííàÿ ïåðåìåííàÿ
PROCEDURE WriteAtCode(P: POINTER; Buf: POINTER; Count: INTEGER);
BEGIN
Win.VirtualProtect(P, Count, PAGE_READWRITE, @Temp);
Win.CopyMemory(P, Buf, Count);
Win.VirtualProtect(P, Count, Temp, NIL);
END; // .procedure WriteAtCode
PROCEDURE HookCode(P: POINTER; NewAddr: POINTER; UseCall: BOOLEAN);
VAR
HookRec: THookRec;
BEGIN
IF UseCall THEN BEGIN
HookRec.Opcode:=C_OPCODE_CALL;
END // .if
ELSE BEGIN
HookRec.Opcode:=C_OPCODE_JUMP;
END; // .else
HookRec.Ofs:=INTEGER(NewAddr)-INTEGER(P)-C_UNIHOOK_SIZE;
WriteAtCode(P, @HookRec, 5);
END; // .procedure HookCode
PROCEDURE Hook_SAG_2;
BEGIN
PByte(PINTEGER($699538)^+$4DF18)^:= 0;
PByte(PINTEGER($699538)^+$4DF19)^:= 0;
END;
PROCEDURE Hook_SAG_1; ASSEMBLER; {$FRAME-}
ASM
PUSHAD
PUSHFD
CALL Hook_SAG_2
POPFD
POPAD
// old code from exe
MOV EDX, $2917560
//
PUSH $7792BF
END;
BEGIN
HookCode(POINTER($7792B9), @Hook_SAG_1, C_HOOKTYPE_JUMP);
END.
1) первым делом определяем место кода экзе куда мы вклиниваемся. Место можно определить шаманскими ритуалами с использованием программы IDA Pro + X-rays. Это самое сложное....В примере мы вклиниваемся по адресу $7792B9 который кстати не совсем верный (нам нужна процедура листания героев, а этот адрес срабатывает на любой лево-мышиный клик на экране старта карты).
HookCode(POINTER($7792B9), @Hook_SAG_1, C_HOOKTYPE_JUMP);
2) далее HookCode(POINTER($7792B9),
@Hook_SAG_1, C_HOOKTYPE_JUMP); отправляет нас в процедуру PROCEDURE Hook_SAG_1;
В ней мы вызываем процедуру PROCEDURE Hook_SAG_2;
путем CALL Hook_SAG_2 и не забываем выполнить исходный код который мы затерли своим хуком. а именно : выполняем
MOV EDX, $2917560
и переход на следующую команду PUSH $7792BF
3) процедура PROCEDURE Hook_SAG_2; простая до ужаса:
PByte(PINTEGER($699538)^+$4DF18)^:= 0;
PByte(PINTEGER($699538)^+$4DF19)^:= 0;
в ней просто обнуляем 2 элемента массива доступности героев (Оррин $4DF18, Валеска $4DF19). массив байтовый, начинается с адреса PINTEGER($699538)^+$4DF18. мы выковыриваем адрес смещения из $699538 и суммируем со вторым смещением $4DF18. по умолчанию в массиве все элементы = FF, если обнулить один элемент, то добавляется один герой из кампаний
4) далее распаковываем
http://wog.nxt.ru/diakon/patchexe.rar и ищем патчер Дьякона, запускаем его с аргументом в командной строке (бросаем нужный геройский экзе в папку с патчер-экзе и указывает его как аргумент патчер-экзе). На выходе - пропатченный геройский экзе который будет искать в корневой папке героев dll с названием Test.dll
5) компилируем dll в Virtual Pascal (результат - Test.dll )
6) бросаем Test.dll и патченный-геройский-экзе в корневую папку героев.
7) наслаждаемся результатом!