Example #1
0
void GetLinkedModulesInfo(TCHAR *moduleName, CMString &buffer)
{
	HANDLE hDllFile = CreateFile(moduleName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hDllFile == INVALID_HANDLE_VALUE)
		return;

	HANDLE hDllMapping = CreateFileMapping(hDllFile, NULL, PAGE_READONLY, 0, 0, NULL);
	if (hDllMapping == INVALID_HANDLE_VALUE) {
		CloseHandle(hDllFile);
		return;
	}

	LPVOID dllAddr = MapViewOfFile(hDllMapping, FILE_MAP_READ, 0, 0, 0);

	static const TCHAR format[] = TEXT("    Plugin statically linked to missing module: %S\r\n");

	__try {
		PIMAGE_NT_HEADERS nthdrs = ImageNtHeader(dllAddr);

		ULONG tableSize;
		PIMAGE_IMPORT_DESCRIPTOR importData = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(dllAddr, FALSE,
			IMAGE_DIRECTORY_ENTRY_IMPORT, &tableSize);
		if (importData) {
			while (importData->Name) {
				char* moduleName = (char*)ImageRvaToVa(nthdrs, dllAddr, importData->Name, NULL);
				if (!SearchPathA(NULL, moduleName, NULL, NULL, 0, NULL))
					buffer.AppendFormat(format, moduleName);

				importData++; //go to next record
			}
		}

		bool found = false;
		PIMAGE_EXPORT_DIRECTORY exportData = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryEntryToData(dllAddr, FALSE,
			IMAGE_DIRECTORY_ENTRY_EXPORT, &tableSize);
		if (exportData) {
			ULONG* funcAddr = (ULONG*)ImageRvaToVa(nthdrs, dllAddr, exportData->AddressOfNames, NULL);
			for (unsigned i = 0; i < exportData->NumberOfNames && !found; ++i) {
				char* funcName = (char*)ImageRvaToVa(nthdrs, dllAddr, funcAddr[i], NULL);
				found = strcmp(funcName, "MirandaPluginInfoEx") == 0 || strcmp(funcName, "MirandaPluginInfo") == 0;
				if (strcmp(funcName, "DatabasePluginInfo") == 0) {
					buffer.Append(TEXT("    This dll is a Miranda database plugin, another database is active right now\r\n"));
					found = true;
				}
			}
		}
		if (!found)
			buffer.Append(TEXT("    This dll is not a Miranda plugin and should be removed from plugins directory\r\n"));
	}
	__except (EXCEPTION_EXECUTE_HANDLER) {}

	UnmapViewOfFile(dllAddr);
	CloseHandle(hDllMapping);
	CloseHandle(hDllFile);
}
Example #2
0
void APIHook::ReplaceIATInOneMod(PROC pfnOrig, PROC pfnNew)
{
	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
	MODULEENTRY32 me32 = {sizeof(MODULEENTRY32)};
	Module32First(hSnapshot, &me32);
	HMODULE hThisMod = GetModuleHandleA(m_strCurrentModule.data());
	do 
	{
		if (me32.hModule == hThisMod)
		{
			continue;
		}
		ULONG ulSize;
		PIMAGE_IMPORT_DESCRIPTOR pImportDesc = NULL;
		__try
		{
			pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(me32.hModule, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize);
		}
		__except (EXCEPTION_EXECUTE_HANDLER)
		{

		}
		if (pImportDesc == NULL)
			continue;
		for (; pImportDesc->Name; pImportDesc++)
		{
			PSTR pszName = (PSTR)((PBYTE)me32.hModule + pImportDesc->Name);
			//cout << pszName << endl;
			if (lstrcmpiA(m_strModule.data(), pszName) == 0)
			{
				PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)((PBYTE)me32.hModule + pImportDesc->FirstThunk);
				for (; pThunk->u1.Function; pThunk++) {

					// Get the address of the function address
					PROC* ppfn = (PROC*) &pThunk->u1.Function;

					// Is this the function we're looking for?
					BOOL bFound = (*ppfn == pfnOrig);
					if (bFound) {

						//PROC pfnNew = (PROC)Hook_ExitProcess;
						if (!WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew, sizeof(char*), NULL) &&
							ERROR_NOACCESS == GetLastError())
						{
							DWORD dwOldProtect;
							if (VirtualProtect(ppfn, sizeof(char*), PAGE_WRITECOPY, &dwOldProtect))
							{
								WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew, sizeof(char*), NULL);
								VirtualProtect(ppfn, sizeof(char*), dwOldProtect, &dwOldProtect);
							}
						}
						CloseHandle(hSnapshot);
						return ;
					}
				}
			}
		}
	} while (Module32Next(hSnapshot, &me32));
	CloseHandle(hSnapshot);
}
Example #3
0
 void InitTable()
 {
   IMAGE_IMPORT_DESCRIPTOR *pIID;
   DWORD base = (DWORD)hModule;
   DWORD size;
   pIID = (IMAGE_IMPORT_DESCRIPTOR*) ImageDirectoryEntryToData(hModule, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size); 
   while(pIID->FirstThunk != 0){
     char *name1 = (char*) (base+pIID->Name);
     static char modname[1024];
     strncpy(modname, name1, 1024);
     for (char *p = modname; *p; p++) *p = tolower(*p);
     if (strcmp(modname, "common.dll") == 0) {
       IMAGE_THUNK_DATA *piatthunk = (IMAGE_THUNK_DATA*) ( base + pIID->FirstThunk);
       IMAGE_THUNK_DATA *pintthunk = (IMAGE_THUNK_DATA*) ( base + *(DWORD*)pIID ); 
       while(piatthunk->u1.Function != 0) {
         char *name2 = (char*)(((IMAGE_IMPORT_BY_NAME*) (base+pintthunk->u1.AddressOfData))->Name);
         static char out[2048];
         sprintf(out, "%s.%s", modname, name2);
         IATAddress[out]=&piatthunk->u1.Function;
         RealAddress[out]=(void *)piatthunk->u1.Function;
         piatthunk++;
         pintthunk++;
       }
     }
     pIID++;
   }   
 }
