Welcome!

Join our community of MMO enthusiasts and game developers! By registering, you'll gain access to discussions on the latest developments in MMO server files and collaborate with like-minded individuals. Join us today and unlock the potential of MMO server development!

Join Today!

HE - HookEngine

NN - Nord & Noob
Loyal Member
Joined
Jul 15, 2004
Messages
1,207
Reaction score
689



Code:
unit uSection;

{
http://rce.su/пишем-криптор-на-delphi-исходник-криптора/
http://www.xakep.ru/post/19658/default.asp?print=true
}

interface

uses
  Windows, Classes, SysUtils, uTypes, uCodeSize;

function AddSection(FileName: string; Info: PRecInfo; SectionSize: Word): Boolean;

var
 LOAD_ORION_NEW: array [0 .. 50] of Byte = (
 $68,                   // PUSH
 $1A, $5E, $75, $00,    // main_exe.00755E1A          Orion.dll
 $FF, $15,              // CALL
 $7C, $62, $75, $00,    // DWORD PTR DS:[75627C]      LoadLibraryA  7
 $85, $C0,              // TEST EAX,EAX
 $74, $00,              // JE SHORT main_exe.0920200F
 $68,                   // PUSH
 $25, $5E, $75, $00,    // main_exe.00755E25          Initialize
 $50,                   // PUSH EAX
 $FF, $15,              // CALL
 $78, $64, $75, $00,    // DWORD PTR DS:[756278]      GetProcessAddress 23
 $85, $C0,              // TEST EAX,EAX
 $74, $10,              // JE SHORT main_exe.0920202F
 $FF, $D0,              // CALL EAX                   Call Initialize
 $6A, $10,              // PUSH 10
 $68,                   // PUSH
 $FC, $5D, $75, $00,    // main_exe.00755DFC          Caption   36
 $68,                   // PUSH
 $C0, $5D, $75, $00,    // main_exe.00755DC0          Content   41
 $FF, $15,              // CALL
 $50, $13, $75, $00);   // DWORD PTR DS:[756350]      MessageBoxA

 LOAD_ORION: array [0 ..59] of Byte = (
 $68,                   // PUSH
 $00, $34, $20, $09,    // main_exe.00755E1A          Orion.dll
 $FF, $15,              // CALL
 $08, $12, $8D, $00,    // DWORD PTR DS:[75627C]      LoadLibraryA  7
 $85, $C0,              // TEST EAX,EAX
 $74, $17,              // JE 17 Bytes    14
 $68,                   // PUSH
 $10, $34, $20, $09,    // main_exe.00755E25          Initialize
 $50,                   // PUSH EAX
 $FF, $15,              // CALL
 $04, $12, $8D, $00,    // DWORD PTR DS:[756278]      GetProcessAddress 23
 $85, $C0,              // TEST EAX,EAX
 $74, $07,              // JE 7 bytes
 $FF, $D0,              // CALL EAX
 $E9,                   // JMP
 $C6, $EB, $69, $F7,    // OEP OFFSET   34
 $6A, $10,              // PUSH 10
 $68,                   // PUSH
 $40, $34, $20, $09,    // Header offset   42
 $68,                   // PUSH
 $20, $34, $20, $09,    // Content offset
 $6A, $00,              // PUSH 0
 $FF, $15,              // CALL
 $50, $13, $75, $00,    // MESSAGEBOXA   55
 $C3,
 $90
 );

implementation

{$REGION 'Functions'}

function GetFieldOffset(const Struc; const Field): Cardinal; stdcall;
begin
  Result := Cardinal(@Field) - Cardinal(@Struc);
end;

function GetImageFirstSection(NtHeader: PImageNtHeaders): PImageSectionHeader; stdcall;
begin
 Result := PImageSectionHeader(Cardinal(NtHeader) +
    GetFieldOffset(NtHeader^, NtHeader^.OptionalHeader) +
    NtHeader^.FileHeader.SizeOfOptionalHeader);
end;

function PEAlign(Num, AlignTo: DWORD):DWORD;
begin
  while (Num mod AlignTo) <> 0 do
   inc(Num);
  Result := Num;
end;

