操作内存引出的问题~~求解!请高手指教~!

jiangmenghen 2004-10-05 04:17:50
下面是照一个教程做的代码,请高手指教一下我如果要把得到的数据显示出来应该怎么办!!

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);

private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

Resource: array[1..7] of dword;//这一段不明白什么意思!!?

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);

const
ResourceOffset: dword = $004DF788;//是把内存地址赋给ResourceOffset吧?
var

hw: HWND;
pid: dword;
h: THandle;
tt: Cardinal;

begin
hw := FindWindow('计算器', nil);
if hw = 0 then
ShowMessage('1');
GetWindowThreadProcessId(hw, @pid);
h := OpenProcess(PROCESS_ALL_ACCESS, false, pid);
if h = 0 then
ReadProcessMemory(h,Pointer(ResourceOffset),
@Resource,
20,
tt);

在这想把 Resource 中的数值显示到 Memo 组件中,应该怎么做!??

CloseHandle(h);
end;

end.



论坛上有关操作内存的文章我都看了,那些方法我编译不通过!!不明为什么中!!以上的通过又不知怎么读出来.
...全文
233 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
快乐老猫 2004-10-24
  • 打赏
  • 举报
回复
如果你需要详细的代码,可以去 http://game.ali213.net/showthread.php?s=&threadid=142937&goto=lastpost 下载我的源代码,这个源代码是游戏太阁5繁体版的修改器,应该是目前功能最全的了。

PS:这个论坛需要注册,所以我没法给你直接下载的连接,我也没有自己的空间上传,你需要的话就去哪里下载吧。
快乐老猫 2004-10-24
  • 打赏
  • 举报
回复
我这里提供的是函数阿,你直接调用就可以,调用的时候传进去你要访问的进程文件名(不包含路径的),如果你提供的是STRING类型,就用PCHAR(STRING)方法强制转换
jiangmenghen 2004-10-22
  • 打赏
  • 举报
回复
谢谢 快乐老猫(无米下炊) 的讲解,非常详细让我受益非浅.
我想请教一下
s := ExtractFileName(ProcessStruct.szExeFile); //获取进程的可执行文件名称
if AnsiCompareText(Trim(s), EXE_Name)=0 then //如果是HL程序名,表示找到游戏进程。

其中是不是有一个地方加入在进程中的相关程序名? 是EXE_Name这里换吗??
比如在进程中程序的对应进程名是 XXX.EXE 那EXE_Name就改成 XXX.EXE 是这样的吗?!?
快乐老猫 2004-10-21
  • 打赏
  • 举报
回复
Resource: array[1..7] of dword;//这里是4*8=32 byte,就是用于数据交换的缓冲区,因为你不能直接访问外部进程空间,必须把对方空间内的数据先复制到自己的空间里面。
hw := FindWindow('计算器', nil);//这个是用于查找目标程序窗口的
GetWindowThreadProcessId(hw, @pid);//通过窗口句柄查找进程ID
ReadProcessMemory(h,Pointer(ResourceOffset),@Resource,20,tt);//而这里仅获得了20BYTE应该是输入错误,理论上应该是$20,最好的方法是sizeof(Resource),这样安全一些
//--------------------------------------------------------

//利用窗口查找进程是一种方法,不过感觉效果并不理想,而且你无法得到更具体的信息,如果对方窗口隐藏了,你更加无法获得进程编号,可以用如下方法获得进程编号
function GetProcessID(EXE_Name: PChar): THandle;
var
s: string;
ok: Bool;
ProcessListHandle: THandle;
ProcessStruct: TProcessEntry32;
begin
Result := 0;
//获得进程列表句柄
ProcessListHandle := CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS, 0);
try
ProcessStruct.dwSize := Sizeof(ProcessStruct);
//获得第一个进程句柄
ok := Process32First(ProcessListHandle, ProcessStruct);

while ok do
begin
s := ExtractFileName(ProcessStruct.szExeFile); //获取进程的可执行文件名称
if AnsiCompareText(Trim(s), EXE_Name)=0 then //如果是HL程序名,表示找到游戏进程。
begin
Result := ProcessStruct.th32ProcessID; //保留游戏进程句柄
break;
end;
ok := Process32Next(ProcessListHandle, ProcessStruct); //获取下一个进程信息。
end;
finally
CloseHandle(ProcessListHandle); //关闭进程列表句柄
end;
end;
//----------------------------------------
//甚至可以用下列函数获得进程所在目录,这样更方便你获得文件的版本信息,对于要支持多种版本的修改器,这个是必须的。
function GetModuleMainFileName(ProcessID: THandle; EXE_Name, ModuleMainFileName:PChar; iLen: integer): integer;
//获得进程模块主文件名字(包含目录)
var
ModuleList :Thandle;
pm :TMODULEENTRY32;
begin
Result := 0;
ModuleList:=CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,processID);
try
pm.dwSize:=sizeof(TMODULEENTRY32);
if not module32first(ModuleList,pm) then Exit;