Example #4
0
int InstallAPIHook(const char *modname, const char *fnname,
				   const char *targetmod, int newfn) {
	int len, i, *blah, lookingfor;
	unsigned long oldprotect;

	HANDLE hModule = GetModuleHandle(targetmod);
	if (!hModule) {
		DispMsg("Failed to get base of %s!", targetmod);
		return 0;
	}

	blah = (int *)ImageDirectoryEntryToData((void *)hModule,
		1, IMAGE_DIRECTORY_ENTRY_IAT, (unsigned long *)&len);
	lookingfor = (int)GetProcAddress(GetModuleHandle(modname), fnname);

	for (i = 0; i != len; i++) {
		if (lookingfor == blah[i])
			goto success;
	}

	DispMsg("Failed to find %s in IAT of %s!", fnname, modname);
	return 0;

success:
	VirtualProtect(&blah[i], sizeof(int), PAGE_EXECUTE_READWRITE, &oldprotect);
	blah[i] = newfn;
	VirtualProtect(&blah[i], sizeof(int), oldprotect, &oldprotect);
	return 1;
}
Example #5
0
void CAPIHook::ReplaceIATEntryInOneMod(PCSTR pszCalleeModName, 
   PROC pfnCurrent, PROC pfnNew, HMODULE hmodCaller) {

   // Get the address of the module's import section
   ULONG ulSize;

   // An exception was triggered by Explorer (when browsing the content of 
   // a folder) into imagehlp.dll. It looks like one module was unloaded...
   // Maybe some threading problem: the list of modules from Toolhelp might 
   // not be accurate if FreeLibrary is called during the enumeration.
   PIMAGE_IMPORT_DESCRIPTOR pImportDesc = NULL;
   __try {
      pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ImageDirectoryEntryToData(
         hmodCaller, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize);
   } 
   __except (InvalidReadExceptionFilter(GetExceptionInformation())) {
      // Nothing to do in here, thread continues to run normally
      // with NULL for pImportDesc 
   }
   
   if (pImportDesc == NULL)
      return;  // This module has no import section or is no longer loaded


   // Find the import descriptor containing references to callee's functions
   for (; pImportDesc->Name; pImportDesc++) {
      PSTR pszModName = (PSTR) ((PBYTE) hmodCaller + pImportDesc->Name);
      if (lstrcmpiA(pszModName, pszCalleeModName) == 0) {

         // Get caller's import address table (IAT) for the callee's functions
         PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA) 
            ((PBYTE) hmodCaller + pImportDesc->FirstThunk);

         // Replace current function address with new function address
         for (; pThunk->u1.Function; pThunk++) {

            // Get the address of the function address
            PROC* ppfn = (PROC*) &pThunk->u1.Function;

            // Is this the function we're looking for?
            BOOL bFound = (*ppfn == pfnCurrent);
            if (bFound) {
               if (!WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew, 
                    sizeof(pfnNew), NULL) && (ERROR_NOACCESS == GetLastError())) {
                  DWORD dwOldProtect;
                  if (VirtualProtect(ppfn, sizeof(pfnNew), PAGE_WRITECOPY, 
                     &dwOldProtect)) {

                     WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew, 
                        sizeof(pfnNew), NULL);
                     VirtualProtect(ppfn, sizeof(pfnNew), dwOldProtect, 
                        &dwOldProtect);
                  }
               }
               return;  // We did it, get out
            }
         }
      }  // Each import section is parsed until the right entry is found and patched
   }
}
Example #6
0
BOOL InstallHook(LPCSTR module, LPCSTR function, void* hook, void** original) {
	HMODULE process = GetModuleHandle(NULL);

	// Save original address to function
	*original = (void*)GetProcAddress(
		GetModuleHandleA(module), function);

	ULONG entrySize;

	IMAGE_IMPORT_DESCRIPTOR* iid =
		(IMAGE_IMPORT_DESCRIPTOR*)ImageDirectoryEntryToData(
			process,
			1,
			IMAGE_DIRECTORY_ENTRY_IMPORT,
			&entrySize);

	// Search for module
	while (iid->Name) {
		const char* name = ((char*)process) + iid->Name;

		if (_stricmp(name, module) == 0) {
			return ModifyImportTable(iid, *original, hook);
		}
		iid += 1;
	}

	return FALSE;
}
Example #7
0
void CAPIHook::ReplaceEATEntryInOneMod(HMODULE hmod, PCSTR pszFunctionName, 
   PROC pfnNew) {

   // Get the address of the module's export section
   ULONG ulSize;

   PIMAGE_EXPORT_DIRECTORY pExportDir = NULL;
   __try {
      pExportDir = (PIMAGE_EXPORT_DIRECTORY) ImageDirectoryEntryToData(
         hmod, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &ulSize);
   } 
   __except (InvalidReadExceptionFilter(GetExceptionInformation())) {
      // Nothing to do in here, thread continues to run normally
      // with NULL for pExportDir 
   }
   
   if (pExportDir == NULL)
      return;  // This module has no export section or is unloaded

   PDWORD pdwNamesRvas = (PDWORD) ((PBYTE) hmod + pExportDir->AddressOfNames);
   PWORD pdwNameOrdinals = (PWORD) 
      ((PBYTE) hmod + pExportDir->AddressOfNameOrdinals);
   PDWORD pdwFunctionAddresses = (PDWORD) 
      ((PBYTE) hmod + pExportDir->AddressOfFunctions);

   // Walk the array of this module's function names 
   for (DWORD n = 0; n < pExportDir->NumberOfNames; n++) {
      // Get the function name
      PSTR pszFuncName = (PSTR) ((PBYTE) hmod + pdwNamesRvas[n]);

      // If not the specified function, try the next function
      if (lstrcmpiA(pszFuncName, pszFunctionName) != 0) continue;

      // We found the specified function
      // --> Get this function's ordinal value
      WORD ordinal = pdwNameOrdinals[n];

      // Get the address of this function's address
      PROC* ppfn = (PROC*) &pdwFunctionAddresses[ordinal];
      
      // Turn the new address into an RVA
      pfnNew = (PROC) ((PBYTE) pfnNew - (PBYTE) hmod);

      // Replace current function address with new function address
      if (!WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew, 
         sizeof(pfnNew), NULL) && (ERROR_NOACCESS == GetLastError())) {
         DWORD dwOldProtect;
         if (VirtualProtect(ppfn, sizeof(pfnNew), PAGE_WRITECOPY, 
            &dwOldProtect)) {
            
            WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew, 
               sizeof(pfnNew), NULL);
            VirtualProtect(ppfn, sizeof(pfnNew), dwOldProtect, &dwOldProtect);
         }
      }
      break;  // We did it, get out
   }
}
Example #8
0
BOOL hook_getprocaddress()
{
    HMODULE vim;
    PIMAGE_IMPORT_DESCRIPTOR impdesc;
    PIMAGE_IMPORT_DESCRIPTOR kernel32;
    PIMAGE_THUNK_DATA lookuptbl;
    PIMAGE_THUNK_DATA addrtbl;
    MEMORY_BASIC_INFORMATION bufinfo;
    BOOL succeeded;
    DWORD oldprotect;
    DWORD retsize;
    int i;

    vim = GetModuleHandle(NULL);

    impdesc = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData((HMODULE)vim, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &retsize);
    if (retsize == 0) return FALSE;
    OutputDebugString("dynfont: importdir found");

    kernel32 = NULL;
    for (i = 0; impdesc[i].Characteristics != 0; ++i) {
        LPCSTR libname = (LPCSTR)((char*)vim + impdesc[i].Name);
        OutputDebugString(libname);
        if (lstrcmpi(libname, "KERNEL32.DLL") == 0) {
            kernel32 = &impdesc[i];
            break;
        }
    }
    if (kernel32 == NULL) return FALSE;
    OutputDebugString("dynfont: kernel32 found.");

    lookuptbl = (PIMAGE_THUNK_DATA)((char*)vim + kernel32->OriginalFirstThunk);
    addrtbl = (PIMAGE_THUNK_DATA)((char*)vim + kernel32->FirstThunk);
    for (; lookuptbl->u1.Function != 0; ++lookuptbl, ++addrtbl) {
        if (!IMAGE_SNAP_BY_ORDINAL(lookuptbl->u1.Ordinal)) {
           PIMAGE_IMPORT_BY_NAME impfun = (PIMAGE_IMPORT_BY_NAME)((char*)vim + lookuptbl->u1.AddressOfData);
            if (strcmp((LPCSTR)impfun->Name, "GetProcAddress") == 0) {
                break;
            }
        }
    }
    if (lookuptbl->u1.Function == 0) return FALSE;
    OutputDebugString("dynfont: getprocaddr found.");

    orig_GetProcAddress = (GETPROCADDRESS_PROTO)addrtbl->u1.Function;
    retsize = VirtualQuery((LPCVOID)&addrtbl->u1.Function, &bufinfo, sizeof(bufinfo));
    if (retsize == 0) return FALSE;
    succeeded = VirtualProtect(bufinfo.BaseAddress, bufinfo.RegionSize, PAGE_READWRITE, &oldprotect);
    if (succeeded == FALSE) return FALSE;
    addrtbl->u1.Function = (DWORD_PTR)oncall_GetProcAddress;
    VirtualProtect(bufinfo.BaseAddress, bufinfo.RegionSize, bufinfo.Protect, &oldprotect);
    OutputDebugString("dynfont: hooked.");
    return TRUE; 
}
Example #9
0
void SetupLibProfiling (LPCSTR ImageName, BOOL fFirstLevelCall)
{
	BOOL		fStat;
	PPROFBLK	pProfBlk;
	ULONG		ulImportSize;
	PIMAGE_IMPORT_DESCRIPTOR pImports;

    if (fFirstLevelCall)
    {
        // Get the GLOBAL semaphore... (valid accross all process contexts)
        // Prevents anyone else from updating profile block data
        if (WAIT_FAILED == WaitForSingleObject (hGlobalSem, INFINITE))
        {
             CapDbgPrint ("CAP:  CAP_GetLibSyms() - ERROR - "
                       "Wait for GLOBAL semaphore failed - 0x%lx\n",
                       GetLastError());
            return;
        }
    }

	// Setup profiling block for the module
	pProfBlk = SetupProfiling(ImageName);
	
	// If successfully loaded	
	if (pProfBlk != NULL && pProfBlk->ImageBase != NULL)
	{
    	// Locate the import array for this image/dll
    	pImports = (PIMAGE_IMPORT_DESCRIPTOR) ImageDirectoryEntryToData(pProfBlk->ImageBase,
                                 	TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ulImportSize);

		// Recursively call SetupLibProfiling on each imported dll
    	for (;pImports; pImports++)
    	{
        	if (!pImports->Name)
            	break;

       		SetupLibProfiling((PTCHAR)((ULONG)pProfBlk->ImageBase + pImports->Name), FALSE);
        }
    }

    if (fFirstLevelCall)
    {
        // Release the GLOBAL semaphore
        fStat = ReleaseSemaphore (hGlobalSem, 1, NULL);
        if (!fStat)
        {
            CapDbgPrint ("CAP:  CAP_GetLibSyms() - "
                      "Error releasing GLOBAL semaphore - 0x%lx\n", GetLastError());
        }
    }

    return;

}
Example #10
0
// ひとつのモジュールに対してAPIフックを行う関数
void CAPIHook::ReplaceIATEntryInOneMod(
									   PCSTR pszModuleName, 
									   PROC pfnCurrent, 
									   PROC pfnNew, 
									   HMODULE hmodCaller) 
{
	// モジュールのインポートセクションのアドレスを取得
	ULONG ulSize;
	PIMAGE_IMPORT_DESCRIPTOR pImportDesc;
	pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(
		hmodCaller, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize);

	// インポートセクションを持っていない
	if (pImportDesc == NULL)
		return;

	// インポートディスクリプタを検索
	while(pImportDesc->Name) {
		PSTR pszModName = (PSTR) ((PBYTE) hmodCaller + pImportDesc->Name);
		if (lstrcmpiA(pszModName, pszModuleName) == 0) 
			break;
		pImportDesc++;
	}

	// このモジュールは呼び出し先から関数をインポートしていない
	if (pImportDesc->Name == 0)
		return;

	// インポートアドレステーブルを取得
	PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA) 
		((PBYTE) hmodCaller + pImportDesc->FirstThunk);

	// 新しい関数アドレスに置き換える
	while(pThunk->u1.Function) {
		
		// 関数アドレスのアドレスを取得
		PROC *ppfn = (PROC*) &pThunk->u1.Function;

		// 該当関数であるならば発見!
		BOOL fFound = (*ppfn == pfnCurrent);

		if (fFound) {
			// アドレスが一致したので、インポートセクションのアドレスを書き換える
			DWORD dwDummy;
			VirtualProtect(ppfn, sizeof(ppfn), PAGE_EXECUTE_READWRITE, &dwDummy);
			WriteProcessMemory(
				GetCurrentProcess(), ppfn, &pfnNew, sizeof(pfnNew), NULL);
			return;
		}
		pThunk++;
	}
	// ここに処理が移った場合、インポートセクションに該当関数がなかったことになる
	return;
}
Example #11
0
void HookOnImport(HMODULE hModule, char *lpszImpModName, DWORD lpOrigFunc, DWORD lpNewFunc)
{
	ULONG ulSize;
	PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ImageDirectoryEntryToData(
		hModule, 
		TRUE,
		IMAGE_DIRECTORY_ENTRY_IMPORT,
		&ulSize);
	if(pImportDesc == NULL) return;

	for(; pImportDesc->Name; pImportDesc++) 
	{
		char *pszModName = (char *)((PBYTE)hModule + pImportDesc->Name);
		
		if (lstrcmpiA(lpszImpModName, pszModName) == 0)
		{
			PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)((PBYTE)hModule + pImportDesc->FirstThunk);

			for (; pThunk->u1.Function; pThunk++) 
			{
				DWORD* ppfn = (DWORD*) &pThunk->u1.Function;

				if(*ppfn == lpOrigFunc)
				{
					DWORD oldProtect;

					g_mod++;

					if(!VirtualProtect((LPVOID)ppfn, 4, PAGE_EXECUTE_READWRITE, &oldProtect))
					{
						if(!g_HookError)
						{
							TCHAR buf[200];

							g_HookError = TRUE;
							mir_sntprintf(buf, SIZEOF(buf), TranslateT("VirtualProtect failed. Code %d\nTry to call the author"), GetLastError());
							prevMessageBox(0, buf, TranslateT("Error"), MB_OK);
						}
					}
					*(DWORD*)ppfn = lpNewFunc;
					if(*(DWORD*)ppfn != lpNewFunc)
					{
						if(!g_HookError2)
						{
							g_HookError2 = TRUE;
							prevMessageBox(0, TranslateT("Hmm. Something goes wrong. I can't write into the memory.\nAnd as you can see, there are no any exception raised...\nTry to call the author"), TranslateT("Error"), MB_OK);
						}
					}
				}
			}
		}
	}
}
Example #12
0
FARPROC CHookAPI::HookAPI(LPCTSTR pstrDllName,LPCSTR pstrFuncName,FARPROC pfnNewFunc,HMODULE hModCaller)
{
	if(hModCaller==NULL)
		return NULL;

	ULONG size;
	//获取指向PE文件中的Import中IMAGE_DIRECTORY_DESCRIPTOR数组的指针
	PIMAGE_IMPORT_DESCRIPTOR pImportDesc=(PIMAGE_IMPORT_DESCRIPTOR)
		ImageDirectoryEntryToData(hModCaller,TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT,&size);
	if(pImportDesc==NULL)
		return NULL;
	HMODULE hModule=LoadLibrary(pstrDllName);
	//纪录函数地址
	FARPROC pfnOriginFunc=GetProcAddress(hModule,pstrFuncName);

	//查找记录,看看有没有我们想要的DLL
	USES_CONVERSION;
	char* pstrDest=W2A(pstrDllName);
	for(;pImportDesc->Name;pImportDesc++)
	{
		LPSTR pszDllName=(LPSTR)((PBYTE)hModCaller+pImportDesc->Name);
		if(lstrcmpiA(pszDllName,pstrDest)==0)
			break;
	}
	if(pImportDesc->Name==NULL)
	{
		return NULL;
	}
	//寻找我们想要的函数
	PIMAGE_THUNK_DATA pThunk=(PIMAGE_THUNK_DATA)((PBYTE)hModCaller+pImportDesc->FirstThunk);
	for(;pThunk->u1.Function;pThunk++)
	{
		//ppfn记录了与IAT表相应的地址
		PROC*ppfn=(PROC*)&pThunk->u1.Function ;
		if(*ppfn==pfnOriginFunc)
		{
			DWORD dwOldProtect;
			//修改内存包含属性
			VirtualProtect(ppfn, sizeof(DWORD), PAGE_READWRITE, &dwOldProtect);
			WriteProcessMemory(GetCurrentProcess(),ppfn,&(pfnNewFunc),sizeof(pfnNewFunc),NULL);
			return pfnOriginFunc;
		}
	}

	return NULL;
}
Example #13
0
static
//std::vector<WineModuleInfo> WineEnumModuleInfos(void)
void win32_find_implicit_tls(void)
{
    //std::vector<WineModuleInfo> v_result;
    HMODULE hMods[1024];
    DWORD cbNeeded;
    HANDLE hProcess = GetCurrentProcess();
    if(EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
    {
        for ( unsigned int i = 0; i < (cbNeeded / sizeof(HMODULE)); i++ )
        {
            MODULEINFO mi;
            GetModuleInformation(hProcess, hMods[i], &mi, sizeof(MODULEINFO));
            WineModuleInfo wmi;
            wmi.BaseAddress = (HMODULE)mi.lpBaseOfDll;
            //WINE_DBG("wmi.BaseAddress=0x%08x", wmi.BaseAddress);
            wmi.SizeOfImage = mi.SizeOfImage;
            wmi.EntryPoint  = mi.EntryPoint;
            wmi.FileFullPath = WineGetModuleFileName(wmi.BaseAddress);
            WineSplitPath v_split_path(wmi.FileFullPath);
            wmi.FileLocalName = v_split_path.FName + v_split_path.Ext;
            ULONG v_size;
            PIMAGE_TLS_DIRECTORY v_tls_dir = (PIMAGE_TLS_DIRECTORY)ImageDirectoryEntryToData(
                                                 (PVOID)wmi.BaseAddress,
                                                 TRUE,
                                                 IMAGE_DIRECTORY_ENTRY_TLS,
                                                 &v_size
                                             );
            if(v_tls_dir)
            {
                //WINE_DBG("WineEnumModuleInfos(): AddressOfIndex=0x%08x", v_tls_dir->AddressOfIndex);
                assert(v_tls_dir->AddressOfIndex);
                wmi.TlsIndex = (LONG)((DWORD *)v_tls_dir->AddressOfIndex)[0];
            }
            else
            {
                wmi.TlsIndex = -1;
            }
            v_result.push_back(wmi);
        }
    }
    return v_result;
}
Example #14
0
// http://ruffnex.oc.to/kenji/text/api_hook/ex2.cpp
// ひとつのモジュールに対してAPIフックを行う関数
bool ReplaceIATEntryInOneMod(
                             PCSTR pszModuleName,
                             PROC pfnCurrent,
                             PROC pfnNew,
                             HMODULE hmodCaller) 
{
	ULONG ulSize;
	PIMAGE_IMPORT_DESCRIPTOR pImportDesc;
	pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(
		hmodCaller, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize);

	if (pImportDesc == NULL) {
		return false;
	}

	while(pImportDesc->Name) {
		PSTR pszModName = (PSTR) ((PBYTE) hmodCaller + pImportDesc->Name);
		if (lstrcmpiA(pszModName, pszModuleName) == 0) 
			break;
		pImportDesc++;
	}

	if (pImportDesc->Name == 0) {
		return false;
	}

	PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA) 
		((PBYTE) hmodCaller + pImportDesc->FirstThunk);

	while(pThunk->u1.Function) {
		PROC *ppfn = (PROC*) &pThunk->u1.Function;
		BOOL fFound = (*ppfn == pfnCurrent);
		if (fFound) {
			DWORD dwDummy;
			VirtualProtect(ppfn, sizeof(ppfn), PAGE_EXECUTE_READWRITE, &dwDummy);
			WriteProcessMemory(
				GetCurrentProcess(), ppfn, &pfnNew, sizeof(pfnNew), NULL);
			return true;
		}
		pThunk++;
	}
	return false;
}
Example #15
0
void Replace( HMODULE hModule, // .idata를 가진 모듈의 주소
			  PCSTR	  dllname, // Hooking 할 함수를 가진 DLL이름
			  PROC	  oldfunc, // 훅킹할 API 함수.
			  PROC    newfunc) // 바꿀 함수 
{
	// 1. module 에서 .idata section 의주소를 찾는다.
	ULONG sz = 0;
	PIMAGE_IMPORT_DESCRIPTOR pImage = (PIMAGE_IMPORT_DESCRIPTOR)
						ImageDirectoryEntryToData( hModule, TRUE,
									IMAGE_DIRECTORY_ENTRY_IMPORT, & sz);

	// 2. .idata section 에서 원하는 Dll의 위치를 찾는다. 
	for ( ; pImage->Name; ++pImage )
	{
		char* p = ((char*)hModule + pImage->Name);

		if ( strcmpi( p, dllname) == 0 ) break; // 찾은 경우
	}
	//--------------------------------------------------------------
	// 3. Thunk Table 에서 원하는 주소를 얻는다.
	PIMAGE_THUNK_DATA pThunk = 
				(PIMAGE_THUNK_DATA)( (char*)hModule + pImage->FirstThunk);

	for ( ; pThunk->u1.Function; ++pThunk )
	{
		if ( (PROC)(pThunk->u1.Function) == oldfunc ) // 찾은 경우.
		{
			PROC* p = (PROC*)&(pThunk->u1.Function);

			// .idata section 부분의 보호 속성을 변경한다.
			DWORD old;
			VirtualProtect( p,		// 이 주소의 부터
							4,		// 4 Byte 를 
							PAGE_READWRITE,		// 읽고 쓰기로 
							&old);				// 이전 보호속성 리턴.



			*p = newfunc; // 덮어 쓴다.
		}
	}
}
Example #16
0
int
main(int argc, char *argv[])
{
	util_suppress_errmsg();
	if (argc < 2) {
		fprintf(stderr, "usage: %s dllname\n", argv[0]);
		exit(1);
	}

	const char *dllname = argv[1];

	LOADED_IMAGE img;
	if (MapAndLoad(dllname, NULL, &img, 1, 1) == FALSE) {
		fprintf(stderr, "cannot load DLL image\n");
		exit(2);
	}

	IMAGE_EXPORT_DIRECTORY *dir;
	ULONG dirsize;
	dir = (IMAGE_EXPORT_DIRECTORY *)ImageDirectoryEntryToData(
			img.MappedAddress, 0 /* mapped as image */,
			IMAGE_DIRECTORY_ENTRY_EXPORT, &dirsize);
	if (dir == NULL) {
		fprintf(stderr, "cannot read image directory\n");
		UnMapAndLoad(&img);
		exit(3);
	}

	DWORD *rva;
	rva = (DWORD *)ImageRvaToVa(img.FileHeader, img.MappedAddress,
			dir->AddressOfNames, NULL);

	for (DWORD i = 0; i < dir->NumberOfNames; i++) {
		char *name = (char *)ImageRvaToVa(img.FileHeader,
				img.MappedAddress, rva[i], NULL);
		printf("%s\n", name);
	}

	UnMapAndLoad(&img);
	return 0;
}
Example #17
0
VOID
Dummy (
    VOID
    )
{
    PVOID Base;
    ULONG size;
    PIMAGE_LOAD_CONFIG_DIRECTORY loadConfig;
    DWORD old;
    PIMAGE_NT_HEADERS64 ntHeaders;

    //
    // Hardcoded for notepad -- get its base address
    //
    Base = GetModuleHandle("notepad.exe");

    //
    // Get the NT headers
    //
    ntHeaders = ImageNtHeader(Base);

    //
    // Get the load config directory
    //
    loadConfig = ImageDirectoryEntryToData(Base, TRUE, IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, &size);

    //
    // Make the CFG pointer writeable
    //
    VirtualProtect((PVOID)loadConfig->GuardCFCheckFunctionPointer, sizeof(PVOID), PAGE_READWRITE, &old);

    //
    // Take over it
    //
    *(PVOID*)loadConfig->GuardCFCheckFunctionPointer = (PVOID)(ULONG_PTR)CfgHook;

    //
    // Restore protection
    //
    VirtualProtect((PVOID)loadConfig->GuardCFCheckFunctionPointer, sizeof(PVOID), old, &old);
}
Example #18
0
///////////////////////////////////// HookOneAPI 函数 /////////////////////////////////////////   
//进行IAT转换的关键函数,其参数含义:   
//pszCalleeModuleName:需要hook的模块名   
//pfnOriginApiAddress:要替换的自己API函数的地址   
//pfnDummyFuncAddress:需要hook的模块名的地址   
//hModCallerModule:我们要查找的模块名称,如果没有被赋值,   
//     将会被赋值为枚举的程序所有调用的模块   
void WINAPI HookOneAPI(LPCTSTR pszCalleeModuleName,PROC pfnOriginApiAddress,    
	PROC pfnDummyFuncAddress,HMODULE hModCallerModule)   
{   
	
	ULONG size;   
	short sts =0;
	//获取指向PE文件中的Import中IMAGE_DIRECTORY_DESCRIPTOR数组的指针   
	PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)   
		ImageDirectoryEntryToData(hModCallerModule,TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT,&size);   
	MY_ASSERT (pImportDesc != NULL) ;
	//查找记录,看看有没有我们想要的DLL   
	for (;pImportDesc->Name;pImportDesc++)   
	{   
		LPSTR pszDllName = (LPSTR)((PBYTE)hModCallerModule+pImportDesc->Name);   
		if (lstrcmpiA(pszDllName,pszCalleeModuleName) == 0)   
			break;   
	}   
	MY_ASSERT (pImportDesc->Name != NULL) ;
	//寻找我们想要的函数   
	PIMAGE_THUNK_DATA pThunk =    
		(PIMAGE_THUNK_DATA)((PBYTE)hModCallerModule+pImportDesc->FirstThunk);//IAT   
	BOOL bFind=0;
	for (;pThunk->u1.Function;pThunk++)   
	{   
		//ppfn记录了与IAT表项相应的函数的地址   
		PROC * ppfn= (PROC *)&pThunk->u1.Function;     
		if (*ppfn == pfnOriginApiAddress)    
		{   
			//如果地址相同,也就是找到了我们想要的函数,进行改写,将其指向我们所定义的函数   
			MY_ASSERT(WriteProcessMemory(GetCurrentProcess(),ppfn,&(pfnDummyFuncAddress),   
				sizeof(pfnDummyFuncAddress),NULL));   
			bFind=1;
			break;
		}   
	} 
	MY_ASSERT(bFind);