function Align(dwValue:DWORD; dwAlign:DWORD):DWORD;
begin
 if dwAlign <> 0 then
  begin
   if dwValue mod dwAlign <> 0 then
    begin
     Result := (dwValue + dwAlign) - (dwValue mod dwAlign);
     Exit;
    end;
  end;
  Result := dwValue;
end;

function LastSectionRaw(Sections: array of TImageSectionHeader):DWORD;
var
 i:    integer;
 Ret:  DWORD;
begin
 Ret := 0;
 for i := Low(Sections) to High(Sections) do
  begin
   if Sections[i].SizeOfRawData + Sections[i].PointerToRawData > Ret then
    Ret := Sections[i].SizeOfRawData + Sections[i].PointerToRawData;
  end;
 Result := Ret;
end;

function LastSectionVirtual(Sections: array of TImageSectionHeader):DWORD;
var
 i:   integer;
 Ret: DWORD;
begin
 Ret := 0;
 for i := Low(Sections) to High(Sections) do
  begin
   if Sections[i].Misc.VirtualSize + Sections[i].VirtualAddress > Ret then
    Ret := Sections[i].Misc.VirtualSize + Sections[i].VirtualAddress;
  end;
  Result := Ret;
end;

function GetSection(NTHeader: PImageNtHeaders; Section: word):PImageSectionHeader;
var
 Adr: DWORD;
begin
  Adr := Integer(NTHeader)+SizeOf(IMAGE_NT_HEADERS)+(Section-1)*SizeOf(IMAGE_SECTION_HEADER);
  Result := Ptr(Adr);
end;

function RAWToSection(Head: PImageNtHeaders; RAW: DWORD):PImageSectionHeader;
var i: integer;
    Section: PImageSectionHeader;
begin
  Section := nil;
  for i:=1 to Head.FileHeader.NumberOfSections do
  begin
    Section := GetSection(Head, i);
    if Section.PointerToRawData>RAW then
     begin
      result := GetSection(Head, i-1);
      exit;
     end;
  end;
  Result := Section; // most probably the last section...
end;

function RVAToSection(Head: PImageNtHeaders; RVA: DWORD):PImageSectionHeader;
// this is because ImageRVAToSection exported from
// imagehlp.dll sucks. Sucks a lot. And doesn't work...
var i: integer;
    Section: PImageSectionHeader;
begin
  Section:=nil;
  for i:=1 to Head.FileHeader.NumberOfSections do
  begin
    Section:=GetSection(Head, i);
    if Section.VirtualAddress>RVA then
    begin
      result:=GetSection(Head, i-1);
      exit;
    end;
  end;
  Result:=Section; // most probably the last section...
end;

function RVAToRAW(Head: PImageNtHeaders; RVA: DWORD):DWORD;
var s: PImageSectionHeader;
begin
  s:= RVAToSection(Head, RVA);
  Result:=RVA - s.VirtualAddress + s.PointerToRawData;
end;

function RAWToRVA(Head: PImageNtHeaders; RAW: DWORD):DWORD;
var s: PImageSectionHeader;
begin
  s:=RAWToSection(Head, RAW);
  Result:=RAW-s.PointerToRawData+s.VirtualAddress;
end;

function GetImageNTHeaders(Address: DWORD):PImageNtHeaders;
var NewHeader: PWord;
begin
  NewHeader:=Ptr(Address+$3C);     // Position of PE header
  result:=Ptr(NewHeader^+Address); // Map it to IMAGE_NT_HEADERS
  if PDWORD(Result)^<>IMAGE_NT_SIGNATURE then
     result:=nil;
end;

function WriteBuffer(Buffer,Data: TBytes): TBytes;
begin
 SetLength(Result, Length(Buffer) + 5);
 Move(Buffer, Result, Length(Buffer));
 Move(Result[Length(Buffer)], Data[0], 5);
end;

procedure Obfuscate(Head: PImageSectionHeader);
begin
 Head.PointerToRawData := Head.PointerToRawData + $100;
end;

{$ENDREGION}

function AddSection(FileName: string;  Info: PRecInfo; SectionSize: Word): Boolean;
var
 Fs: TFileStream;
 ImgDosHdr: TImageDosHeader;
 NtImgDosHdr: TImageNtHeaders;
 ImportDesc: PImageImportDescriptor;
 Sections: TArray<TImageSectionHeader>;
 SectionsCount: Word;
 Buffer: TBytes;
 i: Integer;
 x: Cardinal;
 PointerIAT: DWORD;
 FTunk: Cardinal;
 FLoadLibrary, FMessageBox, FGetProcAddress: Cardinal;
 OEP: Cardinal;

