如何动态得到运行中的其它进程中的控件在内存中的真实地址和偏移量, 得到后读出其数据(300分)

  • 主题发起人 主题发起人 gzbxmcx
  • 开始时间 开始时间
G

gzbxmcx

Unregistered / Unconfirmed
GUEST, unregistred user!
如何动态得到运行中的其它进程中的控件在内存中的真实地址和偏移量, 得到后读出其数据
以下这个地址:$013609A0 偏移量: $013609A0 如何通过程序得到.
for i:=$013609A0 to $013609A0 do
begin
ReadProcessMemory(
ProcessHndle,
Pointer(i),
lpBuffer,
nSize,
lpNumberOfBytesRead
);

copymemory(@u,Ptr($013609A0),4);
Memo1.Lines.Add(inttostr(u));
//格式化输出
end;
 
不懂
顶下
时刻关注
等待高手出现
 
{**********

Author:CMZY
Version:
Time:2008/02/20
mail:dashoumail@163.com

读写物理和其它进程内存的API

function:
function ReadOrWritePhyMem(ReadOnly:Boolean; //为TRUE时表示读,FALSE时表示写
Address, //起始地址
Length:DWORD; //长度
buffer:Pointer //缓冲区
):boolean; //成功返回true

function ReadOrWriteProcessMem(ReadOrWrite:Boolean; //为TRUE时表示读,FALSE时表示写
Pid:Cardinal; //进程PID
Address, //起始地址
Length:DWORD; //长度
buffer:Pointer //缓冲区
):Boolean; //成功返回true


**********}


unit MemReadWrite;

interface

uses Windows,SysUtils, Variants, Dialogs, Classes,Aclapi,Accctrl;
type
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; //成功则返回status_success

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;
hNtdll:HMODULE;
function ReadOrWritePhyMem(ReadOnly:Boolean;
Address,
Length:DWORD;
buffer:Pointer
):boolean;
function ReadOrWriteProcessMem(ReadOrWrite:Boolean;
Pid,
Address,
Length:DWORD;
buffer:Pointer
):Boolean;
implementation

//加载NT.dll并找到函数
function LocateNtdllEntryPoints: BOOLEAN;
begin
Result:=false;
hNtDll:=GetModuleHandle(NTDLL);
if hNTdll=0 then Exit;

if not Assigned(ZwOpenSection) then
ZwOpenSection:=GetProcAddress(hNtdll,'ZwOpenSection');
if not Assigned(ZwClose) then
ZwClose:=GetProcAddress(hNtDll,'ZwClose');
if Not Assigned(RtlInitUnicodeString) then
RtlInitUnicodeString:=GetProcAddress(hNtDll,'RtlInitUnicodeString');

Result:=true;
end;

//设置物理内存为可写
function SetPhyMemCanBeWrite(hSection:THandle):Boolean;
var
pDacl,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
if pSD<>nil then LocalFree(Cardinal(pSD^));
if pNewDacl<>nil then LocalFree(Cardinal(pSD^));
raise Exception.Create('不能获得物理内存的安全信息!')
end;

