I have a DLL which is acting like a hooking engine. I am going to inject this library to processes in order to analysis APIs that they are calling.
It will hook functions like MessageBoxA after loading to address space of the target process. The following method parse IAT table and then try to overwrite MessageBoxA address in IAT table with modified API (my own api).
void triggered()
{
PIMAGE_IMPORT_DESCRIPTOR import_descriptor = import_directory_table();
while (import_descriptor->Name != NULL)
{
m_lib_name = reinterpret_cast<LPCSTR>(import_descriptor->Name + (DWORD_PTR)va_image_base());
m_library = LoadLibraryA(m_lib_name);
if (m_library)
{
m_original_first_thunk = reinterpret_cast<PIMAGE_THUNK_DATA>((DWORD_PTR)va_image_base() + import_descriptor->OriginalFirstThunk);
m_first_thunk = reinterpret_cast<PIMAGE_THUNK_DATA>((DWORD_PTR)va_image_base() + import_descriptor->FirstThunk);
while (m_original_first_thunk->u1.AddressOfData != NULL)
{
m_function_name = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>((DWORD_PTR)va_image_base() + pe::m_original_first_thunk->u1.AddressOfData);
// MessageBoxA redirected to _MessageBox which is a modified version of Sleep API
if (std::string(m_function_name->Name).compare("MessageBoxA") == 0)
{
VirtualProtect((LPVOID)(&m_first_thunk->u1.Function), 8, PAGE_READWRITE, &m_old_protect);
m_first_thunk->u1.Function = (DWORD_PTR)hook::statically::ui::_MessageBoxA;
}
++m_original_first_thunk;
++m_first_thunk;
}
}
import_descriptor++;
}
}
But when Dll loaded into the process, target process when call MessageBoxA, it give me access violation in debugging mode of visual studio. In the following, you will see the code _MessageBoxA.
namespace hook
{
namespace statically
{
namespace ui
{
// MessageBox call redirected to this function.
int _MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
if (std::string(lpText).compare("test") == 0)
{
return load_time::prototype::ui::OMessageBoxA(NULL, "Hahahahahhaa", "Hahahahaha", MB_OK);
}
else
{
return load_time::prototype::ui::OMessageBoxA(hWnd, lpText, lpCaption, uType);
}
return 0;
}
}
}
}
Where is my mistake? I did research a lot in google but couldn't find out a solution.
Related
I would need to get all elements of webpage displayed in IE from a c++ program.
I tried to see with spy++ but there's only the IEFrame.
So I'm thinking about using the developement tool (F12 in IE), I heard there's a way to automat it, a good idea ?
Thanks
You can get an IHtmlDocument2 reference from an IE's window handle, even out-of-process. This is documented here https://support.microsoft.com/en-us/help/249232/how-to-get-ihtmldocument2-from-a-hwnd, but not really supported by Microsoft.
However it looks like it still works today, I've tested it with a Windows 10 box, and IE is now a frozen app, so not going to change any time soon.
Once you have the proper HWND for Internet Explorer, than you can get the DOM with a code like this. Make sure IE and your program run at the same security level
The DOM is the same as when you're coding IE inprocess (host, activex, etc.), however for security reasons, some things may not work :
void DoSomeDomOperations(HWND hwnd)
{
UINT msg = RegisterWindowMessage(L"WM_HTML_GETOBJECT");
LRESULT result = 0;
SendMessageTimeout(hwnd, msg, NULL, NULL, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&result);
if (!result)
return;
// get main document object
IHTMLDocument2 *doc = NULL;
ObjectFromLresult(result, IID_IHTMLDocument2, NULL, (void**)&doc);
if (!doc)
return;
// get document's url
BSTR url = NULL;
doc->get_URL(&url);
wprintf(L"url:%s\n", url);
SysFreeString(url);
// get body element
IHTMLElement *element = NULL;
doc->get_body(&element);
if (element)
{
BSTR text = NULL;
element->get_innerText(&text);
wprintf(L"text:%s\n", text);
SysFreeString(text);
element->Release();
}
// etc.
// etc.
doc->Release();
}
And here is a full sample console app that scans all current IE processes running:
BOOL CALLBACK GetIEServerWindowProc(HWND hwnd, LPARAM lParam)
{
// enumerate all child windows to find IE's COM server
wchar_t className[100];
GetClassName(hwnd, className, 100);
if (!wcscmp(className, L"Internet Explorer_Server"))
{
*((HWND*)lParam) = hwnd;
return FALSE;
}
return TRUE;
}
HWND GetIEServerWindow(HWND hwnd)
{
HWND serverHwnd = NULL;
EnumChildWindows(hwnd, GetIEServerWindowProc, (LPARAM)&serverHwnd);
return serverHwnd;
}
struct IEServer
{
DWORD processId;
HWND serverHwnd;
};
BOOL CALLBACK GetIEProcessServerWindowProc(HWND hwnd, LPARAM lParam)
{
DWORD processId = ((IEServer*)lParam)->processId;
DWORD pid;
GetWindowThreadProcessId(hwnd, &pid);
if (pid == processId)
{
HWND serverHwnd = GetIEServerWindow(hwnd);
if (serverHwnd)
{
((IEServer*)lParam)->serverHwnd = serverHwnd;
return FALSE;
}
}
return TRUE;
}
HWND GetIEProcessServerWindow(DWORD processId)
{
IEServer ie = { processId, NULL };
EnumWindows(GetIEProcessServerWindowProc, (LPARAM)&ie);
return ie.serverHwnd;
}
void EnumerateIEProcesses()
{
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (h == INVALID_HANDLE_VALUE)
return;
PROCESSENTRY32 process;
process.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(h, &process))
{
do
{
// we only consider IE processes
if (!wcscmp(process.szExeFile, L"iexplore.exe"))
{
HWND serverHwnd = GetIEProcessServerWindow(process.th32ProcessID);
if (serverHwnd)
{
DoSomeDomOperations(serverHwnd);
}
}
} while (Process32Next(h, &process));
}
CloseHandle(h);
}
int main()
{
CoInitialize(NULL);
EnumerateIEProcesses();
CoUninitialize();
return 0;
}
I have found a code that promises to intercept and detour calls to the TerminateProcess function and thus prevent my software from being killed directly from other program.
But this code is not working and I am still able to kill my process via other program.
Here is the last my attempt with a code I have found in this YouTube video:
PS: victim.exe is the killer program.
DLL
// DllRedirectAPI.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include <Windows.h>
BYTE MOV[10] = { 0x48, 0xB8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
BYTE JMP_RAX[2] = { 0xFF, 0xE0 };
#define BuffSizeX64 (sizeof(MOV) + sizeof(JMP_RAX))
BOOL Hook_Det_x64(char LibName[], char API_Name[], LPVOID NewFun) {
DWORD OldProtect;
DWORD64 OrgAddress = (DWORD64)GetProcAddress(LoadLibraryA(LibName), API_Name);
if (OrgAddress == NULL) return 0;
memcpy(&MOV[2], &NewFun, 8);
VirtualProtect((LPVOID)OrgAddress, BuffSizeX64, PAGE_EXECUTE_READWRITE, &OldProtect);
memcpy((LPVOID)OrgAddress, MOV, sizeof(MOV));
memcpy((LPVOID)(OrgAddress + sizeof(MOV)), JMP_RAX, sizeof(JMP_RAX));
VirtualProtect((LPVOID)OrgAddress, BuffSizeX64, OldProtect, &OldProtect);
return 1;
}
int WINAPI MessageBoxAX(
HWND hWnd,
LPCSTR lpText,
LPCSTR lpCaption,
UINT uType) {
MessageBoxExA(0, "Hooked ...", "Mahmoud", 0, 0);
return 999;
}
BOOL WINAPI DllMain(HMODULE hModule, DWORD Call_Reason, LPVOID lpReserved) {
switch (Call_Reason) {
case DLL_PROCESS_ATTACH:
Hook_Det_x64("Kernel32.dll", "TerminateProcess", MessageBoxAX);
}
return 1;
}
INJECTOR
// Injector.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <tlhelp32.h>
#include <shlwapi.h>
#include <conio.h>
#include <stdio.h>
#include <comdef.h>
#define WIN32_LEAN_AND_MEAN
#define CREATE_THREAD_ACCESS (PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ)
BOOL Inject(DWORD pID, const char * DLL_NAME);
DWORD GetTargetThreadIDFromProcName(const char * ProcName);
int main(int argc, char * argv[])
{
//############### CHANGE HERE ONLY ###################
char *Target_Process = "victim.exe"; //###
//#######################################################
char *buf;
DWORD pID = GetTargetThreadIDFromProcName(Target_Process);
buf = "DllRedirectAPI.dll";
if (!Inject(pID, buf))
{
printf("DLL Not Loaded!");
}
else{
printf("DLL is Injected in torget Process");
}
_getch();
return 0;
}
BOOL Inject(DWORD pID, const char * DLL_NAME)
{
HANDLE Proc;
char buf[50] = { 0 };
LPVOID RemoteString, LoadLibAddy;
if (!pID)
return false;
Proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
if (!Proc)
{
sprintf_s(buf, "OpenProcess() failed: %d", GetLastError());
printf(buf);
return false;
}
LoadLibAddy = (LPVOID)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "LoadLibraryA");
RemoteString = (LPVOID)VirtualAllocEx(Proc, NULL, strlen(DLL_NAME), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(Proc, (LPVOID)RemoteString, DLL_NAME, strlen(DLL_NAME), NULL);
CreateRemoteThread(Proc, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)RemoteString, NULL, NULL);
CloseHandle(Proc);
return true;
}
DWORD GetTargetThreadIDFromProcName(const char * ProcName)
{
PROCESSENTRY32 pe;
HANDLE thSnapShot;
BOOL retval, ProcFound = false;
thSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (thSnapShot == INVALID_HANDLE_VALUE)
{
printf("Error: Unable create toolhelp snapshot!");
return false;
}
pe.dwSize = sizeof(PROCESSENTRY32);
retval = Process32First(thSnapShot, &pe);
while (retval)
{
if (_bstr_t(pe.szExeFile) == _bstr_t(ProcName))
{
return pe.th32ProcessID;
}
retval = Process32Next(thSnapShot, &pe);
}
return 0;
}
Can someone help me, telling me where I'm making a mistake?
My system is Windows 7 Ultimate 64 Bits.
Thanks in advance.
(Wanted to write a comment, but it got quite long...)
As #AndrewMedico says in the comment: You need to hook the TerminateProcess of the Task Manager process to prevent the Task Manager from terminating anything.
I suggest you the following approach:
Try a simple DLL injection
a/ Make a DLL which prints some text in its DllMain, e.g. printf("I am here\n"); fflush(stdout);
b/ Try to inject it into some other command line process using the process hacker's Miscellaneous>Inject DLL...
c/ Verify your DLL was executed inside the target process by checking it's standard output
Try a simple API hook:
a/ Make a command line application which waits for a key and then terminates itself using some variant of TerminateProcess(GetCurrentProcess(), 1);. Add code to print some text after the TerminateProcess call.
b/ Run this application to verify the text after calling the TerminateProcess is not printed.
c/ Hook the TerminateProcess before waiting for the key using, e.g. mhook. Print some text in the replacement function and then return. Do not call the original TerminateProcess here.
d/ Run this application to verify the text inside the hook is printed and the text after the TerminateProcess call is printed as well (i.e. verify the process termination was suppressed).
Combine the results of previous steps to reach your goal:
a/ Put the hooking code from from step 2 into the DLL from step 1
b/ Inject it into the application from step 2b (i.e. the one without the hook) while it is waiting for the key and verify the text after TerminateProcess is printed.
c/ Enjoy (or debug/blame me)
Good luck!
EDIT>
OK, here is my view of what we have here:
Code in the question:
(Is an application very similar to what I suggest in "2b")
Hooks the TerminateProcess and shows a message box instead.
Should display a message box when executed
(Looks like it is a 32-bit only version)
YouTube video
Shows an application "Terminate process.exe" which terminates process given by name
After the "Injector.exe" is executed the application ceases to terminate the process and displays a message box instead (IMHO the "Injector.exe" injects a "DllFile.dll" into the running "Terminate process.exe")
Source code for the injector in the YouTube comments
This code injects DLL "C:\DllRedirectAPI.dll" into the first process with name "victim.exe" it finds
(It does not inject into "Terminate process.exe", it does not use "DllFile.dll")
Source code for the DLL in the YouTube comments
This code hooks function MessageBoxA that it shows a different message box instead. It is worth noting that the hook code itself calls the original MessageBoxA and takes the approach that it reverts the modification it did during the hooking, calls the original function and then re-applies the hook.
(It does not hook 'TerminateProcess' at all)
(Looks like it is a 32-bit only version)
64-bit version excerpts
Destructive hook of MessageBoxA (i.e. does not backup the original code)
The hook uses MessageBoxExA (which is intact) to display a different message box instead (i.e. it does not use the overwritten MessageBoxA)
(It does not hook 'TerminateProcess' at all)
(It is a 64-bit version)
Disclaimer: I am not that proficient with the topic to be 100% sure, feel free to correct/clarify me.
For the actual hooking I personally recommend to use the mhook library, which worked for me. It's documentation is worth reading as well.
See e.g. this for some alternatives (I have not tried any of them)...
EDIT>
This one works for me on Win XP inside VirtualBox:
#include <windows.h>
#include <stdio.h>
#include <mhook.h>
static BOOL WINAPI
(*_TerminateProcess)(
_In_ HANDLE hProcess,
_In_ UINT uExitCode
) = NULL;
BOOL WINAPI
TerminateProcessImpl(
_In_ HANDLE hProcess,
_In_ UINT uExitCode) {
printf("\nBlocked\n"); fflush(stdout);
return 0;
}
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD Reason, LPVOID Reserved) {
if(Reason==DLL_PROCESS_ATTACH) {
printf("\nDLL attached!\n"); fflush(stdout);
HMODULE h = LoadLibrary("Kernel32");
if(h!=NULL) {
printf("\nGot Kernel32!\n"); fflush(stdout);
_TerminateProcess=(void*)GetProcAddress(h,"TerminateProcess");
if(_TerminateProcess!=NULL) {
printf("\nAbout to hook...\n"); fflush(stdout);
if(Mhook_SetHook((void*)&_TerminateProcess, &TerminateProcessImpl)) {
printf("\nHooked OK!\n"); fflush(stdout);
} else {
printf("\nHook failed!\n"); fflush(stdout);
}
}
}
}
return TRUE;
}
I have a C++ application in Visual Studio 2010 and I have a Windows Installer (i.e. setup project) to install it. I want to be able to invoke the installer like this:
Setup1.msi MYPROPERTY=MyValue
And then be able to extract the value "MyValue" from the property from within my custom action.
I tried to get it working by following this tutorial(C++ custom actions) and this tutorial (passing arguments to custom actions, but in C#) combined with some MSDN searches to get this code:
#define WINDOWS_LEAN_AND_MEAN
#include <Windows.h>
#include <msi.h>
#include <msiquery.h>
#include <stdio.h>
BOOL APIENTRY DllMain(HANDLE, DWORD, LPVOID) {
return TRUE;
}
UINT APIENTRY InstallCustomAction(MSIHANDLE install_handle) {
static const wchar_t* kPropertyName = L"MYPROPERTY";
//auto msi_handle = MsiGetActiveDatabase(install_handle);
DWORD n = 0;
//auto result = MsiGetProperty(msi_handle, kPropertyName, L"", &n);
auto result = MsiGetProperty(install_handle, kPropertyName, L"", &n);
wchar_t* value = nullptr;
if (result == ERROR_MORE_DATA) {
++n;
value = new wchar_t[n];
//result = MsiGetProperty(msi_handle, kPropertyName, value, &n);
result = MsiGetProperty(install_handle, kPropertyName, value, &n);
}
if (result == ERROR_SUCCESS) {
wchar_t buffer[128];
swprintf_s(buffer, L"n = %d, value = %s", n, value);
MessageBox(nullptr, buffer, L"CustomAction", MB_OK);
} else {
MessageBox(nullptr, L"Error reading property", L"Error", MB_OK);
}
delete value;
//MsiCloseHandle(msi_handle);
return ERROR_SUCCESS;
}
I'm following the C# tutorial exactly in terms of the IDE (I have Entry Point set to InstallCustomAction and Custom Action Data set to /MYPROPERTY=[MYPROPERTY]) The custom action fires correctly but I don't get the parameter.
With the code as-is, I get n=0. If I use the msi_handle from MsiGetActiveDatabase I get an error (i.e. MsiGetProperty returns something other than ErrorSuccess).
How can I get the property that the user passes in on the command line from within my custom action?
There's no need to call MsiGetActiveDatabase. From what you've written it sounds like your custom action is scheduled for deferred execution. In that scenario you should be trying to get the property named "CustomActionData".
I am working on an installer project in Advanced Installer 10.2. I found out that I can use a DLL for serial validation then I found this resource on their website.
I succeeded in building that DLL, here is my code:
// SerialValidationLib.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "SerialValidationLib.h"
#include <Msi.h>
#include <MsiQuery.h>
#include <MsiDefs.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// The one and only application object
CWinApp theApp;
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
HMODULE hModule = ::GetModuleHandle(NULL);
if (hModule != NULL)
{
// initialize MFC and print and error on failure
if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
_tprintf(_T("Fatal Error: MFC initialization failed\n"));
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
}
}
else
{
// TODO: change error code to suit your needs
_tprintf(_T("Fatal Error: GetModuleHandle failed\n"));
nRetCode = 1;
}
return nRetCode;
}
UINT __stdcall ValidateSerial_Sample(MSIHANDLE hInstall)
{
TCHAR szPidKey[256];
DWORD dwLen = sizeof(szPidKey)/sizeof(szPidKey[0]);
//retrive the text entered by the user
UINT res = MsiGetProperty(hInstall, _T("PIDKEY"), szPidKey, &dwLen);
if(res != ERROR_SUCCESS)
{
//fail the installation
return 1;
}
bool snIsValid = false;
//validate the text from szPidKey according to your algorithm
//put the result in snIsValid
TCHAR * serialValid;
if(snIsValid)
serialValid = _T("TRUE");
else
{
//eventually say something to the user
MessageBox(0, _T("Serial invalid!"), _T("Message"), MB_ICONSTOP);
serialValid = _T("FALSE");
}
res = MsiSetProperty(hInstall, _T("SERIAL_VALIDATION"), serialValid);
if(res != ERROR_SUCCESS)
{
return 1;
}
//the validation succeeded - even the serial is wrong
//if the SERIAL_VALIDATION was set to FALSE the installation
//will not continue
return 0;
}
I also imported it to Advanced Installer, look here:
But when I run the installer, and try to proceed with the installation, after serial insertion point, I get this error message:
Where is my mistake? Does anybody know a good tutorial about this? I searched on the internet, but nothing helps me...
You could have two problems:
either you have typed the method name instead of picking it from the combo loaded by Advanced Installer. In this case the installer fails to call the method from the DLL, as it cannot find it.
or, there is a problem with your code, in which case you need to debug it, as you would do with a normal custom action, attaching from VS (add a mesagebox with a breakpoint after it).
I want to hook functions that are called from a loaded DLL on Run time, i used the class CAPIHook from the book "Windows Via C/C++" (the DLL Injecting done by Install System Wide hook and The hooking by Modify IAT) but this code work only if the DLL name/symbols exist in the IAT in the executable file. (i.e. for Implicit DLL Linking)
this is DLL code:
CAPIHook::CAPIHook(PSTR pszCalleeModName, PSTR pszFuncName, PROC pfnHook) {
// Note: the function can be hooked only if the exporting module
// is already loaded. A solution could be to store the function
// name as a member; then, in the hooked LoadLibrary* handlers, parse
// the list of CAPIHook instances, check if pszCalleeModName
// is the name of the loaded module to hook its export table and
// re-hook the import tables of all loaded modules.
m_pNext = sm_pHead; // The next node was at the head
sm_pHead = this; // This node is now at the head
// Save information about this hooked function
m_pszCalleeModName = pszCalleeModName;
m_pszFuncName = pszFuncName;
m_pfnHook = pfnHook;
m_pfnOrig = GetProcAddressRaw(GetModuleHandleA(pszCalleeModName), m_pszFuncName);
// If function does not exit,... bye bye
// This happens when the module is not already loaded
if (m_pfnOrig == NULL)
{
wchar_t szPathname[MAX_PATH];
GetModuleFileNameW(NULL, szPathname, _countof(szPathname));
wchar_t sz[1024];
StringCchPrintfW(sz, _countof(sz),
TEXT("[%4u - %s] impossible to find %S\r\n"),
GetCurrentProcessId(), szPathname, pszFuncName);
OutputDebugString(sz);
return;
}
// Hook this function in all currently loaded modules
ReplaceIATEntryInAllMods(m_pszCalleeModName, m_pfnOrig, m_pfnHook);
}
this is the hook functions:
HMODULE WINAPI CAPIHook::LoadLibraryA(PCSTR pszModulePath) {
HMODULE hmod = ::LoadLibraryA(pszModulePath);
FixupNewlyLoadedModule(hmod, 0);
return(hmod);
}
HMODULE WINAPI CAPIHook::LoadLibraryW(PCWSTR pszModulePath) {
HMODULE hmod = ::LoadLibraryW(pszModulePath);
FixupNewlyLoadedModule(hmod, 0);
return(hmod);
}
HMODULE WINAPI CAPIHook::LoadLibraryExA(PCSTR pszModulePath,
HANDLE hFile, DWORD dwFlags) {
HMODULE hmod = ::LoadLibraryExA(pszModulePath, hFile, dwFlags);
FixupNewlyLoadedModule(hmod, dwFlags);
return(hmod);
}
HMODULE WINAPI CAPIHook::LoadLibraryExW(PCWSTR pszModulePath,
HANDLE hFile, DWORD dwFlags) {
HMODULE hmod = ::LoadLibraryExW(pszModulePath, hFile, dwFlags);
FixupNewlyLoadedModule(hmod, dwFlags);
return(hmod);
}
the method for replacing IAT:
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
}
}
the author added comments to add this functionality, but I am not sure how to do it
Note: the function can be hooked only if the exporting module
is already loaded. A solution could be to store the function
name as a member; then, in the hooked LoadLibrary* handlers, parse
the list of CAPIHook instances, check if pszCalleeModName
is the name of the loaded module to hook its export table and
re-hook the import tables of all loaded modules.
he also write this on the book, but again i don't know what to do
A possible solution is to use the hooked LoadLibrary* functions to
detect when a module is exporting an unpatched hooked function and
then execute two actions:
Hook again the import table of the module already loaded because it is
now possible to call GetProcAddress and get a pointer to the original
implementation of the function to hook. Notice that the name of the
function needs to be stored as a class member and set in the
constructor.
Directly update this hooked function in the Export Address Table of
the exporting module as shown by the implementation of the
ReplaceEATEntryInOneMod function. That way, all new modules calling
the hooked function will call our handler
i try to modify the IAT after loading the DLL, but my hooking function is not called
HMODULE WINAPI CAPIHook::LoadLibraryW(PCWSTR pszModulePath) {
HMODULE hmod = ::LoadLibraryW(pszModulePath);
if (StrCmpIW(pszModulePath, myDLLUnicodeName.c_str()) == 0 ) {
PROC proc = GetProcAddressRaw(GetModuleHandleA(myDLLName.c_str()), myFunctionName.c_str());
if ( proc != NULL ) {
for (CAPIHook* p = sm_pHead; p != NULL; p = p->m_pNext) {
if (StrCmpIA(p->m_pszCalleeModName, myDLLName.c_str()) == 0) {
MessageBox(NULL, L"This is the New Dynamic DLL", L"Test!", 0);
ReplaceIATEntryInAllMods(p->m_pszCalleeModName, proc , p->m_pfnHook);
}
}
}
}
FixupNewlyLoadedModule(hmod, 0);
return(hmod);
}
so, how to modify this code to handle dynamic loading case ?
I've done this before.
What you want is EAT hooking instead of IAT. Also, hook the ::LoadLibrary API itself so you know when the DLL is loaded, and hook the requested api from the DLL after it is loaded.
There are some examples on the Internet on how to do this. Here is one I found just now:
http://board.cheat-project.com/showthread.php?t=10633