Exit:
	TRACE("HookOneAPI %s %x->%x %x %d\n",pszCalleeModuleName,pfnOriginApiAddress, pfnDummyFuncAddress,hModCallerModule, sts);
}   
Example #19
0
HRESULT
GetExportsFromFile(
    _In_ HMODULE hmod,
    _Out_ PEXPORT_DATA* ppExportData)
{
    PBYTE pjImageBase;
    PIMAGE_EXPORT_DIRECTORY pExportDir;
    ULONG i, cjExportSize, cFunctions, cjTableSize;
    PEXPORT_DATA pExportData;
    PULONG pulAddressTable, pulNameTable;
    PUSHORT pusOrdinalTable;

    pjImageBase = (PBYTE)hmod;

    /* Get the export directory */
    pExportDir = ImageDirectoryEntryToData(pjImageBase,
                                           TRUE,
                                           IMAGE_DIRECTORY_ENTRY_EXPORT,
                                           &cjExportSize);
    if (pExportDir == NULL)
    {
        fprintf(stderr, "Failed to get export directory\n");
        return E_FAIL;
    }

    cFunctions = pExportDir->NumberOfFunctions;
    cjTableSize = FIELD_OFFSET(EXPORT_DATA, aExports[cFunctions]);

    pExportData = malloc(cjTableSize);
    if (pExportData == NULL)
    {
        error("Failed to allocate %u bytes of memory for export table\n", cjTableSize);
        return E_OUTOFMEMORY;
    }

    RtlZeroMemory(pExportData, cjTableSize);

    pulAddressTable = (PULONG)(pjImageBase + pExportDir->AddressOfFunctions);

    pExportData->cNumberOfExports = cFunctions;

    /* Loop through the function table */
    for (i = 0; i < cFunctions; i++)
    {
        PVOID pvFunction = (pjImageBase + pulAddressTable[i]);

        /* Check if this is a forwarder */
        if ((ULONG_PTR)((PUCHAR)pvFunction - (PUCHAR)pExportDir) < cjExportSize)
        {
            pExportData->aExports[i].pszForwarder = _strdup(pvFunction);
        }
        else
        {
            pExportData->aExports[i].ulRva = pulAddressTable[i];
        }
    }

    pulNameTable = (PULONG)(pjImageBase + pExportDir->AddressOfNames);
    pusOrdinalTable = (PUSHORT)(pjImageBase + pExportDir->AddressOfNameOrdinals);

    /* Loop through the name table */
    for (i = 0; i < pExportDir->NumberOfNames; i++)
    {
        ULONG iIndex = pusOrdinalTable[i];
        PSTR pszName = (PSTR)(pjImageBase + pulNameTable[i]);

        pExportData->aExports[iIndex].pszName = _strdup(pszName);
    }

    *ppExportData = pExportData;
    return S_OK;
}
//---------------------------------------------------------------------------
//ReplaceIATEntryInModule
void WINAPI TAPIHook::ReplaceIATEntryInModule(PCSTR DllName,
  PROC pfnCurrent,PROC pfnNew,HMODULE hModCaller)
{
  // 查询模块函数引入表的地址
  DWORD ulSize;
  PIMAGE_IMPORT_DESCRIPTOR pImportDesc;

  pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(hModCaller, true,
					    IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize);

  if(pImportDesc == NULL)
    return ;  // 模块没有函数引入表

  // 查询模块是否引入了某个DLL的函数
  for(;pImportDesc->Name; pImportDesc++)
  {
    PSTR pszModName = (PSTR) ((PBYTE)hModCaller + pImportDesc->Name);
    if(lstrcmpiA(pszModName, DllName) == 0)
      break;   // Found
  }

  if(pImportDesc->Name == 0)
    return ;  // 这个模块没有引入指定DLL的函数

  //查询模块是否在DLL中引入了指定的函数
  PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)((PBYTE)hModCaller + pImportDesc->FirstThunk);

  for(; pThunk->u1.Function; pThunk++)
  {
    // 得到这个模块引入的每一个函数的地址
    PROC* ppfn = (PROC*) &pThunk->u1.Function;

    // 比较这个地址是否是我们准备Hook的函数地址
    bool IsFound = (*ppfn == pfnCurrent);

    if(!IsFound && (*ppfn > pvMaxAppAddr))
    {
      // If this is not the function and the address is in a shared DLL,
      // then maybe we're running under a debugger on Windows 98. In this
      // case, this address points to an instruction that may have the
      // correct address.

      PBYTE pbInFunc = (PBYTE) *ppfn;
      if(pbInFunc[0] == PushOpCode)
      {
        // We see the PUSH instruction, the real function address follows
        ppfn = (PROC*) &pbInFunc[1];

        // Is this the function we're looking for?
        IsFound = (*ppfn == pfnCurrent);
      }
    }

    //找到我们要Hook的函数,替换它的地址为我们自定义的函数的地址
    if(IsFound)
    {
      DWORD dwOldProtect;

      //必须修改相应的页面属性,否则有可能无法写入代码
      VirtualProtect(ppfn,sizeof(pfnNew),PAGE_READWRITE,&dwOldProtect);

      WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew,sizeof(pfnNew), NULL);

      VirtualProtect(ppfn,sizeof(pfnNew),dwOldProtect,0);
      return ;  // We did it, get out
    }
  }
}
Example #21
0
static void
process_exports(void *dcontext, char *dllname, LOADED_IMAGE *img)
{
    IMAGE_EXPORT_DIRECTORY *dir;
    IMAGE_SECTION_HEADER *sec;
    DWORD *name, *code;
    WORD *ordinal;
    const char *string;
    ULONG size;
    uint i;
    byte *addr, *start_exports, *end_exports;

    verbose_print("Processing exports of \"%s\"\n", dllname);
    dir = (IMAGE_EXPORT_DIRECTORY *)
        ImageDirectoryEntryToData(img->MappedAddress, FALSE,
                                  IMAGE_DIRECTORY_ENTRY_EXPORT, &size);
    verbose_print("mapped at "PFX" (preferred "PFX"), exports 0x%08x, size 0x%x\n",
                  img->MappedAddress, get_preferred_base(img), dir, size);
    start_exports = (byte *) dir;
    end_exports = start_exports + size;
    verbose_print("name=%s, ord base=0x%08x, names=%d 0x%08x\n",
                  (char *) ImageRvaToVa(img->FileHeader, img->MappedAddress,
                                        dir->Name, NULL),
                  dir->Base, dir->NumberOfNames, dir->AddressOfNames);

    /* don't limit functions to lie in .text --
     * for ntdll, some exported routines have their code after .text, inside
     * ECODE section!
     */
    sec = img->Sections;
    for (i = 0; i < img->NumberOfSections; i++) {
        verbose_print("Section %d %s: 0x%x + 0x%x == 0x%08x through 0x%08x\n",
                      i, sec->Name, sec->VirtualAddress, sec->SizeOfRawData,
                      ImageRvaToVa(img->FileHeader, img->MappedAddress,
                                   sec->VirtualAddress, NULL),
                      (ptr_uint_t) ImageRvaToVa(img->FileHeader, img->MappedAddress,
                                                sec->VirtualAddress, NULL) +
                      sec->SizeOfRawData);
        sec++;
    }

    name = (DWORD *) ImageRvaToVa(img->FileHeader, img->MappedAddress,
                                  dir->AddressOfNames, NULL);
    code = (DWORD *) ImageRvaToVa(img->FileHeader, img->MappedAddress,
                                  dir->AddressOfFunctions, NULL);
    ordinal = (WORD *) ImageRvaToVa(img->FileHeader, img->MappedAddress,
                                    dir->AddressOfNameOrdinals, NULL);
    verbose_print("names: from 0x%08x to 0x%08x\n",
                  ImageRvaToVa(img->FileHeader, img->MappedAddress, name[0], NULL),
                  ImageRvaToVa(img->FileHeader, img->MappedAddress,
                               name[dir->NumberOfNames-1], NULL));

    for (i = 0; i < dir->NumberOfNames; i++) {
        string = (char *) ImageRvaToVa(img->FileHeader, img->MappedAddress, name[i], NULL);
        /* ordinal is biased (dir->Base), but don't add base when using as index */
        assert(dir->NumberOfFunctions > ordinal[i]);
        /* I don't understand why have to do RVA to VA here, when dumpbin /exports
         * seems to give the same offsets but by simply adding them to base we
         * get the appropriate code location -- but that doesn't work here...
         */
        addr = ImageRvaToVa(img->FileHeader, img->MappedAddress,
                            code[ordinal[i]], NULL);
        verbose_print("name=%s 0x%08x, ord=%d, code=0x%x -> 0x%08x\n",
                      string, string, ordinal[i], code[ordinal[i]], addr);
        if (list_exports) {
            print("ord %3d offs 0x%08x %s\n", ordinal[i],
                  addr - img->MappedAddress, string);
        }
        if (list_Ki && string[0] == 'K' && string[1] == 'i') {
            print("\n==================================================\n");
            print("%s\n\n", string);
            check_Ki(string);
            print("\ndisassembly:\n");
            decode_function(dcontext, addr);
            print(  "==================================================\n");
        }
        /* forwarded export points inside exports section */
        if (addr >= start_exports && addr < end_exports) {
            if (list_forwards || verbose) {
                /* I've had issues w/ forwards before, so avoid printing crap */
                if (addr[0] > 0 && addr[0] < 127)
                    print("%s is forwarded to %.128s\n", string, addr);
                else
                    print("ERROR identifying forwarded entry for %s\n", string);
            }
        } else if (list_syscalls) {
            process_syscall_wrapper(dcontext, addr, string, "export", img);
        }
    }
}
Example #22
0
PROC HookManager::HookInOneModule(HMODULE hModule, LPCSTR baseLibraryName, PROC oldFunctionPointer, PROC newFunctionPointer)
{
        char text[1000];
        ULONG size;
        PROC result = NULL; // If the function is found, returns the old address
		
		//Modules that are global hooked will not need to be hooked again
		if (hModule==NULL) return NULL;
        
		// Retrieving the position of the first Import Descriptor Table
        // This table holds the information about the imports from one
        // single dll. It holds the address to dll's name, to dll's IAT
        // and some other data.
PIMAGE_IMPORT_DESCRIPTOR pImportDesc;

        pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ImageDirectoryEntryToData(
                hModule,
                TRUE,
                IMAGE_DIRECTORY_ENTRY_IMPORT,
                &size
        );

        // No Import Descriptor Tables found or some error occured
        if (pImportDesc == NULL) 
        {
                return NULL;
        }

        // For each Import Descriptor Table (for each DLL) check for the
        // existance of wanted DLL
        while (pImportDesc -> Name)
        {
                // We add the base address of the module whose IAT we are going to read and the 
                // RVA offset to the DLL (module's) name. We cast this to pointer to string.
                PSTR IDTModName = (PSTR)((PBYTE)hModule + pImportDesc -> Name);

                // We compare the library names. If the comparrison returns zero, we have found
                // out that this module imports something from the library which holds a function
                // that we want to control. That means we have to check all the functions and see
                // if our function is one of them.
                if (_stricmp(baseLibraryName, IDTModName) == 0)
                {
                        break;
                }

                 //If the compared names were not the same, go to the next Import Descriptor Table.
                pImportDesc++;
        }
        
        // If we went through all the descriptor tables and haven't found wanted dll, we are
        // done with this module.
        if (pImportDesc -> Name == NULL)        
        {
                return NULL;
        }

        // If we found a module we want to hook, we need to search through all of the functions
        // for the one we want.

        // First we add the RVA to the first IAT entry (first address of the imported function) to
        // the base of the module.
        PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)((PBYTE)hModule + pImportDesc -> FirstThunk);


        // For each function in the IAT we check if it's the wanted one
        while (pThunk -> u1.Function)
        {
                // Retrieve the pointer to pointer to function. pfn will point inside the IAT where
                // the pointer to function is stored.
                PROC *ppfn = (PROC *) &pThunk -> u1.Function;
                
                // If the pointer to current function equals our wanted function, we found a hit
                sprintf_s(text, "%p <--> %p", *ppfn, oldFunctionPointer);
                if (*ppfn == oldFunctionPointer)
                {
                        // First we store the page information of the IAT. Note the pfn holds
                        // the pointer to IAT entry, and not directy to function
                        MEMORY_BASIC_INFORMATION info;

                        if (VirtualQuery(ppfn, &info, sizeof(MEMORY_BASIC_INFORMATION)) == 0)
                        {
                                return NULL;
                        }

                        // This function attempts to change the protection scheme of a region of pages.
                        // It also copies the old protection scheme to the last parameter (in this case
                        // it is info.Protect).
                        if (VirtualProtect(info.BaseAddress, info.RegionSize, PAGE_EXECUTE_READWRITE, &info.Protect) == FALSE)
                        {
                                return NULL;
                        }

                        // We store the old pointer in the IAT memory and change it to point to our function.
                        result = *ppfn;	
                        *ppfn = *newFunctionPointer;
						sprintf_s(text, "%p <--> %p", result);
               
                        // Lastly we attempt to restore the previous protection. "dummyProtect is used
                        // to store the PAGE_READWRITE protection, although we don't need it. NULL can't
                        // be used because in that case the function fails.
                        DWORD dummyProtect;

                        if (VirtualProtect(info.BaseAddress, info.RegionSize, info.Protect, &dummyProtect) == FALSE)
                        {
                             /*    Actually this should not be vital, so could be turned off in case of trouble.
                                 But if the first VirtualProtect succeeded, this one should, too.
                       */         return NULL;
                        }


                        return result;
                }

                pThunk++;
        }

        return NULL;
}
Example #23
0
BOOL CHookedFunctions::GetFunctionNameFromExportSection(
	HMODULE hmodOriginal,
	DWORD   dwFuncOrdinalNum,
	PSTR    pszFuncName
	) 
{
	BOOL bResult = FALSE;
	// Make sure we return a valid string (atleast an empty one)
	strcpy(pszFuncName, "\0");
	__try
	{
		ULONG ulSize;
		// Get the address of the module's export section
		PIMAGE_EXPORT_DIRECTORY pExportDir = 
			(PIMAGE_EXPORT_DIRECTORY)ImageDirectoryEntryToData(
			hmodOriginal, 
			TRUE, 
			IMAGE_DIRECTORY_ENTRY_EXPORT, 
			&ulSize
			);
		// Does this module has export section ?
		if (pExportDir == NULL)
			__leave;  
		// Get the name of the DLL
		PSTR pszDllName = reinterpret_cast<PSTR>( pExportDir->Name + (DWORD)hmodOriginal);
		// Get the starting ordinal value. By default is 1, but
		// is not required to be so
		DWORD dwFuncNumber = pExportDir->Base;
		// The number of entries in the EAT
		DWORD dwNumberOfExported = pExportDir->NumberOfFunctions;
		// Get the address of the ENT
		PDWORD pdwFunctions = (PDWORD)( pExportDir->AddressOfFunctions + (DWORD)hmodOriginal);
		//  Get the export ordinal table
		PWORD pwOrdinals = (PWORD)(pExportDir->AddressOfNameOrdinals + (DWORD)hmodOriginal);
		// Get the address of the array with all names
		DWORD *pszFuncNames =	(DWORD *)(pExportDir->AddressOfNames + (DWORD)hmodOriginal);

		PSTR pszExpFunName;

		// Walk through all of the entries and try to locate the
		// one we are looking for
		for (long i = 0; i < dwNumberOfExported; i++, pdwFunctions++)
		{
			DWORD entryPointRVA = *pdwFunctions;
			if ( entryPointRVA == 0 )   // Skip over gaps in exported function
				continue;               // ordinals (the entrypoint is 0 for
										// these functions).
			// See if this function has an associated name exported for it.
			for ( unsigned j=0; j < pExportDir->NumberOfNames; j++ )
			{
				// Note that pwOrdinals[x] return values starting form 0.. (not from 1)
				if ( pwOrdinals[j] == i  )
				{
					pszExpFunName = (PSTR)(pszFuncNames[j] + (DWORD)hmodOriginal);
					// Is this the same ordinal value ?
					// Notice that we need to add 1 to pwOrdinals[j] to get actual 
					// number
					if (dwFuncOrdinalNum == pwOrdinals[j] + 1)
					{
						if ((pszExpFunName != NULL) && (strlen(pszExpFunName) > 0))
							strcpy(pszFuncName, pszExpFunName);
						__leave;
					}
				}
			}
		} // for
	}
	__finally
	{
		// do nothing
	}
	// This function is not in the caller's import section
	return bResult;
}
Example #24
0
BOOL CHookedFunction::ReplaceInOneModule(
	PCSTR   pszCalleeModName, 
	PROC    pfnCurrent, 
	PROC    pfnNew, 
	HMODULE hmodCaller
	) 
{
	BOOL bResult = FALSE;
	__try
	{
		ULONG ulSize;
		// Get the address of the module's import section
		PIMAGE_IMPORT_DESCRIPTOR pImportDesc = 
			(PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(
			hmodCaller, 
			TRUE, 
			IMAGE_DIRECTORY_ENTRY_IMPORT, 
			&ulSize
			);
		// Does this module has import section ?
		if (pImportDesc == NULL)
			__leave;  
		// Loop through all descriptors and
		// find the import descriptor containing references to callee's functions
		while (pImportDesc->Name)
		{
			PSTR pszModName = (PSTR)((PBYTE) hmodCaller + pImportDesc->Name);
			if (stricmp(pszModName, pszCalleeModName) == 0) 
				break;   // Found
			pImportDesc++;
		} // while
		// Does this module import any functions from this callee ?
		if (pImportDesc->Name == 0)
			__leave;  
		// Get caller's IAT 
		PIMAGE_THUNK_DATA pThunk = 
			(PIMAGE_THUNK_DATA)( (PBYTE) hmodCaller + pImportDesc->FirstThunk );
		// Replace current function address with new one
		while (pThunk->u1.Function)
		{
			// Get the address of the function address
			PROC* ppfn = (PROC*) &pThunk->u1.Function;
			// Is this the function we're looking for?
			BOOL bFound = (*ppfn == pfnCurrent);
			// Is this Windows 9x
			if (!bFound && (*ppfn > sm_pvMaxAppAddr)) 
			{
				PBYTE pbInFunc = (PBYTE) *ppfn;
				// Is this a wrapper (debug thunk) represented by PUSH instruction?
				if (pbInFunc[0] == cPushOpCode) 
				{
					ppfn = (PROC*) &pbInFunc[1];
					// Is this the function we're looking for?
					bFound = (*ppfn == pfnCurrent);
				} // if
			} // if

			if (bFound) 
			{
				MEMORY_BASIC_INFORMATION mbi;
				::VirtualQuery(ppfn, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
				// In order to provide writable access to this part of the 
				// memory we need to change the memory protection
				if (FALSE == ::VirtualProtect(
					mbi.BaseAddress,
					mbi.RegionSize,
					PAGE_READWRITE,
					&mbi.Protect)
					)
					__leave;
				// Hook the function.
                *ppfn = *pfnNew;
				bResult = TRUE;
				// Restore the protection back
                DWORD dwOldProtect;
				::VirtualProtect(
					mbi.BaseAddress,
					mbi.RegionSize,
					mbi.Protect,
					&dwOldProtect
					);
				break;
			} // if
			pThunk++;
		} // while
	}
	__finally
	{
		// do nothing
	}
	// This function is not in the caller's import section
	return bResult;
}
Example #25
0
File: enum.c Project: jaykrell/j
int wmain()
{
    HMODULE Module;
    HANDLE File = { 0 };
    BYTE* MappedFile = { 0 };
    BYTE* MappedFile_End = { 0 };
    HANDLE FileMapping = { 0 };
    ULARGE_INTEGER FileSize;
    DWORD Error = { 0 };
    IMAGE_NT_HEADERS* NtHeaders = { 0 };
    IMAGE_DOS_HEADER* DosHeader = { 0 };
    size_t OffsetToPE = { 0 };
    IMAGE_RESOURCE_DIRECTORY* TopDirectory = { 0 };
    ULONG ResourcesSize = { 0 };

    Module = LoadLibraryW(L".\\notepad.exe");
    if (!EnumResourceTypesW(Module, EnumTypesProc, 0))
    {
        DWORD Error = GetLastError();
        wprintf(L"EnumResourceTypes failed %x\n", Error);
    }
    FreeLibrary(Module);

    File = CreateFileW(L".\\notepad.exe", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
    if (INVALID_HANDLE_VALUE == File)
    {
        Error = GetLastError();
        wprintf(L"CreateFile fails with error: %u", Error);
        goto Exit;
    }

    FileSize.LowPart = GetFileSize(File, &FileSize.HighPart);
    if ((FileSize.LowPart == -1) && ((Error = GetLastError()) != 0))
    {
        wprintf(L"GetFileSize failed with error %u\n", Error);
        goto Exit;
    }
    if (FileSize.HighPart != 0)
    {
        wprintf(L"file too large\n");
        goto Exit;
    }
    if (FileSize.QuadPart <= (sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS)))
    {
        wprintf(L"file too small\n");
        goto Exit;
    }
    
    FileMapping = CreateFileMappingW(File, NULL, PAGE_READONLY, 0, 0, NULL);
    if (FileMapping == NULL)
    {
        Error = GetLastError();
        wprintf(L"CreateFileMapping fails with error: %u", Error);
        goto Exit;
    }

    MappedFile = (BYTE*) MapViewOfFile(FileMapping, FILE_MAP_READ, 0, 0, 0);
    if (MappedFile == NULL)
        goto Exit;

    wprintf(L"MappedFile:%p\n", MappedFile);
    MappedFile_End = (MappedFile + FileSize.QuadPart);
    DosHeader = (IMAGE_DOS_HEADER*) MappedFile;
    if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
    {
        wprintf(L"invalid file");
        goto Exit;
    }

    OffsetToPE = DosHeader->e_lfanew;
    if (OffsetToPE >= FileSize.QuadPart)
    {
        wprintf(L"invalid file");
        goto Exit;
    }
    if ((OffsetToPE + sizeof(IMAGE_NT_HEADERS)) >= FileSize.QuadPart)
    {
        wprintf(L"invalid file");
        goto Exit;
    }
    NtHeaders = (IMAGE_NT_HEADERS*) (MappedFile + OffsetToPE);
    if (NtHeaders->Signature != IMAGE_NT_SIGNATURE)
    {
        wprintf(L"invalid file");
        goto Exit;
    }
    if (NtHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
    {
        wprintf(L"invalid file");
        goto Exit;
    }
    if (NtHeaders->OptionalHeader.NumberOfRvaAndSizes < IMAGE_DIRECTORY_ENTRY_RESOURCE)
    {
        wprintf(L"no resources");
        goto Exit;
    }
    if (NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress == 0)
    {
        wprintf(L"no resources");
        goto Exit;
    }
    if (NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size == 0)
    {
        wprintf(L"no resources");
        goto Exit;
    }

    TopDirectory = (IMAGE_RESOURCE_DIRECTORY*) ImageDirectoryEntryToData(MappedFile, FALSE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &ResourcesSize);
    if (TopDirectory == NULL)
    {
        wprintf(L"no resources");
        goto Exit;
    }
    DumpResourceDirectory(MappedFile, 0, TopDirectory, TopDirectory);
 
Exit:
    if (MappedFile != NULL)
        UnmapViewOfFile(MappedFile);

    if (FileMapping != NULL)
        CloseHandle(FileMapping);

    if ((File != NULL) && (File != INVALID_HANDLE_VALUE))
        CloseHandle(File);

    return 0;
}
Example #26
0
static PROC SetProcAddressA(
	__in  HINSTANCE targetModule,
	__in  LPCSTR lpLibFileName,
	__in  LPCSTR lpProcName,
	__in  PROC  newFunction
	)
{
	PROC pfnHookAPIAddr = GetProcAddress( LoadLibraryA( lpLibFileName ), lpProcName );

	HINSTANCE hInstance = targetModule; 

	ULONG ulSize;
	PIMAGE_IMPORT_DESCRIPTOR pImportDesc = 
		(PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(
		hInstance,
		TRUE,
		IMAGE_DIRECTORY_ENTRY_IMPORT,
		&ulSize
		);

	while (pImportDesc->Name)
	{
		PSTR pszModName = (PSTR)((PBYTE) hInstance + pImportDesc->Name);
		if (_stricmp(pszModName, lpLibFileName) == 0) 
			break;   
		pImportDesc++;
	}

	PIMAGE_THUNK_DATA pThunk = 
		(PIMAGE_THUNK_DATA)((PBYTE) hInstance + pImportDesc->FirstThunk);

	while (pThunk->u1.Function)
	{
		PROC* ppfn = (PROC*) &pThunk->u1.Function;
		BOOL bFound = (*ppfn == pfnHookAPIAddr);

		if (bFound) 
		{
			MEMORY_BASIC_INFORMATION mbi;
			VirtualQuery(
				ppfn,
				&mbi,
				sizeof(MEMORY_BASIC_INFORMATION)
				);
			VirtualProtect(
				mbi.BaseAddress,
				mbi.RegionSize,
				PAGE_READWRITE,
				&mbi.Protect);

			*ppfn = *newFunction;

			DWORD dwOldProtect;
			VirtualProtect(
				mbi.BaseAddress,
				mbi.RegionSize,
				mbi.Protect,
				&dwOldProtect
				);
			break;
		}
		pThunk++;
	}

	return pfnHookAPIAddr;
}
HMODULE CRemoteLoader::LoadLibraryFromMemory( PVOID BaseAddress, DWORD SizeOfModule, BOOL PEHeader, PCHAR OptionalPath )
{
	DebugShout( "[LoadLibraryFromMemory] BaseAddress (0x%X) - SizeOfModule (0x%X)", BaseAddress, SizeOfModule );

	IMAGE_NT_HEADERS* ImageNtHeaders = ToNts( BaseAddress );

	if( ImageNtHeaders == NULL )
	{
		DebugShout( "[LoadLibraryFromMemory] Invalid Image: No IMAGE_NT_HEADERS" );

		return NULL;
	}

	DebugShout( "[LoadLibraryFromMemory] SizeOfImage (0x%X)", ImageNtHeaders->OptionalHeader.SizeOfImage );

	if( ImageNtHeaders->FileHeader.NumberOfSections == 0 )
	{
		DebugShout( "[LoadLibraryFromMemory] Invalid Image: No Sections" );

		return NULL;
	}

	if( ( ImageNtHeaders->OptionalHeader.ImageBase % 4096 ) != 0 )
	{
		DebugShout( "[LoadLibraryFromMemory] Invalid Image: Not Page Aligned" );
		
		return NULL;
	}

	if( ImageNtHeaders->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR ].Size )
	{
		if( ImageDirectoryEntryToData( BaseAddress, IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR ) )
		{
			DebugShout( "[LoadLibraryFromMemory] This method is not supported for Managed executables!" );

			return NULL;
		}
	}

	DebugShout( "[LoadLibraryFromMemory] No COM/CLR data found!" );

	// SizeOfImage NOT the same as module size M**********R
	// http://www.youtube.com/watch?v=pele5vptVgc

	PVOID AllocatedRemoteMemory = RemoteAllocateMemory( ImageNtHeaders->OptionalHeader.SizeOfImage );

	if( AllocatedRemoteMemory == NULL )
	{
		DebugShout( "[LoadLibraryFromMemory] Failed to allocate remote memory for module!" );

		return NULL;
	}

	DebugShout( "[LoadLibraryFromMemory] Allocated remote module at [0x%X]!", AllocatedRemoteMemory );

	if( ProcessImportTable( BaseAddress, AllocatedRemoteMemory, OptionalPath ) == FALSE )
	{
		DebugShout( "[LoadLibraryFromMemory] Failed to fix imports!" );

		return NULL;
	}

	DebugShout( "[LoadLibraryFromMemory] Fixed Imports!" );

	if( ProcessRelocations( BaseAddress, AllocatedRemoteMemory ) == FALSE )
	{
		DebugShout( "[LoadLibraryFromMemory] Failed to process relocations!" );

		RemoteFreeMemory( AllocatedRemoteMemory, SizeOfModule );

		return NULL;
	}

	DebugShout( "[LoadLibraryFromMemory] Fixed Relocations!" );

	if( ProcessSections( BaseAddress, AllocatedRemoteMemory, PEHeader ) == FALSE )
	{
		DebugShout( "[LoadLibraryFromMemory] Failed to process sections!" );
	}

	DebugShout( "[LoadLibraryFromMemory] Processed sections!" );

	if( ProcessTlsEntries( BaseAddress, AllocatedRemoteMemory ) == FALSE )
	{
		DebugShout( "[LoadModuleFromMemory] ProcessTlsEntries Failed!" );

		// we can also choose to continue here..

		return NULL;
	}

	DebugShout( "[LoadModuleFromMemory] Processed Tls Entries!" );

	if( ImageNtHeaders->OptionalHeader.AddressOfEntryPoint )
	{
		FARPROC DllEntryPoint = MakePtr( FARPROC, AllocatedRemoteMemory, ImageNtHeaders->OptionalHeader.AddressOfEntryPoint );

		DebugShout( "[LoadModuleFromMemory] DllEntrypoint = 0x%X", DllEntryPoint );

		if( CallEntryPoint( AllocatedRemoteMemory, DllEntryPoint ) == false )
		{
			DebugShout( "[LoadModuleFromMemory] Failed to execute remote thread buffer" );
		}
		else
		{
			DebugShout( "[LoadModuleFromMemory] Executed the remote thread buffer successfully [0x%X]", DllEntryPoint );
		}
	}
	else
	{
		DebugShout( "[LoadModuleFromMemory] AddressOfEntryPoint is NULL" );
	}

	DebugShout( "[LoadModuleFromMemory] Returning Pointer (0x%X)", AllocatedRemoteMemory );

	return ( HMODULE ) AllocatedRemoteMemory;
}
Example #28
0
BOOL EditSymbols(
    LPSTR pImageName,
    LPSTR pDbgFileName
    )
{
    PIMAGE_NT_HEADERS NtHeaders;
    HANDLE FileHandle, SymbolFileHandle;
    HANDLE hMappedFile;
    LPVOID ImageBase;
    PIMAGE_DEBUG_DIRECTORY DebugDirectories;
    PIMAGE_DEBUG_DIRECTORY DebugDirectoriesSave;
    DWORD DebugDirectorySize, NumberOfDebugDirectories;
    DWORD SavedErrorCode;
    PIMAGE_DEBUG_DIRECTORY DebugDirectory;
    DWORD i;
    DWORD NewFileSize, HeaderSum, CheckSum;
    DWORD ImageNameOffset, DebugDataSize;
    LPBYTE DebugData;
    IMAGE_SEPARATE_DEBUG_HEADER DbgFileHeader;

    ImageBase = NULL;
    hMappedFile = 0;
    FileHandle = SymbolFileHandle = 0;
    DebugDirectoriesSave = NULL;

    //
    // open and map the file.
    //
    FileHandle = CreateFile( pImageName,
                             GENERIC_READ | GENERIC_WRITE,
                             FILE_SHARE_READ,
                             NULL,
                             OPEN_EXISTING,
                             0,
                             NULL
                           );

    if (FileHandle == INVALID_HANDLE_VALUE) {
        return FALSE;
        }


    hMappedFile = CreateFileMapping( FileHandle,
                                     NULL,
                                     PAGE_READWRITE,
                                     0,
                                     0,
                                     NULL
                                   );
    if (!hMappedFile) {
        CloseHandle( FileHandle );
        return FALSE;
        }

    ImageBase = MapViewOfFile( hMappedFile,
                               FILE_MAP_WRITE,
                               0,
                               0,
                               0
                             );
    if (!ImageBase) {
        CloseHandle( hMappedFile );
        CloseHandle( FileHandle );
        return FALSE;
        }

    //
    // Everything is mapped. Now check the image and find nt image headers
    //

    NtHeaders = ImageNtHeader( ImageBase );
    if (NtHeaders == NULL) {
        SetLastError( ERROR_BAD_EXE_FORMAT );
        goto nosyms;
        }

    if ((NtHeaders->OptionalHeader.MajorLinkerVersion < 3) &&
        (NtHeaders->OptionalHeader.MinorLinkerVersion < 5)
       ) {
        SetLastError( ERROR_BAD_EXE_FORMAT );
        goto nosyms;
        }

    if (!(NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED)) {
        SetLastError( ERROR_ALREADY_ASSIGNED );
        goto nosyms;
        }

    DebugDirectories = (PIMAGE_DEBUG_DIRECTORY) ImageDirectoryEntryToData( ImageBase,
                                                  FALSE,
                                                  IMAGE_DIRECTORY_ENTRY_DEBUG,
                                                  &DebugDirectorySize
                                                );
    if (!DebugDirectoryIsUseful(DebugDirectories, DebugDirectorySize)) {
        SetLastError( ERROR_BAD_EXE_FORMAT );
        goto nosyms;
    }

    NumberOfDebugDirectories = DebugDirectorySize / sizeof( IMAGE_DEBUG_DIRECTORY );

    SymbolFileHandle = CreateFile( pDbgFileName,
                                   GENERIC_READ | GENERIC_WRITE,
                                   FILE_SHARE_READ,
                                   NULL,
                                   OPEN_EXISTING,
                                   0,
                                   NULL
                                 );
    if (SymbolFileHandle == INVALID_HANDLE_VALUE)
        goto nosyms;

    if (!ReadFile( SymbolFileHandle,
            &DbgFileHeader,
            sizeof(DbgFileHeader),
            &DebugDataSize,
            NULL) ||
        DebugDataSize != sizeof(DbgFileHeader)) {
        SetLastError( ERROR_BAD_EXE_FORMAT );
        goto nosyms;
        }

    if (DbgFileHeader.Signature != IMAGE_SEPARATE_DEBUG_SIGNATURE ||
        (DbgFileHeader.Flags & ~IMAGE_SEPARATE_DEBUG_FLAGS_MASK) != 0 ||
        DbgFileHeader.Machine != NtHeaders->FileHeader.Machine ||
        DbgFileHeader.Characteristics != NtHeaders->FileHeader.Characteristics ||
        DbgFileHeader.TimeDateStamp != NtHeaders->FileHeader.TimeDateStamp ||
        DbgFileHeader.CheckSum != NtHeaders->OptionalHeader.CheckSum ||
        DbgFileHeader.ImageBase != NtHeaders->OptionalHeader.ImageBase ||
        DbgFileHeader.SizeOfImage != NtHeaders->OptionalHeader.SizeOfImage) {
        SetLastError( ERROR_BAD_EXE_FORMAT );
        goto nosyms;
        }

    if (DbgFileHeader.Flags & IMAGE_SEPARATE_DEBUG_MISMATCH) {
        fprintf(stderr, "Warning: %s updated unsafely; symbols may be wrong\n",
                pDbgFileName);
    }


    // check if this is the right dbg file

    // save the DebugDirectory and get ready to write the
    // debug data to the image file.
    DebugDirectoriesSave = (PIMAGE_DEBUG_DIRECTORY) malloc( DebugDirectorySize );
    if (DebugDirectoriesSave == NULL)
        goto nosyms;

    RtlMoveMemory( DebugDirectoriesSave,
                   DebugDirectories,
                   DebugDirectorySize);

    DebugDirectory = DebugDirectoriesSave;
    NewFileSize = SetFilePointer( FileHandle, 0, NULL, FILE_END );
    NewFileSize = (NewFileSize + 3) & ~3;

    for (i=0; i<NumberOfDebugDirectories; i++) {
        // Is it one of the debug sections we need to special case?
        if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_MISC) {
            // fix the mage name
            ImageNameOffset = (DWORD) ((PCHAR) ImageBase +
               DebugDirectory->PointerToRawData +
               FIELD_OFFSET( IMAGE_DEBUG_MISC, Data ));

            RtlCopyMemory((LPVOID)ImageNameOffset,
                          FilePart,
                          strlen(FilePart) + 1);

        }
        else if (DebugDirectory->Type != IMAGE_DEBUG_TYPE_FPO) {
            DebugData = (LPBYTE) malloc( DebugDirectory->SizeOfData );
            if (SetFilePointer( SymbolFileHandle,
                    DebugDirectory->PointerToRawData,
                    NULL,
                    FILE_BEGIN ) != DebugDirectory->PointerToRawData) {
                SetLastError( ERROR_BAD_EXE_FORMAT );
                goto nosyms;
                }

            if (ReadFile( SymbolFileHandle,
                          DebugData,
                          DebugDirectory->SizeOfData,
                          &DebugDataSize,
                          NULL) &&
                DebugDataSize == DebugDirectory->SizeOfData) {
                if (WriteFile( FileHandle,
                               DebugData,
                               DebugDirectory->SizeOfData,
                               &DebugDataSize,
                               NULL) &&
                    DebugDataSize == DebugDirectory->SizeOfData) {
                    DebugDirectory->PointerToRawData = NewFileSize;
                    NewFileSize += DebugDataSize;
                    NewFileSize = (NewFileSize + 3) & ~3;
                }
                else {
                    SetLastError( ERROR_WRITE_FAULT );
                    free( DebugData );
                    goto nosyms;
                }
            }
            else {
                SetLastError( ERROR_BAD_EXE_FORMAT );
                free( DebugData );
                goto nosyms;
            }
            free( DebugData );
        }
        DebugDirectory += 1;
    }


    // somehow I needed to close the file and re-open it again.
    // otherwise it would AV inside CheckSumMappedFile.
    UnmapViewOfFile( ImageBase );
    CloseHandle( hMappedFile );
    ImageBase = NULL;
    hMappedFile = 0;

    SetFilePointer( FileHandle, NewFileSize, NULL, FILE_BEGIN );
    SetEndOfFile( FileHandle );
    CloseHandle( FileHandle );


    //
    // re-open and map the file.
    //
    FileHandle = CreateFile( pImageName,
                             GENERIC_READ | GENERIC_WRITE,
                             FILE_SHARE_READ,
                             NULL,
                             OPEN_EXISTING,
                             0,
                             NULL
                           );


    hMappedFile = CreateFileMapping( FileHandle,
                                     NULL,
                                     PAGE_READWRITE,
                                     0,
                                     0,
                                     NULL
                                   );
    if (!hMappedFile) {
        goto nosyms;
        }

    ImageBase = MapViewOfFile( hMappedFile,
                               FILE_MAP_WRITE,
                               0,
                               0,
                               0
                             );
    if (!ImageBase) {
        goto nosyms;
        }

    NtHeaders = ImageNtHeader( ImageBase );
    if (NtHeaders == NULL) {
        SetLastError( ERROR_BAD_EXE_FORMAT );
        goto nosyms;
        }

    DebugDirectories = (PIMAGE_DEBUG_DIRECTORY) ImageDirectoryEntryToData( ImageBase,
                                                  FALSE,
                                                  IMAGE_DIRECTORY_ENTRY_DEBUG,
                                                  &DebugDirectorySize
                                                );

    if (DebugDirectories == NULL || DebugDirectorySize == 0) {
        SetLastError( ERROR_BAD_EXE_FORMAT );
        goto nosyms;
        }


    RtlMoveMemory( DebugDirectories,
                   DebugDirectoriesSave,
                   DebugDirectorySize);

    free( DebugDirectoriesSave );

    NtHeaders->FileHeader.Characteristics &= ~IMAGE_FILE_DEBUG_STRIPPED;

    CheckSumMappedFile( ImageBase,
                        NewFileSize,
                        &HeaderSum,
                        &CheckSum
                      );

    NtHeaders->OptionalHeader.CheckSum = CheckSum;


    CloseHandle( SymbolFileHandle );

    UnmapViewOfFile( ImageBase );
    CloseHandle( hMappedFile );
    CloseHandle( FileHandle );

    return TRUE;

nosyms:
    SavedErrorCode = GetLastError();

    if (DebugDirectoriesSave)
        free( DebugDirectoriesSave );

    if (SymbolFileHandle && SymbolFileHandle != INVALID_HANDLE_VALUE) {
        CloseHandle( SymbolFileHandle );
    }

    if (ImageBase)
        UnmapViewOfFile( ImageBase );

    if (hMappedFile)
        CloseHandle( hMappedFile );

    if (FileHandle && FileHandle != INVALID_HANDLE_VALUE) {
        CloseHandle( FileHandle );
    }

    SetLastError( SavedErrorCode );
    return FALSE;
}
Example #29
0
PROC HookManager::HookExportTable(LPCSTR lpDllName, PROC oldFunctionPointer, PROC newFunctionPointer)
{
        ULONG size;
        PROC result = NULL; // If the function is found, returns the old address
		HMODULE hModule=LoadLibraryA(lpDllName);
        // Retrieving the position of the first Export Table
        // This table holds the information about the imports from one
        // single dll. It holds the address to dll's name, to dll's EAT
        // and some other data.
PIMAGE_EXPORT_DIRECTORY pExportDesc;

        pExportDesc = (PIMAGE_EXPORT_DIRECTORY) ImageDirectoryEntryToData(
                hModule,
                TRUE,
                IMAGE_DIRECTORY_ENTRY_EXPORT ,
                &size        );

        // No Import Descriptor Tables found or some error occured
        if (pExportDesc == NULL) 
        {
                return NULL;
        }
//		EAT Redirection - The EAT, or Export Address Table is similar to the 
//		IAT.  Except in the opposite direction.  When a module exports a function 
//		so that it can be used by other modules, it stores the address of  
//		that function in it's EAT.  EAT redirection overwrites that address 
//		with the offset of your hook.  EAT redirection will not effect any 
//		currently loaded modules.  It will only effect modules loaded after the 
//		redirection	has been made.  It will also effect subsequent calls to 
//		GetProcAddress(), as they will return the address of your hook instead of 
//		the real function. 
        
		ULONG *addressoffunctions=(ULONG*)((BYTE*) hModule +pExportDesc->AddressOfFunctions);
		ULONG * addressofnames=(ULONG*)((BYTE*) hModule +pExportDesc->AddressOfNames);
        // For each function in the EAT we check if it's the wanted one
		for(DWORD x=0; x < pExportDesc->NumberOfFunctions;x++)
			{
				char*functionname=(char*)((BYTE*) hModule +addressofnames[x]);
				DWORD functionaddress=(DWORD)((BYTE*)hModule +addressoffunctions[x]);
				PROC *pfunc=(PROC*)&functionaddress;
				  if (*pfunc==oldFunctionPointer)
				  {
						 PROC* ppfn = (PROC *) &addressoffunctions[x];
						 MEMORY_BASIC_INFORMATION info;

                        if (VirtualQuery(ppfn, &info, sizeof(MEMORY_BASIC_INFORMATION)) == 0)
                        {
                                return NULL;
                        }

                        // This function attempts to change the protection scheme of a region of pages.
                        // It also copies the old protection scheme to the last parameter (in this case
                        // it is info.Protect).
                        if (VirtualProtect(info.BaseAddress, info.RegionSize, PAGE_EXECUTE_READWRITE, &info.Protect) == FALSE)
                        {
                                return NULL;
                        }

                        // We store the old pointer in the IAT memory and change it to point to our function.
                        result = *ppfn;	
                        *ppfn = GetAddressOfInjectedFunction(PROC,newFunctionPointer,hModule);
					    // Lastly we attempt to restore the previous protection. "dummyProtect is used
                        // to store the PAGE_READWRITE protection, although we don't need it. NULL can't
                        // be used because in that case the function fails.
                        DWORD dummyProtect;

                        if (VirtualProtect(info.BaseAddress, info.RegionSize, info.Protect, &dummyProtect) == FALSE)
                        {
                             /*    Actually this should not be vital, so could be turned off in case of trouble.
                                 But if the first VirtualProtect succeeded, this one should, too.
                       */         return NULL;
                        }


                        return result;
                
				  }
			
		}
}