HookAPI 之 ExitWindowsEX

本文介绍了一种病毒通过HOOK ExitWindowsEx API函数导致机器无法正常关机的原理,并展示了如何使用Delphi编写一个简单的示例,演示如何设置和移除钩子,以及如何替换原有函数的行为,以便理解HOOK机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

 

有些病毒经常搞的机器无法关机到底是什么原因呢?其实就是HOOK 了ExitWindowsEx这个API函数,以下代码简要实现

{主程序}

//--------------------------------------------------
// 程序作者:zorro MYBlog:http://blog.youkuaiyun.com/zorro0920/
// QQ:15124763      All rights reserved!!
// 转载请保留此信息
//--------------------------------------------------
unit Main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Button1: TButton;
    Button2: TButton;
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private

  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  h_Hook:HHook;
implementation

{$R *.dfm}
procedure TForm1.Button2Click(Sender: TObject);
begin
  //结束
  if  h_Hook<>0 then
    UnhookWindowsHookEx(h_Hook);
  Application.Terminate;
end;
//------------------------------------------------------------------------------
procedure TForm1.Button1Click(Sender: TObject);
var
  hHookDll,htaskmar,ThreadID:thandle;
  pHookFunction:Pointer;
begin
     hHookDll:= LoadLibrary('Hook.dll');
     if hHookDll<>0 then
     begin
       ShowMessage('hHookDll<>0');
       pHookFunction:=GetProcAddress(hHookDll,'HookFunction');
       if  pHookFunction<>nil then
       begin
           h_Hook:=SetWindowsHookEx(3,pHookFunction,hHookDll,0);
          
       end;
     end
     else
       ShowMessage('hHookDll=0');
end;

end.

 

{HOOK.DLL}

 

library Hook;

uses
  SysUtils,
  Classes,
  HookApi in 'HookApi.pas';

{$R *.res}
exports
  HookFunction;
 
begin
 
end.
 

{主要单元文件}

unit HookAPI;

interface
uses
Windows, Classes,dialogs,SysUtils,Messages;
type
  PImage_Import_Entry = ^Image_Import_Entry;
  Image_Import_Entry = record
    OriginalFirstThunk : DWORD;
    TimeDateStamp : DWORD;
    forwarderChain:DWORD;
    Name : DWORD;
    LookupTable : DWORD;
  end;

  PImageThunkData = ^TImageThunkData;
  TImageThunkData = record
  case integer of
    1:( ForwarderString : DWord; );
    2:( Function_       : DWord; );
    3:( Ordinal         : DWord; );
    4:( AddressOfData   : DWord; );
  end;
 
  Function TrueFunctionAddress(Code: Pointer): Pointer;
  Function WriteFunction(OldFunc, NewFunc: Pointer):Integer;
  function HookFunction(nCode:Integer;WParam:WPARAM;LParam:LPARAM):LRESULT;stdcall;
var
 h_hook:HHook;
 hmod:Dword;
 //flag:Boolean = True;
implementation

type
TImportCode = packed record
JumpInstruction: Word;
AddressOfPointerToFunction: ^Pointer;
end;
PImportCode = ^TImportCode;
//-----------------------------------------------------------------------------
function TrueFunctionAddress(Code: Pointer): Pointer;
var
  func: PImportCode;
begin
  Result := Code;
  if Code = nil then exit;
  try
  func := code;
  if (func.JumpInstruction=$25FF) then begin
    Result := func.AddressOfPointerToFunction^;
  end;
  except
    Result := nil;
  end;
end;
//------------------------------------------------------------------------------
Function WriteFunction(OldFunc, NewFunc: Pointer):Integer;
var
  BeenDone: TList;

  Function WriteAddrInModule(hModule: THandle; OldFunc,NewFunc: Pointer): Integer;
  var
    Dos : PImageDosHeader;
    NT : PImageNTHeaders;
    ImportDesc : PImage_Import_Entry;
    RVA : DWORD;
    Func : ^Pointer;
    DLL : String;
    //f : Pointer;
    written : DWORD;
  begin
  Result := 0;
  Dos := Pointer(hModule);
  if BeenDone.IndexOf(Dos) >= 0 then exit;
  BeenDone.Add(Dos);
  //OldFunc := TrueFunctionAddress(OldFunc);//函数的实际地址
  if IsBadReadPtr(Dos,SizeOf(TImageDosHeader)) then exit;

  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;  //如果引入函数表为空,则退出
  ImportDesc := pointer(integer(Dos)+RVA);

  While(ImportDesc^.Name<>0) do
  begin
    DLL := PChar(Integer(Dos) + ImportDesc^.Name);
    WriteAddrInModule(GetModuleHandle(PChar(DLL)),OldFunc,NewFunc);
    //定位至被引入的下级DLL模块的函数表
    Func := Pointer(Integer(DOS) + ImportDesc.LookupTable);
    While Func^ <> nil do
    begin
      //f := TrueFunctionAddress(Func^);
      if Func^ = OldFunc then //如果函数实际地址就是所要找的地址
      begin
        //showmessage('准备覆盖函数');
        WriteProcessMemory(GetCurrentProcess,Func,@NewFunc,4,written);//把新函数地址覆盖它
        If Written > 0 then Inc(Result);
      end;
      Inc(Func); //如果函数实际地址就是所要找的地址
   end;
  Inc(ImportDesc); //下一个被引入的下级DLL模块
  end;
 end;

begin
  BeenDone := TList.Create;
  try
  Result := WriteAddrInModule(GetModuleHandle(nil),OldFunc,NewFunc);
  finally
    BeenDone.Free;
  end;
end;

//------------------------------------------------------------------------------

Function My_Process(uFlags:UINT;dwReserved:DWORD):Boolean;
begin
  Result:=True;
end;
//------------------------------------------------------------------------------

Function HookFunction(nCode:Integer;WParam:WPARAM;LParam:LPARAM):LRESULT;stdcall;export;
var
  OldFunction:Pointer;
begin
  //ShowMessage('HookFunction');
  OldFunction:=GetProcAddress(GetModuleHandle('User32.DLL'),'ExitWindowsEx');
  WriteFunction(OldFunction,@My_Process);
  Result:=CallNextHookEx(h_hook, ncode, wParam, lParam);
end;
end.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值