{$REGION 'More Functions T_T'}

function GetSectionIndex(dwAddr: DWORD): DWORD;
var
	i: Integer;
begin
 for i := 0 to NtImgDosHdr.FileHeader.NumberOfSections -1 do
  if (dwAddr >= Sections[i].VirtualAddress) and (dwAddr < Sections[i].VirtualAddress + Sections[i].Misc.VirtualSize) then
   begin
	  Result := i;
		break;
   end;
end;

function RVAToOffset(dwRVA: DWORD): DWORD;
var
	sIndex: DWORD;
begin
	sIndex := GetSectionIndex(dwRVA);
	Result := Sections[sIndex].PointerToRAWData - Sections[sIndex].VirtualAddress + dwRVA;
end;

function RVA2RAW(Addr: DWORD; SectionHeaders: TArray<TImageSectionHeader>): DWORD;
var
  i: Integer;
begin
  Result := 0;
  for i:=0 to length(SectionHeaders)-1 do
  if (SectionHeaders[i].VirtualAddress <= Addr) and (SectionHeaders[i].VirtualAddress+SectionHeaders[i].Misc.VirtualSize > Addr) then
  begin
    Result := Addr - SectionHeaders[i].VirtualAddress + SectionHeaders[i].PointerToRawData;
    break;
  end;
end;

function RvaOfNewSection(Rva,LastRva,SizeLast: Word): Dword;
begin
 Result := (Rva - LastRva) + SizeLast;
end;

procedure ASMJmpOEP();
asm
 mov eax, 0FFFFFFFFh
 jmp eax
end;

{$ENDREGION}

begin
 Result := False;

 try
  Fs := TFileStream.Create(FileName,fmOpenRead);
   try
    SetLength(Buffer, Fs.Size);
    Fs.ReadBuffer(Buffer[0],Length(Buffer));

    Fs.Position := 0;
    if Fs.Read(ImgDosHdr, 64) <> 64 then
     Exit;

    Fs.Position := ImgDosHdr._lfanew;
    if Fs.Read(NtImgDosHdr, 248) <> 248 then
     Exit;

   finally
    Fs.Free;
   end;


  if ImgDosHdr.e_magic = IMAGE_DOS_SIGNATURE then
   if NtImgDosHdr.Signature = IMAGE_NT_SIGNATURE then
    begin

     SectionsCount := NtImgDosHdr.FileHeader.NumberOfSections;
     SetLength(Sections, SectionsCount);

     x := ImgDosHdr._lfanew + 24 + NtImgDosHdr.FileHeader.SizeOfOptionalHeader;

     for i := low(Sections) to high(Sections) do
      begin
       Move(Buffer[x], Sections[i] ,40);
       Inc(x, 40);
      end;

   if NtImgDosHdr.OptionalHeader.SizeOfHeaders >= (x + 40) then
    begin
     Inc(NtImgDosHdr.FileHeader.NumberOfSections, 1);
     SetLength(Sections, NtImgDosHdr.FileHeader.NumberOfSections);

      with Sections[NtImgDosHdr.FileHeader.NumberOfSections] do
       begin
        FillChar(Name, SizeOf(Name), #0);
        Name[0] :=  Ord('.');
        Name[1] :=  Ord('O');
        Name[2] :=  Ord('r');
        Name[3] :=  Ord('i');
        Name[4] :=  Ord('o');
        Name[5] :=  Ord('n');
        Characteristics  := $E0000060;
        PointerToRawData := Align(LastSectionRaw(Sections), NtImgDosHdr.OptionalHeader.FileAlignment);
        SizeOfRawData    := Align(SectionSize, NtImgDosHdr.OptionalHeader.FileAlignment);
        VirtualAddress   := Align(LastSectionVirtual(Sections), NtImgDosHdr.OptionalHeader.SectionAlignment);
        Misc.VirtualSize := Align(SectionSize, NtImgDosHdr.OptionalHeader.SectionAlignment);
       end;
     end;

    ImportDesc := @Buffer[RVAToOffset(NtImgDosHdr.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)];
     if ASSIGNED(ImportDesc) then
      begin
       with NtImgDosHdr.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] do
        begin
         repeat
         if Size > 0 then
          begin
           PointerIAT := RVA2RAW(ImportDesc.FirstThunk, Sections);
           FTunk := importDesc.FirstThunk ;
           repeat

             if Pos('LoadLibraryA', PAnsiChar(@Buffer[RVA2RAW(pdword(@Buffer[PointerIAT])^ +2, Sections)])) > 0 then
               FLoadLibrary := FTunk + NtImgDosHdr.OptionalHeader.ImageBase;
             if Pos('GetProcAddress', PAnsiChar(@Buffer[RVA2RAW(pdword(@Buffer[PointerIAT])^ +2, Sections)])) > 0 then
               FGetProcAddress := FTunk + NtImgDosHdr.OptionalHeader.ImageBase;
             if Pos('MessageBoxA', PAnsiChar(@Buffer[RVA2RAW(pdword(@Buffer[PointerIAT])^ +2, Sections)])) > 0 then
               FMessageBox := FTunk + NtImgDosHdr.OptionalHeader.ImageBase;

            inc(PointerIAT, 4);
            Inc(FTunk,4);
           until (PDword(@Buffer[PointerIAT])^ = 0);
          end;
          ImportDesc := ptr(dword(ImportDesc) + SizeOf(TImageImportDescriptor));
         until (ImportDesc.OriginalFirstThunk = 0) and (ImportDesc.Name = 0);
        end;
       end;

     NtImgDosHdr.OptionalHeader.DataDirectory[11].VirtualAddress := 0;
     NtImgDosHdr.OptionalHeader.DataDirectory[11].Size := 0;
     Inc(NtImgDosHdr.OptionalHeader.SizeOfImage, Sections[NtImgDosHdr.FileHeader.NumberOfSections].Misc.VirtualSize);

     OEP := NtImgDosHdr.OptionalHeader.AddressOfEntryPoint +  NtImgDosHdr.OptionalHeader.ImageBase;
