www.pudn.com > SPYQQ3.rar > ReEntry.pas


unit ReEntry; 
 
interface 
 
uses Windows; 
 
  // 修改模块引入表 
type 
  TReEntry = class(TObject) 
  public 
    constructor Create(CallerModName, CalleeModName, FuncName: PChar; HookProc: FarProc); 
    destructor Destroy(); override; 
    function OriginProc(): FarProc; // 返回原始地址 
  private 
    m_CallerModName: PChar;   // 调用者模块名 
    m_hCallerModule: HModule; // 调用者模块句柄 
    m_CalleeModName: PChar;   // 被调者模块名 
    m_HookProc,               // 新老函数地址 
    m_OrigProc: FarProc; 
    m_funcName: PChar; 
    procedure ReplaceIATEntry(CurProc, NewProc: FarProc); 
  end; 
 
implementation 
 
uses Messages, ImageHlp; 
 
type 
  // DLL数组结构 
  TImageImportDescriptor = record 
    OriginalFirstThunk: DWord; // 保存函数信息的TImageThunkData数组的RVA 
    TimeDateStamp, ForwarderChain: DWord; 
    Name: DWord;               // DLL名称字符串的RVA 
    FirstThunk: DWord;         // 另一份TImageThunkData数组的拷贝的RVA,装载后, 
  end;                         // 该TImageThunkData数组被修改为各函数入口地址 
  PImageImportDescriptor = ^TImageImportDescriptor; 
 
  // 函数名称信息 
  TImageImportByName = packed record 
    Hint: Word; // 如果非0, 表示函数的参考序号 
    Name: array [0..0] of Char; // 函数名字符串 
  end; 
  PImageImportByName = ^TImageImportByName; 
 
  // 函数数组结构 
  TImageThunkData = record 
    case Integer of               // 最高位不是1, 则为TImageImportByName的RVA, 
      0: (ForwarderString: PByte);// 否则, 低31位代表引入的函数的序号, 另外, 
      1: (Function_: PDWORD);     // 装载后, 此数组的一份拷贝变为各函数入口地址 
      2: (Ordinal: ULONG); 
      3: (AddressOfData: PImageImportByName); 
  end; 
  PImageThunkData = ^TImageThunkData; 
 
constructor TReEntry.Create( 
  CallerModName,    // 调用者模块名 
  CalleeModName,    // 被调者模块名 
  FuncName: PChar;  // 被调用函数名 
  HookProc: FarProc); // 替换地址 
begin 
  m_CallerModName := CallerModName; 
  m_hCallerModule := GetModuleHandle(CallerModName); 
  if (m_hCallerModule = 0) then Exit; 
 
  m_CalleeModName := CalleeModName; 
  m_HookProc := HookProc; 
  m_funcName := FuncName; 
  m_OrigProc := GetProcAddress(GetModuleHandle(CalleeModName), FuncName); 
  if (m_OrigProc = nil) then Exit; 
  ReplaceIATEntry(m_OrigProc, m_HookProc); 
end; 
 
destructor TReEntry.Destroy(); 
begin 
  if (m_hCallerModule <> 0) and (m_OrigProc <> nil) and 
     (GetModuleHandle(m_CallerModName) = m_hCallerModule) 
  then 
    ReplaceIATEntry(m_HookProc, m_OrigProc); 
end; 
 
function TReEntry.OriginProc(): FarProc; 
begin 
  Result := m_OrigProc; 
end; 
 
procedure TReEntry.ReplaceIATEntry(CurProc, NewProc: FarProc); 
var 
  pImportDesc: PImageImportDescriptor; 
  pThunk: PImageThunkData; 
  CurModName: PChar; 
  dwSize, dwProtect, dwTemp: DWord; 
begin 
  if (m_hCallerModule >= $80000000) then Exit; 
 
  // 定位至函数引入表 
  pImportDesc := ImageDirectoryEntryToData(Pointer(m_hCallerModule), True, IMAGE_DIRECTORY_ENTRY_IMPORT, dwSize); 
  if (pImportDesc = nil) then Exit; 
 
  // 遍历TImageImportDescriptor数组, 寻找名称匹配的DLL 
  while (pImportDesc.Name <> 0) do 
  begin 
    CurModName := PChar(m_hCallerModule + pImportDesc.Name); 
    if (lStrCmpI(CurModName, m_CalleeModName) = 0) then // DLL名字匹配 
    begin 
      // 定位至函数地址表 
      pThunk := PImageThunkData(m_hCallerModule + pImportDesc.FirstThunk); 
 
      // 遍历TImageThunkData数组 (寻找地址匹配的函数) 
      while (pThunk.Function_ <> nil) do 
      begin 
        // 找到则改写Function_ 
        if (pThunk.Function_ = CurProc) then 
        begin 
          //MessageBox(0,m_funcName,CurModName,MB_OK); 
          VirtualProtect(@pThunk.Function_, SizeOf(FarProc), PAGE_EXECUTE_WRITECOPY, @dwProtect); 
          WriteProcessMemory(GetCurrentProcess(), @pThunk.Function_, @NewProc, SizeOf(FarProc), dwTemp); 
          VirtualProtect(@pThunk.Function_, SizeOf(FarProc), dwProtect, @dwTemp); 
          Break; 
        end; 
 
        // 下一个TImageThunkData 
        Inc(pThunk); 
      end; // while (pThunk.Function_ <> nil) do .. 
    end; 
 
    // 下一个TImageImportDescriptor 
    Inc(pImportDesc); 
  end; // while (pImportDesc.Name <> 0) do .. 
end; 
 
end.