if AnsiCompareText(Trim(pm.szModule), EXE_Name)=0 then //如果是HL程序名,表示找到游戏进程。
begin
Result := length(ANSIString(pm.szexepath));
if (ModuleMainFileName <> nil) and (iLen > 0) then
StrLCopy(ModuleMainFileName, pm.szexepath, iLen);
Exit;
end;
while module32next(ModuleList,pm) do
begin
if AnsiCompareText(Trim(pm.szModule), EXE_Name)=0 then //如果是HL程序名,表示找到游戏进程。
begin
Result := length(ANSIString(pm.szexepath));
if (ModuleMainFileName <> nil) and (iLen > 0) then
StrLCopy(ModuleMainFileName, pm.szexepath, iLen);
Exit;
end;
end;
finally
CloseHandle(ModuleList);
end;
end; // ModuleEnum
//------------------------------------------------
//读进程可以用如下代码
function GetProcessMemoryForID(ProcessID: THandle; Address: LongWord; Buf: Pointer; Len: LongWord): boolean;
var
hProcessHandle: THandle;
lpNumberOfBytes: LongWord;
begin
Result := false;
if ProcessID = 0 then exit; //如果进程不存在,返回

//只读方式打开游戏进程
hProcessHandle := OpenProcess(PROCESS_VM_READ, false, ProcessID);
if hProcessHandle = 0 then exit; //如果进程无法打开,返回
try
//读进程
ReadProcessMemory(hProcessHandle, Pointer(Address), buf, Len, lpNumberOfBytes);
finally
CloseHandle(hProcessHandle); //关闭游戏进程访问
end;
Result := True;
end;

//写进程用如下代码实现
function SetProcessMemoryForID(ProcessID: THandle; Address: LongWord; Buf: Pointer; Len: LongWord): boolean;
//写进程内存
var
lpNumberOfBytes: LongWord;
hProcessHandle: THandle;
begin
Result := false;
if ProcessID = 0 then exit; //如果进程不存在,返回

//只读方式打开游戏进程
hProcessHandle := OpenProcess(PROCESS_VM_READ or PROCESS_VM_WRITE or PROCESS_VM_OPERATION, false, ProcessID);
if hProcessHandle = 0 then exit; //如果进程无法打开,返回
try
WriteProcessMemory(hProcessHandle, Pointer(Address), buf, len, lpNumberOfBytes);
finally
CloseHandle(hProcessHandle); //关闭游戏进程访问
end;
Result := True;
end;

jiangmenghen 2004-10-19
  • 打赏
  • 举报
回复
5555不理解 如果按楼上这样写 那金山游侠之类是怎么得到数据的?!?不明~~请指教!
jiangmenghen 2004-10-08
  • 打赏
  • 举报
回复
谢谢 scycgjr(夏日荷) !
代码好全..同时也好复杂,看得头晕~我消化一下,懂的话立刻给分!谢谢!!
scycgjr 2004-10-07
  • 打赏
  • 举报
回复
ReadProcessMemory读出的是虚拟地址内容,和物理内容有区别的,不过可以找到对应关系。
你需要了解Win32PE文件的格式。相关信息都可以在文件头里找到。

而一般游戏修改器读取的内存就是物理文件本身的内容,如果你也想写一个游戏修改器,那么就必须游戏程序才知道它的内存地址是怎么变的。给你一个游戏修改器例子(包括代码和原理):http://www.csdn.net/magazine/source/2/Hero.doc

jiangmenghen 2004-10-06
  • 打赏
  • 举报
回复
谢谢大家的指教,特别是 scycgjr(夏日荷)的指点,我照上面的方法做了可以显示出数据,但数据同我用一般游戏修改器查出的地址中的数据不一样的,想问下我应该怎么做!?
是不是还得HOOK那个进程!??具体怎么操作!!
scycgjr 2004-10-06
  • 打赏
  • 举报
回复
procedure TForm1.Button1Click(Sender: TObject);
const
ResourceOffset: dword = $004DF788;//是把内存地址赋给ResourceOffset吧?
var
hw: HWND;
pid: dword;
h: THandle;
tt: Cardinal;
i: Integer;
Resource: array[1..20] of byte;
mm: String;
begin
hw := FindWindow('计算器', nil);
if hw = 0 then GetWindowThreadProcessId(hw, @pid);
h := OpenProcess(PROCESS_ALL_ACCESS, false, pid);
if h = 0 then ReadProcessMemory(h,Pointer(ResourceOffset),@Resource,20,tt);

//在把 Resource 中的数值显示到 Memo 组件中!!
for i := 0 to 20 do
begin
mm:= IntToHex(Resource[i], 2);
Memo1.Lines.Add(mm);
end;


CloseHandle(h);
end;
crossbow 2004-10-06
  • 打赏
  • 举报
回复
>Resource: array[1..7] of dword;//这一段不明白什么意思!!?

缓冲区,说白了就是一个数组

crossbow 2004-10-06
  • 打赏
  • 举报
回复
读到缓冲区,遍历之
jiangmenghen 2004-10-05
  • 打赏
  • 举报
回复
问题就是我不会,好像怎么转都不行啊~~给个完整代码好吗!?? 谢谢了!!!
FrameSniper 2004-10-05
  • 打赏
  • 举报
回复
很简单啊,直接把整型的转换为字符型就可以了.....

1,184

社区成员

发帖
与我相关
我的任务
社区描述
Delphi Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