fpPS4/rtl/stub_manager.pas
2022-05-31 10:20:10 +03:00

184 lines
3.2 KiB
ObjectPascal

unit stub_manager;
{$mode objfpc}{$H+}
interface
uses
Windows;
type
TStubMemory=object
protected
type
PNode=^TNode;
TNode=record
pNext:PNode;
Stub_va:Pointer;
end;
Const
VA_SIZE=16*1024;
var
pHead:PNode;
Stub_va:Pointer;
Stub_pos:Word;
procedure Push(P:Pointer);
function Pop:Pointer;
public
Procedure Clear;
procedure FinStub;
function NewStub(data:Pointer;size:Word):Pointer;
end;
TStubMemoryProc=object(TStubMemory)
function NewNopStub(nid:QWORD;lib,proc:Pointer):Pointer;
end;
implementation
procedure TStubMemory.Push(P:Pointer);
var
Node:PNode;
begin
Node:=AllocMem(SizeOf(TNode));
Node^.Stub_va:=P;
if (pHead=nil) then
begin
node^.pNext:=nil;
end else
begin
node^.pNext:=pHead;
end;
pHead:=node;
end;
function TStubMemory.Pop:Pointer;
var
Node:PNode;
begin
Result:=nil;
Node:=pHead;
if (pHead<>nil) then
begin
pHead:=pHead^.pNext;
end;
if (Node<>nil) then
begin
Node^.pNext:=nil;
end;
if (Node<>nil) then
begin
Result:=Node^.Stub_va;
FreeMem(Node);
end;
end;
Procedure TStubMemory.Clear;
var
P:Pointer;
begin
P:=Pop;
While (P<>nil) do
begin
VirtualFree(P,0,MEM_RELEASE);
P:=Pop;
end;
if (Stub_va<>nil) then
begin
VirtualFree(Stub_va,0,MEM_RELEASE);
end;
Stub_va:=nil;
Stub_pos:=0;
end;
procedure TStubMemory.FinStub;
var
dummy:DWORD;
begin
if (Stub_va<>nil) then
begin
Push(Stub_va);
//VirtualProtect(Stub_va,VA_SIZE,PAGE_EXECUTE_READ,@dummy);
FlushInstructionCache(GetCurrentProcess,Stub_va,VA_SIZE);
Stub_va:=nil;
Stub_pos:=0;
end;
end;
function TStubMemory.NewStub(data:Pointer;size:Word):Pointer;
begin
if ((Stub_pos+size)>VA_SIZE) then
FinStub;
if (Stub_va=nil) then
begin
Stub_va:=VirtualAlloc(nil,VA_SIZE,MEM_COMMIT or MEM_RESERVE,{PAGE_READWRITE}PAGE_EXECUTE_READWRITE);
end;
Result:=Stub_va+Stub_pos;
Move(data^,Result^,size);
Stub_pos:=Stub_pos+size;
end;
//
//52 push %rdx
//51 push %rcx
//48ba0100000000000000 movabs $0x1,%rdx
//48b90200000000000000 movabs $0x2,%rcx
//48b80300000000000000 movabs $0x3,%rax
//ffd0 callq *%rax
//4831c0 xor %rax,%rax
//59 pop %rcx
//5a pop %rdx
//c3 retq
Type
Pnopstub=^Tnopstub;
Tnopstub=packed record
_push_rdx:Byte; // $52
_push_rcx:Byte; // $51
_movabs_rdx:array[0..1] of Byte; // $48 $ba
_lib:Pointer;
_movabs_rcx:array[0..1] of Byte; // $48 $B9
_nid:QWord;
_movabs_rax:array[0..1] of Byte; // $48 $B8
_addr:Pointer;
_call_rax:array[0..1] of Byte; // $FF $D0
_pop_rcx:Byte; // $59
_pop_rdx:Byte; // $5A
_ret:Byte; // $C3
end;
const
_nopstub:Tnopstub=(
_push_rdx:$52;
_push_rcx:$51;
_movabs_rdx:($48,$BA);
_lib:nil;
_movabs_rcx:($48,$B9);
_nid:0;
_movabs_rax:($48,$B8);
_addr:nil;
_call_rax:($FF,$D0);
_pop_rcx:$59;
_pop_rdx:$5A;
_ret:$C3
);
function TStubMemoryProc.NewNopStub(nid:QWORD;lib,proc:Pointer):Pointer;
var
nopstub:Tnopstub;
begin
nopstub:=_nopstub;
nopstub._lib:=lib;
nopstub._nid:=nid;
nopstub._addr:=proc;
Result:=NewStub(@nopstub,SizeOf(Tnopstub));
end;
end.