Пример #1
0
/*
  Get the relative address of the 32-bit LoadLibraryW function from 64-bit code.
  This was originally done via executing a helper program (errout-LLW.exe), but
  I never liked doing that, so now I do it the "hard" way - load the 32-bit
  kernel32.dll directly and search the exports.
*/
BOOL get_LLW32( void )
{
  HMODULE kernel32;
  TCHAR   buf[MAX_PATH];
  UINT	  len;
  PIMAGE_NT_HEADERS32	  pNTHeader;
  PIMAGE_EXPORT_DIRECTORY pExportDir;
  PDWORD  fun_table, name_table;
  PWORD   ord_table;
  PDWORD  pLLW;

  len = GetSystemWow64Directory( buf, MAX_PATH );
  wcscpy( buf + len, L"\\kernel32.dll" );
  // MinGW-w64 had a typo, calling it LINRARY.
  kernel32 = LoadLibraryEx( buf, NULL, 0x20/*LOAD_LIBRARY_AS_IMAGE_RESOURCE*/ );
  if (kernel32 == NULL)
    return FALSE;

  // The handle uses low bits as flags, so strip 'em off.
  pDosHeader = (PIMAGE_DOS_HEADER)((DWORD_PTR)kernel32 & ~0xFFFF);
  pNTHeader  = MakeVA( PIMAGE_NT_HEADERS32, pDosHeader->e_lfanew );
  pExportDir = MakeVA( PIMAGE_EXPORT_DIRECTORY,
		       pNTHeader->OptionalHeader.
			DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].
			 VirtualAddress );

  fun_table  = MakeVA( PDWORD, pExportDir->AddressOfFunctions );
  name_table = MakeVA( PDWORD, pExportDir->AddressOfNames );
  ord_table  = MakeVA( PWORD,  pExportDir->AddressOfNameOrdinals );

  pLLW = bsearch( "LoadLibraryW", name_table, pExportDir->NumberOfNames,
		  sizeof(DWORD), export_cmp );
  if (pLLW == NULL)
  {
    FreeLibrary( kernel32 );
    return FALSE;
  }
  LLW32 = fun_table[ord_table[pLLW - name_table]];

  FreeLibrary( kernel32 );
  return TRUE;
}
Пример #2
0
BOOL HookAPIOneMod(
    HMODULE hFromModule,	// Handle of the module to intercept calls from
    PHookFn Hooks,		// Functions to replace
    BOOL    restore		// Restore the original functions
    )
{
  PIMAGE_DOS_HEADER	   pDosHeader;
  PIMAGE_NT_HEADERS	   pNTHeader;
  PIMAGE_IMPORT_DESCRIPTOR pImportDesc;
  PIMAGE_THUNK_DATA	   pThunk;
  PHookFn		   hook;

  // Tests to make sure we're looking at a module image (the 'MZ' header)
  pDosHeader = (PIMAGE_DOS_HEADER)hFromModule;
  if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
    return FALSE;

  // The MZ header has a pointer to the PE header
  pNTHeader = MakeVA( PIMAGE_NT_HEADERS, pDosHeader->e_lfanew );

  // One more test to make sure we're looking at a "PE" image
  if (pNTHeader->Signature != IMAGE_NT_SIGNATURE)
    return FALSE;

  // We now have a valid pointer to the module's PE header.
  // Get a pointer to its imports section.
  pImportDesc = MakeVA( PIMAGE_IMPORT_DESCRIPTOR,
			pNTHeader->OptionalHeader.
			 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].
			  VirtualAddress );

  // Bail out if the RVA of the imports section is 0 (it doesn't exist)
  if (pImportDesc == (PIMAGE_IMPORT_DESCRIPTOR)pDosHeader)
    return TRUE;

  // Iterate through the array of imported module descriptors, looking
  // for the module whose name matches the pszFunctionModule parameter.
  for (; pImportDesc->Name; pImportDesc++)
  {
    BOOL kernel = TRUE;
    PSTR pszModName = MakeVA( PSTR, pImportDesc->Name );
    if (_stricmp( pszModName, APIKernel ) != 0)
    {
      PAPI_DATA lib;
      for (lib = APIs; lib->name; ++lib)
      {
	if (_strnicmp( pszModName, lib->name, lib->len ) == 0)
	{
	  if (lib->base == NULL)
	  {
	    lib->base = GetModuleHandleA( pszModName );
	    for (hook = Hooks; hook->name; ++hook)
	      if (hook->lib == lib->name)
		hook->apifunc = GetProcAddress( lib->base, hook->name );
	  }
	  break;
	}
      }
      if (lib->name == NULL)
	continue;
      kernel = FALSE;
    }

    // Get a pointer to the found module's import address table (IAT).
    pThunk = MakeVA( PIMAGE_THUNK_DATA, pImportDesc->FirstThunk );

    // Blast through the table of import addresses, looking for the ones
    // that match the original addresses.
    while (pThunk->u1.Function)
    {
      for (hook = Hooks; hook->name; ++hook)
      {
	PROC patch = 0;
	if (restore)
	{
	  if ((PROC)pThunk->u1.Function == hook->newfunc)
	    patch = (kernel) ? hook->oldfunc : hook->apifunc;
	}
	else if ((PROC)pThunk->u1.Function == hook->oldfunc ||
		 (PROC)pThunk->u1.Function == hook->apifunc)
	{
	  patch = hook->newfunc;
	}
	if (patch)
	{
	  DWORD flOldProtect, flNewProtect, flDummy;
	  MEMORY_BASIC_INFORMATION mbi;

	  // Get the current protection attributes.
	  VirtualQuery( &pThunk->u1.Function, &mbi, sizeof(mbi) );
	  // Take the access protection flags.
	  flNewProtect = mbi.Protect;
	  // Remove ReadOnly and ExecuteRead flags.
	  flNewProtect &= ~(PAGE_READONLY | PAGE_EXECUTE_READ);
	  // Add on ReadWrite flag
	  flNewProtect |= (PAGE_READWRITE);
	  // Change the access protection on the region of committed pages in the
	  // virtual address space of the current process.
	  VirtualProtect( &pThunk->u1.Function, sizeof(PVOID),
			  flNewProtect, &flOldProtect );

	  // Overwrite the original address with the address of the new function.
	  if (!WriteProcessMemory( GetCurrentProcess(),
				   &pThunk->u1.Function,
				   &patch, sizeof(patch), NULL ))
	  {
	    return FALSE;
	  }

	  // Put the page attributes back the way they were.
	  VirtualProtect( &pThunk->u1.Function, sizeof(PVOID),
			  flOldProtect, &flDummy );
	}
      }
      pThunk++; // Advance to next imported function address
    }
  }

  return TRUE;	// Function not found
}
Пример #3
0
DWORD GetProcRVA( LPCTSTR module, LPCSTR func )
#endif
{
    HMODULE hMod;
    TCHAR   buf[MAX_PATH];
    UINT	  len;
    PIMAGE_NT_HEADERS	  pNTHeader;
    PIMAGE_EXPORT_DIRECTORY pExportDir;
    PDWORD  fun_table, name_table;
    PWORD   ord_table;
    PDWORD  pFunc;
    DWORD   rva;

#ifdef _WIN64
    if (bits == 32)
        len = GetSystemWow64Directory( buf, MAX_PATH );
    else
#endif
        len = GetSystemDirectory( buf, MAX_PATH );
    buf[len++] = '\\';
    wcscpy( buf + len, module );
    hMod = LoadLibraryEx( buf, NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE );
    if (hMod == NULL)
    {
#ifdef _WIN64
        DEBUGSTR( 1, L"Unable to load %d-bit %s (%lu)!",
                  bits, module, GetLastError() );
#else
        DEBUGSTR( 1, L"Unable to load %s (%lu)!", module, GetLastError() );
#endif
        return 0;
    }
    // The handle uses low bits as flags, so strip 'em off.
    pDosHeader = (PIMAGE_DOS_HEADER)((DWORD_PTR)hMod & ~0xFFFF);
    pNTHeader  = MakeVA( PIMAGE_NT_HEADERS, pDosHeader->e_lfanew );
#ifdef _WIN64
    if (bits == 32)
        pExportDir	= MakeVA( PIMAGE_EXPORT_DIRECTORY,
                              ((PIMAGE_NT_HEADERS32)pNTHeader)->EXPORTDIR.VirtualAddress );
    else
#endif
        pExportDir = MakeVA( PIMAGE_EXPORT_DIRECTORY,
                             pNTHeader->EXPORTDIR.VirtualAddress );
    fun_table  = MakeVA( PDWORD, pExportDir->AddressOfFunctions );
    name_table = MakeVA( PDWORD, pExportDir->AddressOfNames );
    ord_table  = MakeVA( PWORD,  pExportDir->AddressOfNameOrdinals );

    pFunc = bsearch( func, name_table, pExportDir->NumberOfNames,
                     sizeof(DWORD), export_cmp );
    if (pFunc == NULL)
    {
#ifdef _WIN64
        DEBUGSTR( 1, L"Could not find %d-bit %s!", bits, func );
#else
        DEBUGSTR( 1, L"Could not find %s!", func );
#endif
        rva = 0;
    }
    else
    {
        rva = fun_table[ord_table[pFunc - name_table]];
    }
    FreeLibrary( hMod );
    return rva;
}
Пример #4
0
static int export_cmp( const void* a, const void* b )
{
    return strcmp( (LPCSTR)a, MakeVA( LPCSTR, *(const PDWORD)b ) );
}