Beispiel #1
0
// findpatch - Determines if the specified module has been patched to use the
//   specified replacement.
//
//  - importmodule (IN): Handle (base address) of the module to be searched to
//      see if it imports the specified replacement export.
//
//  - exportmodulename (IN): ANSI string containing the name of the module that
//      normally exports that import that would have been patched to use the
//      replacement export.
//
//  - replacement (IN): Address of the replacement, or destination, function or
//      variable to search for.
//
//  Return Value:
//
//    Returns TRUE if the module has been patched to use the specified
//    replacement export.
//
BOOL findpatch (HMODULE importmodule, moduleentry_t *module)
{
    IMAGE_IMPORT_DESCRIPTOR *idte;
    IMAGE_SECTION_HEADER    *section;
    ULONG                    size;

    // Locate the importing module's Import Directory Table (IDT) entry for the
    // exporting module. The importing module actually can have several IATs --
    // one for each export module that it imports something from. The IDT entry
    // gives us the offset of the IAT for the module we are interested in.
    EnterCriticalSection(&imagelock);
    idte = (IMAGE_IMPORT_DESCRIPTOR*)ImageDirectoryEntryToDataEx((PVOID)importmodule, TRUE,
        IMAGE_DIRECTORY_ENTRY_IMPORT, &size, &section);
    LeaveCriticalSection(&imagelock);
    if (idte == NULL) {
        // This module has no IDT (i.e. it imports nothing).
        return FALSE;
    }
    while (idte->OriginalFirstThunk != 0x0) {
        if (_stricmp((PCHAR)R2VA(importmodule, idte->Name), module->exportmodulename) == 0) {
            // Found the IDT entry for the exporting module.
            break;
        }
        idte++;
    }
    if (idte->OriginalFirstThunk == 0x0) {
        // The importing module does not import anything from the exporting
        // module.
        return FALSE;
    }

    int i = 0;
    patchentry_t *entry = module->patchtable;
    while(entry->importname)
    {
        LPCVOID replacement = entry->replacement;

        IMAGE_THUNK_DATA        *iate;

        // Locate the replacement's IAT entry.
        iate = (IMAGE_THUNK_DATA*)R2VA(importmodule, idte->FirstThunk);
        while (iate->u1.Function != 0x0) {
            if (iate->u1.Function == (DWORD_PTR)replacement) {
                // Found the IAT entry for the replacement. This patch has been
                // installed.
                return TRUE;
            }
            iate++;
        }
        entry++; i++;
    }

    // The module does not import the replacement. The patch has not been
    // installed.
    return FALSE;
}
Beispiel #2
0
// restoreimport - Restores the IAT entry for an import previously patched via
//   a call to "patchimport" to the original address of the import.
//
//  - importmodule (IN): Handle (base address) of the target module for which
//      calls or references to the import should be restored.
//
//  - exportmodule (IN): Handle (base address) of the module that exports the
//      function or variable to be patched.
//
//  - exportmodulename (IN): ANSI string containing the name of the module that
//      exports the function or variable to be patched.
//
//  - importname (IN): ANSI string containing the name of the imported function
//      or variable to be restored. May be an integer cast to a string if the
//      import is exported by ordinal.
//
//  - replacement (IN): Address of the function or variable which the import was
//      previously patched through to via a call to "patchimport".
//
//  Return Value:
//
//    None.
//   
VOID restoreimport (HMODULE importmodule, HMODULE exportmodule, LPCSTR exportmodulename, LPCSTR importname,
                    LPCVOID replacement)
{
    IMAGE_THUNK_DATA        *iate;
    IMAGE_IMPORT_DESCRIPTOR *idte;
    FARPROC                  import;
    DWORD                    protect;
    IMAGE_SECTION_HEADER    *section;
    ULONG                    size;

    // Locate the importing module's Import Directory Table (IDT) entry for the
    // exporting module. The importing module actually can have several IATs --
    // one for each export module that it imports something from. The IDT entry
    // gives us the offset of the IAT for the module we are interested in.
    EnterCriticalSection(&imagelock);
    idte = (IMAGE_IMPORT_DESCRIPTOR*)ImageDirectoryEntryToDataEx((PVOID)importmodule, TRUE,
                                                                  IMAGE_DIRECTORY_ENTRY_IMPORT, &size, &section);
    LeaveCriticalSection(&imagelock);
    if (idte == NULL) {
        // This module has no IDT (i.e. it imports nothing).
        return;
    }
    while (idte->OriginalFirstThunk != 0x0) {
        if (_stricmp((PCHAR)R2VA(importmodule, idte->Name), exportmodulename) == 0) {
            // Found the IDT entry for the exporting module.
            break;
        }
        idte++;
    }
    if (idte->OriginalFirstThunk == 0x0) {
        // The importing module does not import anything from the exporting
        // module.
        return;
    }
    
    // Get the *real* address of the import.
    import = GetProcAddress(exportmodule, importname);
    assert(import != NULL); // Perhaps the named export module does not actually export the named import?

    // Locate the import's original IAT entry (it currently has the replacement
    // address in it).
    iate = (IMAGE_THUNK_DATA*)R2VA(importmodule, idte->FirstThunk);
    while (iate->u1.Function != 0x0) {
        if (iate->u1.Function == (DWORD_PTR)replacement) {
            // Found the IAT entry. Overwrite the address stored in the IAT
            // entry with the import's real address. Note that the IAT entry may
            // be write-protected, so we must first ensure that it is writable.
            VirtualProtect(&iate->u1.Function, sizeof(iate->u1.Function), PAGE_READWRITE, &protect);
            iate->u1.Function = (DWORD_PTR)import;
            VirtualProtect(&iate->u1.Function, sizeof(iate->u1.Function), protect, &protect);
            break;
        }
        iate++;
    }
}
Beispiel #3
0
	// search in IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT for the special module
	BOOL ReplaceIATEntryInDelayImageImportTable(HANDLE hBaseAddress, LPCSTR lpszDllName, LPVOID pfnCurrent, LPVOID pfnNew)
	{
		DWORD dwSize = 0;
		PIMAGE_SECTION_HEADER pFoundHeader = NULL;
		PImgDelayDescr pImgDelayDescr
			= (PImgDelayDescr)ImageDirectoryEntryToDataEx( hBaseAddress
			, TRUE
			, IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
			, &dwSize
			, &pFoundHeader
			);
		if( pImgDelayDescr == NULL ){ return FALSE; }

		while (pImgDelayDescr->rvaDLLName)
		{
			try
			{
				if ( lstrcmpiA((CHAR*)((PBYTE)hBaseAddress+pImgDelayDescr->rvaDLLName), lpszDllName) == 0 )
				{
					break;
				}
			}
			catch(...)
			{

			}
			++pImgDelayDescr;
		}
		// Not found in IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
		if( !pImgDelayDescr->rvaDLLName )
			return FALSE;

		// retrieve IAT
		PIMAGE_THUNK_DATA pThunk = NULL;
		if( (pImgDelayDescr->grAttrs & dlattrRva) == 0 )
			return FALSE;
		pThunk = (PIMAGE_THUNK_DATA)(((LPBYTE)hBaseAddress) + pImgDelayDescr->rvaIAT); 

		// enumerate functions in the IAT
		while(pThunk->u1.Function)
		{
			PDWORD lpAddr = (PDWORD)&(pThunk->u1.Function);
			if(*lpAddr == (DWORD)pfnCurrent)
			{
				// modify the address
				::WriteProcessMemory(::GetCurrentProcess(), lpAddr, &pfnNew, sizeof(DWORD), NULL);
				return TRUE;
			} 
			pThunk++;
		}

		return FALSE;
	}