//      Mainam OEP -> uz jauno EP:)
     NtImgDosHdr.OptionalHeader.AddressOfEntryPoint := Sections[NtImgDosHdr.FileHeader.NumberOfSections].VirtualAddress;

     Move(NtImgDosHdr, Buffer[ImgDosHdr._lfanew], 248);
     Move(Sections[NtImgDosHdr.FileHeader.NumberOfSections], Buffer[x], 40);

     SectionSize := Align(SectionSize, NtImgDosHdr.OptionalHeader.FileAlignment);
     SetLength(Buffer, Length(Buffer) + SectionSize);

//      Mainam IAT pirms rakstam

     Move(Info^.DLL[0],Info^.WriteBytes[Length(LOAD_ORION) + 1], Length(Info^.DLL));
     Move(Info^.Hdr[0],Info^.WriteBytes[Length(Info^.DLL) + Length(LOAD_ORION) + 2], Length(Info^.Hdr));
     Move(Info^.Content[0],Info^.WriteBytes[Length(Info^.DLL) + Length(Info^.Hdr) + Length(LOAD_ORION) + 3], Length(Info^.Content));

     if Info^.CallApi then
      begin
       Move(Info^.API[0],Info^.WriteBytes[Length(Info^.DLL) + Length(Info^.Hdr) +  Length(Info^.Content) + Length(LOAD_ORION) + 4], Length(Info^.API));   // Add API name
       PDWORD(@LOAD_ORION[1])^  := (NtImgDosHdr.OptionalHeader.AddressOfEntryPoint + NtImgDosHdr.OptionalHeader.ImageBase) + (Length(LOAD_ORION) + 1);   //DLL Name
       PDWORD(@LOAD_ORION[16])^ := (NtImgDosHdr.OptionalHeader.AddressOfEntryPoint + NtImgDosHdr.OptionalHeader.ImageBase) + (Length(Info^.DLL) + Length(LOAD_ORION) + Length(Info^.Hdr) + Length(Info^.Content)  + 4);   //API Name position
       PDWORD(@LOAD_ORION[41])^ := (NtImgDosHdr.OptionalHeader.AddressOfEntryPoint + NtImgDosHdr.OptionalHeader.ImageBase) + (Length(Info^.DLL) + Length(LOAD_ORION) + 2);  //Message header
       PDWORD(@LOAD_ORION[46])^ := (NtImgDosHdr.OptionalHeader.AddressOfEntryPoint + NtImgDosHdr.OptionalHeader.ImageBase) + (Length(Info^.DLL) + Length(LOAD_ORION) + Length(Info^.Hdr) + 3);  //Message content
       PDWORD(@LOAD_ORION[23])^ := FGetProcAddress; // Call GetProcessAddress
       LOAD_ORION[30] := $07;                       // Jmp 7 bytes to MessageBox
       PDWORD(@LOAD_ORION[54])^ := FMessageBox;     // Call MessageBoxA
       PDWORD(@LOAD_ORION[7])^  := FLoadLibrary;    // Call loadlibrary
       LOAD_ORION[14] := $17;                       // Jmp 19 bytes to MessageBox
       PDWORD(@LOAD_ORION[34])^ := OEP  - (NtImgDosHdr.OptionalHeader.AddressOfEntryPoint +  NtImgDosHdr.OptionalHeader.ImageBase + 38);
      end
     else
      begin
       PDWORD(@LOAD_ORION[1])^  := (NtImgDosHdr.OptionalHeader.AddressOfEntryPoint + NtImgDosHdr.OptionalHeader.ImageBase) - (Length(Info^.DLL) + Length(Info^.Hdr) + Length(Info^.Content) + 3);   //DLL Name
       PDWORD(@LOAD_ORION[7])^  := FLoadLibrary;    // Call loadlibrary
       Move(LOAD_ORION[33],LOAD_ORION[15],25);
       FillChar(LOAD_ORION[39], 21, #0);
       LOAD_ORION[14] := $05;

       PDWORD(@LOAD_ORION[1])^  := (NtImgDosHdr.OptionalHeader.AddressOfEntryPoint + NtImgDosHdr.OptionalHeader.ImageBase) + (Length(LOAD_ORION) + 1);   //DLL Name
       PDWORD(@LOAD_ORION[23])^ := (NtImgDosHdr.OptionalHeader.AddressOfEntryPoint + NtImgDosHdr.OptionalHeader.ImageBase) + (Length(Info^.DLL) + Length(LOAD_ORION) + 2);  //Message header
       PDWORD(@LOAD_ORION[28])^ := (NtImgDosHdr.OptionalHeader.AddressOfEntryPoint + NtImgDosHdr.OptionalHeader.ImageBase) + (Length(Info^.DLL) + Length(LOAD_ORION) + Length(Info^.Hdr) + 3);  //Message content
       PDWORD(@LOAD_ORION[36])^ := FMessageBox;     // Call MessageBoxA
       PDWORD(@LOAD_ORION[16])^ := OEP  - (NtImgDosHdr.OptionalHeader.AddressOfEntryPoint +  NtImgDosHdr.OptionalHeader.ImageBase + 20);
      end;


     Move(LOAD_ORION,Info.WriteBytes[0], Length(LOAD_ORION));
     Move(Info.WriteBytes[0], Buffer[Length(Buffer) - SectionSize], Length(Info.WriteBytes));
    end;

    Fs := TFileStream.Create(Filename+'_HOOKED_DLL.exe',fmCreate or fmShareExclusive);
     try
      Result := Fs.Write(Buffer[0],Length(Buffer)) = Length(Buffer);
     finally
      Fs.Free
     end;
 except
  on E: Exception do
   MessageBox(0, PWideChar(E.Message) , '', MB_ICONERROR or MB_OK);
 end;
end;

end.

Project Dead!
Added source of this crap ^^ i must forgot to upload it.
 

Attachments

You must be registered for see attachments list
Last edited:
MFS Team Owner
Joined
Jan 10, 2007
Messages
767
Reaction score
227
here are mirrows:


 
Newbie Spellweaver
Joined
Oct 29, 2004
Messages
51
Reaction score
4
so let me ask this.. can I take a .DLL file from gameserver1.exe and hook it to gameserver2.exe and have those options on the gameserver2.exe or will that not work..
 
Legendary Battlemage
Loyal Member
Joined
Dec 13, 2007
Messages
613
Reaction score
161
how many can be hooked?>
 
Skilled Illusionist
Joined
Mar 3, 2009
Messages
388
Reaction score
10
good release :D 10/10 thanks for help us with your works!
 
NN - Nord & Noob
Loyal Member
Joined
Jul 15, 2004
Messages
1,207
Reaction score
689
Its definitely will not work with packed files! U can pack your main.exe after u atach dll to it!

Tool creates own space and write all there after jmp to OEP (EP what u have)!


PS. i become again very bussy maybe release source of this so other can learn some tricks about PE or simple finish / update this crap :)
The project is writed in Delphi XE - nothing hard there, just small tricks
 
