1 Star 0 Fork 0

JonK/cheat-engine

加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
rttihelper.pas 6.03 KB
一键复制 编辑 原始数据 按行查看 历史
cheat-engine 提交于 2021-03-29 04:09 +08:00 . modifications to make it compile on mac
unit rttihelper;
{helper for rtti structures}
{$mode delphi}
interface
uses
{$ifdef darwin}macport,{$endif}
Classes, SysUtils;
function getRTTIClassName(StructureBaseAddress: ptruint; var classname: string): boolean;
implementation
uses newkernelhandler, ProcessHandlerUnit, symbolhandler, symbolhandlerstructs;
function isvalidstring(s: string): boolean;
var i: integer;
begin
result:=length(s)>0;
for i:=1 to length(s) do
if (ord(s[i])<32) or (ord(s[i])>126) then exit(false);
end;
function getRTTIClassNamePascal(StructureBaseAddress: ptruint; var classname: string): boolean;
{
vInstanceSize: SizeInt;
vInstanceSize2: SizeInt;
vParentRef: pointer
vClassName: PShortString;
}
var
vtable: ptruint;
classnameaddress: ptruint;
cname: array [0..255] of byte;
x: ptruint;
i: integer;
count: integer;
begin
result:=false;
vtable:=0;
if readprocessmemory(processhandle, pointer(StructureBaseAddress), @vtable,processhandler.pointersize,x) then
begin
classnameaddress:=0;
if readprocessmemory(processhandle, pointer(vtable+processhandler.pointersize*3), @classnameaddress,processhandler.pointersize,x) then
begin
//make sure it is a proper shortstring. (byte, chars[byte],0)
if readprocessmemory(processhandle, pointer(classnameaddress), @cname[0],256,x) then
begin
count:=cname[0];
if count>0 then
begin
for i:=1 to count do
begin
if not (char(cname[i]) in ['0'..'9','a'..'z','A'..'Z']) then
break;
end;
//still here
if (count>0) and (count<255) and (cname[count+1]=0) then
begin
classname:=pchar(@cname[1]);
if length(classname)=count then
exit(isvalidstring(classname));
end;
end;
end;
end;
end;
end;
//based on visual studio 2017 rtti stuff
function getRTTIClassNameVS2017(StructureBaseAddress: ptruint; var classname: string): boolean;
const UNDNAME_NAME_ONLY=$1000;
var
vtable: ptruint;
rttiinfo: ptruint;
x: ptruint;
mi: tmoduleinfo;
something: packed record
somethingtype: dword; //1 for 64-bit it seems
dword1: dword;
dword2: dword;
dwTypeInfo: dword;
end;
TypeInfoAddress: ptruint;
TypeInfo32: packed record
pointertosomethingelse: dword;
undecoratednamepointer: dword;
decoratedname: array [0..255] of char;
end;
TypeInfo64: packed record
pointertosomethingelse: qword;
undecoratednamepointer: qword;
decoratedname: array [0..255] of char;
end;
decoratedname: string;
undecoratedstring: array [0..255] of byte;
i: integer;
s: string;
cp: pchar;
slen: integer;
begin
result:=false;
vtable:=0;
if readprocessmemory(processhandle, pointer(StructureBaseAddress), @vtable,processhandler.pointersize,x) then
begin
rttiinfo:=0;
if readprocessmemory(processhandle, pointer(vtable-processhandler.pointersize), @rttiinfo,processhandler.pointersize, x) then
begin
if symhandler.getmodulebyaddress(rttiinfo,mi) then
begin
//inside a module |||||||||||
//01 00 00 00 00 00 00 00 00 00 00 00 D8 50 00 00 50 37 00 00 80 37 00 00 = 64-bit
//00 00 00 00 00 00 00 00 00 00 00 00 90 30 EC 00 88 24 EC 00 00 00 00 00 = 32-bit
if readprocessmemory(processhandle, pointer(rttiinfo), @something,sizeof(something), x) then
begin
if something.somethingtype=1 then //dwTypeInfo is relative to the modulebase
TypeInfoAddress:=mi.baseaddress+something.dwTypeInfo
else //dwTypeInfo is the exact address
TypeInfoAddress:=something.dwTypeInfo;
// ^^^^^^^^^^^
// undecorated name decoratedname[1]
//->48 32 6D 5F F6 7F 00 00 00 00 00 00 00 00 00 00 2E 3F 41 56 74 65 73 74
//->48 32 6D 22 F7 7F 00 00 00 AE 7A F5 BE 01 00 00 2E 3F 41 56 74 65 73 74
//->14 21 9E 00 00 00 00 00 2E 3F 41 56 74 65 73 74 32 40 40 00 14 21 9E 00 = 32bit
cp:=nil;
if processhandler.is64Bit then
begin
if readprocessmemory(processhandle, pointer(TypeInfoAddress), @TypeInfo64,sizeof(TypeInfo64), x) then
begin
TypeInfo64.decoratedname[255]:=#0;
if copy(pchar(@TypeInfo64.decoratedname[0]),1,4)='.?AV' then
cp:=@TypeInfo64.decoratedname[4]
end;
end
else
begin
if readprocessmemory(processhandle, pointer(TypeInfoAddress), @TypeInfo32,sizeof(TypeInfo32), x) then
begin
TypeInfo32.decoratedname[255]:=#0;
if copy(pchar(@TypeInfo32.decoratedname[0]),1,4)='.?AV' then
cp:=@TypeInfo32.decoratedname[4]
end;
end;
if cp<>nil then //found the string
begin
s:='?'+cp;
{$ifdef windows}
i:=UnDecorateSymbolName(pchar(s), @undecoratedstring[0],255,UNDNAME_NAME_ONLY);
undecoratedstring[i]:=0;
classname:=pchar(@undecoratedstring[0]);
{$else}
classname:=cp;
{$endif}
if isvalidstring(classname) then exit(true);
classname:=cp;
if isvalidstring(classname) then exit(true);
//everything matches (including the .?AV line), except the name is bad, still useful as an identifier
classname:='unknown classid ';
for i:=0 to 15 do
begin
if ord(cp[i])=0 then
break;
classname:=classname+inttohex(ord(cp[i]),2);
end;
exit(true);
end;
end;
end;
end;
end;
end;
function getRTTIClassName(StructureBaseAddress: ptruint; var classname: string): boolean;
begin
result:=false;
if getRTTIClassNameVS2017(StructureBaseAddress, classname) then exit(True);
if getRTTIClassNamePascal(StructureBaseAddress, classname) then exit(True);
//todo: add other compilers
end;
end.
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/JonDO/cheat-engine.git
git@gitee.com:JonDO/cheat-engine.git
JonDO
cheat-engine
cheat-engine
master

搜索帮助