Ai
1 Star 0 Fork 0

phy0292/cheat-engine

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
PointerscanresultReader.pas 20.91 KB
一键复制 编辑 原始数据 按行查看 历史
Dark Byte 提交于 2020-07-25 03:01 +08:00 . fix opening pointerscan network results
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787
unit PointerscanresultReader;
{$MODE Delphi}
{
The TPointerscanresultReader will read the results from the pointerfile and present them to the pointerscanner as if it is just one file
}
interface
{$ifdef darwin}
uses macport, MacTypes, LCLIntf, sysutils, classes, CEFuncProc, NewKernelHandler,
symbolhandler, math, dialogs, LazUTF8,macportdefines;
{$endif}
{$ifdef windows}
uses windows, LCLIntf, sysutils, classes, CEFuncProc, NewKernelHandler,
symbolhandler, math, dialogs, LazUTF8;
{$endif}
resourcestring
rsPSRCorruptedPointerscanFile = 'Corrupted pointerscan file';
rsPSRInvalidPointerscanFileVersion = 'Invalid pointerscan file version';
rsBuggedList = 'BuggedList';
{$ifdef windows}
function GetFileSizeEx(hFile:HANDLE; FileSize:PQWord):BOOL; stdcall; external 'kernel32.dll' name 'GetFileSizeEx';
{$endif}
type TPointerscanResult=packed record
modulenr: integer;
moduleoffset: int64;
offsetcount: integer;
offsets: array [0..1000] of integer;
end;
type PPointerscanResult= ^TPointerscanResult;
type
TPointerscanresultReader=class;
TPointerscanresultReader=class
private
Fcount: qword;
sizeOfEntry: integer;
maxlevel: integer;
modulelist: tstringlist;
FFileName: string;
files: array of record
startindex: qword;
lastindex: qword;
filename: string;
filesize: qword;
f,fm: Thandle;
end;
cacheStart: integer;
cacheSize: size_t;
cache: pointer;
cacheStart2: integer;
cacheSize2: integer;
cache2: pointer;
fExternalScanners: integer;
fGeneratedByWorkerID: integer;
fCompressedPtr: boolean;
fAligned: boolean;
MaskModuleIndex: dword;
MaskLevel: dword;
MaskOffset: dword;
fMaxBitCountModuleIndex: dword;
fMaxBitCountModuleOffset: dword;
fMaxBitCountLevel: dword;
fMaxBitCountOffset: dword;
fEndsWithOffsetList: array of dword;
fCanResume: boolean;
fdidBaseRangeScan: boolean;
foriginalBaseScanRange: qword;
CompressedPointerScanResult: PPointerscanResult;
compressedTempBuffer: PByteArray;
fLastRawPointer: pointer;
fmergedresults: array of integer;
function InitializeCache(i: qword): boolean;
function getModuleListCount: integer;
function getMergedResultCount: integer;
function getMergedResult(index: integer): integer;
function getEndsWithOffsetListCount: integer;
function getEndsWithOffsetListEntry(index: integer): dword;
public
procedure resyncModulelist;
procedure saveModulelistToResults(s: Tstream);
function getModulename(modulenr: integer): string;
function getModuleBase(modulenr: integer): ptrUint;
procedure setModuleBase(modulenr: integer; newModuleBase: ptruint);
function getPointer(i: qword): PPointerscanResult; overload;
function getPointer(i: qword; var pointsto: ptrUint): PPointerscanResult; overload;
procedure getFileList(list: TStrings);
procedure ReleaseFiles;
constructor create(filename: string; original: TPointerscanresultReader=nil);
destructor destroy; override;
property count: qword read FCount;
property offsetCount: integer read maxlevel;
property filename: string read FFilename;
property entrySize: integer read sizeOfEntry;
property modulelistCount: integer read getModuleListcount;
property modulename[index: integer]: string read getModuleName;
property modulebase[index: integer]: ptruint read getModuleBase write setModuleBase;
property mergedresultcount: integer read getMergedResultCount;
property mergedresults[index: integer]: integer read getMergedResult;
property EndsWithOffsetListCount: integer read getEndsWithOffsetListCount;
property EndsWithOffsetList[index: integer]: dword read getEndsWithOffsetListEntry;
property compressedptr: boolean read fCompressedPtr;
property aligned: boolean read fAligned;
property MaxBitCountModuleIndex: dword read fMaxBitCountModuleIndex;
property MaxBitCountModuleOffset: dword read fMaxBitCountModuleOffset;
property MaxBitCountLevel: dword read fMaxBitCountLevel;
property MaxBitCountOffset: dword read fMaxBitCountOffset;
property LastRawPointer: pointer read fLastRawPointer;
property CanResume: boolean read fCanResume;
property DidBaseRangeScan: boolean read fdidBaseRangeScan;
property BaseScanRange: qword read foriginalBaseScanRange;
end;
procedure findAllResultFilesForThisPtr(filename: string; rs: TStrings; lookupmode: integer=0);
implementation
uses ProcessHandlerUnit, PointerscanStructures, Maps, AvgLvlTree;
procedure findAllResultFilesForThisPtr(filename: string; rs: TStrings; lookupmode: integer=0);
var
fr: TRawbyteSearchRec;
i,j: integer;
ext1, ext2: string;
basesort: boolean;
v1, v2: int64;
sepindex: integer;
temp: string;
swap: boolean;
filemap: TMap;
f: string;
fn: pchar;
path: string;
it: TMapIterator;
begin
//search the folder this ptr file is in for .result.* files
//extract1
rs.clear;
filemap:=TMap.Create(its8, sizeof(pointer));
if lookupmode=1 then
filename:=UTF8ToWinCP(filename);
path:=ExtractFilePath(filename);
if FindFirst(filename+'.results.*', 0, fr)=0 then
begin
repeat
ext1:=ExtractFileExt(fr.name);
ext1:=copy(ext1, 2, length(ext1)-1);
if copy(ext1,1,5)='child' then
begin
rs.add(path+fr.name); //no need to sort
end
else if TryStrToInt64('$'+ext1, v1) then
begin
f:=path+fr.name;
getmem(fn, length(f)+1);
strcopy(fn, @f[1]);
filemap.Add(v1, fn);
end;
until FindNext(fr)<>0;
FindClose(fr);
end
else
begin
if lookupmode<1 then
begin
findAllResultFilesForThisPtr(filename, rs, lookupmode+1);
exit;
end;
end;
it:=TMapIterator.Create(filemap);
it.First;
while not it.EOM do
begin
it.GetData(fn);
rs.add(fn);
freememandnil(fn);
it.Next;
end;
it.free;
filemap.Clear;
freeandnil(filemap);
end;
function TPointerscanresultreader.getMergedResultCount: integer;
begin
result:=length(fmergedresults);
end;
function TPointerscanresultreader.getMergedResult(index: integer): integer;
begin
if index<mergedresultcount then
result:=fmergedresults[index]
else
result:=-1;
end;
function TPointerscanresultreader.getEndsWithOffsetListCount: integer;
begin
result:=length(fEndsWithOffsetList);
end;
function TPointerscanresultreader.getEndsWithOffsetListEntry(index: integer): dword;
begin
result:=fEndsWithOffsetList[index]
end;
procedure TPointerscanresultreader.resyncModulelist;
var
tempmodulelist: TStringList;
i,j: integer;
begin
tempmodulelist:=tstringlist.Create;
try
symhandler.getModuleList(tempmodulelist);
//sift through the list filling in the modulelist of the opened pointerfile
for i:=0 to modulelist.Count-1 do
begin
j:=tempmodulelist.IndexOf(modulelist[i]);
if j<>-1 then
modulelist.Objects[i]:=tempmodulelist.Objects[j]
else
begin
try
modulelist.Objects[i]:=pointer(symhandler.getAddressFromName(modulelist[i]));
except
modulelist.Objects[i]:=nil;
end;
end;
end;
finally
tempmodulelist.free;
end;
end;
procedure TPointerscanresultReader.saveModuleListToResults(s: TStream);
var i: integer;
x: dword;
begin
//save the number of modules
x:=modulelist.Count;
s.Write(x,sizeof(x));
for i:=0 to modulelist.Count-1 do
begin
//for each module
//save the length
x:=length(modulelist[i]);
s.Write(x,sizeof(x));
//and the name
s.Write(modulelist[i][1],x);
//and the base (for debugging info)
s.WriteQWord(qword(modulelist.Objects[i]));
end;
end;
function TPointerscanresultReader.InitializeCache(i: qword): boolean;
var j: integer;
actualread: dword;
wantedoffset: qword;
offset: qword;
begin
result:=false;
// OutputDebugString('InitializeCache');
if i>=fcount then exit;
//find which file to use
for j:=0 to length(files)-1 do
begin
if InRangeQ(i, files[j].startindex, files[j].lastindex) then
begin
wantedoffset:=int64(sizeOfEntry*(i-files[j].startindex));
if (wantedoffset mod systeminfo.dwAllocationGranularity)<>0 then
begin
//bring offset down to a location matching systeminfo.dwAllocationGranularity
offset:=wantedoffset-(wantedoffset mod systeminfo.dwAllocationGranularity);
end
else
offset:=wantedoffset;
{$if FPC_FULLVERSION<30200}
cachesize:=min(files[j].filesize-offset, systeminfo.dwAllocationGranularity*32); //normally 2MBZ
{$else}
cachesize:=min(files[j].filesize-offset, qword(systeminfo.dwAllocationGranularity*32)); //normally 2MBZ
{$endif}
if cache2<>nil then
unmapviewoffile(cache2);
cache2:=MapViewOfFile(files[j].fm, FILE_MAP_READ, offset shr 32, offset and $ffffffff, cachesize );
// if cache2=nil then
// OutputDebugString('Failure to map view of file');
//point cache to the start of the wanted offset
cache:=pointer(ptruint(cache2)+(wantedoffset-offset));
cachesize:=(cachesize-(wantedoffset-offset)) div sizeofentry;
result:=cache2<>nil;
// OutputDebugString('InitializeCache success');
exit;
end;
end;
//nothing found...
// OutputDebugString('InitializeCache nothing found');
end;
function TPointerscanresultReader.getModuleListCount: integer;
begin
result:=modulelist.count;
end;
function TPointerscanresultReader.getModuleBase(modulenr: integer): ptrUint;
{pre: modulenr must be valid, so not -1 }
begin
if (modulenr>=0) and (modulenr<modulelist.Count) then
result:=ptrUint(modulelist.Objects[modulenr])
else
result:=0;
end;
procedure TPointerscanresultReader.setModuleBase(modulenr: integer; newModuleBase: ptruint);
begin
if (modulenr>=0) and (modulenr<modulelist.Count) then
modulelist.objects[modulenr]:=pointer(newModulebase);
end;
function TPointerscanresultReader.getModulename(modulenr: integer): string;
begin
if (modulenr>=0) and (modulenr<modulelist.Count) then
result:=modulelist[modulenr]
else
result:=rsBuggedList;
end;
function TPointerscanresultReader.getPointer(i: uint64): PPointerscanResult;
{
for those that know what they want
}
var
cachepos: integer;
p: PByteArray;
bit: integer;
j: integer;
begin
result:=nil;
if i>=count then exit;
//check if i is in the cache
if not InRange(i, cachestart,cachestart+cachesize-1) then
begin
//if not, reload the cache starting from i
if not InitializeCache(i) then exit;
cachestart:=i;
end;
//find out at which position in the cache this index is
cachepos:=i-cachestart;
if fCompressedPtr then
begin
p:=PByteArray(ptrUint(cache)+(cachepos*sizeofentry));
CopyMemory(compressedTempBuffer, p, sizeofentry);
if MaxBitCountModuleOffset=32 then //only 2 possibilities
compressedPointerScanResult.moduleoffset:=PInteger(compressedTempBuffer)^
else
compressedPointerScanResult.moduleoffset:=PInt64(compressedTempBuffer)^;
bit:=MaxBitCountModuleOffset;
compressedPointerScanResult.modulenr:=pdword(@compressedTempBuffer[bit shr 3])^;
compressedPointerScanResult.modulenr:=compressedPointerScanResult.modulenr and MaskModuleIndex;
if compressedPointerScanResult.modulenr shr (fMaxBitCountModuleIndex-1) = 1 then //most significant bit is set, sign extent this value
begin
//should be -1 as that is the only one possible
dword(compressedPointerScanResult.modulenr):=dword(compressedPointerScanResult.modulenr) or (not MaskModuleIndex);
if compressedPointerScanResult.modulenr<>-1 then
begin
//my assumption was wrong
compressedPointerScanResult.modulenr:=-1;
end;
end;
inc(bit, fMaxBitCountModuleIndex);
{
compressedPointerScanResult.offsetcount:=pdword(@compressedTempBuffer[bit div 8])^;
compressedPointerScanResult.offsetcount:=compressedPointerScanResult.offsetcount shr (bit mod 8);
compressedPointerScanResult.offsetcount:=compressedPointerScanResult.offsetcount and MaskLevel;
}
compressedPointerScanResult.offsetcount:=(pdword(@compressedTempBuffer[bit shr 3])^ shr (bit and $7)) and MaskLevel;
inc(compressedPointerScanResult.offsetcount, length(fEndsWithOffsetList));
inc(bit, fMaxBitCountLevel);
for j:=0 to length(fEndsWithOffsetList)-1 do
compressedPointerScanResult.offsets[j]:=fEndsWithOffsetList[j];
for j:=length(fEndsWithOffsetList) to compressedPointerScanResult.offsetcount-1 do
begin
{
compressedPointerScanResult.offsets[j]:=pdword(@compressedTempBuffer[bit div 8])^;
compressedPointerScanResult.offsets[j]:=compressedPointerScanResult.offsets[j] shr (bit mod 8);
compressedPointerScanResult.offsets[j]:=compressedPointerScanResult.offsets[j] and MaskOffset;
if aligned then
compressedPointerScanResult.offsets[j]:=compressedPointerScanResult.offsets[j] shl 2;
}
if aligned then
compressedPointerScanResult.offsets[j]:=((pdword(@compressedTempBuffer[bit shr 3])^ shr (bit and $7) ) and MaskOffset) shl 2
else
compressedPointerScanResult.offsets[j]:=(pdword(@compressedTempBuffer[bit shr 3])^ shr (bit and $7) ) and MaskOffset;
inc(bit, fMaxBitCountOffset);
end;
result:=compressedPointerScanResult;
fLastRawPointer:=compressedTempBuffer;
end
else
begin
result:=PPointerscanResult(ptrUint(cache)+(cachepos*sizeofentry));
fLastRawPointer:=result;
end;
end;
function TPointerscanresultReader.getPointer(i: qword; var pointsto: ptrUint): PPointerscanResult;
{
For use for simple display
}
var
x: ptruint;
address,address2: ptrUint;
j: integer;
begin
result:=getpointer(i);
address:=0;
address2:=0;
//resolve the pointer
pointsto:=0;
if result.modulenr=-1 then
address:=result.moduleoffset
else
begin
if result.modulenr<modulelist.count then
begin
address:=ptruint(modulelist.objects[result.modulenr]);
address:=address+result.moduleoffset;
end
else
begin
//error. Should never happen
address:=$12345678;
end;
end;
for j:=result.offsetcount-1 downto 0 do
begin
if readprocessmemory(processhandle, pointer(address), @address2, processhandler.pointersize, x) then
address:=address2+result.offsets[j]
else
exit; //can't fully resolve
end;
pointsto:=address;
end;
procedure TPointerscanresultReader.getFileList(list: TStrings);
var i: integer;
begin
for i:=0 to length(files)-1 do
list.add(files[i].FileName);
end;
constructor TPointerscanresultReader.create(filename: string; original: TPointerscanresultReader=nil);
var
configfile: TFileStream;
modulelistLength: integer;
tempmodulelist: Tstringlist;
x: dword;
i,j: integer;
temppchar: pchar;
temppcharmaxlength: dword;
filenamecount: integer;
error: boolean;
a: ptruint;
fn: string;
filenames: array of string;
fnames: tstringlist;
pscanversion: byte;
begin
FFilename:=filename;
configfile:=TFileStream.Create(filename, fmOpenRead or fmShareDenyWrite);
if configfile.ReadByte<>$ce then
raise exception.create(rsPSRCorruptedPointerscanFile);
pscanversion:=configfile.ReadByte;
if pscanversion>pointerscanfileversion then
raise exception.create(rsPSRInvalidPointerscanFileVersion);
configfile.ReadBuffer(modulelistlength,sizeof(modulelistlength));
modulelist:=tstringlist.create;
tempmodulelist:=tstringlist.create;
temppcharmaxlength:=256;
getmem(temppchar, temppcharmaxlength);
//get the module list myself
if original=nil then
symhandler.getModuleList(tempmodulelist)
else
modulelist.Assign(original.modulelist);
//sift through the list filling in the modulelist of the opened pointerfile
for i:=0 to modulelistlength-1 do
begin
configfile.Read(x,sizeof(x));
while x>=temppcharmaxlength do
begin
temppcharmaxlength:=temppcharmaxlength*2;
ReallocMem(temppchar, temppcharmaxlength);
end;
configfile.Read(temppchar[0], x);
temppchar[x]:=#0;
a:=configfile.ReadQWord; //discard this info (only used for scandata)
if original=nil then
begin
j:=tempmodulelist.IndexOf(temppchar);
if j<>-1 then
modulelist.Addobject(temppchar, tempmodulelist.Objects[j]) //add it and store the base address
else
begin
a:=symhandler.getAddressFromName(temppchar,false,error,nil);
if not error then
modulelist.Addobject(temppchar, pointer(a))
else
modulelist.Add(temppchar);
end;
end;
end;
//read maxlevel
configfile.Read(maxlevel,sizeof(maxlevel));
//read compressedptr info
fCompressedPtr:=configfile.ReadByte=1;
if fCompressedPtr then
begin
fAligned:=configFile.ReadByte=1;
fMaxBitCountModuleIndex:=configfile.ReadByte;
fMaxBitCountModuleOffset:=configfile.ReadByte;
fMaxBitCountLevel:=configfile.ReadByte;
fMaxBitCountOffset:=configfile.ReadByte;
setlength(fEndsWithOffsetList, configfile.ReadByte);
for i:=0 to length(fEndsWithOffsetList)-1 do
fEndsWithOffsetList[i]:=configfile.ReadDWord;
sizeofentry:=MaxBitCountModuleOffset+MaxBitCountModuleIndex+MaxBitCountLevel+MaxBitCountOffset*(maxlevel-length(fEndsWithOffsetList));
sizeofentry:=(sizeofentry+7) div 8;
MaskModuleIndex:=0;
for i:=1 to MaxBitCountModuleIndex do
MaskModuleIndex:=(MaskModuleIndex shl 1) or 1;
for i:=1 to MaxBitCountLevel do
MaskLevel:=(MaskLevel shl 1) or 1;
for i:=1 to MaxBitCountOffset do
MaskOffset:=(MaskOffset shl 1) or 1;
getmem(CompressedPointerScanResult, 16+4*maxlevel);
getmem(CompressedTempBuffer, sizeofentry+4);
end
else
begin
sizeofentry:=16+(4*maxlevel)
end;
if pscanversion>=2 then
begin
fdidBaseRangeScan:=configFile.readByte=1;
if fdidBaseRangeScan then
foriginalBaseScanRange:=configfile.ReadQWord;
end;
//get the filenames
fnames:=tstringlist.create;
findAllResultFilesForThisPtr(filename, fnames);
setlength(filenames, fnames.count);
for i:=0 to fnames.count-1 do
filenames[i]:=fnames[i];
fnames.free;
setlength(files, length(filenames));
j:=0;
for i:=0 to length(filenames)-1 do
begin
try
if pos(PathDelim, filenames[i])=0 then
fn:=ExtractFilePath(filename)+filenames[i]
else
fn:=filenames[i];
files[j].filename:=fn;
files[j].f:=CreateFile(pchar(fn), GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_DELETE, nil, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0);
if (files[j].f<>0) and (files[j].f<>INVALID_HANDLE_VALUE) then
begin
files[j].startindex:=fcount;
if GetFileSizeEx(files[j].f, @files[j].filesize)=false then
begin
OutputDebugString('GetFileSizeEx failed with error: '+inttostr(GetLastError));
end;
if files[j].filesize>0 then
begin
fcount:=fcount+uint64(files[j].filesize div uint64(sizeofentry));
files[j].lastindex:=fcount-1;
files[j].fm:=CreateFileMapping(files[j].f, nil,PAGE_READONLY, 0,0,nil);
end
else
files[j].fm:=0;
if (files[j].fm=0) then
closehandle(files[j].f)
else
inc(j);
end;
except
end;
end;
setlength(files,j);
// getmem(cache, sizeofEntry*maxcachecount);
// getmem(cache2, sizeofEntry*maxcachecount);
InitializeCache(0);
freememandnil(temppchar);
configfile.Free;
fCanResume:=fileexists(filename+'.resume.config') and fileexists(filename+'.resume.scandata') and fileexists(filename+'.resume.queue');
if length(filenames)=0 then
MessageDlg('There was an error loading the results. Check that the path is readable', mtError, [mbok],0);
end;
procedure TPointerscanresultReader.ReleaseFiles;
//if only the config file is needed. This releases the results
var i: integer;
begin
for i:=0 to length(files)-1 do
if files[i].f<>0 then
begin
if files[i].fm<>0 then
closehandle(files[i].fm);
closehandle(files[i].f);
end;
end;
destructor TPointerscanresultReader.destroy;
var i: integer;
begin
if modulelist<>nil then
modulelist.free;
if cache2<>nil then
UnmapViewOfFile(cache2);
ReleaseFiles;
if compressedTempBuffer<>nil then
freememandnil(compressedTempBuffer);
if compressedPointerScanResult<>nil then
freememandnil(compressedPointerScanResult);
end;
end.
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/phy0292/cheat-engine.git
git@gitee.com:phy0292/cheat-engine.git
phy0292
cheat-engine
cheat-engine
master

搜索帮助