mirror of https://github.com/red-prig/fpPS4.git
797 lines
21 KiB
Plaintext
797 lines
21 KiB
Plaintext
unit md_systm_reserve;
|
|
|
|
{$mode ObjFPC}{$H+}
|
|
{$CALLING SysV_ABI_CDecl}
|
|
|
|
interface
|
|
|
|
uses
|
|
sysutils,
|
|
windows,
|
|
ntapi;
|
|
|
|
type
|
|
t_md_map_reserve_result=record
|
|
error:DWORD;
|
|
id :DWORD;
|
|
base :Pointer;
|
|
size :QWORD;
|
|
end;
|
|
|
|
function md_map_reserve(hProcess:THandle=NtCurrentProcess;rip:QWORD=0):t_md_map_reserve_result;
|
|
|
|
implementation
|
|
|
|
uses
|
|
vmparam,
|
|
md_systm,
|
|
md_map,
|
|
md_context,
|
|
md_hook;
|
|
|
|
var
|
|
md_map_init_flags:Byte=0;
|
|
md_hook_page:Pointer;
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
type
|
|
t_NtCreateThreadEx=function(
|
|
hThread :PHandle;
|
|
DesiredAccess :ACCESS_MASK;
|
|
ObjectAttributes:POBJECT_ATTRIBUTES;
|
|
ProcessHandle :THandle;
|
|
StartRoutine :Pointer;
|
|
Argument :Pointer;
|
|
CreateFlags :ULONG; // THREAD_CREATE_FLAGS_*
|
|
ZeroBits :ULONG_PTR;
|
|
StackSize :ULONG_PTR;
|
|
MaximumStackSize:ULONG_PTR;
|
|
AttributeList :PPS_ATTRIBUTE_LIST
|
|
):DWORD; stdcall;
|
|
|
|
var
|
|
real_NtCreateThreadEx:t_NtCreateThreadEx=@NtCreateThreadEx;
|
|
|
|
function Inj_NtCreateThreadEx(
|
|
hThread :PHandle;
|
|
DesiredAccess :ACCESS_MASK;
|
|
ObjectAttributes:POBJECT_ATTRIBUTES;
|
|
ProcessHandle :THandle;
|
|
StartRoutine :Pointer;
|
|
Argument :Pointer;
|
|
CreateFlags :ULONG; // THREAD_CREATE_FLAGS_*
|
|
ZeroBits :ULONG_PTR;
|
|
StackSize :ULONG_PTR;
|
|
MaximumStackSize:ULONG_PTR;
|
|
AttributeList :PPS_ATTRIBUTE_LIST
|
|
):DWORD; stdcall; forward;
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
type
|
|
t_NtMapViewOfSection=function(
|
|
SectionHandle :THandle;
|
|
ProcessHandle :THandle;
|
|
BaseAddress :PPointer;
|
|
ZeroBits :ULONG_PTR;
|
|
CommitSize :ULONG_PTR;
|
|
SectionOffset :PLARGE_INTEGER;
|
|
ViewSize :PULONG_PTR;
|
|
InheritDisposition:DWORD;
|
|
AllocationType :ULONG;
|
|
Protect :ULONG
|
|
):DWORD; stdcall;
|
|
|
|
var
|
|
real_NtMapViewOfSection:t_NtMapViewOfSection=@NtMapViewOfSection;
|
|
|
|
function Inj_NtMapViewOfSection(
|
|
SectionHandle :THandle;
|
|
ProcessHandle :THandle;
|
|
BaseAddress :PPointer;
|
|
ZeroBits :ULONG_PTR;
|
|
CommitSize :ULONG_PTR;
|
|
SectionOffset :PLARGE_INTEGER;
|
|
ViewSize :PULONG_PTR;
|
|
InheritDisposition:DWORD;
|
|
AllocationType :ULONG;
|
|
Protect :ULONG
|
|
):DWORD; stdcall; forward;
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
type
|
|
t_NtMapViewOfSectionEx=function(
|
|
SectionHandle :THandle;
|
|
ProcessHandle :THandle;
|
|
BaseAddress :PPointer;
|
|
SectionOffset :PLARGE_INTEGER;
|
|
ViewSize :PULONG_PTR;
|
|
AllocationType :ULONG;
|
|
Protect :ULONG;
|
|
ExtendedParameters :Pointer; //MEM_EXTENDED_PARAMETER
|
|
ExtendedParameterCount:ULONG
|
|
):DWORD; stdcall;
|
|
|
|
var
|
|
real_NtMapViewOfSectionEx:t_NtMapViewOfSectionEx=@NtMapViewOfSectionEx;
|
|
|
|
function Inj_NtMapViewOfSectionEx(
|
|
SectionHandle :THandle;
|
|
ProcessHandle :THandle;
|
|
BaseAddress :PPointer;
|
|
SectionOffset :PLARGE_INTEGER;
|
|
ViewSize :PULONG_PTR;
|
|
AllocationType :ULONG;
|
|
Protect :ULONG;
|
|
ExtendedParameters :Pointer; //MEM_EXTENDED_PARAMETER
|
|
ExtendedParameterCount:ULONG
|
|
):DWORD; stdcall; forward;
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
type
|
|
t_NtAllocateVirtualMemory=function(
|
|
ProcessHandle :THandle;
|
|
BaseAddress :PPointer;
|
|
ZeroBits :ULONG_PTR;
|
|
RegionSize :PULONG_PTR;
|
|
AllocationType:ULONG;
|
|
Protect :ULONG
|
|
):DWORD; stdcall;
|
|
|
|
var
|
|
real_NtAllocateVirtualMemory:t_NtAllocateVirtualMemory=@NtAllocateVirtualMemory;
|
|
|
|
function Inj_NtAllocateVirtualMemory(
|
|
ProcessHandle :THandle;
|
|
BaseAddress :PPointer;
|
|
ZeroBits :ULONG_PTR;
|
|
RegionSize :PULONG_PTR;
|
|
AllocationType:ULONG;
|
|
Protect :ULONG
|
|
):DWORD; stdcall; forward;
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
type
|
|
t_NtAllocateVirtualMemoryEx=function(
|
|
ProcessHandle :THandle;
|
|
BaseAddress :PPointer;
|
|
RegionSize :PULONG_PTR;
|
|
AllocationType :ULONG;
|
|
Protect :ULONG;
|
|
ExtendedParameters :Pointer; //MEM_EXTENDED_PARAMETER
|
|
ExtendedParameterCount:ULONG
|
|
):DWORD; stdcall;
|
|
|
|
var
|
|
real_NtAllocateVirtualMemoryEx:t_NtAllocateVirtualMemoryEx=@NtAllocateVirtualMemoryEx;
|
|
|
|
function Inj_NtAllocateVirtualMemoryEx(
|
|
ProcessHandle :THandle;
|
|
BaseAddress :PPointer;
|
|
RegionSize :PULONG_PTR;
|
|
AllocationType :ULONG;
|
|
Protect :ULONG;
|
|
ExtendedParameters :Pointer; //MEM_EXTENDED_PARAMETER
|
|
ExtendedParameterCount:ULONG
|
|
):DWORD; stdcall; forward;
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
function md_map_reserve(hProcess:THandle=NtCurrentProcess;rip:QWORD=0):t_md_map_reserve_result;
|
|
var
|
|
Module:t_dll_base_pair;
|
|
page :t_hook_page;
|
|
|
|
temp_pmap_mem:t_addr_range_array;
|
|
|
|
base:Pointer;
|
|
size:QWORD;
|
|
i:Integer;
|
|
orig_flags:Byte;
|
|
init_flags:Byte;
|
|
begin
|
|
Result:=Default(t_md_map_reserve_result);
|
|
|
|
//load flags
|
|
init_flags:=0;
|
|
md_copyin(@md_map_init_flags,@init_flags,sizeof(init_flags),nil,hProcess);
|
|
orig_flags:=init_flags;
|
|
|
|
if ((init_flags and 1)=0) then
|
|
begin
|
|
///
|
|
|
|
{
|
|
if you reserve up to 43 bits of memory, then when searching for free memory from address 0,
|
|
the Windows virtual memory manager starts to lag terribly, in particular,
|
|
NtCreateThreadEx is visible here, which automatically allocates memory for the stack,
|
|
it takes about 5 seconds to execute.
|
|
Need to hook NtCreateThreadEx and emulate it through NtCreateThread and
|
|
a custom allocator with setting the lower search limit to LowestStartingAddress
|
|
and this generally worked and everything became faster.
|
|
}
|
|
|
|
if (hProcess<>NtCurrentProcess) and (rip<>0) then
|
|
begin
|
|
//RIP -> RtlUserThreadStart
|
|
Module:=NtQueryNtdllByRTUTS(hProcess,rip);
|
|
end else
|
|
begin
|
|
Module:=NtQueryModuleByName(hProcess,'ntdll.dll');
|
|
end;
|
|
|
|
page :=NewHookPage(hProcess,Module.DllBaseProc,4*1024,VM_RW);
|
|
|
|
WriteHook(page,NewHookPlan(Module,'NtCreateThreadEx' ,@Inj_NtCreateThreadEx ,@real_NtCreateThreadEx ));
|
|
WriteHook(page,NewHookPlan(Module,'NtMapViewOfSection' ,@Inj_NtMapViewOfSection ,@real_NtMapViewOfSection));
|
|
WriteHook(page,NewHookPlan(Module,'NtMapViewOfSectionEx' ,@Inj_NtMapViewOfSectionEx ,@real_NtMapViewOfSectionEx));
|
|
WriteHook(page,NewHookPlan(Module,'NtAllocateVirtualMemory' ,@Inj_NtAllocateVirtualMemory ,@real_NtAllocateVirtualMemory));
|
|
WriteHook(page,NewHookPlan(Module,'NtAllocateVirtualMemoryEx',@Inj_NtAllocateVirtualMemoryEx,@real_NtAllocateVirtualMemoryEx));
|
|
|
|
//allow execute
|
|
i:=md_protect(page.base,4*1024,VM_RX,hProcess);
|
|
|
|
//save change
|
|
i:=md_copyout(@page.base,@md_hook_page,sizeof(Pointer),nil,hProcess);
|
|
|
|
///
|
|
init_flags:=init_flags or 1;
|
|
end;
|
|
|
|
if ((init_flags and 2)=0) and (Length(temp_pmap_mem)<>0) then
|
|
begin
|
|
|
|
//copy original
|
|
temp_pmap_mem:=initial_pmap_mem;
|
|
|
|
i:=0;
|
|
while (i<=High(temp_pmap_mem)) do
|
|
begin
|
|
base:=Pointer(temp_pmap_mem[i].start);
|
|
|
|
//try union range
|
|
if (base=Pointer(DL_AREA_START)) then
|
|
begin
|
|
size:=VM_MAXUSER_ADDRESS-DL_AREA_START;
|
|
|
|
Result.error:=md_placeholder_mmap(base,size,MD_MAP_FIXED,hProcess);
|
|
if (Result.error=0) then
|
|
begin
|
|
//union range
|
|
temp_pmap_mem[i+0].__end:=VM_MAXUSER_ADDRESS;
|
|
temp_pmap_mem[i+1].start:=VM_MAXUSER_ADDRESS;
|
|
//
|
|
i:=i+2;
|
|
Continue;
|
|
end;
|
|
end;
|
|
|
|
base:=Pointer(temp_pmap_mem[i].start);
|
|
size:=temp_pmap_mem[i].__end-temp_pmap_mem[i].start;
|
|
|
|
Result.error:=md_placeholder_mmap(base,size,MD_MAP_FIXED,hProcess);
|
|
|
|
if (Result.error<>0) then
|
|
begin
|
|
Result.id :=i;
|
|
Result.base:=base;
|
|
Result.size:=size;
|
|
//STATUS_COMMITMENT_LIMIT = $C000012D
|
|
Exit;
|
|
end;
|
|
|
|
//update start region
|
|
temp_pmap_mem[i].start:=QWORD(base);
|
|
|
|
i:=i+1;
|
|
end;
|
|
|
|
//save change
|
|
md_copyout(@temp_pmap_mem,@pmap_mem,sizeof(pmap_mem),nil,hProcess);
|
|
|
|
init_flags:=init_flags or 2;
|
|
end;
|
|
|
|
//save change
|
|
if (orig_flags<>init_flags) then
|
|
begin
|
|
md_copyout(@init_flags,@md_map_init_flags,sizeof(init_flags),nil,hProcess);
|
|
end;
|
|
end;
|
|
|
|
const
|
|
C_REQ:TMEM_ADDRESS_REQUIREMENTS=(
|
|
LowestStartingAddress:Pointer(KERNEL_LOWER);
|
|
HighestEndingAddress :nil;
|
|
Alignment :0
|
|
);
|
|
C_EXT:TMEM_EXTENDED_PARAMETER=(
|
|
pType :MemExtendedParameterAddressRequirements;
|
|
Pointer:@C_REQ
|
|
);
|
|
|
|
type
|
|
TMEM_EXTENDED_PARAMETER_4=array[0..3] of TMEM_EXTENDED_PARAMETER;
|
|
|
|
TEXT_PATCHER=object
|
|
data:TMEM_EXTENDED_PARAMETER_4;
|
|
REQ :TMEM_ADDRESS_REQUIREMENTS;
|
|
Procedure Patch(var EParams:Pointer;var ECounts:ULONG);
|
|
end;
|
|
|
|
Procedure TEXT_PATCHER.Patch(var EParams:Pointer;var ECounts:ULONG); inline;
|
|
var
|
|
P:TMEM_EXTENDED_PARAMETER;
|
|
R:TMEM_ADDRESS_REQUIREMENTS;
|
|
i:Byte;
|
|
used:Boolean;
|
|
begin
|
|
if (EParams=nil) or (ECounts=0) then
|
|
begin
|
|
EParams:=@C_EXT;
|
|
ECounts:=1;
|
|
end else
|
|
if (ECounts<=Length(data)) then
|
|
begin
|
|
REQ:=C_REQ;
|
|
used:=False;
|
|
For i:=0 to ECounts-1 do
|
|
begin
|
|
P:=PMEM_EXTENDED_PARAMETER(EParams)[i]; //if use md_copyin then the initial load will crash 0xC0000005
|
|
|
|
case P.pType of
|
|
MemExtendedParameterAddressRequirements:
|
|
begin
|
|
R:=PMEM_ADDRESS_REQUIREMENTS(P.Pointer)^;
|
|
|
|
if (R.LowestStartingAddress>REQ.LowestStartingAddress) then
|
|
begin
|
|
REQ.LowestStartingAddress:=R.LowestStartingAddress;
|
|
end;
|
|
|
|
if (R.Alignment>REQ.Alignment) then
|
|
begin
|
|
REQ.Alignment:=R.Alignment;
|
|
end;
|
|
|
|
if (R.HighestEndingAddress<>nil) then
|
|
if (REQ.LowestStartingAddress>=R.HighestEndingAddress) then
|
|
begin
|
|
//oof
|
|
Exit;
|
|
end;
|
|
|
|
P.Pointer:=@REQ;
|
|
data[i]:=P;
|
|
used:=True;
|
|
end;
|
|
else
|
|
begin
|
|
data[i]:=P;
|
|
end;
|
|
end; //case
|
|
|
|
end; //for
|
|
|
|
if (not used) then
|
|
begin
|
|
if (ECounts=Length(data)) then
|
|
begin
|
|
//oof
|
|
Exit;
|
|
end;
|
|
|
|
i:=ECounts;
|
|
ECounts:=ECounts+1;
|
|
|
|
data[i]:=C_EXT;
|
|
end;
|
|
|
|
EParams:=@data;
|
|
end;
|
|
|
|
end;
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
procedure BaseInitializeStack(InitialTeb :PINITIAL_TEB;
|
|
StackAddress:Pointer;
|
|
StackSize :Ptruint); inline;
|
|
begin
|
|
InitialTeb^.PreviousStackBase :=nil;
|
|
InitialTeb^.PreviousStackLimit:=nil;
|
|
InitialTeb^.StackBase :=StackAddress+StackSize; //start addr
|
|
InitialTeb^.StackLimit :=StackAddress; //lo addr
|
|
InitialTeb^.AllocatedStackBase:=StackAddress; //DeallocationStack
|
|
end;
|
|
|
|
var
|
|
BaseThreadInitThunk:Pointer=nil; //ECX->0 RDX->StartRoutine R8->Argument
|
|
|
|
procedure BaseInitializeContext(Context :PCONTEXT;
|
|
Parameter :Pointer;
|
|
StartAddress:Pointer;
|
|
StackAddress:Pointer); inline;
|
|
begin
|
|
Context^:=Default(TCONTEXT);
|
|
|
|
if (BaseThreadInitThunk=nil) then
|
|
begin
|
|
BaseThreadInitThunk:=GetProcAddress(GetModuleHandle('kernel32.dll'),'BaseThreadInitThunk');
|
|
end;
|
|
|
|
// Setup the Initial Win64 Thread Context
|
|
Context^.Rsp:=ptruint(StackAddress - $A8);
|
|
Context^.Rdx:=ptruint(StartAddress);
|
|
Context^.R8 :=ptruint(Parameter);
|
|
Context^.Rip:=ptruint(BaseThreadInitThunk);
|
|
|
|
Context^.SegGs:=KGDT64_R3_DATA or RPL_MASK;
|
|
Context^.SegEs:=KGDT64_R3_DATA or RPL_MASK;
|
|
Context^.SegDs:=KGDT64_R3_DATA or RPL_MASK;
|
|
Context^.SegCs:=KGDT64_R3_CODE or RPL_MASK;
|
|
Context^.SegSs:=KGDT64_R3_DATA or RPL_MASK;
|
|
Context^.SegFs:=KGDT64_R3_CMTEB or RPL_MASK;
|
|
|
|
Context^.EFlags:=$3000 or EFLAGS_INTERRUPT_MASK;
|
|
|
|
Context^.MxCsr:=__INITIAL_MXCSR__;
|
|
|
|
Context^.FltSave.ControlWord:=__INITIAL_FPUCW__;
|
|
//Context^.FltSave.StatusWord: WORD;
|
|
Context^.FltSave.MxCsr :=__INITIAL_MXCSR__;
|
|
Context^.FltSave.MxCsr_Mask :=__INITIAL_MXCSR_MASK__;
|
|
|
|
Context^.ContextFlags:=CONTEXT_THREAD;
|
|
//Context^.ContextFlags:=CONTEXT_CONTROL or CONTEXT_INTEGER or CONTEXT_SEGMENTS;
|
|
end;
|
|
|
|
function NtQueryTeb(td_handle:THandle;var teb:Pointer):Integer;
|
|
var
|
|
data:array[0..SizeOf(THREAD_BASIC_INFORMATION)-1+7] of Byte;
|
|
P_TBI:PTHREAD_BASIC_INFORMATION;
|
|
begin
|
|
Result:=0;
|
|
teb:=nil;
|
|
P_TBI:=Align(@data,8);
|
|
P_TBI^:=Default(THREAD_BASIC_INFORMATION);
|
|
|
|
Result:=NtQueryInformationThread(
|
|
td_handle,
|
|
ThreadBasicInformation,
|
|
P_TBI,
|
|
SizeOf(THREAD_BASIC_INFORMATION),
|
|
nil);
|
|
if (Result<>0) then Exit;
|
|
|
|
teb:=P_TBI^.TebBaseAddress;
|
|
end;
|
|
|
|
const
|
|
MinStackSize=$1000000;
|
|
|
|
function Inj_NtCreateThreadEx(
|
|
hThread :PHandle;
|
|
DesiredAccess :ACCESS_MASK;
|
|
ObjectAttributes:POBJECT_ATTRIBUTES;
|
|
ProcessHandle :THandle;
|
|
StartRoutine :Pointer;
|
|
Argument :Pointer;
|
|
CreateFlags :ULONG; // THREAD_CREATE_FLAGS_*
|
|
ZeroBits :ULONG_PTR;
|
|
StackSize :ULONG_PTR;
|
|
MaximumStackSize:ULONG_PTR;
|
|
AttributeList :PPS_ATTRIBUTE_LIST
|
|
):DWORD; stdcall;
|
|
var
|
|
|
|
_ClientId :array[0..SizeOf(TCLIENT_ID )+14] of Byte;
|
|
_InitialTeb:array[0..SizeOf(TINITIAL_TEB)+14] of Byte;
|
|
_Context :array[0..SizeOf(TCONTEXT )+14] of Byte;
|
|
|
|
ClientId :PCLIENT_ID;
|
|
InitialTeb:PINITIAL_TEB;
|
|
Context :PCONTEXT;
|
|
|
|
stack_base:Pointer;
|
|
Stack :Pointer;
|
|
|
|
teb :Pointer;
|
|
|
|
Attribute :PS_ATTRIBUTE;
|
|
|
|
a,count:Integer;
|
|
begin
|
|
|
|
if (ZeroBits<>0) then
|
|
begin
|
|
Result:=real_NtCreateThreadEx(
|
|
hThread ,
|
|
DesiredAccess ,
|
|
ObjectAttributes,
|
|
ProcessHandle ,
|
|
StartRoutine ,
|
|
Argument ,
|
|
CreateFlags ,
|
|
ZeroBits ,
|
|
StackSize ,
|
|
MaximumStackSize,
|
|
AttributeList
|
|
);
|
|
Exit;
|
|
end;
|
|
|
|
ClientId :=Align(@_ClientId ,16);
|
|
InitialTeb:=Align(@_InitialTeb,16);
|
|
Context :=Align(@_Context ,16);
|
|
|
|
ClientId^.UniqueProcess:=hThread^;
|
|
ClientId^.UniqueThread :=ProcessHandle;
|
|
|
|
if (MaximumStackSize<MinStackSize) then MaximumStackSize:=MinStackSize;
|
|
if (StackSize <MinStackSize) then StackSize :=MinStackSize;
|
|
if (StackSize <MaximumStackSize) then StackSize :=MaximumStackSize;
|
|
|
|
StackSize:=MinStackSize;
|
|
|
|
stack_base:=nil;
|
|
Result:=real_NtAllocateVirtualMemoryEx(
|
|
ProcessHandle ,
|
|
@stack_base ,
|
|
@StackSize ,
|
|
MEM_COMMIT or MEM_RESERVE,
|
|
PAGE_READWRITE ,
|
|
@C_EXT ,
|
|
1
|
|
);
|
|
if (Result<>0) then Exit;
|
|
|
|
BaseInitializeStack(InitialTeb,stack_base,StackSize);
|
|
|
|
Stack:=stack_base+StackSize;
|
|
Stack:=Pointer((ptruint(Stack) and (not $F)));
|
|
|
|
BaseInitializeContext(Context,
|
|
Argument,
|
|
StartRoutine,
|
|
Stack);
|
|
|
|
Result:=NtCreateThread(
|
|
hThread,
|
|
DesiredAccess,
|
|
ObjectAttributes,
|
|
ProcessHandle,
|
|
ClientId,
|
|
Context,
|
|
InitialTeb,
|
|
(CreateFlags and THREAD_CREATE_FLAGS_CREATE_SUSPENDED)<>0);
|
|
|
|
if (Result=0) and (AttributeList<>nil) then
|
|
begin
|
|
count:=AttributeList^.TotalLength div sizeof(PS_ATTRIBUTE);
|
|
|
|
if (count<>0) then
|
|
for a:=0 to count-1 do
|
|
begin
|
|
|
|
Attribute:=AttributeList^.Attributes[a];
|
|
|
|
case (Attribute.Attribute and PS_ATTRIBUTE_NUMBER_MASK) of
|
|
|
|
PsAttributeClientId:
|
|
if (Attribute.size<>0) and (Attribute.Value<>0) then
|
|
begin
|
|
if (Attribute.size>sizeof(TCLIENT_ID)) then Attribute.size:=sizeof(TCLIENT_ID);
|
|
Move(ClientId^,Pointer(Attribute.Value)^,Attribute.size);
|
|
if (Attribute.ReturnLength<>nil) then
|
|
begin
|
|
Attribute.ReturnLength^:=Attribute.size;
|
|
end;
|
|
end;
|
|
PsAttributeTebAddress:
|
|
if (Attribute.size<>0) and (Attribute.Value<>0) then
|
|
begin
|
|
if (Attribute.size>sizeof(Pointer)) then Attribute.size:=sizeof(Pointer);
|
|
teb:=nil;
|
|
if (NtQueryTeb(hThread^,teb)=0) then
|
|
begin
|
|
Move(teb,Pointer(Attribute.Value)^,Attribute.size);
|
|
if (Attribute.ReturnLength<>nil) then
|
|
begin
|
|
Attribute.ReturnLength^:=Attribute.size;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
else;
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
function Inj_NtMapViewOfSection(
|
|
SectionHandle :THandle;
|
|
ProcessHandle :THandle;
|
|
BaseAddress :PPointer;
|
|
ZeroBits :ULONG_PTR;
|
|
CommitSize :ULONG_PTR;
|
|
SectionOffset :PLARGE_INTEGER;
|
|
ViewSize :PULONG_PTR;
|
|
InheritDisposition:DWORD;
|
|
AllocationType :ULONG;
|
|
Protect :ULONG
|
|
):DWORD; stdcall;
|
|
begin
|
|
AllocationType:=AllocationType and (not MEM_TOP_DOWN);
|
|
|
|
if (ZeroBits=0) and
|
|
(ViewSize<>nil) and
|
|
(BaseAddress<>nil) then
|
|
begin
|
|
if (CommitSize=ViewSize^) and
|
|
(BaseAddress^=nil) then
|
|
begin
|
|
|
|
Result:=real_NtMapViewOfSectionEx(
|
|
SectionHandle ,
|
|
ProcessHandle ,
|
|
BaseAddress ,
|
|
SectionOffset ,
|
|
ViewSize ,
|
|
AllocationType,
|
|
Protect ,
|
|
@C_EXT ,
|
|
1
|
|
);
|
|
|
|
|
|
Exit;
|
|
end;
|
|
end;
|
|
|
|
Result:=real_NtMapViewOfSection(
|
|
SectionHandle ,
|
|
ProcessHandle ,
|
|
BaseAddress ,
|
|
ZeroBits ,
|
|
CommitSize ,
|
|
SectionOffset ,
|
|
ViewSize ,
|
|
InheritDisposition,
|
|
AllocationType ,
|
|
Protect
|
|
);
|
|
|
|
end;
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
function Inj_NtMapViewOfSectionEx(
|
|
SectionHandle :THandle;
|
|
ProcessHandle :THandle;
|
|
BaseAddress :PPointer;
|
|
SectionOffset :PLARGE_INTEGER;
|
|
ViewSize :PULONG_PTR;
|
|
AllocationType :ULONG;
|
|
Protect :ULONG;
|
|
ExtendedParameters :Pointer; //MEM_EXTENDED_PARAMETER
|
|
ExtendedParameterCount:ULONG
|
|
):DWORD; stdcall;
|
|
var
|
|
EXT:TEXT_PATCHER;
|
|
begin
|
|
AllocationType:=AllocationType and (not MEM_TOP_DOWN);
|
|
|
|
if (BaseAddress<>nil) then
|
|
if (BaseAddress^=nil) then
|
|
begin
|
|
EXT.Patch(ExtendedParameters,ExtendedParameterCount);
|
|
end;
|
|
|
|
Result:=real_NtMapViewOfSectionEx(
|
|
SectionHandle ,
|
|
ProcessHandle ,
|
|
BaseAddress ,
|
|
SectionOffset ,
|
|
ViewSize ,
|
|
AllocationType ,
|
|
Protect ,
|
|
ExtendedParameters ,
|
|
ExtendedParameterCount
|
|
);
|
|
|
|
end;
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
function Inj_NtAllocateVirtualMemory(
|
|
ProcessHandle :THandle;
|
|
BaseAddress :PPointer;
|
|
ZeroBits :ULONG_PTR;
|
|
RegionSize :PULONG_PTR;
|
|
AllocationType:ULONG;
|
|
Protect :ULONG
|
|
):DWORD; stdcall;
|
|
begin
|
|
AllocationType:=AllocationType and (not MEM_TOP_DOWN);
|
|
|
|
if (ZeroBits=0) and
|
|
(BaseAddress<>nil) then
|
|
begin
|
|
if (BaseAddress^=nil) then
|
|
begin
|
|
|
|
Result:=real_NtAllocateVirtualMemoryEx(
|
|
ProcessHandle ,
|
|
BaseAddress ,
|
|
RegionSize ,
|
|
AllocationType,
|
|
Protect ,
|
|
@C_EXT ,
|
|
1
|
|
);
|
|
|
|
Exit;
|
|
end;
|
|
end;
|
|
|
|
Result:=real_NtAllocateVirtualMemory(
|
|
ProcessHandle ,
|
|
BaseAddress ,
|
|
ZeroBits ,
|
|
RegionSize ,
|
|
AllocationType,
|
|
Protect
|
|
);
|
|
|
|
end;
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
function Inj_NtAllocateVirtualMemoryEx(
|
|
ProcessHandle :THandle;
|
|
BaseAddress :PPointer;
|
|
RegionSize :PULONG_PTR;
|
|
AllocationType :ULONG;
|
|
Protect :ULONG;
|
|
ExtendedParameters :Pointer; //MEM_EXTENDED_PARAMETER
|
|
ExtendedParameterCount:ULONG
|
|
):DWORD; stdcall;
|
|
|
|
var
|
|
EXT:TEXT_PATCHER;
|
|
begin
|
|
AllocationType:=AllocationType and (not MEM_TOP_DOWN);
|
|
|
|
if (BaseAddress<>nil) then
|
|
if (BaseAddress^=nil) then
|
|
begin
|
|
EXT.Patch(ExtendedParameters,ExtendedParameterCount);
|
|
end;
|
|
|
|
Result:=real_NtAllocateVirtualMemoryEx(
|
|
ProcessHandle ,
|
|
BaseAddress ,
|
|
RegionSize ,
|
|
AllocationType ,
|
|
Protect ,
|
|
ExtendedParameters ,
|
|
ExtendedParameterCount
|
|
);
|
|
|
|
end;
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
end.
|
|
|