cheat-engine/Cheat Engine/stacktrace2.pas

158 lines
4.5 KiB
ObjectPascal

unit stacktrace2;
{$MODE Delphi}
interface
uses LCLIntf, sysutils, classes, symbolhandler, CEFuncProc, NewKernelHandler,
byteinterpreter, commonTypeDefs;
procedure seperatestacktraceline(s: string; var address: string; var bytes: string; var details: string);
procedure ce_stacktrace(esp: ptrUint; ebp: ptrUint; eip: ptrUint; stack: Pbytearray; sizeinbytes: integer; trace: tstrings; force4byteblocks: boolean=true; showmodulesonly: boolean=false; nosystemmodules:boolean=false; maxdepth:integer=0; ShowEBPinsteadOfESP: boolean=false);
implementation
uses StrUtils, ProcessHandlerUnit;
procedure seperatestacktraceline(s: string; var address: string; var bytes: string; var details: string);
var i,j: integer;
begin
//has 2 ' - ' occurances
i:=pos(' - ',s);
address:=copy(s,1,i-1);
j:=posex(' - ',s,i+3);
bytes:=copy(s,i+3,j-(i+3));
details:=copy(s,j+3,length(s)); //leftover
end;
procedure ce_stacktrace(esp: ptrUint; ebp: ptrUint; eip: ptrUint; stack: Pbytearray; sizeinbytes: integer; trace: tstrings; force4byteblocks: boolean=true; showmodulesonly: boolean=false; nosystemmodules:boolean=false; maxdepth:integer=0; ShowEBPinsteadOfESP: boolean=false);
{
ce_stacktrace will walk the provided stack trying to figure out functionnames ,passed strings and optional other data
esp must be aligned on a 4 byte boundary the first entry alignment but other entries will try to be forced to 4 byte alignment unless otherwise needed (double, string,...)
if eip is in a known function location this can help with the parameter naming (for the location of ebp)
esp is the first 4 byte of stack
nosystemmodules is only in effect when show moduleso only is enabled
}
var
alignedstack: pbytearray;
alignedstack32: PDwordArray absolute alignedstack;
alignedstack64: Puint64Array absolute alignedstack;
i: integer;
Entries: integer;
currentStackpos: ptruint;
currentStackValue: ptruint;
address: string;
value: string;
secondary: string;
v: TVariableType;
oldi: integer;
originalesp: ptruint;
offset: ptrint;
offsetstring: string;
pref: char;
begin
if processhandler.is64bit then
pref:='r'
else
pref:='e';
originalesp:=esp;
i:=esp mod processhandler.pointersize;
if i>0 then
begin
//unalligned
alignedstack:=stack+(processhandler.pointersize-i);
dec(sizeinbytes,processhandler.pointersize-i);
inc(esp,i);
end else alignedstack:=stack;
dec(sizeinbytes,sizeinbytes mod processhandler.pointersize); //so it's a full boundary
Entries:=sizeinbytes div processhandler.pointersize;
i:=0;
while i<entries do
begin
oldi:=i;
if not ShowEBPinsteadOfESP then
offsetstring:='('+pref+'sp+'+inttohex(esp-originalesp,1)+')'
else
begin
offset:=esp-ebp;
if offset<0 then
offsetstring:='('+pref+'bp-'+inttohex(-offset,1)+')'
else
offsetstring:='('+pref+'bp+'+inttohex(offset,1)+')';
end;
address:=inttohex(esp,8)+offsetstring;
if processhandler.is64bit then
begin
currentStackpos:=ptruint(@alignedstack64[i]);
value:=inttohex(alignedstack64[i],16);
currentStackValue:=ptruint(alignedstack64[i]);
end
else
begin
currentStackpos:=ptruint(@alignedstack32[i]);
value:=inttohex(alignedstack32[i],8);
currentStackValue:=ptruint(alignedstack32[i]);
end;
v:=vtdword;
//figure out what alignedstack[i] is.
if showmodulesonly then
begin
if symhandler.inModule(currentStackValue) and ((not nosystemmodules) or (not symhandler.inSystemModule(currentStackValue))) then
v:=vtPointer
else
begin
inc(i);
inc(esp, (i-oldi)*processhandler.pointersize);
continue; //skip
end;
end
else
v:=FindTypeOfData(esp,pointer(currentstackpos),sizeinbytes-(i*processhandler.pointersize));
if v in [vtbyte..vtQword] then
begin
//override into pointersize type
if processhandler.is64bit then
v:=vtQword
else
v:=vtDword;
end;
secondary:=DataToString(@currentStackValue,processhandler.pointersize, v);
//optional: find the lengts of a string and increase i with the number of stack elements used in the string
inc(i);
trace.AddObject(address+' - '+value+' - '+secondary, pointer(esp));
if (maxdepth>0) and (trace.Count>=maxdepth) then exit;
inc(esp, (i-oldi)*processhandler.pointersize);
end;
end;
end.