unit ProtectMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, ImageHlp, Mask, Spin;
type
TForm1 = class(TForm)
Memo1: TMemo;
BitBtn1: TBitBtn;
BitBtn2: TBitBtn;
BitBtn3: TBitBtn;
OpenDialog1: TOpenDialog;
SpinEdit1: TSpinEdit;
procedure BitBtn2Click(Sender: TObject);
procedure BitBtn3Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure BitBtn1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
LoadedImage:TLoadedImage;
Mapped:boolean;
ImageBase:longword;
EntryRVA,EntryVA:longword;
ImportRVA,ImportATRVA:longword;
FileAlign,SectAlign:longword;
HeaderFree,HeaderOffset:longword;
ImageSize,FileSize:longword;
CodeSize,ImportSize,ImportATSize:longword;
SectionCount:longword;
procedure DoUnmap;
function DoAlign(Size,Align:longword):longword;
function DoSize(Size,Align:longword):longword;
end;
TMyCode=packed record
{My code}
Push:byte;{+0}
DataRVA:longword;{+1}
CallCanRunGame:word;{+5}
CanRunGameVA:longword;{+7}
OrEAXEAX:word;{+11}
JneOldEP:word;{+13}
OldEntryPointRA:longword;{+15}
PushEAX:byte;{+19}
CallExitProcess:word;{+20}
ExitProcessVA:longword;{+22}
{My data}
ImportRVA:longword;{+26}
ImportSize:longword;
ImportATRVA:longword;
ImportATSize:longword;
EntryRVA:longword;
ImageSize:longword;
CheckSum:longword;
VirtCDID:longword;
{My import}
KernelILT:longword;{+54}
KernelTimeDate:longword;
KernelChain:longword;
KernelName:longword;
KernelIAT:longword;
RunGameILT:longword;{+74}
RunGameTimeDate:longword;
RunGameChain:longword;
RunGameName:longword;
RunGameIAT:longword;
NullILT:longword;{+94}
NullTimeDate:longword;
NullChain:longword;
NullName:longword;
NullIAT:longword;
ExitProcessIAT:longword;{+114}
KernelNullIAT:longword;{+118}
CanRunGameIAT:longword;{+122}
RunGameNullIAT:longword;{+126}
ExitProcessILT:longword;{+130}
KernelNullILT:longword;{+134}
CanRunGameILT:longword;{+138}
RunGameNullILT:longword;{+142}
DllKernel:array[0..13] of char;{Kernel32.dll__}{+146}
DllRunGame:array[0..13] of char;{RunGame32.dll_}{+160}
ExitProcessHint:word;{+174}
ExitProcessName:array[0..11] of char;{ExitProcess_}{+176}
CanRunGameHint:word;{+188}
CanRunGameName:array[0..11] of char;{CanRunGame__}{+190}
{+202}
end;
const
PushOffset=$68;
CallPtr=$15ff;
CallRel=$E8;
OrEaxEax=$C009;
JneRel=$850f;
PushEax=$50;
{DataRVA=OurRVA+DataOffset}
{DataOffset=26;}
{ExitProcessIAT=ImageBase+OurRVA+ExitProcessIATOffset}
{ExitProcessIATOffset=114;}
{CanRunGameIAT=ImageBase+OurRVA+CanRunGameIATOffset}
{CanRunGameIATOffset=122;}
{OldEntryPointRA=OldEntryPointRVA-(OurRVA+OldEntryPointOffset}
{OldEntryPointOffset=19;}
{ExitProcessIAT=ExitProcessILT=OurRVA+ExitProcessOffset}
{ExitProcessOffset=174;}
{CanRunGameIAT=CanRunGameILT=OurRVA+CanRunGameOffset}
{CanRunGameOffset=188;}
{KernelILT=OurRVA+KernelILTOffset}
{KernelILTOffset=130;}
{KernelIAT=OurRVA+KernelIATOffset}
{KernelIATOffset=114;}
{RunGameILT=OurRVA+RunGameILTOffset}
{RunGameILTOffset=138;}
{RunGameIAT=OurRVA+RunGameIATOffset}
{RunGameIATOffset=122;}
{KernelName=OurRVA+KernelNameOffset}
{KernelNameOffset=146;}
{RunGameName=OurRVA+RunGameNameOffset}
{RunGameNameOffset=160;}
{OurImportOffset=54;
OurImportSize=202-54;
OurImportATOffset=114;
OurImportATSize=130-114;}
SectName:array[0..7] of char='.gameprt';
TM_OK=' Ok';
TM_NOK=' !!!';
var
Form1: TForm1;
MyCode:TMyCode=(
Push:PushOffset;
CallCanRunGame:CallPtr;
OrEaxEax:OrEaxEax;
JneOldEP:JneRel;
PushEax:PushEax;
CallExitProcess:CallPtr;
DllKernel:'Kernel32.dll'+Chr(0);
DllRunGame:'RunGame32.dll'+Chr(0);
ExitProcessName:'ExitProcess'+Chr(0);
CanRunGameName:'CanRunGame'+Chr(0)+Chr(0);
);
DataOffset,
ExitProcessIATOffset,
CanRunGameIATOffset,
OldEntryPointOffset,
ExitProcessOffset,
CanRunGameOffset,
KernelILTOffset,
KernelIATOffset,
RunGameILTOffset,
RunGameIATOffset,
KernelNameOffset,
RunGameNameOffset,
OurImportOffset,
OurImportSize,
OurImportATOffset,
OurImportATSize
:longword;
implementation
{$R *.dfm}
function GetOffset(Org,Dest:pointer):longword;
begin
Result:=longword(Dest)-longword(Org);
end;
function GetSize(Org,Dest:pointer;Size:longword):longword;
begin
Result:=longword(Dest)-longword(Org)+Size;
end;
procedure TForm1.DoUnmap;
begin
UnmapAndLoad(@LoadedImage);
end;
procedure TForm1.BitBtn2Click(Sender: TObject);
begin
Close;
end;
procedure TForm1.BitBtn3Click(Sender: TObject);
var Temp:string;
begin
if Mapped then DoUnmap;
Memo1.Clear;
Memo1.Lines.Add('Selecting image file...');
ForceCurrentDirectory:=true;
if not OpenDialog1.Execute then Exit;
Memo1.Lines.Add('Trying to load image file...');
if not MapAndLoad(PChar(OpenDialog1.FileName),nil,@LoadedImage,false,false) then begin
Memo1.Lines.Add('**Error**:Can not load '+OpenDialog1.FileName);
Exit;
end;
Memo1.Lines.Add('Getting information...');
Memo1.Lines.Add(StringOfChar('-',120));
Memo1.Lines.Add('Image file status:');
Memo1.Lines.Add(StringOfChar('-',120));
ImageBase:=LoadedImage.FileHeader.OptionalHeader.ImageBase;
Memo1.Lines.Add('Image base'+StringOfChar(Chr(9),4)+IntToHex(ImageBase,8));
EntryRVA:=LoadedImage.FileHeader.OptionalHeader.AddressOfEntryPoint;
EntryVA:=ImageBase+EntryRVA;
Memo1.Lines.Add('Entry RVA/VA'+StringOfChar(Chr(9),4)+
IntToHex(EntryRVA,8)+'/'+IntToHex(EntryVA,8));
FileAlign:=LoadedImage.FileHeader.OptionalHeader.FileAlignment;
SectAlign:=LoadedImage.FileHeader.OptionalHeader.SectionAlignment;
Memo1.Lines.Add('File/Section alignment'+StringOfChar(Chr(9),3)+
IntToHex(FileAlign,8)+'/'+IntToHex(SectAlign,8));
HeaderOffset:=GetImageUnusedHeaderBytes(@LoadedImage,HeaderFree);
if HeaderFree>=IMAGE_SIZEOF_SECTION_HEADER then Temp:=TM_OK else Temp:=TM_NOK;
Memo1.Lines.Add('Header free space/Required free space'
+Chr(9)+Chr(9)+IntToStr(HeaderFree)+'/'
+IntToStr(IMAGE_SIZEOF_SECTION_HEADER)+StringOfChar(Chr(9),2)+Temp);
ImageSize:=LoadedImage.FileHeader.OptionalHeader.SizeOfImage;
CodeSize:=LoadedImage.FileHeader.OptionalHeader.SizeOfCode;
ImportSize:=LoadedImage.FileHeader.OptionalHeader.DataDirectory[1].Size;
ImportATSize:=LoadedImage.FileHeader.OptionalHeader.DataDirectory[12].Size;
FileSize:=SetFilePointer(LoadedImage.hFile,0,nil,FILE_END);
Memo1.Lines.Add('Image size/File size'+StringOfChar(Chr(9),4)+
IntToHex(ImageSize,8)+'/'+IntToHex(FileSize,8));
Memo1.Lines.Add('Code size/Import size'+StringOfChar(Chr(9),3)+
IntToHex(CodeSize,8)+'/'+IntToHex(ImportSize,8));
SectionCount:=LoadedImage.FileHeader.FileHeader.NumberOfSections;
Memo1.Lines.Add('Section count'+StringOfChar(Chr(9),5)+IntToStr(SectionCount));
ImportRVA:=LoadedImage.FileHeader.OptionalHeader.DataDirectory[1].VirtualAddress;
ImportATRVA:=LoadedImage.FileHeader.OptionalHeader.DataDirectory[12].VirtualAddress;
BitBtn1.Enabled:=true;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
if Mapped then DoUnmap;
end;
procedure TForm1.BitBtn1Click(Sender: TObject);
var MyFile:THandle;
MyMapping:THandle;
PhysSize,VirtSize:longword;
Data:pointer;
OurRVA:longword;
I:integer;
MySection:PImageSectionHeader;
CDID:longword;
begin
try
CDID:=StrToInt(SpinEdit1.Text);
except
Exit;
end;
DataOffset:=GetOffset(@MyCode,@MyCode.ImportRVA);
ExitProcessIATOffset:=GetOffset(@MyCode,@MyCode.ExitProcessIAT);
CanRunGameIATOffset:=GetOffset(@MyCode,@MyCode.CanRunGameIAT);
OldEntryPointOffset:=GetOffset(@MyCode,@MyCode.PushEAX);
ExitProcessOffset:=GetOffset(@MyCode,@MyCode.ExitProcessHint);
CanRunGameOffset:=GetOffset(@MyCode,@MyCode.CanRunGameHint);
KernelILTOffset:=GetOffset(@MyCode,@MyCode.ExitProcessILT);
KernelIATOffset:=GetOffset(@MyCode,@MyCode.ExitProcessIAT);
RunGameILTOffset:=GetOffset(@MyCode,@MyCode.CanRunGameILT);
RunGameIATOffset:=GetOffset(@MyCode,@MyCode.CanRunGameIAT);
KernelNameOffset:=GetOffset(@MyCode,@MyCode.DllKernel);
RunGameNameOffset:=GetOffset(@MyCode,@MyCode.DllRunGame);
OurImportOffset:=GetOffset(@MyCode,@MyCode.KernelILT);
OurImportATOffset:=GetOffset(@MyCode,@MyCode.ExitProcessIAT);
OurImportSize:=GetSize(@MyCode.KernelILT,@MyCode.CanRunGameName,SizeOf(MyCode.CanRunGameName));
OurImportATSize:=GetSize(@MyCode.ExitProcessIAT,@MyCode.RunGameNullIAT,SizeOf(MyCode.RunGameNullIAT));
MyFile:=LoadedImage.hFile;
PhysSize:=FileAlign*DoAlign(SizeOf(MyCode),FileAlign);
VirtSize:=SectAlign*DoAlign(SizeOf(MyCode),SectAlign);
FileSize:=DoSize(FileSize,FileAlign);
MyCode.ImageSize:=ImageSize;
ImageSize:=DoSize(ImageSize,SectAlign);
OurRVA:=ImageSize;
MyCode.DataRVA:=OurRVA+DataOffset;
MyCode.ImportRVA:=ImportRVA;
MyCode.ImportSize:=ImportSize;
if ((ImportATRVA=0) or (ImportATSize=0)) then begin
MySection:=ImageRVAToSection(LoadedImage.FileHeader,LoadedImage.MappedAddress,ImportRVA);
MyCode.ImportATRVA:=MySection.VirtualAddress;
MyCode.ImportATSize:=MySection.Misc.VirtualSize;
end
else begin
MyCode.ImportATRVA:=ImportATRVA;
MyCode.ImportATSize:=ImportATSize;
end;
MyCode.EntryRVA:=EntryRVA;
MyCode.CheckSum:=LoadedImage.FileHeader.OptionalHeader.CheckSum;
MyCode.ExitProcessVA:=ImageBase+OurRVA+ExitProcessIATOffset;
MyCode.CanRunGameVA:=ImageBase+OurRVA+CanRunGameIATOffset;
MyCode.OldEntryPointRA:=EntryRVA-(OurRVA+OldEntryPointOffset);
MyCode.VirtCDID:=CDID;
MyCode.ExitProcessIAT:=OurRVA+ExitProcessOffset;
MyCode.ExitProcessILT:=MyCode.ExitProcessIAT;
MyCode.CanRunGameIAT:=OurRVA+CanRunGameOffset;
MyCode.CanRunGameILT:=MyCode.CanRunGameIAT;
MyCode.KernelILT:=OurRVA+KernelILTOffset;
MyCode.KernelIAT:=OurRVA+KernelIATOffset;
MyCode.KernelName:=OurRVA+KernelNameOffset;
MyCode.RunGameILT:=OurRVA+RunGameILTOffset;
MyCode.RunGameIAT:=OurRVA+RunGameIATOffset;
MyCode.RunGameName:=OurRVA+RunGameNameOffset;
UnmapViewOfFile(LoadedImage.MappedAddress);
SetFilePointer(MyFile,FileSize+PhysSize,nil,FILE_BEGIN);
SetEndOfFile(MyFile);
MyMapping:=CreateFileMapping(MyFile,nil,PAGE_READWRITE,0,0,nil);
Data:=MapViewOfFile(MyMapping,FILE_MAP_ALL_ACCESS,0,0,0);
LoadedImage.MappedAddress:=Data;
Inc(longword(Data),FileSize);
ZeroMemory(Data,PhysSize);
CopyMemory(Data,@MyCode,SizeOf(MyCode));
longword(MySection):=longword(LoadedImage.Sections)+
SizeOf(TImageSectionHeader)*LoadedImage.NumberOfSections;
for I:=0 to 7 do
MySection.Name[I]:=byte(SectName[I]);
MySection.Misc.VirtualSize:=SizeOf(MyCode);
MySection.VirtualAddress:=ImageSize;
MySection.SizeOfRawData:=PhysSize;
MySection.PointerToRawData:=FileSize;
MySection.PointerToRelocations:=0;
MySection.PointerToLinenumbers:=0;
MySection.NumberOfRelocations:=0;
MySection.NumberOfLinenumbers:=0;
MySection.Characteristics:=
IMAGE_SCN_CNT_CODE or IMAGE_SCN_MEM_EXECUTE or IMAGE_SCN_MEM_READ;
Inc(LoadedImage.NumberOfSections);
LoadedImage.SizeOfImage:=ImageSize+VirtSize;
Inc(LoadedImage.FileHeader.FileHeader.NumberOfSections);
LoadedImage.FileHeader.OptionalHeader.AddressOfEntryPoint:=OurRVA;
LoadedImage.FileHeader.OptionalHeader.SizeOfImage:=ImageSize+VirtSize;
LoadedImage.FileHeader.OptionalHeader.DataDirectory[1].VirtualAddress:=OurRVA+OurImportOffset;
LoadedImage.FileHeader.OptionalHeader.DataDirectory[1].Size:=OurImportSize;
LoadedImage.FileHeader.OptionalHeader.DataDirectory[12].VirtualAddress:=OurRVA+OurImportATOffset;
LoadedImage.FileHeader.OptionalHeader.DataDirectory[12].Size:=OurImportATSize;
LoadedImage.FileHeader.OptionalHeader.CheckSum:=0;
BitBtn1.Enabled:=false;
end;
function TForm1.DoAlign(Size,Align:longword):longword;
begin
Result:=1;
while (Size>(Result*Align)) do Inc(Result);
end;
function TForm1.DoSize(Size,Align:longword):longword;
begin
if (Size mod Align)<>0 then
Result:=Size+Align-(Size mod Align)
else Result:=Size;
end;
end.