Delphi版的隐藏模块单元 HideModuleUnit.pas


本文整理自网络,侵删。

 

hidemoduleunit.pas
unit HideModuleUnit;

interface

uses Windows, Messages, SysUtils, Classes, TlHelp32;

type
  TVirtualAlloc = function(lpvAddress: Pointer; dwSize, flAllocationType,
    flProtect: DWORD): Pointer; stdcall;
  TVirtualProtect = function(lpAddress: Pointer; dwSize, flNewProtect: DWORD;
    var OldProtect: DWORD): BOOL; stdcall;
  TVirtualFree = function(lpAddress: Pointer;
    dwSize, dwFreeType: DWORD): BOOL; stdcall;
  TWriteProcessMemory = function(hProcess: THandle;
    const lpBaseAddress: Pointer; lpBuffer: Pointer; nSize: DWORD;
    var lpNumberOfBytesWritten: DWORD): BOOL; stdcall;
  TGetCurrentProcess = function: THandle; stdcall;
  TFreeLibrary = function(hLibModule: HMODULE): BOOL; stdcall;

  THideModuleRec = record
    pModule: pointer;
    pVirtualAlloc: TVirtualAlloc;
    pVirtualProtect: TVirtualProtect;
    pVirtualFree: TVirtualFree;
    pWriteProcessMemory: TWriteProcessMemory;
    pGetCurrentProcess: TGetCurrentProcess;
    pFreeLibrary: TFreeLibrary;
  end;
  PHideModuleRec = ^THideModuleRec;

procedure HideModule(hModule: THandle);

implementation

procedure ExecuteHide(HM: THideModuleRec);
var
  pBakMemory: pointer;
  ImageOptionalHeader: TImageOptionalHeader;
  ImageDosHeader: TImageDosHeader;
  td: dword;
  i: Integer;
begin
  { 取得映象数据 }
  ImageDosHeader := PImageDosHeader(HM.pModule)^;
  ImageOptionalHeader := PImageOptionalHeader(Pointer(integer(HM.pModule) +
    ImageDosHeader._lfanew + SizeOf(dword) +
    SizeOf(TImageFileHeader)))^;
  { 申请内存以备份原始模块数据 }
  pBakMemory := HM.pVirtualAlloc(nil, ImageOptionalHeader.SizeOfImage,
    MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  if pBakMemory = nil then
    exit;
  { 修改原始内存为可读写属性 }
  HM.pVirtualProtect(HM.pModule, ImageOptionalHeader.SizeOfImage,
    PAGE_EXECUTE_READWRITE, td);
  { 备份原始模块数据 }
  HM.pWriteProcessMemory(HM.pGetCurrentProcess, pBakMemory, HM.pModule,
    ImageOptionalHeader.SizeOfImage, td);
  { 修改原DllEntryPoint为retn,防止FreeLibrary时的一些卸载操作 }
  pByte(integer(HM.pModule) + ImageOptionalHeader.AddressOfEntryPoint)^ := $C3;
  { 卸载原模块,这里多次卸载防止因为LoadCount的关系一次卸载不掉 }
  //HM.pFreeLibrary(integer(HM.pModule));
  i := 0;
  repeat
    Inc(i);
  until not HM.pFreeLibrary(integer(HM.pModule)) or (i >= 30);
  { 申请dll原始加载地址空间 }
  HM.pModule := HM.pVirtualAlloc(HM.pModule, ImageOptionalHeader.SizeOfImage,
    MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  if HM.pModule = nil then
    exit;
  { 写回原始数据 }
  HM.pWriteProcessMemory(HM.pGetCurrentProcess, HM.pModule, pBakMemory,
    ImageOptionalHeader.SizeOfImage, td);
  { 释放备份时用的内存 }
  HM.pVirtualFree(pBakMemory, 0, MEM_RELEASE);
end;

(*注意该间隔处不能添加任何代码, 且不能改变上下2个函数位置
因为下面使用了2个函数入口来计算上一函数Size*)

procedure LockedAllModule(CurrentModuleHandle: THandle);
var
  ModuleList: THandle;
  pm: tagMODULEENTRY32;
begin
  pm.dwSize := sizeof(tagMODULEENTRY32);
  ModuleList := CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0);
  if not Module32First(ModuleList, pm) then
  begin
    CloseHandle(ModuleList);
    exit;
  end;

  //不处理第一个模块,因为那是主模块
  { 对每个模块LoadLibrary一次,是为了把LoadCount加1 }
  while Module32Next(ModuleList, pm) do
  begin
    if pm.hModule <> CurrentModuleHandle then
      LoadLibrary(PAnsiChar(@GetModuleName(pm.hModule)[1]));
  end;

  CloseHandle(ModuleList);
end;

procedure HideModule(hModule: THandle);
type
  TExecuteHide = procedure(HM: THideModuleRec);
var
  HM: THideModuleRec;
  pExecuteHide: pointer;
  ExecuteHideSize: integer;
  MyExecuteHide: TExecuteHide;
  td: dword;
  Module_kernel32: integer;
begin
  Module_kernel32 := GetModuleHandle('kernel32.dll');
  HM.pModule := pointer(hModule);
  HM.pVirtualAlloc := GetProcAddress(Module_kernel32, 'VirtualAlloc');
  HM.pVirtualProtect := GetProcAddress(Module_kernel32, 'VirtualProtect');
  HM.pVirtualFree := GetProcAddress(Module_kernel32, 'VirtualFree');
  HM.pWriteProcessMemory := GetProcAddress(Module_kernel32,
    'WriteProcessMemory');
  HM.pGetCurrentProcess := GetProcAddress(Module_kernel32, 'GetCurrentProcess');
  HM.pFreeLibrary := GetProcAddress(Module_kernel32, 'FreeLibrary');

  ExecuteHideSize := integer(@LockedAllModule) - integer(@ExecuteHide);
  pExecuteHide := VirtualAlloc(nil, ExecuteHideSize,
    MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  if pExecuteHide = nil then
    exit;

  { 防止系统将需要的Dll卸载掉 }
  LockedAllModule(integer(HM.pModule));

  CopyMemory(pExecuteHide, @ExecuteHide, ExecuteHideSize);
  MyExecuteHide := pExecuteHide;
  MyExecuteHide(HM);
end;

end.

相关阅读 >>

Delphi 过滤网页代码 <script></script>

Delphi 检测用户超过多长时间没有操作键盘或鼠标

Delphi模仿“千千静听”滚动标题栏,非常简单!

Delphi多线程tthread详解

Delphi2010 编译变量$region用法

Delphi xe10.1 andriod app中文名称

Delphi 检测 iat hook api 的方法

Delphi record,两种声明方式

Delphi中exit,abort,break,continue,halt,runerro 的区别

Delphi 判断文件路径,不存在则建立

更多相关阅读请进入《Delphi》频道 >>



打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...