| 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. |