Beispiel #4
0
// findimport - Determines if the specified module imports the named import
//   from the named exporting module.
//
//  - importmodule (IN): Handle (base address) of the module to be searched to
//      see if it imports the specified import.
//
//  - exportmodule (IN): Handle (base address) of the module that exports the
//      import to be searched for.
//
//  - exportmodulename (IN): ANSI string containing the name of the module that
//      exports the import to be searched for.
//
//  - importname (IN): ANSI string containing the name of the import to search
//      for. May be an integer cast to a string if the import is exported by
//      ordinal.
//
//  Return Value:
//
//    Returns TRUE if the module imports to the specified import. Otherwise
//    returns FALSE.
//
BOOL findimport (HMODULE importmodule, HMODULE exportmodule, LPCSTR exportmodulename, LPCSTR importname)
{
    IMAGE_THUNK_DATA        *iate;
    IMAGE_IMPORT_DESCRIPTOR *idte;
    FARPROC                  import;
    IMAGE_SECTION_HEADER    *section;
    ULONG                    size;
            
    // Locate the importing module's Import Directory Table (IDT) entry for the
    // exporting module. The importing module actually can have several IATs --
    // one for each export module that it imports something from. The IDT entry
    // gives us the offset of the IAT for the module we are interested in.
    EnterCriticalSection(&imagelock);
    idte = (IMAGE_IMPORT_DESCRIPTOR*)ImageDirectoryEntryToDataEx((PVOID)importmodule, TRUE,
                                                                  IMAGE_DIRECTORY_ENTRY_IMPORT, &size, &section);
    LeaveCriticalSection(&imagelock);
    if (idte == NULL) {
        // This module has no IDT (i.e. it imports nothing).
        return FALSE;
    }
    while (idte->OriginalFirstThunk != 0x0) {
        if (_stricmp((PCHAR)R2VA(importmodule, idte->Name), exportmodulename) == 0) {
            // Found the IDT entry for the exporting module.
            break;
        }
        idte++;
    }
    if (idte->OriginalFirstThunk == 0x0) {
        // The importing module does not import anything from the exporting
        // module.
        return FALSE;
    }
    
    // Get the *real* address of the import. If we find this address in the IAT,
    // then we've found that the module does import the named import.
    import = GetProcAddress(exportmodule, importname);
    assert(import != NULL); // Perhaps the named export module does not actually export the named import?

    // Locate the import's IAT entry.
    iate = (IMAGE_THUNK_DATA*)R2VA(importmodule, idte->FirstThunk);
    while (iate->u1.Function != 0x0) {
        if (iate->u1.Function == (DWORD_PTR)import) {
            // Found the IAT entry. The module imports the named import.
            return TRUE;
        }
        iate++;
    }

    // The module does not import the named import.
    return FALSE;
}
Beispiel #5
0
	// search in IMAGE_IMPORT_DESCRIPTOR for the special module
	BOOL ReplaceIATEntryInImageImportTable(HANDLE hBaseAddress, LPCSTR lpszDllName, LPVOID pfnCurrent, LPVOID pfnNew)
	{
		try
		{
			DWORD dwSize = 0;
			PIMAGE_SECTION_HEADER pFoundHeader = NULL;
			PIMAGE_IMPORT_DESCRIPTOR pImgImportDescriptor
				= (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToDataEx( hBaseAddress
				, TRUE
				, IMAGE_DIRECTORY_ENTRY_IMPORT
				, &dwSize
				, &pFoundHeader
				);
			if( pImgImportDescriptor == NULL ){ return FALSE; }
			while (pImgImportDescriptor->Name)
			{
				if ( lstrcmpiA((CHAR*)((PBYTE)hBaseAddress+pImgImportDescriptor->Name), lpszDllName) == 0 )
				{
					break; // found
				}
				++pImgImportDescriptor;
			}
			if( !pImgImportDescriptor->Name )
				return ReplaceIATEntryInDelayImageImportTable( hBaseAddress, lpszDllName, pfnCurrent, pfnNew);

			// retrieve IAT
			PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)(((LPBYTE)hBaseAddress) + pImgImportDescriptor->FirstThunk);

			// enumerate functions in the IAT
			while(pThunk->u1.Function)
			{
				PDWORD lpAddr = (PDWORD)&(pThunk->u1.Function);
				if(*lpAddr == (DWORD)pfnCurrent)
				{
					// modify the address
					if(::WriteProcessMemory(::GetCurrentProcess(), lpAddr, &pfnNew, sizeof(DWORD), NULL))
						return TRUE;
					else
						return FALSE;
				} 
				pThunk++;
			}
		}
		catch(...)
		{

		}
		return FALSE;
	}
