fix some of the scanning issues
This commit is contained in:
parent
a3173523df
commit
aac15c7195
@ -8013,7 +8013,7 @@ var
|
||||
|
||||
shouldend: boolean;
|
||||
begin
|
||||
vqe:=TVirtualQueryExCache.create(processhandle);
|
||||
{ vqe:=TVirtualQueryExCache.create(processhandle);
|
||||
a:=0;
|
||||
|
||||
while VirtualQueryEx(processhandle, pointer(a), mbi, sizeof(mbi))<>0 do
|
||||
@ -8056,7 +8056,7 @@ begin
|
||||
|
||||
|
||||
|
||||
vqe.free;
|
||||
vqe.free; }
|
||||
end;
|
||||
|
||||
procedure ChangeIcon(hModule: HModule; restype: PChar; resname: PChar;
|
||||
|
@ -725,6 +725,8 @@ var
|
||||
VirtualQueryEx_StartCache: TVirtualQueryEx_StartCache;
|
||||
VirtualQueryEx_EndCache: TVirtualQueryEx_EndCache;
|
||||
|
||||
GetRegionInfo: function (hProcess: THandle; lpAddress: Pointer; var lpBuffer: TMemoryBasicInformation; dwLength: DWORD; var mapsline: string): DWORD; stdcall;
|
||||
|
||||
|
||||
|
||||
{ just include vmxfunctions
|
||||
@ -1411,6 +1413,33 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
{$ifdef windows}
|
||||
function GetRegionInfo_Windows(hProcess: THandle; lpAddress: Pointer; var lpBuffer: TMemoryBasicInformation; dwLength: DWORD; var mapsline: string): DWORD; stdcall;
|
||||
var
|
||||
i: integer;
|
||||
mappedfilename: pchar;
|
||||
|
||||
begin
|
||||
result:=VirtualQueryEx(hProcess, lpAddress, lpBuffer, dwLength);
|
||||
|
||||
if (result=sizeof(lpbuffer)) then
|
||||
begin
|
||||
getmem(mappedfilename,256);
|
||||
i:=GetMappedFileName(hProcess,lpBuffer.BaseAddress, mappedfilename, 255);
|
||||
mappedfilename[i]:=#0;
|
||||
mapsline:=mappedfilename;
|
||||
|
||||
freemem(mappedfilename);
|
||||
end;
|
||||
end;
|
||||
{$endif}
|
||||
|
||||
|
||||
function GetRegionInfo_Stub(hProcess: THandle; lpAddress: Pointer; var lpBuffer: TMemoryBasicInformation; dwLength: DWORD; var mapsline: string): DWORD; stdcall;
|
||||
begin
|
||||
result:=VirtualQueryEx(hProcess, lpAddress, lpBuffer, dwLength);
|
||||
mapsline:='';
|
||||
end;
|
||||
|
||||
var x: string;
|
||||
psa: thandle;
|
||||
@ -1442,6 +1471,8 @@ initialization
|
||||
WindowsKernel:=LoadLibrary('Kernel32.dll'); //there is no kernel33.dll
|
||||
if WindowsKernel=0 then Raise Exception.create(rsFucked);
|
||||
|
||||
|
||||
|
||||
//by default point to these exports:
|
||||
ReadProcessMemory:=GetProcAddress(WindowsKernel,'ReadProcessMemory');
|
||||
WriteProcessMemory:=GetProcAddress(WindowsKernel,'WriteProcessMemory');
|
||||
@ -1506,6 +1537,12 @@ initialization
|
||||
u32:=loadlibrary('user32.dll');
|
||||
PrintWindow:=GetProcAddress(u32,'PrintWindow');
|
||||
|
||||
{$ifdef windows}
|
||||
GetRegionInfo:=GetRegionInfo_Windows;
|
||||
{$else}
|
||||
GetRegionInfo:=GetRegionInfo_Stub;
|
||||
{$endif}
|
||||
|
||||
|
||||
|
||||
getLBROffset;
|
||||
|
@ -106,7 +106,6 @@
|
||||
<Unit14>
|
||||
<Filename Value="foundlisthelper.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="foundlisthelper"/>
|
||||
</Unit14>
|
||||
<Unit15>
|
||||
<Filename Value="CustomTypeHandler.pas"/>
|
||||
@ -119,7 +118,6 @@
|
||||
<Unit17>
|
||||
<Filename Value="jni\jnitfoundlist.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="jnitfoundlist"/>
|
||||
</Unit17>
|
||||
<Unit18>
|
||||
<Filename Value="jni\jnitmemscan.pas"/>
|
||||
@ -129,7 +127,6 @@
|
||||
<Unit19>
|
||||
<Filename Value="jni\jnitobject.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="jniTObject"/>
|
||||
</Unit19>
|
||||
<Unit20>
|
||||
<Filename Value="symbollisthandler.pas"/>
|
||||
@ -166,12 +163,10 @@
|
||||
<Unit27>
|
||||
<Filename Value="MemoryRecordUnit.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="MemoryRecordUnit"/>
|
||||
</Unit27>
|
||||
<Unit28>
|
||||
<Filename Value="pointerparser.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="pointerparser"/>
|
||||
</Unit28>
|
||||
<Unit29>
|
||||
<Filename Value="jni\jniaddresslist.pas"/>
|
||||
@ -207,7 +202,8 @@
|
||||
</Linking>
|
||||
<Other>
|
||||
<CustomOptions Value="-dJNI
|
||||
-dlowmemoryusage"/>
|
||||
-dlowmemoryusage
|
||||
-OoFASTMATH"/>
|
||||
</Other>
|
||||
</CompilerOptions>
|
||||
<Debugging>
|
||||
|
@ -87,6 +87,8 @@ var
|
||||
|
||||
t: qword;
|
||||
begin
|
||||
result:=0;
|
||||
|
||||
log('CEConnect called');
|
||||
|
||||
hostname:=jniGetString(PEnv, hname);
|
||||
@ -98,11 +100,14 @@ begin
|
||||
log('Host='+inttohex(host.s_addr,1));
|
||||
log('Port='+inttohex(port,1));
|
||||
|
||||
c:=nil;
|
||||
|
||||
t:=GetTickCount64;
|
||||
while GetTickCount64<t+timeout do
|
||||
begin
|
||||
c:=getConnection;
|
||||
if c<>nil then break;
|
||||
sleep(200);
|
||||
end;
|
||||
log('c='+inttohex(ptruint(c),1));
|
||||
|
||||
@ -154,6 +159,85 @@ begin
|
||||
result:=arraylist;
|
||||
end;
|
||||
|
||||
|
||||
function ReadMemoryIntoBuffer(PEnv: PJNIEnv; Obj: JObject; baseAddress: jlong; buffer: jbyteArray):jboolean; //(name: 'ReadMemoryIntoBuffer'; signature: '(L[B)Z'; fnPtr: @ReadMemoryIntoBuffer)
|
||||
var
|
||||
buffersize: jint;
|
||||
iscopy: jboolean;
|
||||
pbuf: PJByte;
|
||||
x: ptruint;
|
||||
|
||||
test: PByteArray;
|
||||
i: integer;
|
||||
begin
|
||||
result:=0;
|
||||
//log('ReadMemoryIntoBuffer');
|
||||
//log('address:'+inttohex(qword(baseAddress),8));
|
||||
|
||||
|
||||
buffersize:=PEnv^.GetArrayLength(penv, buffer);
|
||||
|
||||
// log('buffersize='+inttostr(buffersize));
|
||||
|
||||
iscopy:=0;
|
||||
pbuf:=penv^.GetByteArrayElements(penv, buffer, iscopy);
|
||||
if (pbuf<>nil) then
|
||||
begin
|
||||
|
||||
// log('acquired buffer at '+inttohex(ptruint(pbuf),8)+' iscopy='+inttostr(iscopy));
|
||||
|
||||
for i:=0 to buffersize-1 do
|
||||
pbytearray(pbuf)[i]:=i;
|
||||
|
||||
if ReadProcessMemory(processhandle, pointer(baseaddress), pbuf, buffersize, x) then
|
||||
result:=1;
|
||||
|
||||
|
||||
// log('releasing buffer');
|
||||
|
||||
penv^.ReleaseByteArrayElements(penv, buffer, pbuf, 0);
|
||||
end
|
||||
else
|
||||
begin
|
||||
|
||||
// log('failure to aquire buffer');
|
||||
end;
|
||||
|
||||
|
||||
end;
|
||||
|
||||
function GetRegionInfoString(PEnv: PJNIEnv; Obj: JObject; address: jlong): jstring;
|
||||
var
|
||||
mbi: TMemoryBasicInformation;
|
||||
mapsline: string;
|
||||
begin
|
||||
log('GetRegionInfoString');
|
||||
Log('1');
|
||||
mapsline:='';
|
||||
Log('2');
|
||||
if GetRegionInfo(processhandle, pointer(address), mbi, sizeof(mbi), mapsline)>0 then
|
||||
begin
|
||||
Log('3a');
|
||||
log('success');
|
||||
|
||||
if (mapsline='') then
|
||||
mapsline:=inttohex(ptruint(mbi.BaseAddress),8)+' -> '+inttohex(ptruint(mbi.baseaddress)+mbi.RegionSize,8);
|
||||
|
||||
if (mbi.Protect=PAGE_NOACCESS) then
|
||||
mapsline:='Not readable: '+inttohex(ptruint(mbi.BaseAddress),8)+' -> '+inttohex(ptruint(mbi.baseaddress)+mbi.RegionSize,8);
|
||||
|
||||
|
||||
result:=penv^.NewStringUTF(penv, pchar(mapsline));
|
||||
end
|
||||
else
|
||||
begin
|
||||
Log('3b');
|
||||
Log('fail');
|
||||
result:=penv^.newStringUTF(penv, '----');
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure SetNetworkRPMCacheTimeout(PEnv: PJNIEnv; Obj: JObject; timeout: jfloat); cdecl;
|
||||
begin
|
||||
if timeout>0 then
|
||||
@ -209,7 +293,15 @@ begin
|
||||
tempdirOverride:=_path;
|
||||
end;
|
||||
|
||||
const methodcount=7;
|
||||
procedure TerminateCEServer (PEnv: PJNIEnv; Obj: JObject); cdecl;
|
||||
var c: TCEConnection;
|
||||
begin
|
||||
c:=getConnection;
|
||||
if c<>nil then
|
||||
c.TerminateServer;
|
||||
end;
|
||||
|
||||
const methodcount=10;
|
||||
|
||||
//experiment: make a memscan class in java and give it references to things like memscan_firstscan where the java class contains the memscan long
|
||||
|
||||
@ -221,8 +313,11 @@ var jnimethods: array [0..methodcount-1] of JNINativeMethod =(
|
||||
|
||||
(name: 'FetchSymbols'; signature: '(Z)V'; fnPtr: @FetchSymbols),
|
||||
(name: 'SetTempPath'; signature: '(Ljava/lang/String;)V'; fnPtr: @SetTempPath),
|
||||
(name: 'SetNetworkRPMCacheTimeout'; signature: '(F)V'; fnPtr: @SetNetworkRPMCacheTimeout)
|
||||
(name: 'SetNetworkRPMCacheTimeout'; signature: '(F)V'; fnPtr: @SetNetworkRPMCacheTimeout),
|
||||
(name: 'ReadMemoryIntoBuffer'; signature: '(J[B)Z'; fnPtr: @ReadMemoryIntoBuffer),
|
||||
(name: 'GetRegionInfoString'; signature: '(J)Ljava/lang/String;'; fnPtr: @GetRegionInfoString),
|
||||
|
||||
(name: 'TerminateCEServer'; signature: '()V'; fnPtr: @TerminateCEServer)
|
||||
);
|
||||
|
||||
function JNI_OnLoad(vm: PJavaVM; reserved: pointer): jint; cdecl;
|
||||
|
@ -86,19 +86,16 @@ procedure TFormMemoryRegions.FormShow(Sender: TObject);
|
||||
var address: PtrUInt;
|
||||
mbi : _MEMORY_BASIC_INFORMATION;
|
||||
temp:string;
|
||||
mappedfilename: pchar;
|
||||
mappedfilename: string;
|
||||
i: integer;
|
||||
begin
|
||||
getmem(mappedfilename,256);
|
||||
try
|
||||
|
||||
listview1.Clear;
|
||||
|
||||
//query the process for the memory regions
|
||||
address:=0;
|
||||
mbi.RegionSize:=$1000;
|
||||
|
||||
while (Virtualqueryex(processhandle,pointer(address),mbi,sizeof(mbi))<>0) and ((address+mbi.RegionSize)>address) do
|
||||
while (GetRegionInfo(processhandle,pointer(address),mbi,sizeof(mbi), mappedfilename)<>0) and ((address+mbi.RegionSize)>address) do
|
||||
begin
|
||||
setlength(moreinfo,length(moreinfo)+1);
|
||||
moreinfo[length(moreinfo)-1].address:=ptrUint(mbi.BaseAddress);
|
||||
@ -151,19 +148,12 @@ begin
|
||||
listview1.Items[listview1.Items.Count-1].SubItems.add(inttohex(mbi.regionsize,1));
|
||||
|
||||
// if mbi._Type=MEM_MAPPED then
|
||||
begin
|
||||
i:=GetMappedFileName(processhandle,mbi.BaseAddress, mappedfilename, 255);
|
||||
mappedfilename[i]:=#0;
|
||||
listview1.Items[listview1.Items.Count-1].SubItems.Add(mappedfilename);
|
||||
end;
|
||||
listview1.Items[listview1.Items.Count-1].SubItems.Add(mappedfilename);
|
||||
|
||||
|
||||
|
||||
inc(address,mbi.RegionSize);
|
||||
end;
|
||||
finally
|
||||
freemem(mappedfilename);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
|
@ -237,13 +237,18 @@ begin
|
||||
l:=penv^.GetArrayLength(penv, offsets);
|
||||
// log('the offsets array length='+inttostr(l));
|
||||
|
||||
iscopy:=0;
|
||||
offsetlist:=PJintArray(penv^.GetIntArrayElements(penv,offsets, iscopy));
|
||||
if offsetlist<>nil then
|
||||
begin
|
||||
setlength(r.pointeroffsets, l);
|
||||
for i:=0 to l-1 do
|
||||
r.pointeroffsets[i]:=offsetlist[i];
|
||||
|
||||
setlength(r.pointeroffsets, l);
|
||||
for i:=0 to l-1 do
|
||||
r.pointeroffsets[i]:=offsetlist[i];
|
||||
|
||||
penv^.ReleaseIntArrayElements(penv, offsets, PJint(offsetlist),0);
|
||||
penv^.ReleaseIntArrayElements(penv, offsets, PJint(offsetlist),JNI_ABORT);
|
||||
end
|
||||
else
|
||||
log('offsetlist=nil');
|
||||
end;
|
||||
|
||||
|
||||
|
@ -39,10 +39,20 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
const methodcount=2;
|
||||
function symbolhandler_inModule(PEnv: PJNIEnv; Obj: JObject; address: jlong): jboolean; cdecl;
|
||||
begin
|
||||
if symhandler.inModule(address) then
|
||||
result:=1
|
||||
else
|
||||
result:=0;
|
||||
|
||||
end;
|
||||
|
||||
const methodcount=3;
|
||||
var jnimethods: array [0..methodcount-1] of JNINativeMethod =(
|
||||
(name: 'getAddressFromName'; signature: '(Ljava/lang/String;)J'; fnPtr: @symbolhandler_getAddressFromName),
|
||||
(name: 'getAddressFromName'; signature: '(Ljava/lang/String;Z)J'; fnPtr: @symbolhandler_getAddressFromName2)
|
||||
(name: 'getAddressFromName'; signature: '(Ljava/lang/String;Z)J'; fnPtr: @symbolhandler_getAddressFromName2),
|
||||
(name: 'inModule'; signature: '(J)Z'; fnPtr: @symbolhandler_inModule)
|
||||
);
|
||||
|
||||
procedure InitializeJniSymbolHandler(env: PJNIEnv);
|
||||
@ -50,7 +60,6 @@ var c: jclass;
|
||||
begin
|
||||
c:=env^.FindClass(env, 'org/cheatengine/SymbolHandler');
|
||||
env^.RegisterNatives(env, c, @jnimethods[0], methodcount);
|
||||
|
||||
end;
|
||||
|
||||
end.
|
||||
|
@ -137,6 +137,10 @@ begin
|
||||
scanvalue2:=jniGetString(penv, sv2);
|
||||
protectionflags:=jniGetString(penv, pf);
|
||||
|
||||
log('scanvalue1='+scanvalue1);
|
||||
log('scanvalue2='+scanvalue2);
|
||||
log('protectionflags='+protectionflags);
|
||||
|
||||
ms.parseProtectionflags(protectionflags);
|
||||
ms.firstscan(TScanOption(scanOption), TVariableType(variabletype), TRoundingType(roundingtype), scanvalue1, scanvalue2, startaddress, stopaddress, hexadecimal<>0, binaryasstring<>0, unicode<>0, casesensitive<>0, TFastScanMethod(fastscanmethod), jnigetstring(penv, fastscanparameter), nil);
|
||||
end;
|
||||
|
@ -4656,10 +4656,15 @@ end;
|
||||
|
||||
procedure TScanner.execute;
|
||||
begin
|
||||
(*
|
||||
{$if defined(cpui386) or defined(cpux86_64)}
|
||||
Set8087CW($133f); //disable floating point exceptions in this thread
|
||||
SetSSECSR($1f80);
|
||||
{$endif}
|
||||
*)
|
||||
|
||||
SetExceptionMask([exInvalidOp, exDenormalized, exZeroDivide, exOverflow, exUnderflow, exPrecision]);
|
||||
|
||||
|
||||
try
|
||||
scanwriter:=TScanfilewriter.create(self,self.OwningScanController,addressfile,memoryfile);
|
||||
@ -4683,6 +4688,8 @@ begin
|
||||
haserror:=true;
|
||||
errorstring:='thread '+inttostr(scannernr)+':'+e.message;
|
||||
|
||||
log('Scanner exception:'+errorstring);
|
||||
|
||||
//tell all siblings to terminate, something messed up
|
||||
//and I can just do this, since the ScanController is waiting for us, and terminate is pretty much atomic
|
||||
//for i:=0 to length(OwningScanController.scanners)-1 do
|
||||
@ -6648,6 +6655,10 @@ var i: integer;
|
||||
currentstate: Tscanregionpreference;
|
||||
begin
|
||||
//parse the protectionflags string and set scanWritable, scanExecutable and scanCopyOnWrite;
|
||||
scanWritable:=scanDontCare;
|
||||
scanCopyOnWrite:=scanDontCare;
|
||||
scanExecutable:=scanDontCare;
|
||||
|
||||
protectionflags:=uppercase(protectionflags);
|
||||
|
||||
currentstate:=scanDontCare;
|
||||
|
@ -94,6 +94,8 @@ type
|
||||
function VirtualQueryEx_StartCache(hProcess: THandle; flags: DWORD): boolean;
|
||||
procedure VirtualQueryEx_EndCache(hProcess: THandle);
|
||||
|
||||
function GetRegionInfo(hProcess: THandle; lpAddress: Pointer; var lpBuffer: TMemoryBasicInformation; dwLength: DWORD; var mapsline: string): DWORD;
|
||||
|
||||
function ReadProcessMemory(hProcess: THandle; lpBaseAddress: Pointer; lpBuffer: Pointer; nSize: DWORD; var lpNumberOfBytesRead: PTRUINT): BOOL;
|
||||
function WriteProcessMemory(hProcess: THandle; const lpBaseAddress: Pointer; lpBuffer: Pointer; nSize: DWORD; var lpNumberOfBytesWritten: PTRUINT): BOOL;
|
||||
procedure beginWriteProcessMemory;
|
||||
@ -111,6 +113,9 @@ type
|
||||
function loadModule(hProcess: THandle; modulepath: string): boolean;
|
||||
function loadExtension(hProcess: Thandle): boolean;
|
||||
function speedhack_setSpeed(hProcess: THandle; speed: single): boolean;
|
||||
|
||||
procedure TerminateServer;
|
||||
|
||||
property connected: boolean read fConnected;
|
||||
|
||||
constructor create;
|
||||
@ -166,6 +171,16 @@ const
|
||||
|
||||
//
|
||||
CMD_VIRTUALQUERYEXFULL=31;
|
||||
CMD_GETREGIONINFO=32; //extended version of VirtualQueryEx which also get the full string
|
||||
|
||||
|
||||
procedure TCEConnection.TerminateServer;
|
||||
var command: byte;
|
||||
begin
|
||||
command:=CMD_TERMINATESERVER;
|
||||
send(@command, sizeof(command));
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
@ -360,10 +375,20 @@ var pages: array of TPageInfo;
|
||||
|
||||
m: PByte;
|
||||
begin
|
||||
//log(format('TCEConnection.CReadProcessMemory: Read %d bytes from %p into %p',[nsize, lpBaseAddress, lpBuffer]));
|
||||
|
||||
|
||||
result:=false;
|
||||
lpNumberOfBytesRead:=0;
|
||||
|
||||
pagecount:=1+((ptruint(lpBaseAddress)+nSize-1) shr 12) - (ptruint(lpBaseAddress) shr 12);
|
||||
currenttarget:=ptruint(lpBaseAddress)+nsize-1;
|
||||
if currenttarget<ptruint(lpBaseAddress) then //overflow
|
||||
begin
|
||||
pagecount:=2+(currenttarget shr 12);
|
||||
end
|
||||
else
|
||||
pagecount:=1+((ptruint(lpBaseAddress)+nSize-1) shr 12) - (ptruint(lpBaseAddress) shr 12);
|
||||
|
||||
setlength(pages, pagecount);
|
||||
|
||||
QueryPerformanceFrequency(freq);
|
||||
@ -530,8 +555,13 @@ end;
|
||||
|
||||
function TCEConnection.ReadProcessMemory(hProcess: THandle; lpBaseAddress: Pointer; lpBuffer: Pointer; nSize: DWORD; var lpNumberOfBytesRead: PTRUINT): BOOL;
|
||||
begin
|
||||
// log(format('TCEConnection.ReadProcessMemory: Read %d bytes from %p into %p',[nsize, lpBaseAddress, lpBuffer]));
|
||||
|
||||
|
||||
if ((hProcess shr 24) and $ff)= $ce then
|
||||
begin
|
||||
// Log('hProcess is valid');
|
||||
|
||||
result:=false;
|
||||
lpNumberOfBytesRead:=0;
|
||||
|
||||
@ -541,10 +571,14 @@ begin
|
||||
|
||||
if (nsize<=8192) then
|
||||
begin
|
||||
//log('nsize<=8192. Calling CReadProcessMemory');
|
||||
result:=CReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, nsize, lpNumberOfBytesRead);
|
||||
end
|
||||
else //just fetch it all from the net , ce usually does not fetch more than 8KB for random accesses, so would be a waste of time
|
||||
begin
|
||||
// log('nsize>8192. Calling NReadProcessMemory');
|
||||
result:=NReadProcessMemory(hProcess, lpBaseaddress, lpbuffer, nsize, lpNumberOfBytesRead);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
@ -971,6 +1005,8 @@ var
|
||||
vqecache: TVirtualQueryExCache;
|
||||
|
||||
begin
|
||||
result:=0;
|
||||
|
||||
if VirtualQueryExCacheMap.TryGetValue(hProcess, vqecache) then //check if there is a cache going on for this handle
|
||||
begin
|
||||
//yes, get it from the cache
|
||||
@ -1030,6 +1066,93 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCEConnection.GetRegionInfo(hProcess: THandle; lpAddress: Pointer; var lpBuffer: TMemoryBasicInformation; dwLength: DWORD; var mapsline: string): DWORD;
|
||||
var
|
||||
input: packed record
|
||||
command: byte;
|
||||
handle: integer;
|
||||
baseaddress: qword;
|
||||
end;
|
||||
|
||||
output: packed record
|
||||
result: byte;
|
||||
protection: dword;
|
||||
_type: dword;
|
||||
baseaddress: qword;
|
||||
size: qword;
|
||||
end;
|
||||
|
||||
mapslinesize: byte;
|
||||
|
||||
ml: pchar;
|
||||
begin
|
||||
result:=0;
|
||||
|
||||
log('TCEConnection.GetRegionInfo');
|
||||
|
||||
if isNetworkHandle(hProcess) then
|
||||
begin
|
||||
log('valid handle');
|
||||
result:=0;
|
||||
input.command:=CMD_GETREGIONINFO;
|
||||
input.handle:=hProcess and $ffffff;
|
||||
input.baseaddress:=qword(lpAddress);
|
||||
if send(@input, sizeof(input))>0 then
|
||||
begin
|
||||
if receive(@output, sizeof(output))>0 then
|
||||
begin
|
||||
if output.result>0 then
|
||||
begin
|
||||
lpBuffer.BaseAddress:=pointer(output.baseaddress);
|
||||
lpBuffer.AllocationBase:=lpBuffer.BaseAddress;
|
||||
lpbuffer.AllocationProtect:=PAGE_NOACCESS;
|
||||
lpbuffer.Protect:=output.protection;
|
||||
|
||||
if output.protection=PAGE_NOACCESS then
|
||||
begin
|
||||
lpbuffer.State:=MEM_FREE;
|
||||
lpbuffer._Type:=0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
lpbuffer.State:=MEM_COMMIT;
|
||||
lpbuffer._Type:=output._type;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
lpbuffer.RegionSize:=output.size;
|
||||
|
||||
result:=dwlength;
|
||||
end
|
||||
else
|
||||
result:=0;
|
||||
end;
|
||||
|
||||
//extended part of CMD_GETREGIONINFO;
|
||||
log('receiving extended state');
|
||||
if receive(@mapslinesize, sizeof(mapslinesize))>0 then
|
||||
begin
|
||||
log('received extended state');
|
||||
log('mapelinesize='+inttostr(mapslinesize));
|
||||
|
||||
getmem(ml, mapslinesize+1);
|
||||
if (ml<>nil) then
|
||||
begin
|
||||
receive(ml, mapslinesize);
|
||||
ml[mapslinesize]:=#0;
|
||||
|
||||
mapsline:=ml;
|
||||
freemem(ml);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
end;
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCEConnection.OpenProcess(dwDesiredAccess:DWORD; bInheritHandle:WINBOOL; dwProcessId:DWORD):HANDLE;
|
||||
var OpenProcessCommand: packed record
|
||||
command: byte;
|
||||
@ -1685,9 +1808,12 @@ begin
|
||||
else
|
||||
begin
|
||||
inc(retry);
|
||||
OutputDebugString('fail '+inttostr(retry));
|
||||
// OutputDebugString('fail '+inttostr(retry));
|
||||
end;
|
||||
end;
|
||||
|
||||
if not fconnected then
|
||||
OutputDebugString('Connection failure');
|
||||
end;
|
||||
|
||||
destructor TCEConnection.destroy;
|
||||
|
@ -8,7 +8,7 @@ uses
|
||||
{$ifdef JNI}
|
||||
Classes, SysUtils, networkinterface, unixporthelper, newkernelhandler;
|
||||
{$else}
|
||||
{jwawindows,} windows, Classes, SysUtils, networkinterface, newkernelhandler;
|
||||
{jwawindows,} windows, Classes, SysUtils, networkinterface, newkernelhandler, CEFuncProc;
|
||||
{$endif}
|
||||
|
||||
|
||||
@ -34,6 +34,7 @@ function NetworkCloseHandle(handle: THandle):WINBOOL; stdcall;
|
||||
function NetworkSetBreakpoint(handle: THandle; threadid: integer; debugregister: integer; address: PtrUInt; bptype: integer; bpsize: integer): boolean;
|
||||
function NetworkRemoveBreakpoint(handle: THandle; threadid: integer; debugregister: integer; wasWatchpoint: boolean): boolean;
|
||||
|
||||
function NetworkGetRegionInfo(hProcess: THandle; lpAddress: Pointer; var lpBuffer: TMemoryBasicInformation; dwLength: DWORD; var mapsline: string): DWORD; stdcall;
|
||||
|
||||
implementation
|
||||
|
||||
@ -166,27 +167,47 @@ function NetworkReadProcessMemory(hProcess: THandle; lpBaseAddress, lpBuffer: Po
|
||||
var a,b: dword;
|
||||
c,d: ptruint;
|
||||
begin
|
||||
//log('NetworkReadProcessMemory');
|
||||
//log(format('Read %d bytes from %p into %p',[nsize, lpBaseAddress, lpBuffer]));
|
||||
|
||||
if getConnection<>nil then
|
||||
begin
|
||||
// log('Has connection');
|
||||
|
||||
result:=connection.readProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead);
|
||||
if (result=false) and (connection.connected=false) and (getConnection<>nil) then //try again one more time
|
||||
begin
|
||||
// log('read fail1. Try smaller chunk');
|
||||
|
||||
//try a smaller chunk
|
||||
a:=nsize div 2;
|
||||
b:=nsize-a;
|
||||
c:=0;
|
||||
d:=0;
|
||||
result:=connection.readProcessMemory(hProcess, lpBaseAddress, lpBuffer, a, c);
|
||||
if result and (b>0) then
|
||||
result:=connection.readProcessMemory(hProcess, pointer(ptruint(lpBaseAddress)+a), pointer(ptruint(lpBuffer)+a), b, d);
|
||||
|
||||
lpNumberOfBytesRead:=c+d;
|
||||
//log('a='+inttostr(a));
|
||||
// log('b='+inttostr(b));
|
||||
|
||||
result:=connection.readProcessMemory(hProcess, lpBaseAddress, lpBuffer, a, c);
|
||||
|
||||
// log('after read 1/2');
|
||||
|
||||
if result and (b>0) and (c>0) then //first read succesful, there is something else to read, and it actually has read
|
||||
begin
|
||||
result:=connection.readProcessMemory(hProcess, pointer(ptruint(lpBaseAddress)+a), pointer(ptruint(lpBuffer)+a), b, d);
|
||||
// log('after read 2/2');
|
||||
end;
|
||||
|
||||
if @lpNumberOfBytesRead<>nil then
|
||||
lpNumberOfBytesRead:=c+d;
|
||||
end;
|
||||
|
||||
|
||||
end
|
||||
else
|
||||
result:=false;
|
||||
|
||||
//log('Returning from rpm');
|
||||
end;
|
||||
|
||||
function NetworkWriteProcessMemory(hProcess: THandle; const lpBaseAddress: Pointer; lpBuffer: Pointer; nSize: DWORD; var lpNumberOfBytesWritten: ptruint): BOOL; stdcall;
|
||||
@ -198,6 +219,14 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
function NetworkGetRegionInfo(hProcess: THandle; lpAddress: Pointer; var lpBuffer: TMemoryBasicInformation; dwLength: DWORD; var mapsline: string): DWORD; stdcall;
|
||||
begin
|
||||
if getConnection<>nil then
|
||||
result:=connection.GetRegionInfo(hProcess, lpAddress, lpBuffer, dwLength, mapsline)
|
||||
else
|
||||
result:=0;
|
||||
end;
|
||||
|
||||
function NetworkVirtualQueryEx(hProcess: THandle; lpAddress: Pointer; var lpBuffer: TMemoryBasicInformation; dwLength: DWORD): DWORD; stdcall;
|
||||
begin
|
||||
if getConnection<>nil then
|
||||
@ -298,6 +327,8 @@ begin
|
||||
newkernelhandler.VirtualFreeEx:=@networkVirtualFreeEx;
|
||||
newkernelhandler.CreateRemoteThread:=@networkCreateRemoteThread;
|
||||
|
||||
newkernelhandler.GetRegionInfo:=@NetworkGetRegionInfo;
|
||||
|
||||
|
||||
|
||||
newkernelhandler.VirtualQueryEx_StartCache:=@NetworkVirtualQueryEx_StartCache;
|
||||
|
Loading…
Reference in New Issue
Block a user