cheat-engine/Cheat Engine/ServiceDescriptorTables.pas
cheatengine@gmail.com 0f35a52416 move the processid and handle from cefuncproc to processhandlerunit
move the processlist function from cefuncproc to it's own unit
start work on the jni library for java
2014-09-08 12:00:14 +00:00

398 lines
9.6 KiB
ObjectPascal

unit ServiceDescriptorTables;
{$MODE Delphi}
interface
uses
windows, LCLIntf, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs,CEFuncProc,NewKernelHandler, Menus, ComCtrls,symbolhandler,imagehlp,disassembler,
StdCtrls, LResources;
type tenummodules= class(tthread)
private
symbolname: string;
callnumber: dword;
procedure done;
procedure foundone;
public
procedure execute; override;
end;
type
TfrmServiceDescriptorTables = class(TForm)
TreeView1: TTreeView;
MainMenu1: TMainMenu;
File1: TMenuItem;
Open1: TMenuItem;
Save1: TMenuItem;
N1: TMenuItem;
Scancallnumbersandnames1: TMenuItem;
CancelScan1: TMenuItem;
OpenDialog1: TOpenDialog;
SaveDialog1: TSaveDialog;
FindDialog1: TFindDialog;
PopupMenu1: TPopupMenu;
Find1: TMenuItem;
GotoSTDaddress1: TMenuItem;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormCreate(Sender: TObject);
procedure Scancallnumbersandnames1Click(Sender: TObject);
procedure CancelScan1Click(Sender: TObject);
procedure Save1Click(Sender: TObject);
procedure TreeView1DblClick(Sender: TObject);
procedure Open1Click(Sender: TObject);
procedure FindDialog1Find(Sender: TObject);
procedure Find1Click(Sender: TObject);
procedure GotoSTDaddress1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
frmServiceDescriptorTables: TfrmServiceDescriptorTables;
implementation
uses MemoryBrowserFormUnit, dbk32functions, ProcessHandlerUnit;
resourcestring
rsServiceDescriptorTable = 'Service Descriptor Table';
rsServiceDescriptorTableShadow = 'Service Descriptor Table Shadow';
rsParameter = 'parameter';
rsParameters = 'parameters';
rsUnknownname = 'unknownname';
rsIncompatibleSDT = 'Incompatible Service Descriptor Table. This table '
+'contains more or less than in the file';
rsIncompatibleSSDT = 'Incompatible Service Descriptor Table Shadow. This '
+'table contains more or less than in the file';
rsNothingFound = 'Nothing found';
var symbolname: string;
canceled: boolean;
procedure TfrmServiceDescriptorTables.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
action:=cafree;
frmServiceDescriptorTables:=nil;
end;
procedure TfrmServiceDescriptorTables.FormCreate(Sender: TObject);
type TSdtStruct=record
functionpointers: pointer;
reserved: dword;
nrofpointers: dword;
parametercounts: pointer;
end;
var sdtstruct: tsdtstruct;
sdt: ptrUint;
x: ttreenode;
second: boolean;
p: thandle;
nrofbytes: PtrUInt;
functionpointers:PDwordArray;
parametercounts: PByteArray;
i: integer;
s: string;
begin
//open own process in case kernelmode openprocess wasn't used
p:=dbk32functions.OP(PROCESS_ALL_ACCESS,true,getcurrentprocessid);
second:=true;
repeat
second:=not second;
if not second then
begin
sdt:=newkernelhandler.GetSDT;
x:=treeview1.Items.Add(nil, rsServiceDescriptorTable);
end
else
begin
sdt:=newkernelhandler.GetSDTShadow;
x:=treeview1.Items.Add(nil, rsServiceDescriptorTableShadow);
end;
if RPM(p,pointer(sdt),@sdtstruct,sizeof(sdtstruct),nrofbytes) then
begin
getmem(functionpointers,sdtstruct.nrofpointers*4);
getmem(parametercounts,sdtstruct.nrofpointers);
try
if RPM(p,sdtstruct.parametercounts,parametercounts,sdtstruct.nrofpointers,nrofbytes) then
if RPM(p,sdtstruct.functionpointers,functionpointers,sdtstruct.nrofpointers*4,nrofbytes) then
begin
for i:=0 to sdtstruct.nrofpointers-1 do
begin
s:=inttohex(functionpointers[i],8)+' ('+inttostr(parametercounts[i] div 4);
if parametercounts[i]=4 then
s:=s+' '+rsParameter+')'
else
s:=s+' '+rsParameters+')';
s:=s+' - '+rsUnknownname;
treeview1.Items.AddChild(x,s);
end;
end;
finally
freemem(parametercounts);
freemem(functionpointers);
end;
end;
until second;
if IsValidHandle(p) then
closehandle(p);
end;
function ES(SymName: LPSTR; SymbolAddress, SymbolSize: ULONG; UserContext: Pointer): Bool; stdcall;
var buf: array[0..14] of byte;
ar: ptrUint;
begin
if readprocessmemory(processhandle,pointer(ptrUint(SymbolAddress)),@buf[0],15,ar) then
begin
if (buf[0]=$b8) and (buf[3]=$00) and (buf[4]=$00) and (buf[5]=$ba) and (buf[10]=$ff) and (buf[11]=$12) and (buf[12]=$c2) and (buf[14]=$00) then
begin
//b8 xx xx 00 00 ba xx xx xx xx ff 12 c2 xx 00
tenummodules(UserContext).symbolname:=SymName;
tenummodules(UserContext).callnumber:=pdword(@buf[1])^;
tenummodules(UserContext).synchronize(tenummodules(UserContext).foundone);
end;
end;
result:=not canceled;
end;
function EM(ModuleName: LPSTR; BaseOfDll: ULONG; UserContext: Pointer): Bool; stdcall;
begin
result:=not canceled;
SymEnumerateSymbols(processhandle,BaseOfDLL,@ES,usercontext);
end;
procedure tenummodules.foundone;
var tablenr: integer;
entrynr: integer;
x: ttreenode;
s: string;
begin
if frmServiceDescriptorTables<>nil then
begin
tablenr:=callnumber shr 12;
if tablenr>1 then exit;
entrynr:=callnumber and $fff;
with frmServiceDescriptorTables do
begin
x:=treeview1.Items.GetFirstNode;
if tablenr=1 then
x:=x.getNextSibling;
s:=x.Items[entrynr].Text;
s:=copy(s,1,pos(' - ',s)-1);
s:=s+' - '+symbolname;
x.Items[entrynr].Text:=s;
end;
end;
end;
procedure tenummodules.done;
begin
if frmServiceDescriptorTables<>nil then
begin
with frmServiceDescriptorTables do
begin
CancelScan1.visible:=false;
Scancallnumbersandnames1.enabled:=true;
end;
end;
end;
procedure tenummodules.execute;
begin
freeonterminate:=true;
Priority:=tpLower;
symhandler.waitforsymbolsloaded;
if not canceled then
SymEnumerateModules(processhandle,@EM,self);
synchronize(done);
end;
procedure TfrmServiceDescriptorTables.Scancallnumbersandnames1Click(
Sender: TObject);
begin
Scancallnumbersandnames1.Enabled:=false;
cancelscan1.Visible:=true;
canceled:=false;
tenummodules.Create(false);
end;
procedure TfrmServiceDescriptorTables.CancelScan1Click(Sender: TObject);
begin
Canceled:=true;
end;
procedure TfrmServiceDescriptorTables.Save1Click(Sender: TObject);
var f: textfile;
i: integer;
t: ttreenode;
s: string;
begin
if savedialog1.Execute then
begin
assignfile(f,savedialog1.FileName);
rewrite(f);
t:=treeview1.Items.GetFirstNode;
writeln(f,t.Count);
for i:=0 to t.Count-1 do
begin
s:=t[i].Text;
s:=copy(s,pos(' - ',s)+3,length(s));
writeln(f,s);
end;
t:=t.getNextSibling;
writeln(f,t.Count);
for i:=0 to t.Count-1 do
begin
s:=t[i].Text;
s:=copy(s,pos(' - ',s)+3,length(s));
writeln(f,s);
end;
closefile(f);
end;
end;
procedure TfrmServiceDescriptorTables.TreeView1DblClick(Sender: TObject);
var x: dword;
i: integer;
begin
if (treeview1.Selected<>nil) and (treeview1.Selected.Level=1) then
begin
val('$'+treeview1.Selected.Text,x,i);
memorybrowser.disassemblerview.SelectedAddress:=x;
end;
end;
procedure TfrmServiceDescriptorTables.Open1Click(Sender: TObject);
var f: textfile;
i: integer;
t: ttreenode;
s,s2: string;
x: integer;
begin
if opendialog1.Execute then
begin
assignfile(f,opendialog1.FileName);
reset(f);
try
readln(f,x);
t:=treeview1.Items.GetFirstNode;
if x<>t.Count then
raise exception.Create(rsIncompatibleSDT);
for i:=0 to x-1 do
begin
s:=t.Items[i].Text;
s:=copy(s,1,pos(' - ',s)-1);
s:=s+' - ';
readln(f,s2);
s:=s+s2;
t.Items[i].Text:=s;
end;
readln(f,x);
t:=t.getNextSibling;
if x<>t.Count then
raise exception.Create(rsIncompatibleSSDT);
for i:=0 to x-1 do
begin
s:=t.Items[i].Text;
s:=copy(s,1,pos(' - ',s)-1);
s:=s+' - ';
readln(f,s2);
s:=s+s2;
t.Items[i].Text:=s;
end;
finally
closefile(f);
end;
end;
end;
procedure TfrmServiceDescriptorTables.FindDialog1Find(Sender: TObject);
var t: ttreenode;
begin
t:=treeview1.Selected;
if t=nil then
t:=treeview1.Items.GetFirstNode
else
t:=t.GetNext;
while t<>nil do
begin
if pos(uppercase(finddialog1.FindText),uppercase(t.Text))>0 then
begin
treeview1.Selected:=t;
exit;
end;
t:=t.GetNext;
end;
showmessage(rsNothingFound);
//finddialog1.FindText
end;
procedure TfrmServiceDescriptorTables.Find1Click(Sender: TObject);
begin
finddialog1.Execute;
end;
procedure TfrmServiceDescriptorTables.GotoSTDaddress1Click(
Sender: TObject);
var table: integer;
a: ptrUint;
x,y: ptrUint;
begin
if (treeview1.Selected=nil) or (treeview1.Selected.Level<>1) then exit;
table:=treeview1.Selected.Parent.Index;
if table=0 then
a:=GetSDT
else
a:=GetSDTShadow;
y:=0;
readprocessmemory(processhandle,pointer(a),@y,4,x);
inc(y,treeview1.Selected.Index*4);
memorybrowser.memoryaddress:=y;
end;
initialization
{$i ServiceDescriptorTables.lrs}
end.