📄 memscan.pas.svn-base
字号:
unit memscan;
{
This unit will hold the class object used to control scanning
The old scanning routines will be moved out of cefuncproc and made object oriented into this class
Special care should be taken to add multithreaded scanning routines
}
interface
uses windows,sysutils, classes,ComCtrls,dialogs, cefuncproc,
newkernelhandler, math, SyncObjs, SaveFirstScan, firstscanhandler,
autoassembler;
type TScanOption=(soUnknownValue,soExactValue,soValueBetween,soBiggerThan,soSmallerThan, soIncreasedValue, soIncreasedValueBy, soDecreasedValue, soDecreasedValueBy, soChanged, soUnchanged, soSameAsFirst, soCustom);
type TScanType=(stNewScan, stFirstScan, stNextScan);
type TRoundingType=(rtRounded,rtExtremerounded,rtTruncated);
type TVariableType=(vtByte, vtWord, vtDword, vtQword, vtSingle, vtDouble, vtString, vtByteArray, vtBinary, vtAll, vtCustom);
type TCustomScanType=(cstNone, cstAutoAssembler, cstCPP, cstDLLFunction);
type TCheckRoutine=function(newvalue,oldvalue: pointer):boolean of object;
type TStoreResultRoutine=procedure(address: dword; oldvalue: pointer) of object;
type TFlushRoutine=procedure of object;
type
TMemScan=class;
TScanController=class;
Tscanfilewriter=class(tthread)
{
workerthread:
This class is used because it is more efficient to write only one file at a
time. It will aquire a critical section when writing a file to acomplish that
also, not that it matters much, since you eventually have to wait for the
write anyhow, a double buffered result list so it can keep scanning while the
list is being saved.
}
private
scancontroller: TScanController;
addressfile: TFilestream;
memoryfile: TFilestream;
// cAddressFile,cMemoryFile: TCompressionStream;
addressbuffer: pointer;
memorybuffer: pointer;
addressSize: dword;
memorySize: dword;
datawritten: tevent; //event that is set when the thread has finished writing
dataavailable:tevent; //event that is set when there is a buffer to save
public
procedure execute; override;
procedure writeresults(addressbuffer,memorybuffer: pointer; addressSize,memorySize: dword); //writes the results of address and memory
procedure flush;
constructor create(scancontroller:TScanController; addressfile,memoryfile:TFileStream);
destructor destroy; override;
end;
TScanner=class(tthread)
{
The scanner class will scan a specified range of memory
}
private
CheckRoutine: TCheckRoutine;
StoreResultRoutine: TStoreResultRoutine;
FlushRoutine: TFlushRoutine; //pointer to routine used to flush the buffer, generic, string, etc...
scanWriter: Tscanfilewriter;
firstscanhandler: TFirstscanhandler;
customprologue: procedure; stdcall; //customscan call before scan starts
customepilogue: procedure; stdcall; //customscan call after scan ends
found :dword;
value,value2: int64;
svalue,svalue2: single;
dvalue,dvalue2: double;
minsvalue,maxsvalue: single;
mindvalue,maxdvalue: double;
floataccuracy: integer; //number of digits after the decimal seperator
CurrentAddressBuffer: pointer;
CurrentFoundBuffer: pointer; //generic buffer that points to where the memory can be found
SecondaryFoundBuffer: pointer; //current gets swapped with these ones after a write
SecondaryAddressBuffer: pointer;
//binary scan
bitmask: int64; //contains the bit string where * is replaced with a 0
andmask: int64; //contains the bit string where 1 and 0 is 1 and * is 0
binaryresults: array [0..7] of boolean; //after a byte is checked this contains which startbits match
//array of bytes
abs_arraylength: integer; //optimization so no need to call length()
abs_arraytofind: TBytes;
//all
typesmatch: array [vtByte..vtDouble] of boolean; //will get set depending if that type matches the current address or not
//check routines:
function ByteExact(newvalue,oldvalue: pointer): boolean;
function ByteBetween(newvalue,oldvalue: pointer): boolean;
function ByteBiggerThan(newvalue,oldvalue: pointer): boolean;
function ByteSmallerThan(newvalue,oldvalue: pointer): boolean;
function ByteIncreasedValue(newvalue,oldvalue: pointer): boolean;
function ByteIncreasedValueBy(newvalue,oldvalue: pointer): boolean;
function ByteDecreasedValue(newvalue,oldvalue: pointer): boolean;
function ByteDecreasedValueBy(newvalue,oldvalue: pointer): boolean;
function ByteChanged(newvalue,oldvalue: pointer): boolean;
function ByteUnChanged(newvalue,oldvalue: pointer): boolean;
function WordExact(newvalue,oldvalue: pointer): boolean;
function WordBetween(newvalue,oldvalue: pointer): boolean;
function WordBiggerThan(newvalue,oldvalue: pointer): boolean;
function WordSmallerThan(newvalue,oldvalue: pointer): boolean;
function WordIncreasedValue(newvalue,oldvalue: pointer): boolean;
function WordIncreasedValueBy(newvalue,oldvalue: pointer): boolean;
function WordDecreasedValue(newvalue,oldvalue: pointer): boolean;
function WordDecreasedValueBy(newvalue,oldvalue: pointer): boolean;
function WordChanged(newvalue,oldvalue: pointer): boolean;
function WordUnChanged(newvalue,oldvalue: pointer): boolean;
function DWordExact(newvalue,oldvalue: pointer): boolean;
function DWordBetween(newvalue,oldvalue: pointer): boolean;
function DWordBiggerThan(newvalue,oldvalue: pointer): boolean;
function DWordSmallerThan(newvalue,oldvalue: pointer): boolean;
function DWordIncreasedValue(newvalue,oldvalue: pointer): boolean;
function DWordIncreasedValueBy(newvalue,oldvalue: pointer): boolean;
function DWordDecreasedValue(newvalue,oldvalue: pointer): boolean;
function DWordDecreasedValueBy(newvalue,oldvalue: pointer): boolean;
function DwordChanged(newvalue,oldvalue: pointer): boolean;
function DwordUnChanged(newvalue,oldvalue: pointer): boolean;
function QWordExact(newvalue,oldvalue: pointer): boolean;
function QWordBetween(newvalue,oldvalue: pointer): boolean;
function QWordBiggerThan(newvalue,oldvalue: pointer): boolean;
function QWordSmallerThan(newvalue,oldvalue: pointer): boolean;
function QWordIncreasedValue(newvalue,oldvalue: pointer): boolean;
function QWordIncreasedValueBy(newvalue,oldvalue: pointer): boolean;
function QWordDecreasedValue(newvalue,oldvalue: pointer): boolean;
function QWordDecreasedValueBy(newvalue,oldvalue: pointer): boolean;
function QWordChanged(newvalue,oldvalue: pointer): boolean;
function QwordUnChanged(newvalue,oldvalue: pointer): boolean;
function SingleExact(newvalue,oldvalue: pointer): boolean;
function SingleBetween(newvalue,oldvalue: pointer): boolean;
function SingleBiggerThan(newvalue,oldvalue: pointer): boolean;
function SingleSmallerThan(newvalue,oldvalue: pointer): boolean;
function SingleIncreasedValue(newvalue,oldvalue: pointer): boolean;
function SingleIncreasedValueBy(newvalue,oldvalue: pointer): boolean;
function SingleDecreasedValue(newvalue,oldvalue: pointer): boolean;
function SingleDecreasedValueBy(newvalue,oldvalue: pointer): boolean;
function SingleChanged(newvalue,oldvalue: pointer): boolean;
function singleUnChanged(newvalue,oldvalue: pointer): boolean;
function DoubleExact(newvalue,oldvalue: pointer): boolean;
function DoubleBetween(newvalue,oldvalue: pointer): boolean;
function DoubleBiggerThan(newvalue,oldvalue: pointer): boolean;
function DoubleSmallerThan(newvalue,oldvalue: pointer): boolean;
function DoubleIncreasedValue(newvalue,oldvalue: pointer): boolean;
function DoubleIncreasedValueBy(newvalue,oldvalue: pointer): boolean;
function DoubleDecreasedValue(newvalue,oldvalue: pointer): boolean;
function DoubleDecreasedValueBy(newvalue,oldvalue: pointer): boolean;
function DoubleChanged(newvalue,oldvalue: pointer): boolean;
function DoubleUnChanged(newvalue,oldvalue: pointer): boolean;
function AllExact(newvalue,oldvalue: pointer):boolean; //check byte,word,dword,qword,single and float
function AllBetween(newvalue,oldvalue: pointer): boolean;
function AllBiggerThan(newvalue,oldvalue: pointer): boolean;
function AllSmallerThan(newvalue,oldvalue: pointer): boolean;
function AllIncreasedValue(newvalue,oldvalue: pointer): boolean;
function AllIncreasedValueBy(newvalue,oldvalue: pointer): boolean;
function AllDecreasedValue(newvalue,oldvalue: pointer): boolean;
function AllDecreasedValueBy(newvalue,oldvalue: pointer): boolean;
function AllChanged(newvalue,oldvalue: pointer): boolean;
function AllUnchanged(newvalue,oldvalue: pointer): boolean;
//following types only have exact: Array of byte, binary and string
function ArrayOfByteExact(newvalue,oldvalue: pointer):boolean;
function BinaryExact(newvalue,oldvalue: pointer):boolean;
function CaseSensitiveAnsiStringExact(newvalue,oldvalue: pointer):boolean;
function CaseInsensitiveAnsiStringExact(newvalue,oldvalue: pointer):boolean;
function CaseSensitiveUnicodeStringExact(newvalue,oldvalue: pointer):boolean;
function CaseInsensitiveUnicodeStringExact(newvalue,oldvalue: pointer):boolean;
//save macthing address routines:
procedure GenericSaveResult(address: dword; oldvalue: pointer); //only use as last resort : Call to copymemory just to store one entry
procedure allSaveResult(address: dword; oldvalue: pointer);
procedure binarySaveResult(address: dword; oldvalue: pointer);
procedure arrayOfByteSaveResult(address: dword; oldvalue: pointer);
procedure ByteSaveResult(address: dword; oldvalue: pointer);
procedure WordSaveResult(address: dword; oldvalue: pointer);
procedure DWordSaveResult(address: dword; oldvalue: pointer);
procedure QWordSaveResult(address: dword; oldvalue: pointer);
procedure SingleSaveResult(address: dword; oldvalue: pointer);
procedure DoubleSaveResult(address: dword; oldvalue: pointer);
//flush routines
procedure genericFlush; //generic routine for flushing the buffer
procedure stringFlush; //don't save the memory
procedure binaryFlush; //don't save memory AND use foundaddressb for results
procedure allFlush;
procedure configurescanroutine; //parses scanvalue1,2 according to the VariableType and scanoptions
procedure FirstScanmem(base:dword; buffer: pointer; size: integer); //routine that gets a buffer and saves all the results it finds in the buffer (For firstscan)
procedure FirstNextScanmem(base:dword; buffer,oldbuffer: pointer; size: integer);
procedure nextnextscanmemall(addresslist: pointer; oldmemory: pointer; chunksize: integer);
procedure nextnextscanmembinary(addresslist: pointer; chunksize: integer);
procedure nextnextscanmem(addresslist: pointer; oldmemory: pointer; chunksize: integer);
procedure firstscan; //copy the given range to the memory region
procedure firstnextscan; //routine used when the results list contains nothing but a indicator a unknown scan was done
procedure nextnextscan; //routine used when the results list contains addresses
public
OwningScanController: TScanController;
Addressfile: TFilestream; //CheatEngineDir+'Addresses'+ThreadID.TMP'
MemoryFile: TFileStream; //CheatEngineDir+'Memory'+ThreadID.TMP'
Addressfilename: string;
MemoryFilename: string;
roundingtype: TRoundingtype;
hexadecimal: boolean;
binaryStringAsDecimal: boolean;
readonly: boolean;
fastscan: boolean;
unicode: boolean;
caseSensitive: boolean;
fastscanalignsize: integer;
variablesize: integer;
scanvalue1,scanvalue2: string;
widescanvalue1: widestring;
scanOption: TScanOption;
variableType: TVariableType;
scanType: TScanType; //defines if it's a firstscan or next scan. (newscan is ignored)
useNextNextscan: boolean; //determines to use the nextNextScan or firstNextScan
customscanscript: tstrings; //holds the info for the custom type, script for AA, script for CScript, 2 lines for dll: dllname+function
customscantype: TCustomScanType;
customscanAllocArray: TCEAllocArray;
//thread controlling variables:
isdone: boolean; //will get set to true when the thread finishes normally
haserror: boolean;
errorstring: string;
//region related scans:
//startregion and stopregion
_startregion: integer;
_stopregion: integer;
maxregionsize: dword; //max size of buffer to be allocated when not unknown scan
//recreated memory region list for this specific range, can be used to see which regions where only half read
memRegions: TMemoryregions;
memRegionPos: integer;
startaddress: dword; //specific start for this this thread
stopaddress: dword; //specific stop for this thread, if not fastscan and another thread continue from here, may add some overlopping bytes
//exact address scans:
startentry: integer; //index in the address list
stopentry: integer; //" "
//general:
scanned: dword; //total memory/addresses scanned by this routine
totalfound: dword;
scannernr: integer;
procedure execute; override;
constructor create(suspended: boolean);
destructor destroy; override;
end;
TScanController=class(tthread)
{
The ScanController will configure the scanners and wait till they are done, mainly a idle thread
}
private
threadcount: integer;
addressFile: TFileStream;
memoryFile: TFileStream;
savescannerresults: boolean; //tells the epilogue to save the results to addressfile and memoryfile
procedure updategui;
procedure errorpopup;
procedure firstScan;
procedure nextScan;
procedure firstnextscan; //rotine used when the results list contains nothing but a indicator a unknown scan was done
procedure nextnextscan; //routine used when the results list contains addresses
procedure fillVariableAndFastScanAlignSize; //fills in the variablesize and fastscanalignsizevariables, used for firstscan and firstnextscan
public
OwningMemScan: TMemScan;
resultsaveCS: tcriticalsection; //critical section the scanfilewriter objects use to determine if there is another scanthread writing
scannersCS: TCriticalSection; //Critican section used aty the end of the scancontroller thread, when the scanners are being destroyed
scanners: array of tscanner;
totalAddresses: dword; //how many addresses it will have to scan
roundingtype: TRoundingType;
hexadecimal: boolean;
binaryStringAsDecimal: boolean;
readonly: boolean;
fastscan: boolean;
unicode: boolean;
casesensitive: boolean;
fastscanalignsize: integer;
variablesize: integer;
scanvalue1,scanvalue2: string;
startaddress: dword; //start for the whole scan
stopaddress: dword; //stop of the whole scan
scanOption: TScanOption;
variableType: TVariableType;
scanType: TScanType; //defines if it's a firstscan or next scan. (newscan is ignored)
customscanscript: tstrings; //holds the info for the custom type, script for AA, script for CScript, 2 lines for dll: dllname+function
customscantype: TCustomScanType;
//memregion info
memregion: TMemoryregions; //scanners have access to this, but make sure to NOT WRITE it
memRegionPos: Integer;
//thread controlling variables:
isdone: boolean; //will get set to true when the thread finishes normally
haserror: boolean;
errorstring: string;
//messages
notifywindow: thandle;
notifymessage: integer;
procedure execute; override;
constructor create(suspended: boolean);
destructor destroy; override;
end;
TMemScan=class
{
Configures the gui and related objects and launch TScanner objects with those objects
}
private
previousMemoryBuffer: pointer;
scanController: TScanController; //thread that configures the scanner threads and wait till they are done
SaveFirstScanThread: TSaveFirstScanThread; //thread that will save the results of the first scan that can be used for "same as first scan" scans
memRegion: TMemoryRegions; //after a scan the contents of controller gets copied to here
memRegionPos: integer;
progressbar: TProgressBar;
notifywindow: thandle;
notifymessage: integer;
currentVariableType: TVariableType;
found: uint64;
//string stuff:
stringUnicode: boolean;
stringLength: integer;
//binary stuff:
binaryLength: integer;
//array stuff:
arrayLength: integer;
FLastScanType: TScanType;
public
function GetProgress(var totaladdressestoscan:dword; var currentlyscanned: dword):integer;
function GetErrorString: string;
function GetFoundCount: uint64;
function Getbinarysize: int64; //returns the number of bits of the current type
procedure TerminateScan;
procedure newscan; //will clean up the memory and files
procedure firstscan(scanOption: TScanOption; VariableType: TVariableType; roundingtype: TRoundingType; scanvalue1, scanvalue2: string; startaddress,stopaddress: dword; fastscan,readonly,hexadecimal,binaryStringAsDecimal,unicode,casesensitive: boolean; customscanscript: tstrings; customscantype: TCustomScanType); //first scan routine, e.g unknown initial value, or exact scan
procedure NextScan(scanOption: TScanOption; roundingtype: TRoundingType; scanvalue1, scanvalue2: string; startaddress,stopaddress: dword; fastscan,readonly,hexadecimal,binaryStringAsDecimal,unicode,casesensitive: boolean; customscanscript: tstrings; customscantype: TCustomScanType); //next scan, determine what kind of scan and give to firstnextscan/nextnextscan
constructor create(progressbar: TProgressbar;notifywindow: thandle; notifymessage: integer);
destructor destroy; override;
property LastScanType: TScanType read FLastScanType;
end;
implementation
uses StrUtils;
var foundaddress: byte;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -