如何在Delphi中使用WriteProcessMemory

How to use WriteProcessMemory in Delphi

我无法编译此代码。我可以帮忙吗?谢谢。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
procedure ChangeOutsideDateTime(h: HWND; dt: TDateTime);
var
  st: TSystemTime;
  pst: Pointer;
  hDTP: Cardinal;
  hProc: THandle;
  dwWrote: DWORD;
begin
  DateTimeToSystemTime(dt, st);
  pst:= VirtualAllocEx(h, nil, SizeOf(st), MEM_COMMIT, 0);
  if pst <> nil then begin
    if GetWindowThreadProcessId(h, hDTP) > 0 then begin
      hProc:= OpenProcess(PROCESS_VM_OPERATION, false, hDTP);
      if WriteProcessMemory(hProc, pst, @st, SizeOf(st), dwWrote) > 0 then begin
        SendMessage(h, DTM_SETSYSTEMTIME, GDT_VALID, hDTP);
        CloseHandle(hProc);
      end;
    end;
    VirtualFreeEx(h, pst, 0, MEM_RELEASE);
  end;
end;

在使用" WriteProcessMemory"的行中显示"实际和正式var参数的类型必须相同"。


Types of actual and formal var parameters must be identical

这是编译器错误E2003。如果遇到不了解的编译器错误,则要做的第一件事就是阅读文档。它说:

For a variable parameter, the actual argument must be of the exact type of the formal parameter.

导致此错误的函数调用为WriteProcessMemory。我们来看一下它的声明:

1
2
function WriteProcessMemory(hProcess: THandle; const lpBaseAddress: Pointer;
  lpBuffer: Pointer; nSize: SIZE_T; var lpNumberOfBytesWritten: SIZE_T): BOOL; stdcall;

这里只有一个var参数,即最后一个参数。您传递的变量必须是SIZE_T类型,但是您传递的是DWORD类型变量。那是不匹配。

其他一些评论:

  • VirtualAllocEx的调用注定会失败,因为您传递了窗口句柄而不是进程句柄。
  • 从语义上讲,测试正线程ID是没有意义的。测试成功与否不等于零。
  • 您无需检查OpenProcess返回值。那很容易失败。
  • 您不能使用WriteProcessMemory必需的PROCESS_VM_WRITE访问权限来打开进程。
  • 如果对WriteProcessMemory的调用失败,则泄漏句柄。
  • WriteProcessMemory的返回类型为BOOL
  • hDTP是进程ID的奇怪名称。该名称表明您认为它是日期时间选择器控件的句柄。它不是。这是进程ID。
  • 您在SendMessage调用中传递该进程ID,而不是您刚刚编写的系统时间的地址。


您的代码中有几个错误。

  • 您正在将HWND传递给VirtualAllocEx(),但是它希望将THandle传递给打开的进程。并且您在打开进程句柄之前正在调用VirtualAllocEx()。而且您不要求对分配的内存进行写访问。

  • 在调用OpenProcess()时,您并不是在请求WriteProcessMemory()所需的PROCESS_VM_WRITE许可。

  • 您使用的WriteProcessMemory()与它的声明不匹配。这就是为什么出现编译器错误的原因。

  • 您正在将HWND的进程ID作为DTM_SETSYSTEMTIMELPARAM传递,但是它期望分配的TSystemTime指针代替。

尝试更多类似的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
procedure ChangeOutsideDateTime(h: HWND; dt: TDateTime);
var
  st: TSystemTime;
  PID: DWORD;
  hProc: THandle;
  pst: Pointer;
  NumWrote: SIZE_T;
begin
  GetWindowThreadProcessId(h, PID);
  hProc := OpenProcess(PROCESS_VM_OPERATION or PROCESS_VM_WRITE, false, PID);
  if hProc <> 0 then
  try
    pst := VirtualAllocEx(hProc, nil, SizeOf(st), MEM_COMMIT, PAGE_READWRITE);
    if pst <> nil then
    try
      DateTimeToSystemTime(dt, st);
      if WriteProcessMemory(hProc, pst, @st, SizeOf(st), NumWrote) then begin
        SendMessage(h, DTM_SETSYSTEMTIME, GDT_VALID, LPARAM(pst));
      end;
    finally
      VirtualFreeEx(hProc, pst, 0, MEM_RELEASE);
    end;
  finally
    CloseHandle(hProc);
  end;
end;