zoukankan      html  css  js  c++  java
  • HookEngine源码

    unit uSection;

    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;
    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): 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.

  • 相关阅读:
    mysql数据库常用指令
    解决windows的mysql无法启动 服务没有报告任何错误的经验。
    “Can't open file for writing”或“operation not permitted”的解决办法
    启动Apache出现错误Port 80 in use by "Unable to open process" with PID 4!
    如何打开windows的服务services.msc
    常见的HTTP状态码 404 500 301 200
    linux系统常用的重启、关机指令
    (wifi)wifi移植之命令行调试driver和supplicant
    linux(debian)安装USB无线网卡(tp-link TL-WN725N rtl8188eu )
    alloc_chrdev_region申请一个动态主设备号,并申请一系列次设备号
  • 原文地址:https://www.cnblogs.com/plug/p/8665566.html
Copyright © 2011-2022 走看看