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.

原文地址:https://www.cnblogs.com/plug/p/8665566.html

时间: 2024-08-04 19:21:54

HookEngine源码的相关文章

小说分销系统,微信小说分销,类掌中云小说系统,类818tu系统源码

[演示站参数][][][][][][][][][][][] [后 台 地 址]     http://xiaoshuo.qqsiot.cn/manager          [] [管理员账号]     admin                                                     [] [渠道商账号]     channel                                                  [] [代理商账号]     age

cocos Creator js 房卡麻将/血战/H5四川麻将源码下载搭建

房卡麻将/血战/H5四川麻将 源码 支持iOS/Android/H5 完整源码 1.基于NODEJS+MYSQL的服务器,成熟的技术方案,高效稳定,且方便Windows开发,Linux平台布署,节约服务器运转成本. 2.采用最新版本的cocos引擎,cocos creator开发,可快速的进行界面调整.且能够快速地发布iOS,Android版本. 3.如需H5版本,只需针对H5平台进行资源优化即可. 4.成熟可靠的房卡式设计,能满足大部分用户使用体验. 5.产品经过大量测试,可以运转稳定. 测试

下载-深入浅出Netty源码剖析、Netty实战高性能分布式RPC、NIO+Netty5各种RPC架构实战演练三部曲视频教程

下载-深入浅出Netty源码剖析.Netty实战高性能分布式RPC.NIO+Netty5各种RPC架构实战演练三部曲视频教程 第一部分:入浅出Netty源码剖析 第二部分:Netty实战高性能分布式RPC 第三部分:NIO+Netty5各种RPC架构实战演练

android手机安全卫士、Kotlin漫画、支付宝动画、沉浸状态栏等源码

Android精选源码 轻量级底部导航栏 android手机卫士源码 android实现高仿今日头条源码 一个用Kotlin写的简单漫画App源码 android吐槽项目完整源码 实现可以滑动文字逐渐变色的TabLayout android实现将app隐藏加密功能的源码 android实现横向滚动的卡片堆叠布局 android仿支付宝的咻咻动画源码 android状态栏和沉浸式导航栏管理源码 Android优质博客 从BaseActivity与BaseFragment的封装谈起 这篇博客主要是从

Java企业微信开发_09_身份验证之移动端网页授权(有完整项目源码)

注: 源码已上传github: https://github.com/shirayner/WeiXin_QiYe_Demo 一.本节要点 1.1 授权回调域(可信域名) 在开始使用网页授权之前,需要先设置一下授权回调域.这里瞬间想到之前做JSSDK的时候,也设置过一个域名.二者本质上都是设置可信域名. 当用户授权完毕之后,请求将重定向到此域名(或者子域名)下的执行者(jsp页面或者servlet等).如何设置授权回调域,请见第二节. 1.2 获取Code https://open.weixin.

微信小程序源码下载(200多个)

微信小程序源码下载汇总,点击标题进入对应的微信小程序下载页面. 最新 demo源码(点击标题进入帖子下载) 描述 1 微信小程序 会议室预定小程序 微信小程序 会议室预定小程序**** 本内容被作者隐藏 **** 2 微信小程序-双人五子棋小游戏 微信小程序-双人五子棋小游戏**** 本内容被作者隐藏 **** 3 打卡签到小程序 用微信小程序实现的一个简单的打卡签到的小程序拒绝 4 微信小程序---左滑删除 微信小程序---左滑删除**** 本内容被作者隐藏 **** 5 一个借钱的记事本的微

ViewGroup源码解读

我们之前刚刚分析完事件传递机制和view的源码,如果没有看过的,建议看完View的事件拦截机制浅析以及View的事件源码解析.这次我们来分析下viewgroup的. 可能有人会想,怎么又是源码分析,肯定又是一大通.其实没你想的那么复杂.仔细分析一波就行了. 解读ViewGroup 我们都知道,一个事件完整的流程是从dispatchTouchevent–>onInterceptTouchevent–>onTouchEvent.我们先不说事件监听的问题.上述三个步骤就是正常一个点击的流程.前面我们

Java DES 加密和解密源码

Java密码学结构设计遵循两个原则: 1) 算法的独立性和可靠性. 2) 实现的独立性和相互作用性. 算法的独立性是通过定义密码服务类来获得.用户只需了解密码算法的概念,而不用去关心如何实现这些概念.实现的独立性和相互作用性通过密码服务提供器来实现.密码服务提供器是实现一个或多个密码服务的一个或多个程序包.软件开发商根据一定接口,将各种算法实现后,打包成一个提供器,用户可以安装不同的提供器.安装和配置提供器,可将包含提供器的ZIP和JAR文件放在CLASSPATH下,再编辑Java安全属性文件来

Linux下利用phpize安装memcashe的php源码扩展包

phpize是php的一种构建工具,为PHP扩展准备构建环境,通过phpize可以编译php的扩展源码文件为php扩展模块. 一.安装 phpize工具可以通过安装php-dev包自动集成安装.安装完成后php的bin目录下会有phpize这个命令. 二.使用 举例:在原来编译好的php中加入memcache扩展模块,使用phpize构建的方式如下. tar zxvf memcache-2.2.5.tgz cd memcache-2.2.5/ /usr/local/php/bin/phpize