mirror of
https://github.com/red-prig/fpPS4.git
synced 2024-11-27 00:20:36 +00:00
184 lines
3.2 KiB
ObjectPascal
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.
|
|
|