Local API Redirection

Post date: Mar 16, 2010 3:45:11 PM

{

Unit: uRedirectAPI

Author: steve10120

Description: Redirect imported API's, making rebuilding after dump harder.

Notes: This is just a simple [mov eax, xxxx >> jmp eax] to the API, if you want to defeat generic tracing functions you should obfuscate it somehow.

Website: hackhound.org

History: First try

}

unit uRedirectAPI;
interface
uses Windows;
function RedirectAPIs(dwModule:DWORD):Boolean;
type
  PImageImportDescriptor = ^TImageImportDescriptor;
  TImageImportDescriptor = packed record
    OriginalFirstThunk: DWORD;
    TimeDateStamp: DWORD;
    ForwarderChain: DWORD;
    Name: DWORD;
    FirstThunk: DWORD;
  end;
type
  PImportByName = ^TImportByName;
  TImportByName = packed record
    Name1:        DWORD;
  end;
implementation
function RedirectAPIs(dwModule:DWORD):Boolean;
var
  IDH:          PImageDosHeader;
  INH:          PImageNtHeaders;
  IID:          PImageImportDescriptor;
  IBN:          PImportByName;
  pMem:         Pointer;
  pFunction:    Pointer;
  pWrite:       ^Pointer;
  dwNull:       DWORD;
  xVirtualAlloc:function(lpvAddress: Pointer; dwSize, flAllocationType, flProtect: DWORD): Pointer; stdcall;
begin
  Result := FALSE;
  IDH := Pointer(dwModule);
  if IDH.e_magic = IMAGE_DOS_SIGNATURE then
  begin
    INH := Pointer(dwModule + IDH._lfanew);
    if INH.Signature = IMAGE_NT_SIGNATURE then
    begin
      xVirtualAlloc := GetProcAddress(GetModuleHandle('kernel32.dll'), 'VirtualAlloc');
      VirtualProtect(Pointer(dwModule + INH.OptionalHeader.DataDirectory[1].VirtualAddress), INH.OptionalHeader.DataDirectory[1].Size, PAGE_EXECUTE_READWRITE, dwNull);
      IID := Pointer(dwModule + INH.OptionalHeader.DataDirectory[1].VirtualAddress);
      while IID.Name <> 0 do
      begin
        if IID.OriginalFirstThunk <> 0 then
          IBN := Pointer(dwModule + IID.OriginalFirstThunk)
        else
          IBN := Pointer(dwModule + IID.FirstThunk);
        pWrite := Pointer(dwModule + IID.FirstThunk);
        while IBN.Name1 <> 0 do
        begin
          if (IBN.Name1 and $80000000) <> 0 then
          begin
            pFunction := pWrite^;
            pMem := xVirtualAlloc(nil, 7, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
            if pMem <> nil then
            begin
              PByte(pMem)^ := $B8;
              PDWORD(DWORD(pMem) + 1)^ := DWORD(pFunction);
              PByte(DWORD(pMem) + 5)^ := $FF;
              PByte(DWORD(pMem) + 6)^ := $E0;
              pWrite^ := pMem;
            end;
          end
          else
          begin
            pFunction := pWrite^;
            pMem := xVirtualAlloc(nil, 7, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
            if pMem <> nil then
            begin
              PByte(pMem)^ := $B8;
              PDWORD(DWORD(pMem) + 1)^ := DWORD(pFunction);
              PByte(DWORD(pMem) + 5)^ := $FF;
              PByte(DWORD(pMem) + 6)^ := $E0;
              pWrite^ := pMem;
            end;
          end;
          Inc(IBN, SizeOf(IBN));
          Inc(pWrite);
          end;
        Inc(IID)
      end;
      Result := TRUE;
    end;
  end;
end;
end.

Usage:

RedirectAPIs(GetModuleHandle(nil));