2011-07-04 19:52:53 +00:00
|
|
|
unit DissectCodeThread;
|
|
|
|
|
|
|
|
|
|
{$MODE Delphi}
|
|
|
|
|
|
|
|
|
|
interface
|
|
|
|
|
|
|
|
|
|
uses
|
2019-12-18 12:07:17 +01:00
|
|
|
{$ifdef darwin}
|
|
|
|
|
macport,
|
|
|
|
|
{$endif}
|
|
|
|
|
{$ifdef windows}
|
|
|
|
|
windows,
|
|
|
|
|
{$endif}
|
|
|
|
|
LCLIntf,sysutils,syncobjs,Classes,disassembler, NewKernelHandler, math,
|
2020-10-15 01:34:32 +02:00
|
|
|
MemoryQuery, CEFuncProc, maps, LastDisassembleData, commonTypeDefs, AvgLvlTree;
|
2011-07-04 19:52:53 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
type
|
|
|
|
|
TAddresslist=record
|
|
|
|
|
pos: integer;
|
|
|
|
|
maxsize: integer;
|
|
|
|
|
a: PPtrUintArray;
|
|
|
|
|
isstring: boolean;
|
2020-01-22 23:14:41 +01:00
|
|
|
pointsto: ptruint; //0 if not a pointer
|
|
|
|
|
pointstostring: boolean;
|
2011-07-04 19:52:53 +00:00
|
|
|
end;
|
|
|
|
|
PAddresslist=^TAddresslist;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-02-24 23:49:26 +00:00
|
|
|
type tjumptype=(jtCall=0, jtUnconditional=1, jtConditional=2, jtMemory=3);
|
2011-07-04 19:52:53 +00:00
|
|
|
|
|
|
|
|
type tdissectarray= array of record
|
|
|
|
|
address: ptrUint;
|
|
|
|
|
jumptype: tjumptype;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
type tjumpdata = record
|
|
|
|
|
address:ptrUint;
|
|
|
|
|
codes: integer;
|
|
|
|
|
code: array[0..7] of ptrUint; //default space for 8 addresses
|
|
|
|
|
|
|
|
|
|
nrofextracodes: integer;
|
|
|
|
|
extracodes: array of ptrUint; //but can be expanded to more if really needed
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
type tjumparray=array of tjumpdata;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type TStringReference=class(tobject)
|
|
|
|
|
address: ptrUint;
|
|
|
|
|
s: string;
|
|
|
|
|
references: array of ptrUint;
|
2018-12-23 21:23:08 +01:00
|
|
|
isUnicode: boolean;
|
2011-07-04 19:52:53 +00:00
|
|
|
end;
|
|
|
|
|
|
2014-02-12 20:54:57 +00:00
|
|
|
type TDissectReference=class(tobject)
|
|
|
|
|
address: ptruint;
|
|
|
|
|
addressname: string; //fill these in later
|
|
|
|
|
references: array of record
|
|
|
|
|
address: ptruint;
|
|
|
|
|
addressname: string;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2018-12-17 16:12:52 +01:00
|
|
|
type TOnCallListEntry=procedure(address: ptruint);
|
2011-07-04 19:52:53 +00:00
|
|
|
|
|
|
|
|
type
|
2020-10-15 01:34:32 +02:00
|
|
|
|
|
|
|
|
|
2011-07-04 19:52:53 +00:00
|
|
|
TDissectCodeThread = class(TThread)
|
|
|
|
|
private
|
|
|
|
|
{ Private declarations }
|
2013-02-15 12:31:17 +00:00
|
|
|
calllist: TMap;
|
|
|
|
|
unconditionaljumplist: TMap;
|
|
|
|
|
conditionaljumplist: TMap;
|
|
|
|
|
memorylist: TMap; //e.g strings
|
2011-07-04 19:52:53 +00:00
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
cs: TCriticalSection;
|
2011-07-04 19:52:53 +00:00
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
haswork: TEvent;
|
2013-02-24 23:49:26 +00:00
|
|
|
ready: TEvent;
|
2011-07-04 19:52:53 +00:00
|
|
|
|
2013-03-01 21:09:32 +00:00
|
|
|
canceled: boolean;
|
|
|
|
|
|
2020-10-15 01:34:32 +02:00
|
|
|
oldAddressToNewAddressTree: TAvgLvlTree; //used for loading back addresses and conver them to the new one
|
2013-02-15 12:31:17 +00:00
|
|
|
|
2020-10-18 20:32:44 +02:00
|
|
|
usedModuleList: TStringList;
|
|
|
|
|
|
2020-01-22 23:14:41 +01:00
|
|
|
function isstring(address: ptrUint; v: pqword=nil): boolean;
|
2013-02-15 12:31:17 +00:00
|
|
|
function findaddress(list: TMap; address: ptrUint):PAddresslist;
|
2013-02-17 12:08:42 +00:00
|
|
|
procedure clearList(list: Tmap);
|
2020-10-15 01:34:32 +02:00
|
|
|
|
|
|
|
|
//relocation handlers:
|
|
|
|
|
function OldAddressToNewAddressLookup(Tree: TAvgLvlTree; Data1, Data2: pointer): integer;
|
|
|
|
|
procedure saveModuleListToStream(s: TStream);
|
|
|
|
|
procedure loadModuleListFromStream(s: TStream);
|
|
|
|
|
function convertOldAddressToNew(address: ptruint): ptruint;
|
2020-10-18 20:32:44 +02:00
|
|
|
procedure cleanModuleListRelocator;
|
2020-10-15 01:34:32 +02:00
|
|
|
|
2014-01-07 00:28:32 +00:00
|
|
|
procedure saveListToStream(list: TMap; s: TStream);
|
|
|
|
|
procedure loadListFromStream(list: TMap; s: TStream);
|
2011-07-04 19:52:53 +00:00
|
|
|
public
|
|
|
|
|
percentagedone: dword;
|
|
|
|
|
processid: dword;
|
|
|
|
|
|
|
|
|
|
done: boolean;
|
|
|
|
|
currentaddress:ptrUint;
|
|
|
|
|
memoryregion: tmemoryregions;
|
|
|
|
|
|
|
|
|
|
totalmemory: ptrUint;
|
|
|
|
|
totalread: ptrUint;
|
|
|
|
|
|
|
|
|
|
nrofunconditionaljumps: integer;
|
|
|
|
|
nrofconditionaljumps: integer;
|
|
|
|
|
nrofcalls: integer;
|
|
|
|
|
nrofdata: integer;
|
|
|
|
|
nrofstring: integer;
|
|
|
|
|
maxoffset: integer;
|
|
|
|
|
|
|
|
|
|
function FindOffset(s: string):ptrUint;
|
|
|
|
|
function CheckAddress(address: ptrUint; var aresult: tdissectarray):boolean;
|
2013-02-24 23:49:26 +00:00
|
|
|
procedure addReference(FromAddress, ToAddress: ptruint; reftype: tjumptype; isstring: boolean=false);
|
|
|
|
|
procedure removeReference(FromAddress, ToAddress: ptruint);
|
|
|
|
|
|
2013-02-15 12:31:17 +00:00
|
|
|
procedure addAddress(list: TMap; address: ptrUint; referencedBy: ptruint; couldbestring: boolean=false);
|
|
|
|
|
procedure removeAddress(list: TMap; address: ptruint; referencedBy: ptruint);
|
2013-02-17 12:08:42 +00:00
|
|
|
procedure clear;
|
|
|
|
|
|
|
|
|
|
procedure dowork;
|
|
|
|
|
|
2013-02-24 23:49:26 +00:00
|
|
|
procedure waitTillDone;
|
2013-03-01 21:09:32 +00:00
|
|
|
procedure cancelScan;
|
2013-02-24 23:49:26 +00:00
|
|
|
|
2014-01-07 00:28:32 +00:00
|
|
|
procedure saveTofile(filename: string);
|
|
|
|
|
procedure loadFromFile(filename: string);
|
|
|
|
|
|
2013-02-15 12:31:17 +00:00
|
|
|
|
2020-10-15 01:34:32 +02:00
|
|
|
|
2011-07-04 19:52:53 +00:00
|
|
|
procedure getstringlist(s: tstrings);
|
2014-02-12 20:54:57 +00:00
|
|
|
procedure getCallList(s: TList);
|
2018-12-17 16:12:52 +01:00
|
|
|
|
|
|
|
|
// procedure getCallListEx(callback: TOnCallListEntry);
|
2011-07-04 19:52:53 +00:00
|
|
|
constructor create(suspended: boolean);
|
|
|
|
|
protected
|
|
|
|
|
procedure Execute; override;
|
|
|
|
|
end;
|
|
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
var dissectcode: tdissectcodethread;
|
2011-07-04 19:52:53 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
implementation
|
|
|
|
|
|
2023-11-21 16:26:09 +01:00
|
|
|
uses ProcessHandlerUnit, parsers, symbolhandler, symbolhandlerstructs, {$ifdef laztrunk}AVL_Tree{$else}laz_avl_Tree{$endif};
|
2014-09-08 12:00:14 +00:00
|
|
|
|
2016-06-25 10:35:44 +03:00
|
|
|
resourcestring
|
|
|
|
|
rsInvalidDissectCodeFile = 'Invalid dissect code file';
|
|
|
|
|
rsTDissectCodeThreadgetCallListCalledWithANonEmptyList = 'TDissectCodeThread.getCallList called with a non empty list';
|
2011-07-04 19:52:53 +00:00
|
|
|
|
|
|
|
|
{ TDissectCodeThread }
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
This thread will scan the memory for jumps and conditional jumps
|
|
|
|
|
that data will be added to a list that the disassemblerview can read out for data
|
|
|
|
|
|
|
|
|
|
}
|
2020-10-15 01:34:32 +02:00
|
|
|
|
|
|
|
|
procedure TDissectCodeThread.saveModuleListToStream(s: TStream);
|
|
|
|
|
var
|
|
|
|
|
i: integer;
|
|
|
|
|
begin
|
|
|
|
|
//get the current modulelist and save that to the stream
|
|
|
|
|
|
2020-10-18 20:32:44 +02:00
|
|
|
s.WriteDWord(usedModuleList.Count);
|
|
|
|
|
for i:=0 to usedModuleList.count-1 do
|
2020-10-15 01:34:32 +02:00
|
|
|
begin
|
2020-10-18 20:32:44 +02:00
|
|
|
s.WriteQWord(ptruint(usedModuleList.Objects[i]));
|
|
|
|
|
s.WriteAnsiString(usedModuleList[i]);
|
2020-10-15 01:34:32 +02:00
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type
|
|
|
|
|
TAddressToNewAddressEntry=record
|
|
|
|
|
baseaddress: qword; //old address/searchkey
|
|
|
|
|
size: dword;
|
|
|
|
|
relocatedTo: qword; //new address
|
|
|
|
|
end;
|
|
|
|
|
PAddressToNewAddressEntry=^TAddressToNewAddressEntry;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function TDissectCodeThread.OldAddressToNewAddressLookup(Tree: TAvgLvlTree; Data1, Data2: pointer): integer;
|
|
|
|
|
var d1,d2: PAddressToNewAddressEntry;
|
|
|
|
|
begin
|
|
|
|
|
d1:=data1;
|
|
|
|
|
d2:=data2;
|
|
|
|
|
|
|
|
|
|
if inrangeq(d1.baseaddress,d2.baseaddress,d2.baseaddress+d2.size) or
|
|
|
|
|
inrangeq(d2.baseaddress,d1.baseaddress,d1.baseaddress+d1.size) then exit(0);
|
|
|
|
|
|
|
|
|
|
if d1.baseaddress<d2.baseaddress then exit(-1) else exit(1);
|
|
|
|
|
end;
|
|
|
|
|
|
2020-10-18 20:32:44 +02:00
|
|
|
procedure TDissectCodeThread.cleanModuleListRelocator;
|
2020-10-15 01:34:32 +02:00
|
|
|
var n: TAVLTreeNode;
|
|
|
|
|
enum: TAVLTreeNodeEnumerator;
|
|
|
|
|
begin
|
|
|
|
|
enum:=oldAddressToNewAddressTree.GetEnumerator;
|
|
|
|
|
|
|
|
|
|
while enum.MoveNext do
|
|
|
|
|
begin
|
|
|
|
|
n:=enum.Current;
|
|
|
|
|
if n<>nil then
|
|
|
|
|
freemem(n.data);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
freeandnil(enum);
|
|
|
|
|
freeandnil(oldAddressToNewAddressTree);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TDissectCodeThread.loadModuleListFromStream(s: TStream);
|
|
|
|
|
var
|
|
|
|
|
i: integer;
|
|
|
|
|
list: TList;
|
|
|
|
|
nr: dword;
|
|
|
|
|
|
|
|
|
|
baseaddress: qword;
|
|
|
|
|
modulename: string;
|
|
|
|
|
|
|
|
|
|
data: PAddressToNewAddressEntry;
|
|
|
|
|
mi: TModuleInfo;
|
|
|
|
|
|
|
|
|
|
begin
|
|
|
|
|
oldAddressToNewAddressTree:=TAvgLvlTree.CreateObjectCompare(OldAddressToNewAddressLookup);
|
|
|
|
|
|
|
|
|
|
nr:=s.ReadDWord;
|
|
|
|
|
|
|
|
|
|
for i:=0 to nr-1 do
|
|
|
|
|
begin
|
|
|
|
|
baseaddress:=s.ReadQWord;
|
|
|
|
|
modulename:=s.ReadAnsiString;
|
|
|
|
|
|
|
|
|
|
if symhandler.getmodulebyname(modulename, mi) then
|
|
|
|
|
begin
|
|
|
|
|
getmem(data, sizeof(TAddressToNewAddressEntry));
|
|
|
|
|
data.baseaddress:=baseaddress;
|
|
|
|
|
data.size:=mi.basesize;
|
|
|
|
|
data.relocatedTo:=mi.baseaddress;
|
|
|
|
|
oldAddressToNewAddressTree.Add(data);
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TDissectCodeThread.ConvertOldAddressToNew(address: ptruint): ptruint;
|
|
|
|
|
var
|
|
|
|
|
searcher: TAddressToNewAddressEntry;
|
|
|
|
|
n: TAvlTreeNode;
|
|
|
|
|
begin
|
|
|
|
|
result:=address;
|
|
|
|
|
if oldAddressToNewAddressTree<>nil then
|
|
|
|
|
begin
|
|
|
|
|
searcher.size:=4;
|
|
|
|
|
searcher.baseaddress:=address;
|
|
|
|
|
n:=oldAddressToNewAddressTree.Find(@searcher);
|
|
|
|
|
if n<>nil then
|
|
|
|
|
result:=PAddressToNewAddressEntry(n.Data)^.relocatedTo+(address-PAddressToNewAddressEntry(n.Data)^.baseaddress);
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2014-01-07 00:28:32 +00:00
|
|
|
procedure TDissectCodeThread.saveListToStream(list: TMap; s: TStream);
|
|
|
|
|
var mi: TMapIterator;
|
|
|
|
|
id: ptruint;
|
|
|
|
|
al: PAddresslist;
|
|
|
|
|
count: dword;
|
|
|
|
|
|
|
|
|
|
i: integer;
|
|
|
|
|
begin
|
|
|
|
|
mi:=TMapIterator.Create(list);
|
|
|
|
|
try
|
|
|
|
|
count:=0; //first get the count
|
|
|
|
|
mi.First;
|
|
|
|
|
while not mi.EOM do
|
|
|
|
|
begin
|
|
|
|
|
inc(count);
|
|
|
|
|
|
|
|
|
|
mi.Next;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
s.WriteDWord(count);
|
|
|
|
|
|
|
|
|
|
mi.First;
|
|
|
|
|
while not mi.EOM do
|
|
|
|
|
begin
|
|
|
|
|
mi.GetID(id);
|
|
|
|
|
mi.GetData(al);
|
|
|
|
|
|
|
|
|
|
s.WriteQWord(id);
|
|
|
|
|
s.WriteDWord(ifthen(al.isstring, 1, 0));
|
|
|
|
|
s.WriteDWord(al.pos);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for i:=0 to al.pos-1 do
|
|
|
|
|
s.writeQword(al.a[i]);
|
|
|
|
|
|
|
|
|
|
mi.Next;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
finally
|
|
|
|
|
mi.free;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
2011-07-04 19:52:53 +00:00
|
|
|
|
2014-01-07 00:28:32 +00:00
|
|
|
procedure TDissectCodeThread.saveTofile(filename: string);
|
|
|
|
|
var fs: Tfilestream;
|
|
|
|
|
begin
|
|
|
|
|
fs:=tfilestream.create(filename, fmCreate);
|
|
|
|
|
|
|
|
|
|
try
|
2020-10-15 01:34:32 +02:00
|
|
|
fs.WriteDWord($ce00dc02); //cheat engine dissect code v1
|
|
|
|
|
saveModuleListToStream(fs);
|
2014-01-07 00:28:32 +00:00
|
|
|
saveListToStream(calllist, fs);
|
|
|
|
|
saveListToStream(unconditionaljumplist, fs);
|
|
|
|
|
saveListToStream(conditionaljumplist, fs);
|
|
|
|
|
saveListToStream(memorylist, fs);
|
|
|
|
|
finally
|
|
|
|
|
fs.free;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TDissectCodeThread.loadListFromStream(list: TMap; s: TStream);
|
|
|
|
|
var
|
|
|
|
|
count: dword;
|
|
|
|
|
i,j: integer;
|
|
|
|
|
id: ptruint;
|
|
|
|
|
|
|
|
|
|
pos: integer;
|
|
|
|
|
|
|
|
|
|
al: PAddresslist;
|
|
|
|
|
begin
|
|
|
|
|
clearList(list);
|
|
|
|
|
|
|
|
|
|
count:=s.ReadDWord;
|
|
|
|
|
for i:=0 to count-1 do
|
|
|
|
|
begin
|
|
|
|
|
getmem(al, sizeof(TAddresslist));
|
|
|
|
|
|
2020-10-20 01:10:48 +02:00
|
|
|
id:=ConvertOldAddressToNew(s.ReadQword);
|
2014-01-07 00:28:32 +00:00
|
|
|
al.isstring:=s.ReadDword=1;
|
|
|
|
|
al.maxsize:=s.ReadDWord;
|
|
|
|
|
al.pos:=al.maxsize;
|
|
|
|
|
|
2020-10-20 01:10:48 +02:00
|
|
|
if al.isstring then
|
|
|
|
|
inc(nrofstring);
|
|
|
|
|
|
|
|
|
|
|
2014-01-07 00:28:32 +00:00
|
|
|
if al.pos>0 then
|
|
|
|
|
begin
|
|
|
|
|
getmem(al.a, al.pos*sizeof(PtrUInt));
|
|
|
|
|
for j:=0 to al.pos-1 do
|
2020-10-15 01:34:32 +02:00
|
|
|
al.a[j]:=ConvertOldAddressToNew(s.ReadQWord);
|
2014-01-07 00:28:32 +00:00
|
|
|
|
|
|
|
|
list.Add(id, al);
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TDissectCodeThread.loadFromFile(filename: string);
|
2020-10-15 01:34:32 +02:00
|
|
|
var
|
|
|
|
|
fs: Tfilestream;
|
|
|
|
|
version: dword;
|
2014-01-07 00:28:32 +00:00
|
|
|
begin
|
|
|
|
|
fs:=tfilestream.create(filename, fmOpenRead);
|
|
|
|
|
|
|
|
|
|
clear;
|
2020-10-20 01:10:48 +02:00
|
|
|
nrofstring:=0;
|
|
|
|
|
nrofconditionaljumps:=0;
|
|
|
|
|
nrofunconditionaljumps:=0;
|
|
|
|
|
nrofcalls:=0;
|
|
|
|
|
|
|
|
|
|
|
2014-01-07 00:28:32 +00:00
|
|
|
try
|
2020-10-15 01:34:32 +02:00
|
|
|
version:=fs.ReadDWord;
|
|
|
|
|
if version<$ce00dc01 then
|
2016-06-25 10:35:44 +03:00
|
|
|
raise exception.create(rsInvalidDissectCodeFile);
|
2014-01-07 00:28:32 +00:00
|
|
|
|
2020-10-15 01:34:32 +02:00
|
|
|
if version>=$ce00dc02 then
|
|
|
|
|
loadModuleListFromStream(fs);
|
2014-01-07 00:28:32 +00:00
|
|
|
|
|
|
|
|
loadListFromStream(calllist, fs);
|
2020-10-20 01:10:48 +02:00
|
|
|
nrofcalls:=calllist.Count;
|
|
|
|
|
|
2014-01-07 00:28:32 +00:00
|
|
|
loadListFromStream(unconditionaljumplist, fs);
|
2020-10-20 01:10:48 +02:00
|
|
|
nrofunconditionaljumps:=unconditionaljumplist.Count;
|
|
|
|
|
|
2014-01-07 00:28:32 +00:00
|
|
|
loadListFromStream(conditionaljumplist, fs);
|
2020-10-20 01:10:48 +02:00
|
|
|
nrofconditionaljumps:=conditionaljumplist.count;
|
|
|
|
|
|
|
|
|
|
nrofstring:=0;
|
2014-01-07 00:28:32 +00:00
|
|
|
loadListFromStream(memorylist, fs);
|
2020-10-20 01:10:48 +02:00
|
|
|
nrofdata:=memorylist.Count;
|
2020-10-15 01:34:32 +02:00
|
|
|
|
2020-10-18 20:32:44 +02:00
|
|
|
cleanModuleListRelocator;
|
|
|
|
|
|
|
|
|
|
symhandler.getModuleList(usedmodulelist); //all loaded back addresses are relative to this one now
|
2014-01-07 00:28:32 +00:00
|
|
|
finally
|
|
|
|
|
fs.free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
end;
|
2013-02-24 23:49:26 +00:00
|
|
|
|
2013-03-01 21:09:32 +00:00
|
|
|
procedure TDissectCodeThread.cancelScan;
|
|
|
|
|
begin
|
|
|
|
|
canceled:=true;
|
|
|
|
|
waitTillDone;
|
|
|
|
|
canceled:=false;
|
|
|
|
|
end;
|
|
|
|
|
|
2013-02-24 23:49:26 +00:00
|
|
|
procedure TDissectCodeThread.waitTillDone; //mainly for lua
|
|
|
|
|
begin
|
|
|
|
|
while done=false do
|
|
|
|
|
ready.WaitFor(INFINITE);
|
|
|
|
|
end;
|
|
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
procedure TDissectCodeThread.dowork;
|
|
|
|
|
begin
|
|
|
|
|
//if done=false then exit; Really, if you don't watch the done state it's your own fault
|
2012-02-11 19:53:05 +00:00
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
done:=false;
|
|
|
|
|
haswork.SetEvent;
|
|
|
|
|
end;
|
2012-02-11 19:53:05 +00:00
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
procedure TDissectCodeThread.clearList(list: Tmap);
|
|
|
|
|
var mi: TMapIterator;
|
|
|
|
|
al: PAddresslist;
|
|
|
|
|
begin
|
|
|
|
|
cs.enter;
|
|
|
|
|
mi:=TMapIterator.Create(list);
|
|
|
|
|
mi.First;
|
|
|
|
|
while not mi.EOM do
|
|
|
|
|
begin
|
|
|
|
|
mi.GetData(al);
|
2016-06-22 12:12:11 +02:00
|
|
|
if al<>nil then
|
|
|
|
|
begin
|
|
|
|
|
if al.a<>nil then
|
2018-06-12 20:23:45 +02:00
|
|
|
freememandnil(al.a);
|
2016-06-22 12:12:11 +02:00
|
|
|
|
2018-06-12 20:23:45 +02:00
|
|
|
freememandnil(al);
|
2016-06-22 12:12:11 +02:00
|
|
|
end;
|
2013-02-17 12:08:42 +00:00
|
|
|
mi.Next;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
list.Clear;
|
|
|
|
|
cs.leave;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TDissectCodeThread.clear;
|
|
|
|
|
begin
|
2020-10-18 20:32:44 +02:00
|
|
|
usedModuleList.clear;
|
2013-02-17 12:08:42 +00:00
|
|
|
clearList(calllist);
|
|
|
|
|
clearList(unconditionaljumplist);
|
|
|
|
|
clearList(conditionaljumplist);
|
|
|
|
|
clearList(memorylist);
|
|
|
|
|
|
|
|
|
|
totalmemory:=0;
|
|
|
|
|
totalread:=0;
|
|
|
|
|
|
|
|
|
|
nrofunconditionaljumps:=0;
|
|
|
|
|
nrofconditionaljumps:=0;
|
|
|
|
|
nrofcalls:=0;
|
|
|
|
|
nrofdata:=0;
|
|
|
|
|
nrofstring:=0;
|
|
|
|
|
maxoffset:=0;
|
|
|
|
|
|
|
|
|
|
end;
|
2011-07-04 19:52:53 +00:00
|
|
|
|
2013-02-15 12:31:17 +00:00
|
|
|
function TDissectCodeThread.findaddress(list: TMap; address:ptrUint):PAddresslist;
|
2011-07-04 19:52:53 +00:00
|
|
|
{
|
|
|
|
|
locates the given address and returns the AddressList object pointer if found.
|
|
|
|
|
returns nil if not found
|
|
|
|
|
}
|
|
|
|
|
begin
|
2013-02-17 12:08:42 +00:00
|
|
|
cs.enter;
|
|
|
|
|
try
|
|
|
|
|
if list.GetData(address, result) =false then
|
|
|
|
|
result:=nil;
|
|
|
|
|
finally
|
|
|
|
|
cs.leave;
|
|
|
|
|
end;
|
|
|
|
|
|
2011-07-04 19:52:53 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TDissectCodeThread.CheckAddress(address: ptrUint; var aresult: tdissectarray):boolean;
|
|
|
|
|
var i,j: integer;
|
|
|
|
|
totalsize: integer;
|
|
|
|
|
|
2013-02-24 23:49:26 +00:00
|
|
|
unclist, condlist, clist, mlist: PAddresslist;
|
2011-07-04 19:52:53 +00:00
|
|
|
begin
|
|
|
|
|
totalsize:=0;
|
|
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
cs.Enter;
|
|
|
|
|
try
|
|
|
|
|
unclist:=findaddress(unconditionaljumplist, address);
|
|
|
|
|
if unclist<>nil then //it has unconditonal jumps jumping to it
|
|
|
|
|
inc(totalsize, unclist.pos);
|
2011-07-04 19:52:53 +00:00
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
condlist:=findaddress(conditionaljumplist, address);
|
2011-07-04 19:52:53 +00:00
|
|
|
if condlist<>nil then
|
2013-02-17 12:08:42 +00:00
|
|
|
inc(totalsize, condlist.pos);
|
2011-07-04 19:52:53 +00:00
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
clist:=findaddress(calllist, address);
|
|
|
|
|
if clist<>nil then
|
|
|
|
|
inc(totalsize, clist.pos);
|
2011-07-04 19:52:53 +00:00
|
|
|
|
2013-02-24 23:49:26 +00:00
|
|
|
mlist:=findaddress(memorylist, address);
|
|
|
|
|
if mlist<>nil then
|
|
|
|
|
inc(totalsize, mlist.pos);
|
|
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
if totalsize>0 then
|
2011-07-04 19:52:53 +00:00
|
|
|
begin
|
2013-02-17 12:08:42 +00:00
|
|
|
//has results
|
|
|
|
|
setlength(aresult,totalsize);
|
|
|
|
|
j:=0;
|
|
|
|
|
if condlist<>nil then
|
2011-07-04 19:52:53 +00:00
|
|
|
begin
|
2013-02-17 12:08:42 +00:00
|
|
|
for i:=0 to condlist.pos-1 do
|
|
|
|
|
begin
|
|
|
|
|
aresult[j].address:=condlist.a[i];
|
|
|
|
|
aresult[j].jumptype:=jtConditional;
|
|
|
|
|
inc(j);
|
|
|
|
|
end;
|
|
|
|
|
|
2011-07-04 19:52:53 +00:00
|
|
|
end;
|
|
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
if unclist<>nil then
|
|
|
|
|
begin
|
|
|
|
|
for i:=0 to unclist.pos-1 do
|
|
|
|
|
begin
|
|
|
|
|
aresult[j].address:=unclist.a[i];
|
|
|
|
|
aresult[j].jumptype:=jtUnconditional;
|
|
|
|
|
inc(j);
|
|
|
|
|
end;
|
2011-07-04 19:52:53 +00:00
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
if clist<>nil then
|
2011-07-04 19:52:53 +00:00
|
|
|
begin
|
2013-02-17 12:08:42 +00:00
|
|
|
for i:=0 to clist.pos-1 do
|
|
|
|
|
begin
|
|
|
|
|
aresult[j].address:=clist.a[i];
|
|
|
|
|
aresult[j].jumptype:=jtCall;
|
|
|
|
|
inc(j);
|
|
|
|
|
end;
|
2013-02-24 23:49:26 +00:00
|
|
|
end;
|
2013-02-17 12:08:42 +00:00
|
|
|
|
2013-02-24 23:49:26 +00:00
|
|
|
if mlist<>nil then
|
|
|
|
|
begin
|
|
|
|
|
for i:=0 to mlist.pos-1 do
|
|
|
|
|
begin
|
2013-03-03 22:08:44 +00:00
|
|
|
aresult[j].address:=mlist.a[i];
|
2013-02-24 23:49:26 +00:00
|
|
|
aresult[j].jumptype:=jtMemory;
|
|
|
|
|
inc(j);
|
|
|
|
|
end;
|
2011-07-04 19:52:53 +00:00
|
|
|
end;
|
|
|
|
|
|
2013-02-24 23:49:26 +00:00
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
result:=true;
|
|
|
|
|
end
|
|
|
|
|
else result:=false;
|
2011-07-04 19:52:53 +00:00
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
finally
|
|
|
|
|
cs.leave;
|
|
|
|
|
end;
|
2011-07-04 19:52:53 +00:00
|
|
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
procedure addaddresstostringlist(al: PAddresslist; address: ptrUint; s: tstrings);
|
|
|
|
|
var o: TStringReference;
|
|
|
|
|
begin
|
|
|
|
|
o:=TStringReference.create;
|
|
|
|
|
o.address:=address;
|
|
|
|
|
setlength(o.references, al.pos);
|
2014-02-12 20:54:57 +00:00
|
|
|
CopyMemory(@o.references[0], al.a, al.pos*sizeof(ptrUint));
|
2011-07-04 19:52:53 +00:00
|
|
|
|
|
|
|
|
s.AddObject(IntToHex(address,8), o);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
2014-02-12 20:54:57 +00:00
|
|
|
procedure TDissectCodeThread.getCallList(s: TList);
|
|
|
|
|
var
|
|
|
|
|
mi: TMapIterator;
|
|
|
|
|
al: PAddresslist;
|
|
|
|
|
address: ptruint;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
t: TDissectReference;
|
|
|
|
|
i: integer;
|
|
|
|
|
begin
|
|
|
|
|
if s.Count>0 then
|
2016-06-25 10:35:44 +03:00
|
|
|
raise exception.create(rsTDissectCodeThreadgetCallListCalledWithANonEmptyList);
|
2014-02-12 20:54:57 +00:00
|
|
|
|
|
|
|
|
cs.enter;
|
|
|
|
|
mi:=TMapIterator.Create(calllist);
|
|
|
|
|
try
|
|
|
|
|
while not mi.EOM do
|
|
|
|
|
begin
|
|
|
|
|
mi.GetData(al);
|
|
|
|
|
mi.GetID(address);
|
|
|
|
|
|
|
|
|
|
t:=TDissectReference.Create;
|
|
|
|
|
t.address:=address;
|
|
|
|
|
t.addressname:='';
|
|
|
|
|
setlength(t.references, al.pos);
|
|
|
|
|
for i:=0 to al.pos-1 do
|
|
|
|
|
begin
|
|
|
|
|
t.references[i].address:=al.a[i];
|
|
|
|
|
t.references[i].addressname:='';
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
s.Add(t);
|
|
|
|
|
mi.next;
|
|
|
|
|
end;
|
|
|
|
|
finally
|
|
|
|
|
cs.leave;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
mi.free;
|
|
|
|
|
|
|
|
|
|
end;
|
|
|
|
|
|
2013-02-15 12:31:17 +00:00
|
|
|
procedure TDissectCodeThread.getstringlist(s: tstrings);
|
|
|
|
|
var mi: TMapIterator;
|
|
|
|
|
al: PAddresslist;
|
|
|
|
|
address: ptruint;
|
2011-07-04 19:52:53 +00:00
|
|
|
begin
|
2013-02-15 12:31:17 +00:00
|
|
|
s.clear;
|
2011-07-04 19:52:53 +00:00
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
cs.enter;
|
2013-02-15 12:31:17 +00:00
|
|
|
mi:=TMapIterator.Create(memorylist);
|
2011-07-04 19:52:53 +00:00
|
|
|
|
2013-02-15 12:31:17 +00:00
|
|
|
mi.first;
|
2013-02-17 12:08:42 +00:00
|
|
|
try
|
|
|
|
|
while not mi.EOM do
|
2011-07-04 19:52:53 +00:00
|
|
|
begin
|
2013-02-17 12:08:42 +00:00
|
|
|
mi.GetData(al);
|
|
|
|
|
if al.isstring then
|
|
|
|
|
begin
|
|
|
|
|
mi.GetID(address);
|
|
|
|
|
addaddresstostringlist(al, address, s);
|
|
|
|
|
end;
|
|
|
|
|
mi.Next;
|
2011-07-04 19:52:53 +00:00
|
|
|
end;
|
2013-02-17 12:08:42 +00:00
|
|
|
|
|
|
|
|
finally
|
|
|
|
|
cs.leave;
|
2013-02-15 12:31:17 +00:00
|
|
|
end;
|
2014-02-12 20:54:57 +00:00
|
|
|
|
|
|
|
|
mi.free;
|
2013-02-15 12:31:17 +00:00
|
|
|
end;
|
|
|
|
|
|
2013-02-24 23:49:26 +00:00
|
|
|
procedure TDissectCodeThread.addReference(FromAddress, ToAddress: ptruint; reftype: tjumptype; isstring: boolean=false);
|
|
|
|
|
begin
|
|
|
|
|
case reftype of
|
|
|
|
|
jtCall: addAddress(calllist, toaddress, fromaddress, isstring);
|
|
|
|
|
jtUnconditional: addAddress(unconditionaljumplist, toaddress, fromaddress, isstring);
|
|
|
|
|
jtConditional: addAddress(conditionaljumplist, toaddress, fromaddress, isstring);
|
|
|
|
|
jtMemory: addAddress(memorylist, toaddress, fromaddress, isstring);
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TDissectCodeThread.removeReference(FromAddress, ToAddress: ptruint);
|
|
|
|
|
begin
|
|
|
|
|
//for each list
|
|
|
|
|
removeAddress(calllist, ToAddress, FromAddress);
|
|
|
|
|
removeAddress(unconditionaljumplist, ToAddress, FromAddress);
|
|
|
|
|
removeAddress(conditionaljumplist, ToAddress, FromAddress);
|
|
|
|
|
removeAddress(memorylist, ToAddress, FromAddress);
|
|
|
|
|
end;
|
|
|
|
|
|
2013-02-15 12:31:17 +00:00
|
|
|
procedure TDissectCodeThread.removeAddress(list: TMap; address: ptruint; referencedBy: ptruint);
|
|
|
|
|
var al: PAddresslist;
|
|
|
|
|
i,j: integer;
|
|
|
|
|
begin
|
2013-02-17 12:08:42 +00:00
|
|
|
cs.Enter;
|
|
|
|
|
try
|
|
|
|
|
if list.GetData(address, al) then
|
2011-07-04 19:52:53 +00:00
|
|
|
begin
|
2013-02-17 12:08:42 +00:00
|
|
|
//find this address in the list and remove it
|
|
|
|
|
for i:=0 to al.pos-1 do
|
2011-07-04 19:52:53 +00:00
|
|
|
begin
|
2013-02-17 12:08:42 +00:00
|
|
|
if al.a[i]=referencedBy then
|
|
|
|
|
begin
|
|
|
|
|
//found it, shift all entries after it one spot back
|
|
|
|
|
for j:=i to al.pos-2 do
|
|
|
|
|
al.a[j]:=al.a[j+1];
|
2011-07-04 19:52:53 +00:00
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
//and decrease the pos
|
|
|
|
|
dec(al.pos);
|
2011-07-04 19:52:53 +00:00
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
if al.pos<=0 then //list is empty
|
|
|
|
|
list.Delete(address);
|
2013-02-15 12:31:17 +00:00
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
exit;
|
|
|
|
|
end;
|
2011-07-04 19:52:53 +00:00
|
|
|
end;
|
|
|
|
|
end;
|
2013-02-17 12:08:42 +00:00
|
|
|
|
|
|
|
|
finally
|
|
|
|
|
cs.leave;
|
2011-07-04 19:52:53 +00:00
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2013-02-24 23:49:26 +00:00
|
|
|
|
|
|
|
|
|
2013-02-15 12:31:17 +00:00
|
|
|
procedure TDissectCodeThread.addAddress(list: TMap; address: ptrUint; referencedBy: ptruint; couldbestring: boolean=false);
|
2011-07-04 19:52:53 +00:00
|
|
|
var
|
2013-02-15 12:31:17 +00:00
|
|
|
al: PAddresslist;
|
2020-01-22 23:14:41 +01:00
|
|
|
v: qword;
|
2011-07-04 19:52:53 +00:00
|
|
|
begin
|
|
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
cs.enter;
|
|
|
|
|
try
|
|
|
|
|
if list.GetData(address, al)=false then
|
|
|
|
|
begin
|
|
|
|
|
//not in the list yet, add it
|
|
|
|
|
getmem(al, sizeof(TAddresslist));
|
|
|
|
|
ZeroMemory(al, sizeof(TAddresslist));
|
2020-01-22 23:14:41 +01:00
|
|
|
if couldbestring then
|
|
|
|
|
begin
|
|
|
|
|
v:=0;
|
|
|
|
|
al.isstring:=isString(address, @v);
|
|
|
|
|
|
|
|
|
|
if (al.isstring=false) and (v<>0) then
|
|
|
|
|
begin
|
|
|
|
|
if isAddress(v) then
|
|
|
|
|
begin
|
|
|
|
|
al.pointsto:=v;
|
|
|
|
|
al.pointstostring:=isString(v,nil);
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
2013-02-15 12:31:17 +00:00
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
//allocate some space for it
|
|
|
|
|
al.maxsize:=2;
|
|
|
|
|
getmem(al.a, 2*sizeof(pointer));
|
2011-07-04 19:52:53 +00:00
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
list.Add(address, al);
|
|
|
|
|
end;
|
2011-07-04 19:52:53 +00:00
|
|
|
|
2020-01-22 23:14:41 +01:00
|
|
|
if (couldbestring) and (al.isstring=false) and (al.pointstostring) then
|
|
|
|
|
addAddress(list, al.pointsto,referencedby,couldbestring); //add pointers to pointers to strings
|
|
|
|
|
|
|
|
|
|
//might also be used for function references...
|
|
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
if al.pos>=al.maxsize then //realloc
|
|
|
|
|
begin
|
|
|
|
|
ReallocMem(al.a, al.maxsize*2*sizeof(pointer));
|
|
|
|
|
al.maxsize:=al.maxsize*2;
|
|
|
|
|
end;
|
2011-07-04 19:52:53 +00:00
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
al.a[al.pos]:=referencedby;
|
|
|
|
|
inc(al.pos);
|
2011-07-04 19:52:53 +00:00
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
if couldbestring and al.isstring then inc(nrofstring);
|
2011-07-04 19:52:53 +00:00
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
finally
|
|
|
|
|
cs.leave;
|
|
|
|
|
end;
|
2011-07-04 19:52:53 +00:00
|
|
|
|
|
|
|
|
end;
|
|
|
|
|
|
2020-01-22 23:14:41 +01:00
|
|
|
function TDissectCodeThread.isstring(address: ptrUint; v: pqword=nil): boolean;
|
2011-07-04 19:52:53 +00:00
|
|
|
var
|
2020-01-22 23:14:41 +01:00
|
|
|
p: qword;
|
|
|
|
|
tempbuf: array [0..7] of byte absolute p;
|
2014-05-11 03:08:36 +00:00
|
|
|
x: ptruint;
|
2011-07-04 19:52:53 +00:00
|
|
|
i: integer;
|
|
|
|
|
begin
|
|
|
|
|
result:=false;
|
|
|
|
|
if readprocessmemory(processhandle, pointer(address), @tempbuf[0], 8, x) then
|
|
|
|
|
begin
|
|
|
|
|
//check if ascii string
|
|
|
|
|
result:=true;
|
|
|
|
|
for i:=0 to 4 do //only interested in the first 5 for ascii
|
|
|
|
|
begin
|
|
|
|
|
if not (tempbuf[i] in [32..127]) then
|
|
|
|
|
begin
|
|
|
|
|
result:=false;
|
|
|
|
|
break;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2018-12-22 15:41:51 +01:00
|
|
|
if result then exit;
|
2011-07-04 19:52:53 +00:00
|
|
|
|
|
|
|
|
//check if unicode string
|
|
|
|
|
i:=0;
|
|
|
|
|
result:=true;
|
|
|
|
|
while i<8 do
|
|
|
|
|
begin
|
2018-12-22 15:41:51 +01:00
|
|
|
if not ((tempbuf[i] in [32..127]) and (tempbuf[i+1]=0)) then
|
2011-07-04 19:52:53 +00:00
|
|
|
begin
|
|
|
|
|
result:=false;
|
|
|
|
|
break;
|
|
|
|
|
end;
|
|
|
|
|
inc(i,2);
|
|
|
|
|
end;
|
|
|
|
|
|
2020-01-22 23:14:41 +01:00
|
|
|
if v<>nil then
|
|
|
|
|
begin
|
|
|
|
|
if processhandler.is64Bit then
|
|
|
|
|
p:=p and $ffffffff;
|
|
|
|
|
|
|
|
|
|
v^:=p;
|
|
|
|
|
end;
|
2011-07-04 19:52:53 +00:00
|
|
|
end;
|
2020-01-22 23:14:41 +01:00
|
|
|
|
|
|
|
|
|
2011-07-04 19:52:53 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function TDissectCodeThread.FindOffset(s: string):ptrUint;
|
|
|
|
|
//check an address specifier for an offset
|
|
|
|
|
//returns 0 if no offset
|
|
|
|
|
//yes yes, I know this also finds the EAx EBx, ECx EDx, but I bet there are bigger offsets to be found
|
|
|
|
|
var
|
|
|
|
|
i: integer;
|
|
|
|
|
first: integer;
|
|
|
|
|
o: string;
|
|
|
|
|
begin
|
|
|
|
|
result:=0;
|
|
|
|
|
first:=0;
|
|
|
|
|
for i:=1 to length(s) do
|
|
|
|
|
begin
|
|
|
|
|
if first=0 then //find a start
|
|
|
|
|
begin
|
|
|
|
|
if s[i] in ['0'..'9','A'..'F','a'..'f'] then
|
|
|
|
|
first:=i;
|
|
|
|
|
end else //find an end
|
|
|
|
|
begin
|
|
|
|
|
if not (s[i] in ['0'..'9','A'..'F','a'..'f']) then
|
|
|
|
|
begin
|
|
|
|
|
o:=copy(s, first, i-first);
|
|
|
|
|
|
|
|
|
|
result:=StrToQWordEx('$'+o);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if result>=$10000 then result:=0;
|
|
|
|
|
if isAddress(result) then result:=0;
|
|
|
|
|
|
|
|
|
|
first:=0;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
2013-02-17 12:08:42 +00:00
|
|
|
|
2011-07-04 19:52:53 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
procedure TDissectCodeThread.Execute;
|
|
|
|
|
var
|
|
|
|
|
i,j: integer;
|
|
|
|
|
d: TDisassembler;
|
|
|
|
|
currentAddress: ptrUint;
|
|
|
|
|
oldaddress: ptrUint;
|
|
|
|
|
x: string;
|
|
|
|
|
s: string;
|
2013-04-14 19:00:01 +00:00
|
|
|
tempaddress, tempaddress2: ptrUint;
|
|
|
|
|
|
|
|
|
|
value: ptruint;
|
2011-07-04 19:52:53 +00:00
|
|
|
|
|
|
|
|
a, b, o,special: string;
|
|
|
|
|
|
2014-05-11 03:08:36 +00:00
|
|
|
br: ptruint;
|
2013-04-14 19:00:01 +00:00
|
|
|
|
2011-07-04 19:52:53 +00:00
|
|
|
|
|
|
|
|
begin
|
2020-10-18 20:32:44 +02:00
|
|
|
usedmodulelist.clear;
|
2020-10-20 01:10:48 +02:00
|
|
|
|
2020-10-18 20:32:44 +02:00
|
|
|
|
2011-07-04 19:52:53 +00:00
|
|
|
d:=TDisassembler.Create;
|
2013-02-17 12:08:42 +00:00
|
|
|
try
|
|
|
|
|
d.showsymbols:=false;
|
|
|
|
|
d.showmodules:=false;
|
2020-06-14 11:35:04 +02:00
|
|
|
d.showsections:=false;
|
2020-01-10 16:36:10 +01:00
|
|
|
d.aggressivealignment:=true;
|
2011-07-04 19:52:53 +00:00
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
while not terminated do
|
2011-07-04 19:52:53 +00:00
|
|
|
begin
|
2013-02-17 12:08:42 +00:00
|
|
|
//wait for the haswork event to be set
|
|
|
|
|
if haswork.WaitFor(INFINITE)=wrSignaled then
|
|
|
|
|
begin
|
|
|
|
|
//find out how much memory to go through (for the progressbar)
|
2020-10-20 01:10:48 +02:00
|
|
|
symhandler.getModuleList(usedmodulelist);
|
2013-02-24 23:49:26 +00:00
|
|
|
|
|
|
|
|
ready.ResetEvent;
|
|
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
totalmemory:=0;
|
|
|
|
|
for i:=0 to length(memoryregion)-1 do
|
|
|
|
|
inc(totalmemory,memoryregion[i].MemorySize);
|
2011-07-04 19:52:53 +00:00
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
totalread:=0;
|
|
|
|
|
for i:=0 to length(memoryregion)-1 do
|
|
|
|
|
begin
|
|
|
|
|
currentAddress:=memoryregion[i].BaseAddress;
|
2011-07-04 19:52:53 +00:00
|
|
|
|
|
|
|
|
|
2013-03-01 21:09:32 +00:00
|
|
|
while (not canceled) and (currentaddress<memoryregion[i].BaseAddress+memoryregion[i].MemorySize) do
|
2011-07-04 19:52:53 +00:00
|
|
|
begin
|
2013-02-17 12:08:42 +00:00
|
|
|
oldaddress:=currentaddress;
|
|
|
|
|
s:=d.disassemble(currentaddress, x);
|
|
|
|
|
inc(totalread,currentaddress-oldaddress);
|
|
|
|
|
percentagedone:=(totalread * 100) div totalmemory;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//evaluate S
|
|
|
|
|
splitDisassembledString(s, false, a,b,o,special);
|
|
|
|
|
if hasAddress(o,tempaddress) then
|
2011-07-04 19:52:53 +00:00
|
|
|
begin
|
2013-04-14 19:00:01 +00:00
|
|
|
|
|
|
|
|
//check if it's an indirect jump
|
|
|
|
|
|
|
|
|
|
tempaddress2:=0;
|
2014-02-12 20:54:57 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-04-14 19:00:01 +00:00
|
|
|
if readprocessmemory(processhandle, pointer(tempaddress), @tempaddress2, processhandler.pointersize, br) then
|
|
|
|
|
begin
|
|
|
|
|
if ((tempaddress2 and $ffff)=$25ff) then //it's pointing to a jmp [xxxxxxxx] evaluate that as well
|
|
|
|
|
begin
|
|
|
|
|
value:=0;
|
2014-02-12 20:54:57 +00:00
|
|
|
if readprocessmemory(processhandle,pointer(tempaddress+2),@value,4,br) then
|
2013-04-14 19:00:01 +00:00
|
|
|
begin
|
|
|
|
|
if processhandler.is64bit then
|
|
|
|
|
value:=tempaddress2+6+value; //in 64-bit ff 25 is relative encoded
|
|
|
|
|
|
|
|
|
|
if readprocessmemory(processhandle,pointer(value),@value,processhandler.Pointersize,br) then
|
|
|
|
|
tempaddress:=value; //get the address it actually points to
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
begin
|
|
|
|
|
//use the address it points to
|
|
|
|
|
if (d.LastDisassembleData.isjump or d.LastDisassembleData.isret) and (d.LastDisassembleData.modrmValueType=dvtAddress) then
|
|
|
|
|
tempaddress:=tempaddress2;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
//check the kind of address (calltarget, jumptarget, memory access/indicator)
|
|
|
|
|
case o[1] of
|
|
|
|
|
'c' : //call
|
|
|
|
|
begin
|
|
|
|
|
if (o[2]='a') and (o[3]='l') then
|
|
|
|
|
begin
|
|
|
|
|
addAddress(calllist, tempaddress, oldaddress);
|
|
|
|
|
inc(nrofcalls);
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
'j' : //jmp, conditional or not
|
|
|
|
|
begin
|
2013-04-14 19:00:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
if o[2]='m' then
|
|
|
|
|
begin
|
|
|
|
|
//jmp
|
|
|
|
|
addAddress(unconditionaljumplist, tempaddress,oldaddress);
|
|
|
|
|
inc(nrofunconditionaljumps);
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
begin
|
|
|
|
|
//jx
|
|
|
|
|
addAddress(conditionaljumplist, tempaddress,oldaddress);
|
|
|
|
|
inc(nrofconditionaljumps);
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
else
|
|
|
|
|
begin
|
|
|
|
|
//memoryaccess/indicator
|
|
|
|
|
addAddress(memorylist, tempaddress, oldaddress, true);
|
|
|
|
|
inc(nrofdata);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
end else
|
2011-07-04 19:52:53 +00:00
|
|
|
begin
|
2013-02-17 12:08:42 +00:00
|
|
|
//it doesn't have an address
|
|
|
|
|
j:=pos('[',o);
|
|
|
|
|
if j>0 then
|
|
|
|
|
begin
|
|
|
|
|
//it has an address specifier
|
|
|
|
|
//maxoffset:=max(maxoffset, FindOffset(copy(o,j,pos(']',o)-j+1)));
|
|
|
|
|
end;
|
2011-07-04 19:52:53 +00:00
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
done:=true;
|
2013-02-24 23:49:26 +00:00
|
|
|
ready.SetEvent;
|
2013-02-17 12:08:42 +00:00
|
|
|
end;
|
2011-07-04 19:52:53 +00:00
|
|
|
|
|
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
finally
|
2011-07-04 19:52:53 +00:00
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
d.free;
|
|
|
|
|
end;
|
2011-07-04 19:52:53 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
constructor TDissectCodeThread.create(suspended: boolean);
|
|
|
|
|
begin
|
2013-02-24 23:49:26 +00:00
|
|
|
done:=true; //ready to do some work
|
2013-02-15 12:31:17 +00:00
|
|
|
calllist:=TMap.Create(ituPtrSize, sizeof(PAddresslist) );
|
|
|
|
|
unconditionaljumplist:=TMap.Create(ituPtrSize, sizeof(PAddresslist) );
|
|
|
|
|
conditionaljumplist:=TMap.Create(ituPtrSize, sizeof(PAddresslist) );
|
|
|
|
|
memorylist:=TMap.Create(ituPtrSize, sizeof(PAddresslist) );
|
2013-02-17 12:08:42 +00:00
|
|
|
cs:=TCriticalSection.Create;
|
2013-02-15 12:31:17 +00:00
|
|
|
|
2013-02-17 12:08:42 +00:00
|
|
|
haswork:=TEvent.Create(nil, false, false, '');
|
2013-02-24 23:49:26 +00:00
|
|
|
ready:=TEvent.create(nil, false, true, '');
|
2020-10-18 20:32:44 +02:00
|
|
|
usedmodulelist:=tstringlist.create;
|
|
|
|
|
|
2011-07-04 19:52:53 +00:00
|
|
|
inherited create(suspended);
|
2014-01-07 00:28:32 +00:00
|
|
|
|
2011-07-04 19:52:53 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
end.
|
|
|
|
|
|