| 1 | UNIT Unit2; | 
|---|
| 2 |  | 
|---|
| 3 | INTERFACE | 
|---|
| 4 | USES Windows, SysUtils, Unit8, Unit11; | 
|---|
| 5 |  | 
|---|
| 6 | const | 
|---|
| 7 | _WindowName='ONI '; | 
|---|
| 8 | _WindowClass='ONI '; | 
|---|
| 9 | address_message_pointer:LongWord=$10EC0+$4; | 
|---|
| 10 | address_activate_message_offset:LongWord=$10E0; | 
|---|
| 11 |  | 
|---|
| 12 | var | 
|---|
| 13 | _WindowHandle:LongWord; | 
|---|
| 14 | _ProcessID:LongWord; | 
|---|
| 15 | _ProcessHandle:LongWord; | 
|---|
| 16 |  | 
|---|
| 17 | FUNCTION FindWindowA(ClassName:String; WindowName:String):longword; stdcall; external 'user32.dll' name 'FindWindowA'; | 
|---|
| 18 | FUNCTION GetWindowThreadProcessId(hwnd:longword; out processId:longword):longword; stdcall; external 'user32.dll' name 'GetWindowThreadProcessId'; | 
|---|
| 19 | FUNCTION OpenProcess(dwDesiredAccess:longword; bInheritHandle:longword; dwProcessId:longword):longword; stdcall; external 'kernel32.dll' name 'OpenProcess'; | 
|---|
| 20 | FUNCTION ReadProcessMemory(hProcess:longword; lpBaseAddress:longword; out lpBuffer:byte_array; nSize:longword; out lpNumberOfBytesWritten:longword):longword; stdcall; external 'kernel32.dll' name 'ReadProcessMemory'; | 
|---|
| 21 | FUNCTION WriteProcessMemory(hProcess:longword; lpBaseAddress:longword; lpBuffer:byte_array; nSize:longword; out lpNumberOfBytesWritten:longword):longword; stdcall; external 'kernel32.dll' name 'WriteProcessMemory'; | 
|---|
| 22 | FUNCTION CloseHandle(hObject:longword):longword; stdcall; external 'kernel32.dll' name 'CloseHandle'; | 
|---|
| 23 | FUNCTION GetAsyncKeyState(vkey:smallint):word; stdcall; external 'user32.dll' name 'GetAsyncKeyState'; | 
|---|
| 24 | FUNCTION VirtualProtectEx(hProcess:longword; lpAddress:longword; dwSize:longword; flNewProtect:longword; lpflOldProtect:longword):longword; stdcall; external 'kernel32.dll' name 'VirtualProtectEx'; | 
|---|
| 25 | FUNCTION GetLastError:longword; stdcall; external 'kernel32.dll' name 'GetLastError'; | 
|---|
| 26 |  | 
|---|
| 27 | FUNCTION ConnectToProcess:Boolean; | 
|---|
| 28 | FUNCTION ReadMem(address:longword; size:longword):byte_array; | 
|---|
| 29 | FUNCTION WriteMem(address:longword; size:longword; _buffer:byte_array):boolean; | 
|---|
| 30 | //FUNCTION GetKey(key:smallint):boolean; | 
|---|
| 31 | PROCEDURE SetWindowAOT(Handle:Cardinal;AOT:Boolean); | 
|---|
| 32 |  | 
|---|
| 33 | FUNCTION Decode_Int(buffer:byte_array):LongWord; | 
|---|
| 34 | FUNCTION Decode_Float(buffer:byte_array):Single; | 
|---|
| 35 | FUNCTION Decode_Str(buffer:byte_array):String; | 
|---|
| 36 | FUNCTION Encode_Int(input:LongWord):byte_array; | 
|---|
| 37 | FUNCTION Encode_Float(input:Single):byte_array; | 
|---|
| 38 | FUNCTION Encode_Str(input:String;bytes:byte):byte_array; | 
|---|
| 39 |  | 
|---|
| 40 | FUNCTION patch_messages_loaded:Boolean; | 
|---|
| 41 | PROCEDURE SendMessageToOni(_message:String); | 
|---|
| 42 |  | 
|---|
| 43 | FUNCTION Check_Data_Correct(address:LongWord; requested:array of byte; size:Byte):Byte; | 
|---|
| 44 | PROCEDURE Incorrect_Data_Message(formhandle:LongWord; address:LongWord; error:Byte); | 
|---|
| 45 |  | 
|---|
| 46 | implementation | 
|---|
| 47 |  | 
|---|
| 48 | FUNCTION Check_Data_Correct(address:LongWord; requested:array of byte; size:Byte):Byte; | 
|---|
| 49 | VAR i:Byte; | 
|---|
| 50 | BEGIN | 
|---|
| 51 | result:=0; | 
|---|
| 52 | _temp:=ReadMem(address,size); | 
|---|
| 53 | IF (_temp[250]=123) THEN BEGIN | 
|---|
| 54 | result:=1; | 
|---|
| 55 | exit; | 
|---|
| 56 | END; | 
|---|
| 57 | FOR i:=0 TO size-1 DO BEGIN | 
|---|
| 58 | IF NOT (_temp[i]=requested[i]) THEN BEGIN | 
|---|
| 59 | result:=2; | 
|---|
| 60 | exit; | 
|---|
| 61 | END; | 
|---|
| 62 | END; | 
|---|
| 63 | END; | 
|---|
| 64 | PROCEDURE Incorrect_Data_Message(formhandle:LongWord; address:LongWord; error:Byte); | 
|---|
| 65 | BEGIN | 
|---|
| 66 | CASE error OF | 
|---|
| 67 | 1:BEGIN | 
|---|
| 68 | MessageBox(formhandle,PChar('Couldn''t read data from $'+IntToHex(address,8)+'!'),PChar('Error'),MB_OK); | 
|---|
| 69 | exit; | 
|---|
| 70 | END; | 
|---|
| 71 | 2:BEGIN | 
|---|
| 72 | MessageBox(formhandle,PChar('Incorrect data found for inserting script-var-address-patch at $'+IntToHex(address,8)+'!'),PChar('Error'),MB_OK); | 
|---|
| 73 | exit; | 
|---|
| 74 | END; | 
|---|
| 75 | END; | 
|---|
| 76 | END; | 
|---|
| 77 |  | 
|---|
| 78 | FUNCTION patch_messages_loaded:Boolean; | 
|---|
| 79 | CONST check_for:LongWord=$10725AE9; | 
|---|
| 80 | address_at:LongWord=$425B11; | 
|---|
| 81 | BEGIN | 
|---|
| 82 | IF Decode_Int(ReadMem(address_at,4))=check_for THEN result:=True | 
|---|
| 83 | ELSE result:=False; | 
|---|
| 84 | END; | 
|---|
| 85 |  | 
|---|
| 86 | PROCEDURE SendMessageToOni(_message:String); | 
|---|
| 87 | CONST message_length=100; | 
|---|
| 88 | VAR buffer:byte_array; | 
|---|
| 89 | i:byte; | 
|---|
| 90 | adr_message:LongWord; | 
|---|
| 91 | adr_trigger:LongWord; | 
|---|
| 92 | BEGIN | 
|---|
| 93 | IF _connected AND patch_messages_loaded THEN BEGIN | 
|---|
| 94 | adr_message:=Decode_Int(ReadMem(address_message_pointer,4)); | 
|---|
| 95 | adr_trigger:=Decode_Int(ReadMem(address_script_var_pointer,4))+address_activate_message_offset; | 
|---|
| 96 |  | 
|---|
| 97 | IF adr_message>0 THEN BEGIN | 
|---|
| 98 | FOR i:=0 TO 250 DO buffer[i]:=$00; | 
|---|
| 99 | IF StrLen(PChar(_message))>message_length THEN BEGIN | 
|---|
| 100 | END ELSE BEGIN | 
|---|
| 101 | FOR i:=0 TO StrLen(PChar(_message))-1 DO buffer[i]:=Ord(_message[i+1]); | 
|---|
| 102 | IF StrLen(PChar(_message))<message_length THEN BEGIN | 
|---|
| 103 | FOR i:=(StrLen(PChar(_message))) TO message_length-1 DO buffer[i]:=$00; | 
|---|
| 104 | END; | 
|---|
| 105 | END; | 
|---|
| 106 | WriteMem(adr_message,message_length,buffer); | 
|---|
| 107 | buffer[0]:=1; | 
|---|
| 108 | WriteMem(adr_trigger,1,buffer); | 
|---|
| 109 | END; | 
|---|
| 110 | END; | 
|---|
| 111 | END; | 
|---|
| 112 |  | 
|---|
| 113 | FUNCTION Decode_Int(buffer:byte_array):LongWord; | 
|---|
| 114 | BEGIN | 
|---|
| 115 | result:=buffer[0]+buffer[1]*256+buffer[2]*256*256+buffer[3]*256*256*256; | 
|---|
| 116 | END; | 
|---|
| 117 |  | 
|---|
| 118 | FUNCTION Decode_Float(buffer:byte_array):Single; | 
|---|
| 119 | BEGIN | 
|---|
| 120 | _valueswitcher.ValueInt:=Decode_Int(buffer); | 
|---|
| 121 | result:=_valueswitcher.ValueFloat; | 
|---|
| 122 | END; | 
|---|
| 123 |  | 
|---|
| 124 | FUNCTION Decode_Str(buffer:byte_array):String; | 
|---|
| 125 | VAR i:Byte; | 
|---|
| 126 | BEGIN | 
|---|
| 127 | FOR i:=0 TO 249 DO BEGIN | 
|---|
| 128 | IF buffer[i]=0 THEN break | 
|---|
| 129 | ELSE result:=result+Chr(buffer[i]); | 
|---|
| 130 | END; | 
|---|
| 131 | END; | 
|---|
| 132 | FUNCTION Encode_Int(input:LongWord):byte_array; | 
|---|
| 133 | BEGIN | 
|---|
| 134 | result[0]:=input MOD 256; | 
|---|
| 135 | input:=input DIV 256; | 
|---|
| 136 | result[1]:=input MOD 256; | 
|---|
| 137 | input:=input DIV 256; | 
|---|
| 138 | result[2]:=input MOD 256; | 
|---|
| 139 | input:=input DIV 256; | 
|---|
| 140 | result[3]:=input MOD 256; | 
|---|
| 141 | END; | 
|---|
| 142 | FUNCTION Encode_Float(input:Single):byte_array; | 
|---|
| 143 | BEGIN | 
|---|
| 144 | _valueswitcher.ValueFloat:=input; | 
|---|
| 145 | result:=Encode_Int(_valueswitcher.ValueInt); | 
|---|
| 146 | END; | 
|---|
| 147 | FUNCTION Encode_Str(input:String;bytes:Byte):byte_array; | 
|---|
| 148 | VAR i:Byte; | 
|---|
| 149 | BEGIN | 
|---|
| 150 | FOR i:=1 TO bytes DO BEGIN | 
|---|
| 151 | IF i<=Length(input) THEN BEGIN | 
|---|
| 152 | result[i-1]:=Ord(input[i]); | 
|---|
| 153 | END ELSE BEGIN | 
|---|
| 154 | result[i-1]:=$00; | 
|---|
| 155 | END; | 
|---|
| 156 | END; | 
|---|
| 157 | END; | 
|---|
| 158 |  | 
|---|
| 159 | FUNCTION ConnectToProcess:Boolean; | 
|---|
| 160 | BEGIN | 
|---|
| 161 | _WindowHandle:=FindWindowA(''{_WindowClass},_WindowName); | 
|---|
| 162 | IF not (_WindowHandle>0) THEN BEGIN | 
|---|
| 163 | result:=False; | 
|---|
| 164 | exit; | 
|---|
| 165 | END; | 
|---|
| 166 | GetWindowThreadProcessId(_WindowHandle, _ProcessID); | 
|---|
| 167 | IF not (_ProcessID>0) THEN BEGIN | 
|---|
| 168 | result:=False; | 
|---|
| 169 | exit; | 
|---|
| 170 | END; | 
|---|
| 171 | _ProcessHandle:=OpenProcess(PROCESS_ALL_ACCESS, 0, _ProcessID); | 
|---|
| 172 | IF not (_ProcessHandle>0) THEN BEGIN | 
|---|
| 173 | result:=False; | 
|---|
| 174 | exit; | 
|---|
| 175 | END; | 
|---|
| 176 | result:=True; | 
|---|
| 177 | END; | 
|---|
| 178 | FUNCTION ReadMem(address:longword; size:longword):byte_array; | 
|---|
| 179 | VAR _buffer:byte_array; | 
|---|
| 180 | temp:longword; | 
|---|
| 181 | BEGIN | 
|---|
| 182 | FOR temp:=0 TO 250 DO _buffer[temp]:=0; | 
|---|
| 183 | IF NOT (ReadProcessMemory(_ProcessHandle, address, _buffer, size, temp)>0) THEN BEGIN | 
|---|
| 184 | _buffer[250]:=123; | 
|---|
| 185 | END; | 
|---|
| 186 | result:=_buffer; | 
|---|
| 187 | END; | 
|---|
| 188 | FUNCTION WriteMem(address:longword; size:longword; _buffer:byte_array):boolean; | 
|---|
| 189 | VAR temp:longword; | 
|---|
| 190 | BEGIN | 
|---|
| 191 | IF NOT (WriteProcessMemory(_ProcessHandle, address, _buffer, size, temp)>0) THEN BEGIN | 
|---|
| 192 | result:=False; | 
|---|
| 193 | END ELSE BEGIN | 
|---|
| 194 | result:=True; | 
|---|
| 195 | END; | 
|---|
| 196 | END; | 
|---|
| 197 |  | 
|---|
| 198 | PROCEDURE SetWindowAOT(Handle:Cardinal;AOT:Boolean); | 
|---|
| 199 | VAR aot_value:Integer; | 
|---|
| 200 | BEGIN | 
|---|
| 201 | IF AOT THEN aot_value:=HWND_TOPMOST | 
|---|
| 202 | ELSE aot_value:=HWND_NOTOPMOST; | 
|---|
| 203 | SetWindowPos(Handle,aot_value,0,0,0,0,SWP_NOACTIVATE+SWP_NOMOVE+SWP_NOOWNERZORDER+SWP_NOSIZE); | 
|---|
| 204 | END; | 
|---|
| 205 |  | 
|---|
| 206 | end. | 
|---|