游戏程序每次启动后,它的某个参数所在的内存地址都会改变,我想写个内存修改器,主要任务是确定那个参数所在的内存地址,我认为,虽然每次地址都会改变,但是相对于整个游戏程序的内存起始地址应该是固定的吧。那么我想,只要找到了游戏程序在内存中的起始地址,就可以根据偏移量得到我所要的参数的内存地址了,关键是这个程序在内存中的“起始内存地址”可以得到吗?如何得到?
谢谢各位的帮助
谢谢各位的帮助
解决方案 »
- xe2中的FireMonkey HD窗体如何做成像QQ自动顶部隐藏功能窗体,是否有高人给出答案!
- 来帮小弟个忙
- 为什么fastreport用adoquery 动态语句会死循环一直打印?
- 工程中有个单元不能设置断点
- 寻求delphi源代码实例
- 如何把widestring类型用writefile写入再用readfile读出来?在线等,最好给个例子
- 寻求解决方案,帮忙看看,
- 动态增加计算列?
- 如何用SQL语句在DELPHI程序中将SYBASE数据库中表COPY到SQLSERVER中!!!
- 倾家荡产求解决方案,只是个概念问题,若您做过,就能拿到我所有的分,1000分
- PHOTOSHOP中的字体输出有项特殊功能能使字体四周平滑,请问用DELPHI如何实现。
- package里面怎么发布一个自己定义的CLASS,让外部能够使用?
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Mask, tlhelp32;type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
ComboBox1: TComboBox;
MaskEdit1: TMaskEdit;
Label1: TLabel;
Label2: TLabel;
MaskEdit2: TMaskEdit;
Label3: TLabel;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
IsLoad: boolean;
FSnapshotHandle: THandle;
function GetProcessID(var List: TStringList; FileName: string = ''): TProcessEntry32;
end;var
Form1: TForm1;
implementation{$R *.DFM}function HexToInt(HexStr: string): Int64;
var RetVar: Int64;
i: byte;
begin
HexStr := UpperCase(HexStr);
if HexStr[length(HexStr)] = 'H' then
Delete(HexStr, length(HexStr), 1);
RetVar := 0;
for i := 1 to length(HexStr) do begin
RetVar := RetVar shl 4;
if HexStr[i] in ['0'..'9'] then
RetVar := RetVar + (byte(HexStr[i]) - 48)
else
if HexStr[i] in ['A'..'F'] then
RetVar := RetVar + (byte(HexStr[i]) - 55)
else begin
Retvar := 0;
break;
end;
end; Result := RetVar;
end;procedure TForm1.Button1Click(Sender: TObject);
var
FProcessEntry32: TProcessEntry32;
ProcessID: integer;
ProcessHandle: THandle;
lpBuffer: pchar;
nSize: DWORD;
lpNumberOfBytes: DWORD;
i: integer;
addr:dword;
s: string;
List: TStringList;
mbi_thunk:TMemoryBasicInformation;
dwOldProtect:dword;
begin
if Combobox1.itemindex = -1 then exit;
List := TStringList.Create;
FProcessEntry32 := GetProcessID(List, Combobox1.text);
if FProcessEntry32.th32ProcessID=0 then exit;
ProcessID := FProcessEntry32.th32ProcessID;
Memo1.Lines.Clear;
memo1.lines.add('Process ID ' + IntToHex(FProcessEntry32.th32ProcessID, 8));
memo1.lines.Add('File name ' + FProcessEntry32.szExeFile); ProcessHandle := OpenProcess(PROCESS_ALL_ACCESS, false, ProcessID);
memo1.Lines.Add('Process Handle ' + intTohex(ProcessHandle, 8));
Memo1.Lines.Add('虚拟内存中的数据:');
addr:=HexToInt(MaskEdit1.text);
nSize:=HexToInt(MaskEdit2.text)-addr+1;
if HexToInt(MaskEdit2.text)>addr then
begin
lpBuffer := AllocMem(nSize);
if(not ReadProcessMemory(ProcessHandle, Pointer(addr), lpBuffer, nSize, lpNumberOfBytes))
or(nSize<>lpNumberOfBytes) then
begin
showmessage('读数据出错,可能是指定的地址不存在.');
exit;
end;
s:='';
for i :=0 to nSize-1 do
begin
s := s + format('%.2X ',[ord(lpBuffer[i])]);
{读取内容}
if ((i mod 16 ) = 15)or(i=nSize-1) then
begin
Memo1.Lines.Add(s);
s := '';
end;
end;
VirtualQueryEx(ProcessHandle,Pointer(addr),mbi_thunk, sizeof(TMemoryBasicInformation));
VirtualProtectEx(ProcessHandle,Pointer(addr),nSize,PAGE_EXECUTE_READWRITE,mbi_thunk.Protect);
if(not WriteProcessMemory(ProcessHandle, Pointer(addr), lpBuffer, nSize, lpNumberOfBytes))
then
begin
showmessage('写数据出错,可能是该地址不允许写。如果该处不是Rom,可以通过Ring0或其它特权写该内存。');
end;
VirtualProtectEx(ProcessHandle,Pointer(addr), nSize, mbi_thunk.Protect,dwOldProtect);
FreeMem(lpBuffer, nSize);
end;
CloseHandle(ProcessHandle);
List.free;
end;function Tform1.GetProcessID(var List: TStringList; FileName: string = ''): TProcessEntry32;
var
Ret: BOOL;
s: string;
FProcessEntry32: TProcessEntry32;
begin
FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
FProcessEntry32.dwSize := Sizeof(FProcessEntry32);
Ret := Process32First(FSnapshotHandle, FProcessEntry32);
while Ret do
begin
s := ExtractFileName(FProcessEntry32.szExeFile);
if (FileName = '') then
begin
List.Add(Pchar(s));
end
else if (AnsiCompareText(Trim(s),Trim(FileName))=0) and (FileName <> '') then
begin
List.Add(Pchar(s));
result := FProcessEntry32;
break;
end;
Ret := Process32Next(FSnapshotHandle, FProcessEntry32);
end;
CloseHandle(FSnapshotHandle);
end;procedure TForm1.FormCreate(Sender: TObject);
var
List: TStringList;
i: integer;
begin
Combobox1.clear;
List := TStringList.Create;
GetProcessID(List);
for i := 0 to List.Count - 1 do
begin
Combobox1.items.add(Trim(List.strings[i]));
end;
List.Free;
Combobox1.itemindex := 0;
end;end.
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls,TLHelp32, ComCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
ComboBox1: TComboBox;
ListView1: TListView;
Button2: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
IsBreak:boolean;
end;var
Form1: TForm1;implementation{$R *.DFM}function GetProcessID(var List:TStringList;FileName:string=''):TProcessEntry32;
var
Ret : BOOL;
s:string;
FProcessEntry32:TProcessEntry32;
FSnapshotHandle:THandle;
begin
FSnapshotHandle:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
FProcessEntry32.dwSize:=Sizeof(FProcessEntry32);
Ret:=Process32First(FSnapshotHandle,FProcessEntry32);
while Ret do
begin
s:=ExtractFileName(FProcessEntry32.szExeFile);
if (FileName='') then
begin
List.Add(Pchar(s));
end
else if (AnsicompareText(Trim(s),Trim(FileName))=0)and(FileName<>'')then
begin
List.Add(Pchar(s));
result:=FProcessEntry32;
break;
end;
Ret:=Process32Next(FSnapshotHandle,FProcessEntry32);
end;
CloseHandle(FSnapshotHandle);
end;procedure TForm1.FormCreate(Sender: TObject);
var
List:TStringList;
i:integer;
begin
Combobox1.clear;
List:=TStringList.Create;
GetProcessID(List);
for i:=0 to List.Count-1 do
Combobox1.items.add(Trim(List.strings[i]));
List.Free;
Combobox1.itemindex:=0;
end;procedure TForm1.Button1Click(Sender: TObject);
var
FProcessEntry32:TProcessEntry32;
PID : integer;
List:TStringList;
HeapListHandle:Thandle;
HeapStruct:THeapEntry32;
HeapList:THeapList32;
IsHeapFinish,IsListFinish:boolean;
ListItem:TListItem;
flagStr:string;
begin
Isbreak:=false;
ListView1.Items.clear;
if Combobox1.itemindex=-1 then exit;
List:=TStringList.Create;
FProcessEntry32:=GetProcessID(List,Combobox1.text);
if FProcessEntry32.th32ProcessID=0 then exit;
PID:=FProcessEntry32.th32ProcessID;
HeapListHandle:=CreateToolhelp32Snapshot(TH32CS_SNAPHeaplist,PID);
HeapList.dwSize:=sizeof(THeapList32);
IsListFinish:=Heap32ListFirst(HeapListhandle,HeapList);
while IsListFinish do
begin
Application.ProcessMessages;
if IsBreak then break;
HeapStruct.dwSize:=SizeOf(THEAPENTRY32);
IsHeapFinish:=Heap32First(HeapStruct,PID,HeapList.th32HeapID);
while IsHeapFinish do
begin
Application.ProcessMessages;
if IsBreak then break;
try
ListView1.Items.BeginUpdate;
ListItem:=ListView1.Items.add;
ListItem.Caption:=IntTostr(HeapList.th32HeapId);
Listitem.SubItems.Add(format('$%p',[Pointer(HeapStruct.dwAddress)]));
ListItem.SubItems.add(format('%d字节',[HeapStruct.dwBlockSize]));
case HeapStruct.dwFlags of
LF32_FIXED:
flagStr:='固定块';
LF32_FREE:
flagstr:='空闲块';
LF32_MOVEABLE:
flagstr:='可移动块';
end;
ListItem.SubItems.add(flagstr);
finally
Listview1.Items.EndUpdate;
end;
IsHeapFinish:=Heap32Next(HeapStruct);
end;
IsListFinish:=Heap32ListNext(HeapListHandle,HeapList);
end;
closehandle(HeapListHandle);
List.Free;
end;procedure TForm1.Button2Click(Sender: TObject);
begin
IsBreak:=true;
end;end.
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,Aclapi,Accctrl;type
TForm1 = class(TForm)
Button1: TButton;
Edit2: TEdit;
Label1: TLabel;
Edit1: TEdit;
Label2: TLabel;
ListBox1: TListBox;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
public
end;
PUnicodeString = ^TUnicodeString;
TUnicodeString = packed record
Length: Word;
MaximumLength: Word;
Buffer: PWideChar;
end;
NTSTATUS = Integer;
PObjectAttributes = ^TObjectAttributes;
TObjectAttributes = packed record
Length: DWORD;
RootDirectory: THandle;
ObjectName: PUnicodeString;
Attributes: DWORD;
SecurityDescriptor: PSecurityDescriptor;
SecurityQualityOfService: PSecurityQualityOfService;
end; TZwOpenSection = function(var SectionHandle: THandle;
DesiredAccess: ACCESS_MASK;
var ObjectAttributes: TObjectAttributes): NTSTATUS;stdcall;
TzwClose=procedure(Sectionhandle:Thandle);stdcall;
TRtlInitUnicodeString = procedure(var DestinationString: TUnicodeString;
vSourceString: WideString);stdcall;
const
STATUS_SUCCESS = NTSTATUS(0);
STATUS_INVALID_HANDLE = NTSTATUS($C0000008);
STATUS_ACCESS_DENIED = NTSTATUS($C0000022);
OBJ_INHERIT = $00000002;
OBJ_PERMANENT = $00000010;
OBJ_EXCLUSIVE = $00000020;
OBJ_CASE_INSENSITIVE = $00000040;
OBJ_OPENIF = $00000080;
OBJ_OPENLINK = $00000100;
OBJ_KERNEL_HANDLE = $00000200;
OBJ_VALID_ATTRIBUTES = $000003F2;
ObjectPhysicalMemoryDeviceName = '\Device\Physicalmemory';
ntdll = 'ntdll.dll';
var
ZwOpenSection: TZwOpenSection;
zwClose:TzwClose;
RtlInitUnicodeString: TRtlInitUnicodeString;
var
Form1: TForm1;
NtLayer: HMODULE;
implementation
{$R *.dfm}
function NT_SUCCESS(var Status: longint): boolean;
begin
result := longint(Status) >= 0;
end;procedure InitializeObjectAttributes(var p: TOBJECTATTRIBUTES; n: PUNICODESTRING;
a: DWORD; r: Thandle; s: PSecurityDescriptor);
begin
p.Length := sizeof(TOBJECTATTRIBUTES);
p.RootDirectory := r;
p.Attributes := a;
p.ObjectName := n;
p.SecurityDescriptor := s;
p.SecurityQualityOfService := nil;
end;function SetPhyscialMemorySectionCanBeWrited(hSection:Thandle):boolean;
var
pDacl:PACL;
pNewDacl:PACL;
pSD:PPSECURITY_DESCRIPTOR;
dwRes:cardinal;
ea:EXPLICIT_ACCESS_A;
label CleanUp;
begin
result:=false;
pDacl:=nil;
pNewDacl:=nil;
pSD:=nil;
dwres:=GetSecurityInfo(hSection,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,nil,nil,@pDacl,nil,pSD);
if(dwres<>ERROR_SUCCESS) then
begin
goto CleanUp;
end;
Fillchar(ea, sizeof(EXPLICIT_ACCESS),0);
ea.grfAccessPermissions := SECTION_MAP_WRITE;
ea.grfAccessMode := GRANT_ACCESS;
ea.grfInheritance:= NO_INHERITANCE;
ea.Trustee.TrusteeForm := TRUSTEE_IS_NAME;
ea.Trustee.TrusteeType := TRUSTEE_IS_USER;
ea.Trustee.ptstrName := 'CURRENT_USER';
dwRes:=SetEntriesInAcl(1,@ea,nil,pNewDacl);
dwRes:=SetSecurityInfo(hSection,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,nil,nil,pNewDacl,nil);
if(dwRes=ERROR_SUCCESS) then
begin
goto CleanUp;
end;
result:=true;
CleanUp:
if(pSD<>nil) then
LocalFree(cardinal(pSD^));
if(pNewDacl<>nil) then
LocalFree(cardinal(psD^));
end;function OpenPhysicalMemory(ReadOrNot:boolean): Thandle;
var
status: NTSTATUS;
physmem: Thandle;
physmemString: TUnicodeString;
attributes: TObjectAttributes;
SectionAttrib:integer;
physmemName: WideString;
begin
result:=0;
physmemName := ObjectPhysicalMemoryDeviceName;
RtlInitUnicodeString(physmemString, physmemName);
InitializeObjectAttributes(attributes, @physmemString,
OBJ_CASE_INSENSITIVE or OBJ_KERNEL_HANDLE, 0, nil);
if ReadorNot then
SectionAttrib:=SECTION_MAP_READ
else SectionAttrib:=SECTION_MAP_READ or SECTION_MAP_WRITE;
status := ZwOpenSection(physmem, SectionAttrib, attributes);
if not ReadorNot then
begin
if(status=STATUS_ACCESS_DENIED)then
begin
status := ZwOpenSection(physmem,READ_CONTROL or WRITE_DAC,Attributes);
SetPhyscialMemorySectionCanBeWrited(physmem);
zwClose(physmem);
status :=ZwOpenSection(physmem,SectionAttrib,Attributes);
end;
end;
if (not NT_SUCCESS(status)) then
exit;
result := physmem;
end;function MapPhysicalMemory(ReadOrNot:boolean;PhysicalMemory:THandle;Address,
Length:DWORD;var VirtualAddress: Pchar): boolean;
var
Access:Cardinal;
begin if ReadOrNot then Access:=FILE_MAP_READ
else Access:=FILE_MAP_READ or FILE_MAP_WRITE;
VirtualAddress:=MapViewOfFile(PhysicalMemory,Access,0,Address,Length);
inc(DWORD(VirtualAddress) , Address mod $1000);
result:=true;
end;procedure UnmapPhysicalMemory(Address: Pointer);
begin
UnMapViewOfFile(Address);
end;function LocateNtdllEntryPoints: BOOLEAN;
begin
NtLayer := GetModuleHandle(ntdll);
if NtLayer = 0 then
begin
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
result := false;
exit;
end
else
begin
if not Assigned(ZwOpenSection) then
ZwOpenSection := GetProcAddress(NtLayer, 'ZwOpenSection');
if not assigned(zwClose) then
zwClose:=GetProcAddress(ntlayer,'ZwClose');
if not Assigned(RtlInitUnicodeString) then
RtlInitUnicodeString := GetProcAddress(NtLayer,
'RtlInitUnicodeString');
end;
result := true;
end;
//后接
特别感谢xiangwangz(<*敝屣荣华 浮云生死 此身何惧*>) 兄,你的资料对我帮助很大,谢谢!(结贴)