Last edited:
Junior Spellweaver
Joined
Jul 30, 2005
Messages
176
Reaction score
110
mauka, I can't figure this out yet. Have try many methods of hooking by IAT, but can't understand how it works. Actually I made the hooks by Import Table of LordPE but I need to export everytime one API. I don't use API for the dll init, DllMain is the best, so my API functions is empty. How I can do this whithout the damn API ?

Ps.: Do u have some docs about the IAT hooking that explain how to get the addresses and sh!t ?
 
NN - Nord & Noob
Loyal Member
Joined
Jul 15, 2004
Messages
1,207
Reaction score
689
LordPE is crap dont use it.. its mess all PE :\ u cant clean file after u used LordPE
Best option for manualy add import to a PE is CFF-Explorer u can download it from:

I wanna rebuild my tool same as CFF works :)

PS. if u dont have a export functions (API) in your dll simple add your dll to importtable.. :) i used did it with lordPE before i wakeup (thanks to Blurcode)

PSS. if u use LordPE before add new IMPORT to IAT uncheck - api button, but still if not work u can always add a fake api who does nothing :)


My tool creates new section in PE - change OEP to my section and in my section i write data to call dll and api then after simply set JMP to OEP :) kind a easy, but taked me 2 days to understand all and code :\


About IAT hooks :p u will understand it one start study PE, but i dont see reason why simple dll`s need a hooks if u can simple atach it to target :)

my 2 cents!

Gosh i forgot there is tool called "PE Inject" u can download it from: site, but i sugest u dont use it coz its in maybe weeks (method he uses) will be marked as malware poop :) no need wondering why ^^

a small desription about PE-Inject from authors site
PE-inject is a special library which allows developers to place their own code into Windows executable files (EXE, DLL, OCX and others). PE-inject was designed to be as simple as possible, to make modification of executables (so called PE-files) as easy as writing a “Hello world!” program. The knowledge of Assembler and Windows PE-EXE file format, which was essential before PE-inject came, is no longer required.
 
Last edited:
Junior Spellweaver
Joined
Jul 30, 2005
Messages
176
Reaction score
110
LordPE is crap dont use it.. its mess all PE :\ u cant clean file after u used LordPE
Best option for manualy add import to a PE is CFF-Explorer u can download it from:

I wanna rebuild my tool same as CFF works :)
...

This suite is very usefull. Thank you for sharing. I see that have one rebuilder like LordPE haves, but as u say, use it is not a good ideia, so I wanna know what is the best options in the Rebuilder section that I need to check after add my DLL in the Import Directory. I see to one section called Import Adder. What really does ?

Thanks ;)

---------- Post added at 04:47 PM ---------- Previous post was at 04:19 PM ----------

I have try use the Import Adder with my new DLL (without API export) and the prograns returns that my DLL has a invalid PE. WTF ?
 
Experienced Elementalist
Joined
Oct 12, 2007
Messages
219
Reaction score
5
For what need doind programs when them very more now.
 
Last edited:
Junior Spellweaver
Joined
Jul 30, 2005
Messages
176
Reaction score
110
mauka, sorry disturb you. But I already have questions about IAT hooking. The suite u share is very usefull, but in the CFF Explorer I can't import my dll in Import Adder without a properly API exported. How do that without the damn API ?

Thanks :wink:
 
NN - Nord & Noob
Loyal Member
Joined
Jul 15, 2004
Messages
1,207
Reaction score
689
I create new section in file and write there simply bytes to call DLL :) i dont touch IAT :)


mauka - HE - HookEngine - RaGEZONE Forums
 
Back
Top