| 
 
				Без проблем. 
LIBRARY HookDamage;{!INFO
 MODULENAME = 'Damage'
 VERSION = '1.0'
 AUTHOR = 'Sav'
 }
 
 USES Win, Utils, SysUtils, VPUtils;
 
 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;
 
 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 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;
 
 
 
 //Модификация удара с флагом бить всех вокруг.
 //Вместо вычисления 8-ми атакованных позиций, проверяется каждый из 42 стеков на необходимость атаки по нему (записанную в v-переменных).
 //$890AD8 - v9501 - номера целевых стеков атакующего (побитно), $890ADC - v9502 - номера целевых стеков защищающегося (побитно).
 
 //Модификация условия выполнения прохода цикла (в функции $440030).
 //Запись 0 (что значит - все позиции вокруг могут быть атакованы).
 //Без модификации значение - начение - смежные позиций побитно от правой нижней против часовой стрелки (0 - доступна).
 PROCEDURE Damage_ability; ASSEMBLER; {$FRAME-}
 ASM
 //Если 32-й бит в v9501 = 1, модифицируем.
 PUSH EAX
 MOV EAX, DWORD PTR DS:[$890AD8]
 SHR EAX, 31
 TEST EAX, EAX
 POP EAX
 JNZ @@Modify
 
 //Восстановление изначального кода: получение всех позиций рядом, на которых кто-то стоит побитно (Запись в ECX).
 MOV ECX, [EBP+8]
 JMP @@Exit
 
 //Модифицирование кода: запись 0 (будто на всех клетках рядом кто-то стоит) в возвращаемый результат.
 @@Modify:
 MOV ECX, 0
 
 @@Exit:
 TEST ECX, EAX//Восстанавливаем испорченную команду.
 PUSH $440057
 END;
 
 //Модификация вызова функции, вычисляющей позицию текущего атакованного (в функции $440030).
 //Автоматическое возвращение 1 (легальной позиции) (в EAX), т. к. позиция может быть вычислена неправильно, если будет больше 8 атакованных.
 PROCEDURE Damage_position; ASSEMBLER; {$FRAME-}
 ASM
 //Если 32-й бит в v9501 = 1, модифицируем.
 MOV EAX, DWORD PTR DS:[$890AD8]
 SHR EAX, 31
 TEST EAX, EAX
 JNZ @@Modify
 
 //Восстановление изначального кода: вызов функции, вычисляющей позицию текущего атакованного (Запись в EAX).
 MOV EAX, $5242E0
 CALL EAX//Внутри функции используется ESP - нельзя использовать PUSH перед ней.
 JMP @@Exit
 
 //Модифицирование кода: запись 1 (легальной позиции) в возвращаемый результат.
 @@Modify:
 MOV EAX, 1
 
 @@Exit:
 PUSH $440069
 END;
 
 //Модификация вызова функции вычисления адреса конструкций для атакованного на определённой позиции (в функции $440030).
 //Вместо вычисления стека по позиции, смотрим в бите v-переменной, надо ли атаковать текущий проверяемый стек.
 //Если надо, возвращаем (в EAX) $699420 + 1352*номер стека + 21708, иначе 0.
 PROCEDURE Damage_stack; ASSEMBLER; {$FRAME-}
 ASM
 //Если 32-й бит в v9501 = 1, модифицируем.
 MOV EAX, DWORD PTR DS:[$890AD8]
 SHR EAX, 31
 TEST EAX, EAX
 JNZ @@Modify
 
 //Восстановление изначального кода: вызов функции, вычисляющей адрес конструкций для атакованного на определённой позиции (запись в EAX).
 MOV EAX, $4E7230
 CALL EAX
 JMP @@Exit
 
 //Модифицирование кода: проверка, надо ли атаковать текущий стек и запись адреса его конструкций или 0 в EAX.
 @@Modify:
 //Проверяем, какой стороне принадлежит проверяемый стек.
 CMP EBX, 21
 JAE @@Def_st
 
 //Если стек принадлежит атакующей стороне, помещаем в EAX соответствующий стеку бит из v9501.
 MOV EAX, DWORD PTR DS:[$890AD8]
 MOV CL, BL
 SHR EAX, CL
 JMP @@All_st
 
 //Если стек принадлежит защищающейся стороне, помещаем в EAX соответствующий стеку бит из v9502.
 @@Def_st:
 MOV EAX, DWORD PTR DS:[$890ADC]
 SUB EBX, 21
 MOV CL, BL
 SHR EAX, CL
 ADD EBX, 21
 
 //Оставляем в EAX 0 или помещаем в него адрес конструкций стека (в зависимости от начального значкния EAX, т. е. бита v-переменной).
 @@All_st:
 AND EAX, 1
 JZ @@Exit
 //EAX = $699420 + 1352*EBX + 21708.
 LEA ECX, DS:0[EBX*8]
 SUB ECX, EBX
 LEA EDX, [ECX+ECX*2]
 MOV ECX, DWORD PTR DS:[$699420]
 LEA EAX, [EBX+EDX*8]
 LEA EAX, [ECX+EAX*8+21708]
 
 @@Exit:
 PUSH $44009A
 END;
 
 //Модификация условия выхода из цикла (в функции $440030).
 //42 прохода (для каждого стека) вместо стандартных 8 (для каждой возможной позиции около атакующего).
 PROCEDURE Damage_target; ASSEMBLER; {$FRAME-}
 ASM
 PUSH EAX
 
 //Если 32-й бит в v9501 = 1, модифицируем.
 MOV EAX, DWORD PTR DS:[$890AD8]
 SHR EAX, 31
 TEST EAX, EAX
 JNZ @@Modify
 
 //Восстановление изначального кода: сравнивание номера текущего атакованного с 8.
 CMP EBX, 8
 JMP @@Exit
 
 //Модифицирование кода: сравнивание номера текущего атакованного с 42.
 @@Modify:
 CMP EBX, 42
 
 @@Exit:
 POP EAX
 MOV [EBP-12], EBX//Восстанавливаем испорченную команду.
 PUSH $44019A
 END;
 
 BEGIN
 HookCode(POINTER($440052), @Damage_ability, C_HOOKTYPE_JUMP);
 HookCode(POINTER($440064), @Damage_position, C_HOOKTYPE_JUMP);
 HookCode(POINTER($440095), @Damage_stack, C_HOOKTYPE_JUMP);
 HookCode(POINTER($440194), @Damage_target, C_HOOKTYPE_JUMP);
 END.
Ошибка по адресу 0x004417A4 (MOV EAX, [ESI+34h]) - попытка прочесть память по адресу 34h. 
Ещё - отклонение, вызвавшее, скорее всего, эту ошибку - неправильная работа функции sub_5242E0, вызванной по адресу 0x00440064. Там идёт работа со стеком напрямую и извлекается неверное значение (по адресу 0x0052430F (MOV EBX, [EBP+arg_0]; arg_0 = 8])).
 
Но фишка-то в том, что всё это только при отладке. Просто в игре ничего такого нет.
P.S.  Без включенного режима немодифицируемости (отключить - 32-й бит переменной v9501 = 1) ошибка будет в любом случае (правда, разная в игре и отладчике), но с этим я как-нибудь сам разберусь.
			
				
(This post was last modified: 14.11.2010 23:33 by Sav.)
 |