Beispiel #6
0
void *PeGetProcAddressA(void *Base, LPCSTR Name)
{
	DWORD Tmp;

	IMAGE_NT_HEADERS *NT=ImageNtHeader(Base);
	IMAGE_EXPORT_DIRECTORY *Exp=(IMAGE_EXPORT_DIRECTORY*)ImageDirectoryEntryToDataEx(Base,TRUE,IMAGE_DIRECTORY_ENTRY_EXPORT,&Tmp,0);
	if(Exp==0 || Exp->NumberOfFunctions==0)
	{
		SetLastError(ERROR_NOT_FOUND);
		return 0;
	}

	DWORD *Names=(DWORD*)(Exp->AddressOfNames+(DWORD_PTR)Base);
	WORD *Ordinals=(WORD*)(Exp->AddressOfNameOrdinals+(DWORD_PTR)Base);
	DWORD *Functions=(DWORD*)(Exp->AddressOfFunctions+(DWORD_PTR)Base);

	FARPROC Ret=0;

	if((DWORD_PTR)Name<65536)
	{
		if((DWORD_PTR)Name-Exp->Base<Exp->NumberOfFunctions)
			Ret=(FARPROC)(Functions[(DWORD_PTR)Name-Exp->Base]+(DWORD_PTR)Base);
	} 
	else
	{
		for(DWORD i=0; i<Exp->NumberOfNames && Ret==0; i++)
		{
			char *Func=(char*)(Names[i]+(DWORD_PTR)Base);
			if(Func && strcmp(Func,Name)==0)
				Ret=(FARPROC)(Functions[Ordinals[i]]+(DWORD_PTR)Base);
		}
	}

	if(Ret)
	{
		DWORD ExpStart=NT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress+(DWORD)Base;
		DWORD ExpSize=NT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
		if((DWORD)Ret>=ExpStart && (DWORD)Ret<=ExpStart+ExpSize)
		{
			return 0;
		}
		return Ret;
	}

	return 0;	
}
Beispiel #7
0
/***********************************************************************
 *         ImageDirectoryEntryToData   (DBGHELP.@)
 *
 * NOTES
 *   See ImageDirectoryEntryToDataEx
 */
