📄 structuresfrm.pas
字号:
unit Structuresfrm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus, StdCtrls, ExtCtrls, ComCtrls,cefuncproc,newkernelhandler;
const structureversion=1;
type Tbasestucture=record
name: string;
structelement: array of record
description:string;
pointerto: boolean; //determines if it's a pointer to a structure, or the structure itself
pointertosize: dword;
structurenr: integer; //-1 and lower=base element (they can't be both -1)
bytesize: dword; //size in bytes of how big this element is. (also for base elements)
end;
end;
type Tstructure=class
private
treeviewused: ttreeview;
address:dword;
basestructure: integer;
parentnode: ttreenode; //owner of this object
objects: array of record //same size as the structelement of the base object
nodetoupdate: ttreenode; //same size as the structelement of the base object
child: tstructure; //if it is a pointer then this points to the structure that defines it
currentvalue: string;
end;
public
procedure refresh;
constructor create(treeviewused: ttreeview;parentnode: ttreenode;address:dword; basestructure: integer);
destructor destroy; override;
end;
type
TfrmStructures = class(TForm)
MainMenu1: TMainMenu;
File1: TMenuItem;
Open1: TMenuItem;
Save1: TMenuItem;
Structures1: TMenuItem;
Definenewstructure1: TMenuItem;
N1: TMenuItem;
TreeView1: TTreeView;
Panel1: TPanel;
edtAddress: TEdit;
Button1: TButton;
Button2: TButton;
PopupMenu1: TPopupMenu;
Addelement1: TMenuItem;
updatetimer: TTimer;
Deleteelement1: TMenuItem;
OpenDialog1: TOpenDialog;
SaveDialog1: TSaveDialog;
New1: TMenuItem;
ChangeElement1: TMenuItem;
N2: TMenuItem;
Addtoaddresslist1: TMenuItem;
Recalculateaddress1: TMenuItem;
N3: TMenuItem;
procedure Definenewstructure1Click(Sender: TObject);
procedure Addelement1Click(Sender: TObject);
procedure updatetimerTimer(Sender: TObject);
procedure TreeView1Collapsing(Sender: TObject; Node: TTreeNode;
var AllowCollapse: Boolean);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure edtAddressChange(Sender: TObject);
procedure TreeView1Expanding(Sender: TObject; Node: TTreeNode;
var AllowExpansion: Boolean);
procedure TreeView1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure PopupMenu1Popup(Sender: TObject);
procedure Deleteelement1Click(Sender: TObject);
procedure Save1Click(Sender: TObject);
procedure Open1Click(Sender: TObject);
procedure New1Click(Sender: TObject);
procedure ChangeElement1Click(Sender: TObject);
procedure TreeView1DblClick(Sender: TObject);
procedure Addtoaddresslist1Click(Sender: TObject);
procedure Recalculateaddress1Click(Sender: TObject);
private
{ Private declarations }
currentstructure: tstructure;
definedstructures: array of Tbasestucture;
faddress: dword;
procedure setaddress(x:dword);
procedure refreshmenuitems;
procedure definedstructureselect(sender:tobject);
function RawToType(address: dword; const buf: array of byte; size: integer):integer;
public
{ Public declarations }
property address: dword read faddress write setaddress;
end;
var
frmStructures: TfrmStructures;
implementation
{$R *.dfm}
uses StructuresAddElementfrm,valuechange,mainunit, MemoryBrowserFormUnit;
destructor TStructure.destroy;
var i: integer;
begin
for i:=0 to length(objects)-1 do
if objects[i].child<>nil then objects[i].child.Free;
inherited destroy;
end;
constructor TStructure.create(treeviewused: ttreeview;parentnode: ttreenode;address:dword; basestructure: integer);
var elementnr: integer;
s: tstructure;
begin
self.address:=address;
self.basestructure:=basestructure;
self.treeviewused:=treeviewused;
self.parentnode:=parentnode;
inherited create;
end;
procedure TStructure.refresh;
var i,j,k: integer;
newtext,typename: string;
snr: integer;
elementaddress: dword;
buf: array of byte;
x: dword;
defaultwidth: integer;
ws: widestring;
pc: pchar;
pwc: pwidechar;
newaddress: dword;
s: tstructure;
elementnr: integer;
begin
//check if all nodes are present and remove those not needed anymore
//and adjust the text when needed
// treeviewused.Items.BeginUpdate;
setlength(buf,32);
if basestructure<0 then
begin
//this is a base type, it has to be a child. (and pointer type)
if length(objects)=0 then setlength(objects,1);
end
else
begin
if length(objects)<length(frmStructures.definedstructures[basestructure].structelement) then
setlength(objects,length(frmStructures.definedstructures[basestructure].structelement));
if length(objects)>length(frmStructures.definedstructures[basestructure].structelement) then
begin
//delete the extra ones
for i:=length(frmStructures.definedstructures[basestructure].structelement) to length(objects)-1 do
begin
if objects[i].nodetoupdate<>nil then objects[i].nodetoupdate.Delete;
if objects[i].child<>nil then objects[i].child.Free;
end;
setlength(objects,length(frmStructures.definedstructures[basestructure].structelement));
end;
end;
elementaddress:=address;
for i:=0 to length(objects)-1 do
begin
//define the text for this element
if basestructure<0 then
begin
snr:=basestructure;
end
else
begin
if frmStructures.definedstructures[basestructure].structelement[i].pointerto then
typename:='pointer to '
else
typename:='';
snr:=frmStructures.definedstructures[basestructure].structelement[i].structurenr;
end;
if snr<0 then
begin
if basestructure>=0 then
begin
if frmStructures.definedstructures[basestructure].structelement[i].pointerto then
begin
if readprocessmemory(processhandle,pointer(elementaddress),@buf[0],4,x) then
objects[i].currentvalue:=inttohex(PDWORD(@buf[0])^,8)
else
objects[i].currentvalue:='???';
objects[i].currentvalue:='->'+objects[i].currentvalue;
end;
end;
if (basestructure<0) or (not frmStructures.definedstructures[basestructure].structelement[i].pointerto) then
case snr of
-1:
begin
typename:=typename+'Byte';
//read the value
if readprocessmemory(processhandle,pointer(elementaddress),@buf[0],1,x) then
objects[i].currentvalue:=inttostr(byte(buf[0]))
else
objects[i].currentvalue:='???';
end;
-2:
begin
typename:=typename+'Byte Signed';
//read the value
if readprocessmemory(processhandle,pointer(elementaddress),@buf[0],1,x) then
objects[i].currentvalue:=inttostr(Shortint(buf[0]))
else
objects[i].currentvalue:='???';
end;
-3:
begin
typename:=typename+'Byte Hexadecimal';
if readprocessmemory(processhandle,pointer(elementaddress),@buf[0],1,x) then
objects[i].currentvalue:=inttohex(buf[0],2)
else
objects[i].currentvalue:='???';
end;
-4:
begin
typename:=typename+'2 Bytes';
if readprocessmemory(processhandle,pointer(elementaddress),@buf[0],2,x) then
objects[i].currentvalue:=inttostr(PWORD(@buf[0])^)
else
objects[i].currentvalue:='???';
end;
-5:
begin
typename:=typename+'2 Bytes Signed';
if readprocessmemory(processhandle,pointer(elementaddress),@buf[0],2,x) then
objects[i].currentvalue:=inttostr(PSmallint(@buf[0])^)
else
objects[i].currentvalue:='???';
end;
-6:
begin
typename:=typename+'2 Bytes Hexadecimal';
if readprocessmemory(processhandle,pointer(elementaddress),@buf[0],2,x) then
objects[i].currentvalue:=inttohex(PWORD(@buf[0])^,4)
else
objects[i].currentvalue:='???';
end;
-7:
begin
typename:=typename+'4 Bytes';
if readprocessmemory(processhandle,pointer(elementaddress),@buf[0],4,x) then
objects[i].currentvalue:=inttostr(PDWORD(@buf[0])^)
else
objects[i].currentvalue:='???';
end;
-8:
begin
typename:=typename+'4 Bytes Signed';
if readprocessmemory(processhandle,pointer(elementaddress),@buf[0],4,x) then
objects[i].currentvalue:=inttostr(pinteger(@buf[0])^)
else
objects[i].currentvalue:='???';
end;
-9:
begin
typename:=typename+'4 Bytes Hexadecimal';
if readprocessmemory(processhandle,pointer(elementaddress),@buf[0],4,x) then
objects[i].currentvalue:=inttohex(PDWORD(@buf[0])^,8)
else
objects[i].currentvalue:='???';
end;
-10:
begin
typename:=typename+'8 Bytes';
if readprocessmemory(processhandle,pointer(elementaddress),@buf[0],8,x) then
objects[i].currentvalue:=inttostr(pint64(@buf[0])^)
else
objects[i].currentvalue:='???';
end;
-11:
begin
typename:=typename+'8 Bytes Hexadecimal';
if readprocessmemory(processhandle,pointer(elementaddress),@buf[0],8,x) then
objects[i].currentvalue:=inttohex(pint64(@buf[0])^,16)
else
objects[i].currentvalue:='???';
end;
-12:
begin
typename:=typename+'Float';
if readprocessmemory(processhandle,pointer(elementaddress),@buf[0],4,x) then
objects[i].currentvalue:=floattostr(psingle(@buf[0])^)
else
objects[i].currentvalue:='???';
end;
-13:
begin
typename:=typename+'Double';
if readprocessmemory(processhandle,pointer(elementaddress),@buf[0],8,x) then
objects[i].currentvalue:=floattostr(pdouble(@buf[0])^)
else
objects[i].currentvalue:='???';
end;
-14:
begin
typename:=typename+'String';
if basestructure>=0 then
k:=frmStructures.definedstructures[basestructure].structelement[i].bytesize
else
begin
elementnr:=parentnode.Index;
s:=parentnode.data;
k:=frmStructures.definedstructures[s.basestructure].structelement[elementnr].pointertosize;
end;
if length(buf)<=k then
setlength(buf,k+1);
if readprocessmemory(processhandle,pointer(elementaddress),@buf[0],k,x) then
begin
buf[k]:=0;
for j:=0 to k-1 do
if (buf[j]>0) and (buf[j]<32) then buf[j]:=ord('?');
pc:=@buf[0];
objects[i].currentvalue:=pc;
end
else
objects[i].currentvalue:='???';
end;
-15:
begin
typename:=typename+'String Unicode';
if basestructure>=0 then
k:=frmStructures.definedstructures[basestructure].structelement[i].bytesize
else
begin
elementnr:=parentnode.Index;
s:=parentnode.data;
k:=frmStructures.definedstructures[s.basestructure].structelement[elementnr].pointertosize;
end;
if length(buf)<=k then
setlength(buf,k+1);
if readprocessmemory(processhandle,pointer(elementaddress),@buf[0],k,x) then
begin
buf[k]:=0;
buf[k-1]:=0;
for j:=0 to k-1 do
if (buf[j]>0) and (buf[j]<32) then buf[j]:=ord('?');
pwc:=@buf[0];
ws:=pwc;
objects[i].currentvalue:=ws;
end
else
objects[i].currentvalue:='???';
end;
end;
end else
begin
//it's a defined structure (has to be a pointer)
typename:=frmStructures.definedstructures[snr].name;
if readprocessmemory(processhandle,pointer(elementaddress),@buf[0],8,x) then
objects[i].currentvalue:='->'+inttohex(pdword(@buf[0])^,8)
else
objects[i].currentvalue:='->???';
end;
if basestructure<0 then
begin
newtext:=inttohex(elementaddress,8)+' - '+'('+typename+')';
end
else
begin
newtext:=inttohex(elementaddress,8)+' - '+frmStructures.definedstructures[basestructure].structelement[i].description;//+'('+typename+')';
end;
newtext:=newtext+' ';
while length(newtext)<50 do
newtext:=newtext+' ';
newtext:=newtext+objects[i].currentvalue;
//see if a node exists or not, if not create it.
if objects[i].nodetoupdate=nil then
begin
objects[i].nodetoupdate:=treeviewused.Items.AddChild(self.parentnode,newtext);
objects[i].nodetoupdate.Data:=self;
end
else
begin
if newtext<>objects[i].nodetoupdate.Text then
objects[i].nodetoupdate.Text:=newtext;
end;
if basestructure>=0 then
begin
if objects[i].nodetoupdate.HasChildren <> frmStructures.definedstructures[basestructure].structelement[i].pointerto then
objects[i].nodetoupdate.HasChildren:=frmStructures.definedstructures[basestructure].structelement[i].pointerto;
if objects[i].child<>nil then
begin
//do the same for the children
//pointer
newaddress:=0;
readprocessmemory(processhandle,pointer(elementaddress),@newaddress,4,x);
objects[i].child.address:=newaddress;
objects[i].child.refresh;
end;
inc(elementaddress,frmStructures.definedstructures[basestructure].structelement[i].bytesize);
end;
end;
if treeviewused.Items.GetFirstNode<>nil then
treeviewused.Items.GetFirstNode.Expand(false);
//treeviewused.Items.endupdate;
end;
procedure TfrmStructures.setaddress(x: dword);
begin
faddress:=x;
if not edtAddress.Focused then edtAddress.text:=inttohex(faddress,8);
if currentstructure<>nil then
begin
currentstructure.address:=address;
currentstructure.parentnode.Text:=edtaddress.text+'-'+definedstructures[currentstructure.basestructure].name;
currentstructure.refresh;
end;
end;
function TfrmStructures.RawToType(address: dword; const buf: array of byte; size: integer):integer;
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -