
Question:
This is my Working Code
DriftMul:=99;
WriteProcessMemory(HandleWindow, ptr($4E709C), @DriftMul, 2, Write);
I want to Convert it without using a variable but it wont work Below is just an Example of what i want to do.
WriteProcessMemory(HandleWindow, ptr($4E709C), ptr(99), 2, Write);
Does anyone know a way to make this work with using a variable??? I am able to program in a few languages and every language i use their is a way to to do this. The reason i want to do this is because i am gonna be making a big program that does alot of writing of different values and it will save me around 300+ lines. Below is an Example in c++ i was using.
WriteProcessMemory(hProcess, (void*)0x4E709C, (void*)(PBYTE)"\x20", 1, NULL);
Update: Solved it Im using 4 Procedures that i call depending on how many bytes i want to write.
procedure Wpm(Address: Cardinal; ChangeValues: Byte);
Begin
WriteProcessMemory(HandleWindow, Pointer(Address), @ChangeValues, 1, Write);
End;
procedure Wpm2(Address: Cardinal; ChangeValues: Word);
Begin
WriteProcessMemory(HandleWindow, Pointer(Address), @ChangeValues, 2, Write);
End;
procedure Wpm3(Address: Cardinal; ChangeValues: Word);
Begin
WriteProcessMemory(HandleWindow, Pointer(Address), @ChangeValues, 3, Write);
End;
procedure Wpm4(Address: Cardinal; ChangeValues: Cardinal);
Begin
WriteProcessMemory(HandleWindow, Pointer(Address), @ChangeValues, 4, Write);
End;
Example writes
Wpm($477343,$EB);
Wpm2($40A889,$37EB);
Wpm3($416E34,$0086E9);
Pchar is the only method i found to compile without procedures, i dont want to use assci though.
WriteProcessMemory(HandleWindow, Pointer($449A17), PChar('90'), 1, Write);
Answer1:You have to store the contents of the word that you are writing somewhere. WriteProcessMemory
expects a pointer to some memory in your process space. If you don't want to use a variable, use a constant.
const
DriftMul: word=99;
....
WriteProcessMemory(HandleWindow, ptr($4E709C), @DriftMul, 2, Write);
Passing ptr(99)
fails because ptr(99)
is not a pointer to a word containing the value 99
. It is a pointer to address 99. I think you were trying to write @Word(99)
but you cannot take the address of a true constant.
You can make this more convenient by wrapping up the call to WriteProcessMemory
in a helper methods. Although your question suggests that you want to write Word
values, it became apparent in out lengthy chat that you actually want to write byte sequences. Writing integer data types will lead to machine endianness confusion. So instead I would do it using an open array of Byte
to give the flexibility at the call site.
procedure WriteBytes(hProcess: THandle; Address: Pointer;
const Buffer: array of Byte);
var
NumberOfBytesWritten: DWORD;
begin
if not WriteProcessMemory(hProcess, Address, @Buffer[0], Length(Buffer),
NumberOfBytesWritten) then RaiseLastOSError;
end;
You can then call the code
WriteBytes(Handle, Pointer($523328), [$42]);//single byte
WriteBytes(Handle, Pointer($523328), [$CC, $90, $03]);//3 bytes
Answer2:In C++, this code:
WriteProcessMemory(hProcess, (void*)0x4E709C, (void*)(PBYTE)"\x20", 1, NULL);
Is declaring a const char[]
buffer in the app's memory that contains the two characters '\x20'
and '\x00'
in it. This is evident by the use of the "
double-quote characters around the literal. They are creating a string literal, not a character literal (which uses '
single-quote character instead). The starting address of that literal's first character is being passed to the third parameter and the fourth parameter is set to 1 to tell WriteProcessMemory()
to copy only 1 byte from that 2-byte buffer.
Delphi, on the other hand, uses the '
single-quote character around both single-character and string literals, and thus relies on code context to decide which type of literal needs to be created. As such, Delphi does not have a direct means of declaring a single-character literal that is the equivilent of an inlined char[]
like in the C++ code. The closest equivilent I can think of right now, without declaring a constant, would be something like this:
WriteProcessMemory(hProcess, Pointer($4E709C), PAnsiChar(AnsiString(' ')), 1, nil);
Otherwise, use just an explicit constant instead. The direct equivilent of what the C++ code is doing is the following:
const
buffer: array[0..1] of AnsiChar = (#$20, #0);
WriteProcessMemory(hProcess, Pointer($4E709C), Pointer(PByte(@buffer[0])), 1, nil);
Alternatively, you can simplify it to the following:
const
space: Byte = $20;
WriteProcessMemory(hProcess, Pointer($4E709C), @space, 1, nil);
Answer3:The ptr() Method converts an address to an pointer. So the value in the second method is not 99 but the value that is written at the address 99.
My dirty method, but with few lines of code:
procedure WriteBytes(hProcess: THandle; address: Pointer; buffer: Variant; count: Integer);
begin
WriteProcessMemory(hProcess, address, @buffer, count, nil);
end;
Then you can call the method with:
WriteBytes(HandleWindow, Pointer($449A17), 90, 1);