PVOID WINAPI ImageDirectoryEntryToData( PVOID base, BOOLEAN image, USHORT dir, PULONG size )
{
    return ImageDirectoryEntryToDataEx( base, image, dir, size, NULL );
}
Beispiel #8
0
int main(int argc, char** argv)
{
  if (argc != 2) {
    fprintf(stderr, "usage: fileid <file>\n");
    return 1;
  }

  HANDLE file = CreateFileA(argv[1],
                            GENERIC_READ,
                            FILE_SHARE_READ,
                            nullptr,
                            OPEN_EXISTING,
                            FILE_ATTRIBUTE_NORMAL,
                            nullptr);
  if (file == INVALID_HANDLE_VALUE) {
    fprintf(stderr, "Couldn't open file: %s\n", argv[1]);
    return 1;
  }

  HANDLE mapFile = CreateFileMappingA(file, NULL, PAGE_READONLY, 0, 0, 0);
  if (mapFile == nullptr) {
    fprintf(stderr, "Couldn't create file mapping\n");
    CloseHandle(file);
    return 1;
  }

  uint8_t* base = reinterpret_cast<uint8_t*>(MapViewOfFile(mapFile,
                                                           FILE_MAP_READ,
                                                           0,
                                                           0,
                                                           0));
  if (base == nullptr) {
    fprintf(stderr, "Couldn't map file\n");
    CloseHandle(mapFile);
    CloseHandle(file);
    return 1;
  }

  DWORD size;
  PIMAGE_DEBUG_DIRECTORY debug_dir =
    reinterpret_cast<PIMAGE_DEBUG_DIRECTORY>(
      ImageDirectoryEntryToDataEx(base,
                                  FALSE,
                                  IMAGE_DIRECTORY_ENTRY_DEBUG,
                                  &size,
                                  nullptr));

  bool found = false;
  if (debug_dir->Type == IMAGE_DEBUG_TYPE_CODEVIEW) {
    CV_INFO_PDB70* cv =
      reinterpret_cast<CV_INFO_PDB70*>(base + debug_dir->PointerToRawData);
    if (cv->CvSignature == CV_SIGNATURE_RSDS) {
      found = true;
      print_guid(cv->Signature, cv->Age);
    }
  }

  UnmapViewOfFile(base);
  CloseHandle(mapFile);
  CloseHandle(file);

  return found ? 0 : 1;
}
Beispiel #9
0
bool PLH::IATHook::FindIATFunc(const char* LibraryName,const char* FuncName, PIMAGE_THUNK_DATA* pFuncThunkOut,const char* Module)
{
	bool UseModuleName = true;
	if (Module == NULL || Module[0] == '\0')
		UseModuleName = false;

	HINSTANCE hInst = GetModuleHandleA(UseModuleName ? Module:NULL);
	if (!hInst)
	{
		PostError(RuntimeError(RuntimeError::Severity::UnRecoverable, "PolyHook IATHook:Failed to find Module"));
		return false;
	}

	ULONG Sz;
	PIMAGE_IMPORT_DESCRIPTOR pImports = (PIMAGE_IMPORT_DESCRIPTOR)
		ImageDirectoryEntryToDataEx(hInst, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &Sz, nullptr);

	for (int i = 0; pImports[i].Characteristics != 0; i++)
	{
		char* _ModuleName = (char*)ResolveRVA(hInst, pImports[i].Name);
		if (_stricmp(_ModuleName, LibraryName) != 0)
			continue;

		//Original holds the API Names
		PIMAGE_THUNK_DATA pOriginalThunk = (PIMAGE_THUNK_DATA)
			ResolveRVA(hInst, pImports->OriginalFirstThunk);

		//FirstThunk is overwritten by loader with API addresses, we change this
		PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)
			ResolveRVA(hInst, pImports->FirstThunk);
		
		if (!pOriginalThunk)
		{
			PostError(RuntimeError(RuntimeError::Severity::Critical, "PolyHook IATHook:PE Files without OriginalFirstThunk are unsupported"));
			return false;
		}

		//Table is null terminated, increment both tables
		for (; pOriginalThunk->u1.Function != NULL; pOriginalThunk++,pThunk++)
		{
			if (IMAGE_SNAP_BY_ORDINAL(pOriginalThunk->u1.Ordinal))
			{
				XTrace("Import By Ordinal:[Ordinal:%d]\n",IMAGE_ORDINAL(pOriginalThunk->u1.Ordinal));
				continue;
			}

			PIMAGE_IMPORT_BY_NAME pImport = (PIMAGE_IMPORT_BY_NAME)
				ResolveRVA(hInst, pOriginalThunk->u1.AddressOfData);

			XTrace("Import By Name: [Ordinal:%d] [Name:%s]\n", IMAGE_ORDINAL(pOriginalThunk->u1.Ordinal),pImport->Name);

			//Check the name of API given by OriginalFirthThunk
			if (_stricmp(FuncName, pImport->Name) != 0)
				continue;
			
			/*Name matched in OriginalFirstThunk, return FirstThunk
			so we can changed it's address*/
			*pFuncThunkOut = pThunk;
			return true;
		}
	}
	PostError(RuntimeError(RuntimeError::Severity::UnRecoverable, "PolyHook IATHook:Failed to find import"));
	return false;
}
Beispiel #10
0
// patchimport - Patches all future calls to an imported function, or references
//   to an imported variable, through to a replacement function or variable.
//   Patching is done by replacing the import's address in the specified target
//   module's Import Address Table (IAT) with the address of the replacement
//   function or variable.
//
//  - importmodule (IN): Handle (base address) of the target module for which
//      calls or references to the import should be patched.
//
//  - exportmodule (IN): Handle (base address) of the module that exports the
//      the function or variable to be patched.
//
//  - exportmodulename (IN): ANSI string containing the name of the module that
//      exports the function or variable to be patched.
//
//  - importname (IN): ANSI string containing the name of the imported function
//      or variable to be patched. May be an integer cast to a string if the
//      import is exported by ordinal.
//
//  - replacement (IN): Address of the function or variable to which future
//      calls or references should be patched through to. This function or
//      variable can be thought of as effectively replacing the original import
//      from the point of view of the module specified by "importmodule".
//
//  Return Value:
//
//    Returns TRUE if the patch was installed into the import module. If the
//    import module does not import the specified export, so nothing changed,
//    then FALSE will be returned.
//   
BOOL patchimport (HMODULE importmodule, moduleentry_t *module)
{
    DWORD result = 0;
    HMODULE exportmodule = (HMODULE)module->modulebase;
    LPCSTR exportmodulename = module->exportmodulename;

    IMAGE_IMPORT_DESCRIPTOR *idte;
    IMAGE_SECTION_HEADER    *section;
    ULONG                    size;

    // Locate the importing module's Import Directory Table (IDT) entry for the
    // exporting module. The importing module actually can have several IATs --
    // one for each export module that it imports something from. The IDT entry
    // gives us the offset of the IAT for the module we are interested in.
    EnterCriticalSection(&imagelock);
    idte = (IMAGE_IMPORT_DESCRIPTOR*)ImageDirectoryEntryToDataEx((PVOID)importmodule, TRUE,
        IMAGE_DIRECTORY_ENTRY_IMPORT, &size, &section);
    LeaveCriticalSection(&imagelock);
    if (idte == NULL) {
        // This module has no IDT (i.e. it imports nothing).
        return FALSE;
    }
    while (idte->FirstThunk != 0x0) {
        if (_stricmp((PCHAR)R2VA(importmodule, idte->Name), exportmodulename) == 0) {
            // Found the IDT entry for the exporting module.
            break;
        }
        idte++;
    }
    if (idte->FirstThunk == 0x0) {
        // The importing module does not import anything from the exporting
        // module.
        return FALSE;
    }

    patchentry_t *entry = module->patchtable;
    int i = 0;
    while(entry->importname)
    {
        LPCSTR importname   = entry->importname;
        LPCVOID replacement = entry->replacement;
        IMAGE_THUNK_DATA        *iate;
        DWORD                    protect;
        FARPROC                  import = NULL;
        FARPROC                  import2 = NULL;

        // Get the *real* address of the import. If we find this address in the IAT,
        // then we've found the entry that needs to be patched.
        import2 = VisualLeakDetector::_RGetProcAddress(exportmodule, importname);
        import = GetProcAddress(exportmodule, importname);
        if ( import2 )
            import = import2;

        assert(import != NULL); // Perhaps the named export module does not actually export the named import?

        // Locate the import's IAT entry.
        iate = (IMAGE_THUNK_DATA*)R2VA(importmodule, idte->FirstThunk);
        while (iate->u1.Function != 0x0) {
            if (iate->u1.Function == (DWORD_PTR)import) {
                // Found the IAT entry. Overwrite the address stored in the IAT
                // entry with the address of the replacement. Note that the IAT
                // entry may be write-protected, so we must first ensure that it is
                // writable.
                if ( import != replacement )
                {
                    VirtualProtect(&iate->u1.Function, sizeof(iate->u1.Function), PAGE_READWRITE, &protect);
                    iate->u1.Function = (DWORD_PTR)replacement;
                    VirtualProtect(&iate->u1.Function, sizeof(iate->u1.Function), protect, &protect);
                }
                // The patch has been installed in the import module.
                result++;
            }
            iate++;
        }
        entry++; i++;
    }

    // The import's IAT entry was not found. The importing module does not
    // import the specified import.
    return result > 0;
}