┌─────┐          ┌─────┐ 
│ 我的程序 │┅┅┅>  │ ReadFile │
└─────┘          └─────┘     
     │        
     ˇ        
┌─────┐        ┌──────┐        ┌─────┐    
│  控件A   │┅┅┅>│ UTILITY.DLL│┅┅┅>│ ReadFile │
└─────┘        └──────┘        └─────┘
在“我的程序”中可以HOOK到“我的程序”中使用的ReadFile,我在
View-->Debug windows-->Event Log中查看“UTILITY.DLL”已经加载,但是“我的程序”    
使用的“控件A”调用的“UTILITY.DLL”中的ReadFile却HOOK不了,为什么?
////====程序代码
unit Unit1;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, OleCtrls, MapXLib_TLB;type
  TReadFile = function(hFile: THandle; var Buffer; nNumberOfBytesToRead: DWORD; var lpNumberOfBytesRead: DWORD; lpOverlapped: POverlapped): BOOL; stdcall;
  TReadFileEx = function(hFile: THandle; lpBuffer: Pointer; nNumberOfBytesToRead: DWORD; lpOverlapped: POverlapped; lpCompletionRoutine: TPROverlappedCompletionRoutine): BOOL; stdcall;  PImage_Import_Entry = ^Image_Import_Entry; //定义一个入口结构
  Image_Import_Entry = record
    Characteristics: DWORD;
    TimeDateStamp: DWORD;
    MajorVersion: Word;
    MinorVersion: Word;
    Name: DWORD;
    LookupTable: DWORD;
  end;  TSaveRedir = packed record
    Addr: Pointer;
    Bytes: array[0..4] of Byte;
  end;
  PSaveRedir = ^TSaveRedir;  TImportCode = packed record //定义一个跳转的结构
    JumpInstruction: Word; //定义跳转指令jmp,是$25FF,JUMP指令
    AddressOfPointerToFunction: ^Pointer; //定义要跳转到的函数,//真正开始的地址
  end;
  PImportCode = ^TImportCode;  TForm1 = class(TForm)
    Map1: TMap;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;var
  Form1             : TForm1;implementation
var
  OldReadFile       : TReadFile;
  OldReadFileEx     : TReadFileEx;  {$R *.dfm}function LocateFunctionAddress(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 RepointFunction(OldFunc, NewFunc: Pointer): Integer;
var
  IsDone            : TList;
  function RepointAddrInModule(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 IsDone.IndexOf(Dos) >= 0 then exit;
    IsDone.Add(Dos);    OldFunc := LocateFunctionAddress(OldFunc);    if IsBadReadPtr(Dos, SizeOf(TImageDosHeader)) then exit;
    if Dos.e_magic <> IMAGE_DOS_SIGNATURE then exit;
    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);
        RepointAddrInModule(GetModuleHandle(PChar(DLL)), OldFunc, NewFunc);
        Func := Pointer(Integer(DOS) + ImportDesc.LookupTable);
        while Func^ <> nil do
          begin
            f := LocateFunctionAddress(Func^);
            if f = OldFunc then
              begin //在这里设置断点,发现只有“我的程序”的才HOOK掉了
                WriteProcessMemory(GetCurrentProcess, Func, @NewFunc, 4, written);
                if Written > 0 then Inc(Result);
              end;
            Inc(Func);
          end;
        Inc(ImportDesc);
      end;
  end;begin
  IsDone := TList.Create;
  try
    Result := RepointAddrInModule(GetModuleHandle(nil), OldFunc, NewFunc); //这可以HOOK到“我的程序的代码”
    Result := RepointAddrInModule(GetModuleHandle('UTILITY.DLL'), OldFunc, NewFunc);
  finally
    IsDone.Free;
  end;
end;procedure MyDebug(Str: PChar);
var DC              : HDC;
begin
  Sleep(1000);
  DC := GetDC(0);
  try
    Textout(Dc, 50, 50, PChar(Str + '      '), Length(PChar(Str + '      ')));
  finally
    ReleaseDC(0, DC);
  end;
end;function MyReadFile(hFile: THandle; var Buffer; nNumberOfBytesToRead: DWORD; var lpNumberOfBytesRead: DWORD; lpOverlapped: POverlapped): BOOL; stdcall;
begin
  MyDebug(PChar('OpenFile' + '  ' + IntToStr(hFile) + '  '));
  Result := OldReadFile(hFile, Buffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
end;function MyReadFileEx(hFile: THandle; lpBuffer: Pointer; nNumberOfBytesToRead: DWORD; lpOverlapped: POverlapped; lpCompletionRoutine: TPROverlappedCompletionRoutine): BOOL; stdcall;
begin
  MyDebug(PChar('OpenFileEx' + '  ' + IntToStr(hFile) + '  '));
  Result := OldReadFileEx(hFile, lpBuffer, nNumberOfBytesToRead, lpOverlapped, lpCompletionRoutine);
end;procedure API_Hookup;
begin
  if @OldReadFile = nil then
    @OldReadFile := LocateFunctionAddress(@ReadFile);
  RepointFunction(@OldReadFile, @MyReadFile);  if @OldReadFileEx = nil then
    @OldReadFileEx := LocateFunctionAddress(@ReadFileEx);
  RepointFunction(@OldReadFileEx, @MyReadFileEx);
end;procedure API_HookDown;
begin
  if @OldReadFile <> nil then
    begin
      RepointFunction(@MyReadFile, @OldReadFile);
    end;  if @OldReadFileEx <> nil then
    begin
      RepointFunction(@MyReadFileEx, @OldReadFileEx);
    end;
end;procedure TForm1.Button1Click(Sender: TObject);
begin
  API_Hookup;
end;procedure TForm1.Button2Click(Sender: TObject);
begin
  API_HookDown;
end;end.