unit ServiceDescriptorTables; {$MODE Delphi} interface uses windows, LCLIntf, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,CEFuncProc,NewKernelHandler, Menus, ComCtrls,symbolhandler,imagehlp,disassembler, StdCtrls, LResources, commonTypeDefs; 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.