I want to do the following,but I get errors:
我想做以下,但我得到错误:
procedure JumpToCodeCave(CurrentLocation:DWORD;Destination:Pointer;out_JmpBack:Pointer);
var calc:DWORD;
jmppatch:Array[0..3] of byte absolute calc;
Buffer:Array[0..9] of byte;
begin
calc := (Cardinal(Destination) - $5)-(CurrentLocation + $4);
Buffer := [$90,$90,$90,$90,$E9,jmppatch,$90]; //<< Error here <<
WriteProcessmemory(Handle,Pointer(CurrentLocation),Pointer(Buffer),10,nil);
out_JmpBack^ := Currentlocation + $A;
end;
Buffer should look like this:
缓冲区应如下所示:
0x90,0x90,0x90,0xE9,jmppatch[0],jmppatch[1],jmppatch[2],jmppatch[3],0x90
The function calculates the value that should be written to jump from one address(current) to another address(CodeCave).The result is converted into bytes and written into the process,but I can't put the bytes in the Buffer like I did above.
该函数计算应写入的值,以便从一个地址(当前)跳转到另一个地址(CodeCave)。结果转换为字节并写入进程,但我不能像我那样将字节放入缓冲区以上。
I'm sorry for the stupid question,but I have forgotten Delphi after I began my education with C#.
我很抱歉这个愚蠢的问题,但是在我开始接受C#教育后,我忘记了Delphi。
3 个解决方案
#1
Delphi doesn't support array literals like that, especially not ones that would accept a four-byte value and turn it into four one-byte values.
Delphi不支持这样的数组文字,尤其不支持接受四字节值并将其转换为四个单字节值的数组文字。
You can have array constants, as Kcats's answer demonstrates. You can also have open-array literals, but then you can only pass it to a function expecting an open-array parameter.
你可以有数组常量,正如Kcats的回答所示。您也可以使用开放式数组文字,但是只能将其传递给期望开放数组参数的函数。
I'd do something different, in your case. Code is not just an array of bytes. It has structure, so I'd make a record and give it fields for each of the instructions in the code.
在你的情况下,我会做一些与众不同的事情。代码不仅仅是一个字节数组。它有结构,所以我会创建一个记录,并为代码中的每个指令提供字段。
type
TPatch = packed record
Nops: array [0..3] of Byte;
JmpInst: packed record
Opcode: Byte;
Offset: LongWord;
end;
Nop: Byte;
end;
const
Nop = $90;
Jmp = $e9;
var
Buffer: TPatch;
begin
// nop; nop; nop; nop;
FillChar(Buffer.Nops, SizeOf(Buffer.Nops), Nop);
// jmp xxxx
Buffer.JmpInst.Opcode := Jmp;
Buffer.JmpInst.Offset := LongWord(Destination) - SizeOf(Buffer.JmpInst)
- (CurrentLocation + SizeOf(Buffer.Nops));
// nop
Buffer.Nop := Nop;
WriteProcessmemory(Handle, Ptr(CurrentLocation), @Buffer, SizeOf(Buffer), nil);
end;
Even if you don't do all that, note that I've changed the third parameter of WriteProcessMemory
. Your Buffer
variable is not a pointer, so you really can't type-cast it to be one. You need to pass the address.
即使你没有做到这一切,请注意我已经改变了WriteProcessMemory的第三个参数。您的Buffer变量不是指针,因此您实际上无法将其类型化为一个。你需要传递地址。
#2
There's no way to assign the way you want to. Instead, use the Move() and FillMemory() procedures:
没有办法指定你想要的方式。而是使用Move()和FillMemory()过程:
FillMemory(@Buffer[0], 4, $90);
Buffer[4] := $E9;
Move(Calc, Buffer[5], 4);
Buffer[9] := $90;
Note that I have removed the absolute
variable, as it's no longer necessary.
请注意,我已经删除了绝对变量,因为它不再是必需的。
#3
You can't do that. Try something like:
你不能这样做。尝试类似的东西:
var
Buffer:Array[0..9] of byte = ($90,$90,$90,$90,$E9,$CC,$CC,$CC,$CC,$90);
begin
PCardinal(@buffer[5])^ := (Cardinal(Destination) - $5)-(CurrentLocation + $4);
#1
Delphi doesn't support array literals like that, especially not ones that would accept a four-byte value and turn it into four one-byte values.
Delphi不支持这样的数组文字,尤其不支持接受四字节值并将其转换为四个单字节值的数组文字。
You can have array constants, as Kcats's answer demonstrates. You can also have open-array literals, but then you can only pass it to a function expecting an open-array parameter.
你可以有数组常量,正如Kcats的回答所示。您也可以使用开放式数组文字,但是只能将其传递给期望开放数组参数的函数。
I'd do something different, in your case. Code is not just an array of bytes. It has structure, so I'd make a record and give it fields for each of the instructions in the code.
在你的情况下,我会做一些与众不同的事情。代码不仅仅是一个字节数组。它有结构,所以我会创建一个记录,并为代码中的每个指令提供字段。
type
TPatch = packed record
Nops: array [0..3] of Byte;
JmpInst: packed record
Opcode: Byte;
Offset: LongWord;
end;
Nop: Byte;
end;
const
Nop = $90;
Jmp = $e9;
var
Buffer: TPatch;
begin
// nop; nop; nop; nop;
FillChar(Buffer.Nops, SizeOf(Buffer.Nops), Nop);
// jmp xxxx
Buffer.JmpInst.Opcode := Jmp;
Buffer.JmpInst.Offset := LongWord(Destination) - SizeOf(Buffer.JmpInst)
- (CurrentLocation + SizeOf(Buffer.Nops));
// nop
Buffer.Nop := Nop;
WriteProcessmemory(Handle, Ptr(CurrentLocation), @Buffer, SizeOf(Buffer), nil);
end;
Even if you don't do all that, note that I've changed the third parameter of WriteProcessMemory
. Your Buffer
variable is not a pointer, so you really can't type-cast it to be one. You need to pass the address.
即使你没有做到这一切,请注意我已经改变了WriteProcessMemory的第三个参数。您的Buffer变量不是指针,因此您实际上无法将其类型化为一个。你需要传递地址。
#2
There's no way to assign the way you want to. Instead, use the Move() and FillMemory() procedures:
没有办法指定你想要的方式。而是使用Move()和FillMemory()过程:
FillMemory(@Buffer[0], 4, $90);
Buffer[4] := $E9;
Move(Calc, Buffer[5], 4);
Buffer[9] := $90;
Note that I have removed the absolute
variable, as it's no longer necessary.
请注意,我已经删除了绝对变量,因为它不再是必需的。
#3
You can't do that. Try something like:
你不能这样做。尝试类似的东西:
var
Buffer:Array[0..9] of byte = ($90,$90,$90,$90,$E9,$CC,$CC,$CC,$CC,$90);
begin
PCardinal(@buffer[5])^ := (Cardinal(Destination) - $5)-(CurrentLocation + $4);