【问题标题】:Delphi 7 WriteProcessMemoryDelphi 7 WriteProcessMemory
【发布时间】:2012-03-29 16:59:40
【问题描述】:

这是我的工作代码

  DriftMul:=99;
  WriteProcessMemory(HandleWindow, ptr($4E709C), @DriftMul, 2, Write);

我想在不使用变量的情况下转换它,但它不起作用 下面只是我想做的一个例子。

WriteProcessMemory(HandleWindow, ptr($4E709C),  ptr(99), 2, Write);

有谁知道使用变量来完成这项工作的方法??? 我能够用几种语言编程,我使用的每一种语言都是 方法来做到这一点。我想这样做的原因是因为我要制作一个大程序,它会写很多不同的值,它将为我节省大约 300 多行代码。以下是我使用的 c++ 示例。

WriteProcessMemory(hProcess, (void*)0x4E709C, (void*)(PBYTE)"\x20", 1, NULL);

更新: 解决了 我使用 4 个过程,我根据要写入的字节数调用它们。

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;

示例写入

 Wpm($477343,$EB);
 Wpm2($40A889,$37EB);
 Wpm3($416E34,$0086E9);

Pchar 是我发现的唯一一种无需程序即可编译的方法,不过我不想使用 assci。

WriteProcessMemory(HandleWindow, Pointer($449A17), PChar('90'), 1, Write);

【问题讨论】:

  • "为什么上面的代码写的是43??"你的意思是$43。那么,C 的 ASCII 码是什么?当你只写一个字节时,为什么要使用'C3'?第二个字节有什么意义?为什么不使用'C'
  • 我的转换器我得到了 99
  • 您能解释一下 99 来自哪里,C3 来自哪里以及您的期望是什么?我必须承认,你会愿意像这样混淆你的代码,这让我很吃惊。
  • 我用过这个网站easycalculation.com/ascii-hex.php
  • 非常有趣的讨论 :) 我认为 Tprice88 写的是 c 而不是 C,因为 c 是 ASCII 码 99。

标签: windows delphi delphi-7


【解决方案1】:

你必须将你正在写的单词的内容存储在某个地方。 WriteProcessMemory 需要一个指向进程空间中某些内存的指针。如果不想使用变量,请使用常量。

const
  DriftMul: word=99;
....
WriteProcessMemory(HandleWindow, ptr($4E709C),  @DriftMul, 2, Write);

传递ptr(99) 失败,因为ptr(99) 不是指向包含值99 的单词的指针。它是一个指向地址 99 的指针。我认为您正在尝试编写 @Word(99),但您无法获取真正常量的地址。

您可以通过在辅助方法中封装对WriteProcessMemory 的调用来使这更方便。尽管您的问题表明您想要编写 Word 值,但在冗长的聊天中很明显您实际上想要编写字节序列。写入整数数据类型会导致机器字节序混乱。因此,我会使用Byte 的开放数组来实现,以便在呼叫站点提供灵活性。

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;

然后就可以调用代码了

WriteBytes(Handle, Pointer($523328), [$42]);//single byte
WriteBytes(Handle, Pointer($523328), [$CC, $90, $03]);//3 bytes

【讨论】:

  • 所以在 Delphi 中,如果不将值存储在某处,他们就无法编写?
  • 没有办法创建一个指向包含值的单词的指针,而没有地方存储它,就像他说的那样。
  • 字节或整数呢?对于地址,您必须将其存储在任何地方,因此它们也应该是字节的一种方式。
  • 字节或整数呢?你有什么问题?
  • @Tprice88,您的 C++ 示例和您的 Delphi 示例不等效。您的 C++ 示例正在编写一个 string literal,而您的 Delphi 代码编写一个 integer。 C++ 可以从字符串文字中获取指针,因为字符串文字是数组,并且数组会自动转换为指向其第一个元素的指针。所以你有一个指针。尝试在 C++ 中传递一个整数,它会像在 Delphi 中失败一样失败。
【解决方案2】:

在 C++ 中,这段代码:

WriteProcessMemory(hProcess, (void*)0x4E709C, (void*)(PBYTE)"\x20", 1, NULL); 

在应用程序的内存中声明一个const char[] 缓冲区,其中包含两个字符'\x20''\x00'。通过在文字周围使用" 双引号字符可以明显看出这一点。他们正在创建一个字符串文字,而不是一个字符文字(它使用 ' 单引号字符代替)。该文字的第一个字符的起始地址被传递给第三个参数,第四个参数设置为 1 以告诉 WriteProcessMemory() 从该 2 字节缓冲区中仅复制 1 个字节。

另一方面,Delphi 在单字符和字符串文字周围使用' 单引号字符,因此依赖于代码上下文来决定需要创建哪种类型的文字。因此,Delphi 没有直接的方法来声明与 C++ 代码中的内联 char[] 等效的单字符文字。我现在能想到的最接近的等价物,没有声明一个常数,是这样的:

WriteProcessMemory(hProcess, Pointer($4E709C), PAnsiChar(AnsiString(' ')), 1, nil); 

否则,请仅使用显式常量。 C++ 代码所做的直接等价物如下:

const
  buffer: array[0..1] of AnsiChar = (#$20, #0);

WriteProcessMemory(hProcess, Pointer($4E709C), Pointer(PByte(@buffer[0])), 1, nil); 

或者,您可以将其简化为以下内容:

const
  space: Byte = $20;

WriteProcessMemory(hProcess, Pointer($4E709C), @space, 1, nil); 

【讨论】:

  • 不错,您所做的方法实际上有效,但我遇到了一个问题。 WriteProcessMemory(HandleWindow, Pointer($449A17), PAnsiChar(AnsiString('C3')), 1, Write); 为什么会变成 43
  • @Tprice88 在你太兴奋之前,问问自己你将如何编码,例如,值
  • @Remy 为什么是Pointer(PByte(@buffer[0]))?为什么不@buffer[0]
  • @DavidHeffernan:我用 Delphi 术语展示了 C++ 代码直接在做什么,它使用了额外的(冗余)强制转换。你会看到我在我展示的另一个 Delphi 示例中去掉了额外的演员表。
【解决方案3】:

ptr() 方法将地址转换为指针。所以第二种方法中的值不是99而是写在地址99处的值。

我的肮脏方法,但只有几行代码:

procedure WriteBytes(hProcess: THandle; address: Pointer; buffer: Variant; count: Integer);
begin
  WriteProcessMemory(hProcess, address, @buffer, count, nil);
end;

然后你可以调用该方法:

WriteBytes(HandleWindow, Pointer($449A17), 90, 1);

【讨论】:

  • 这如何工作?变体的第一个字节不是有效负载。
  • 在这种情况下,变体被作为整数处理。当 LSB 在第一个字节中时,它应该在没有人必须转换值以使其适合时工作。它是一种肮脏的方法,我也不想使用,但如果目标是尽可能少地获得代码行,则可以使用它。
  • 变体的第一个字节不是有效负载。这是类型信息。
  • 你确定?嗯,那么必须修改 WriteBytes 方法中的@buffer,以便指针显示在有效负载上。对不起,我还没有安装 Delphi 来测试它。它只是一个展示这个想法的模板。也许它需要一些小的修改。
  • 变体在这里是一个非常糟糕的主意。我突然想到,OP 实际上想要灵活的字节序列,如他的作弊引擎十六进制编辑器中所见。这是一个开放的 Byte 数组。
猜你喜欢
  • 1970-01-01
  • 2011-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-02
  • 1970-01-01
  • 2014-10-22
  • 2011-05-28
相关资源
最近更新 更多