FillChar(ea,SizeOf(EXPLICIT_ACCESS_A),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';
SetEntriesInAcl(1,@ea,nil,pNewDacl);

//设置物理内存段的安全信息
dwRes:=SetSecurityInfo(hSection,
SE_KERNEL_OBJECT,
DACL_SECURITY_INFORMATION,
nil,
nil,
@pNewDacl,
nil);

if dwRes = ERROR_SUCCESS then
begin
if pSD<>nil then LocalFree(Cardinal(pSD^));
if pNewDacl<>nil then LocalFree(Cardinal(pSD^));
Result:=true;
end;
end;

//打开物理内存 Readon_ly=false时可以写,若失败返回 0
function OpenPhyMem(ReadOnly:Boolean):THandle;
var
PhyMemName:TUnicodestring;//物理内存名
wsPhyMemName:WideString;
attrib:TObjectAttributes;
SectionAttrib:Integer;
status:NTSTATUS;
hPhyMem:THandle;
begin
result:=0;

wsPhyMemName:= ObjectPhysicalMemoryDeviceName;

RtlInitUnicodeString(PhyMemName,wsPhyMemName); //初始化设备对象名

attrib.Length:=SizeOf(TObjectAttributes);
attrib.ObjectName:=@PhyMemName;
attrib.Attributes:=OBJ_CASE_INSENSITIVE or OBJ_KERNEL_HANDLE;
attrib.RootDirectory:=0;
attrib.SecurityDescriptor:=nil;
attrib.SecurityQualityOfService:=nil;

if ReadOnly then
SectionAttrib:=SECTION_MAP_READ
else
SectionAttrib:=SECTION_MAP_READ or SECTION_MAP_WRITE;

status:= ZwOpenSection(hPhyMem,SectionAttrib,Attrib);

if (Not ReadOnly) and (status=STATUS_ACCESS_DENIED) then
begin
//用另一种方式打开物理内存
status:= ZwOpenSection(hPhyMem,READ_CONTROL or WRITE_DAC,Attrib);

SetPhyMemCanBeWrite(hPhyMem); //设置物理内存可写

ZwClose(hPhyMem);//关闭物理内存
//重新打开
status:= ZwOpenSection(hPhyMem,SectionAttrib,Attrib);
end;

if status<0 then
begin
Exit; //失败,则推出
end;
Result:=hPhyMem;
end;

//影射物理内存为本进程的虚拟内存
function MapPhyMem(ReadOnly:Boolean; //是否只读
PhyMem:THandle; //物理内存句柄
Address, //起始地址
Length:DWORD; //长度
var VirtualAddress:Pchar //本地虚拟地址
):Boolean; //成功返回true
var
Access:Cardinal;
begin
result:=false;

if ReadOnly then Access:=FILE_MAP_READ
else Access:= FILE_MAP_READ or FILE_MAP_WRITE;

VirtualAddress:=MapViewOfFile(PhyMem,Access,0,Address,Length);

//返回值VirtualAddress自动按页对齐,需要改正??
Inc(DWORD(VirtualAddress),Access mod $1000);

result:=true;
end;

//取消影射
procedure UnMapPhyMem(Address:pointer);
begin
UnmapViewOfFile(Address);
end;

//读写物理内存!
function ReadOrWritePhyMem(ReadOnly:Boolean; //是否只读
Address,
Length:DWORD;
buffer:Pointer
):boolean;
var
hPhyMem:THandle;
VAddress:Pchar;
begin
result:=false;

if not Assigned(ZwOpenSection) then Exit;

hPhyMem:=OpenPhyMem(ReadOnly);

if hPhyMem=0 then Exit;


if not MapPhyMem(ReadOnly,hPhyMem,Address,length,vaddress) then Exit;

try
if ReadOnly then
Move(vaddress^,buffer^,length)
else
Move(buffer^,vaddress^,length);
result:=true;
Except
on e:Exception do
begin
MessageDlg('缓中区长度不足或内存跨段。'+#$D+
'每个内存段为4K的整数倍,每次读写不能跨越多个不同的内存段。',
mtError, [mbok],0);
end;
end;
UnMapPhyMem(VAddress);
ZwClose(hPhyMem);
end;

//读写其它进程内存
function ReadOrWriteProcessMem(ReadOrWrite:Boolean;Pid:Cardinal;Address,Length:DWORD;buffer:Pointer):Boolean;
var
hProcess:THandle;
ReadLength:Cardinal;
mbi:TMemoryBasicInformation;
OldProtect:DWORD;
begin
Result:=false;
if ReadOrWrite then //如果是读取
begin
hProcess:=OpenProcess(PROCESS_ALL_ACCESS,false,Pid); //打开进程



if (not ReadProcessMemory(hProcess, Pointer(Address), buffer, Length, ReadLength))
or (Length<>ReadLength) then
begin
// ShowMessage(IntToStr(GetlastError));
CloseHandle(hProcess);
Exit;
end;

end else //如果是写入
begin
hProcess:=OpenProcess(PROCESS_ALL_ACCESS,false,Pid);

//查询内存属性
VirtualQueryEx(hProcess,Pointer(Address),mbi,SizeOf(TMemoryBasicInformation));

//修改属性
virtualProtectEx(hProcess,Pointer(Address),Length,PAGE_EXECUTE_READWRITE,mbi.Protect);

if (not WriteProcessMemory(hProcess,Pointer(Address),buffer,Length,ReadLength))
or (ReadLength<>Length) then
begin
CloseHandle(hProcess);
Exit;
end;

//恢复属性
VirtualProtectEx(hProcess,Pointer(Address),Length,Mbi.Protect,OldProtect);
end;
CloseHandle(hProcess);
Result:=true;
end;

Initialization
if not LocateNtdllEntryPoints then raise Exception.Create('不能加载NT.dll!');
Finalization
FreeLibrary(hNtdll);
end.
 
不懂.帮顶下
 
不懂汇编的你做不到。
 
TO: HNXXCXG
谢谢你的执情, 请看题: 动态得到, 不是固定.
TO: 白河愁,
我只能看懂简单的汇编, 用汇编如何实现?
 
首选分析程序,程序被编译后会有静态地址部分,一定是固定的。
找到这个地址,然后看看它的程序是怎么用这个静态地址然后偏移数据的,
学之,就可以得到你要的东西的地址。

泼个冷水,如果你的汇编到这个程度,是不会问这个问题的。
 
呵呵....汇编很差劲. 所以才来请教.
 
怎样在内存中识别出控件?控件可以是N个公用一套代码,控件的数据和控件的执行代码,是不是放在一起的怎样得知,这是都不是精通汇编就搞掂的,另外控件在程序里面,只是一堆子程序,我觉得没什么办法。
 
不光精通汇编,还得熟悉编译器在内存中生成的类与对象等的格式、各项的布局等等。一般也是从Application这个全局对象起,找其Components再递归往下找,可以得到个粗略的对象树,而且这个找的过程得用跨进程的内存读写来实现。
 
目前只有一个可行的方法:就是读取内存中的地址。2GB的内存空间中分析找到规律不是件容易的事情。再说了这不是个标准控件,Windows的填写数据的消息跟踪不到,消息就排除了。读取Socket封包数据,找到后里面是一堆乱码,不好解析。。
不知个位还有什么好的见议。。
 
后退
顶部