Delphi中空字符串的汇编字节表示及跨进程写入实现
问题背景
最初提问的备注(Tom Brunberg):尚不明确提问的具体目的与数组的后续使用场景。
本次实际目标为:将空字符串写入目标进程的指定内存地址,实现和已验证C++逻辑一致的写入效果。
参考代码
已验证可用的C++端实现
PVOID hmod = debug_event.u.LoadDll.lpBaseOfDll; ULONG op; SIZE_T NumberOfBytesWritten; if (VirtualProtectEx(pi.hProcess, hmod, 1, PAGE_READWRITE, &op)) { WriteProcessMemory(pi.hProcess, hmod, "", 1, &NumberOfBytesWritten); }
待修正的Delphi端写入流程
procedure WriteBytes(hProcess: THandle; Address: pointer; const Buffer: array of byte); var Read: THandle; oldprot, tmp: dword; begin if (VirtualProtectEx(hProcess, Address, Length(Buffer), PAGE_EXECUTE_READWRITE, @oldprot)) then Writeln('1 - VirtualProtectEx() successfully!'); if (WriteProcessMemory(hProcess, Address, @Buffer, Length(Buffer), Read)) then Writeln('2 - WriteProcessMemory() successfully!'); if (VirtualProtectEx(hProcess, Address, Length(Buffer), oldprot, @tmp)) then Writeln('3 - VirtualProtectEx() successfully!'); end;
待初始化的字节数组
已知参考定义为固定长度字节数组:Values : Array[0..4] of byte = ($C2,$00,$00,$90,$90);
需要按相同逻辑初始化长度为1的字节数组:
const Values: Array[0..0] of Byte = (???); // 此处需要填入对应空字符串的字节内容
实现方案
1. 字节数组的正确初始化
C++中空字符串""的字节构成就是单个值为$00的空终止符,没有其他字符,和参考的固定字节数组定义逻辑完全匹配。长度为1的字节数组直接填写该字节即可:
const Values: Array[0..0] of Byte = ($00);
这个定义生成的内存字节,和C++端传入""时指向的内容完全一致。
2. Delphi写入流程的问题修正
原WriteBytes函数存在两个会导致写入错误的问题,修正后即可完全复刻C++端的运行效果:
- 数据源传参错误:原代码给
WriteProcessMemory传了@Buffer作为数据源地址。对于Delphi的开放数组参数,这个地址是栈上参数变量本身的地址,不是数组实际存储字节的首地址,会把栈上的无关数据写进目标进程。正确写法是直接传PByte(Buffer),Delphi会自动将开放数组隐式转换为指向第一个字节的指针。 - 变量类型不匹配:原代码里接收写入字节数的变量用了
THandle类型,和Windows API要求的SIZE_T类型尺寸不匹配,会引发内存访问异常,需要替换为对应类型的变量。
修正后的完整可运行代码:
procedure WriteBytes(hProcess: THandle; Address: Pointer; const Buffer: array of Byte); var BytesWritten: SIZE_T; oldprot, tmp: DWORD; begin // 调整目标内存保护属性为可写 if VirtualProtectEx(hProcess, Address, Length(Buffer), PAGE_EXECUTE_READWRITE, @oldprot) then Writeln('1 - VirtualProtectEx() 执行成功!'); // 写入目标字节 if WriteProcessMemory(hProcess, Address, PByte(Buffer), Length(Buffer), BytesWritten) then Writeln('2 - WriteProcessMemory() 执行成功!'); // 还原目标内存的原始保护属性 if VirtualProtectEx(hProcess, Address, Length(Buffer), oldprot, @tmp) then Writeln('3 - VirtualProtectEx() 执行成功!'); end;
调用时直接传入之前定义的Values常量即可,最终写入目标地址的内容和C++端验证通过的逻辑完全一致。
内容的提问来源于stack exchange,提问作者user13342561
相关产品推荐
相关产品推荐

