I am working on DLL Injection but getting the error as
failed to hook process: 87 The parameter is incorrect.
The target process as well as the dll are both 64 bit.
The Injection code is:
BOOL HookInjection(TCHAR target[], TCHAR *dll_name)
{
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms644990(v=vs.85).aspx
// SetWindowsHookEx can be used to inject a DLL into another process. A 32 - bit DLL cannot be injected into a 64 - bit process,
// and a 64 - bit DLL cannot be injected into a 32 - bit process.If an application requires the use of hooks in other processes,
// it is required that a 32 - bit application call SetWindowsHookEx to inject a 32 - bit DLL into 32 - bit processes,
// and a 64 - bit application call SetWindowsHookEx to inject a 64 - bit DLL into 64 - bit processes.The 32 - bit and 64 - bit DLLs must have different names.
DbgPrint((char*)"[ ] loading module in local process");
auto hdll = LoadLibrary(dll_name);
//Load module ->Loads the specified module into the address space of the calling process. The specified module may cause other modules to be loaded.
DbgPrint((char*)"[+] loaded dll\n");
typedef LRESULT(WINAPI * MyProc)(int code, WPARAM wp, LPARAM lp); // export from calc_dll.dll
//GetProcAdress -> // GetPROCEDUREAdress Retrieves the address of an exported function or variable from the specified dynamic-link library (DLL).
HOOKPROC addr = (HOOKPROC)(GetProcAddress(hdll, "print_successful_injection"));
//auto mp = MyProc(GetProcAddress(hdll, "StartW"));
//If you know who uses StartW, hush, its a secret ;)
DbgPrint((char*)"[] It worked");
auto pStartupInfo = new STARTUPINFO();
auto pProcessInfo = new PROCESS_INFORMATION();
DbgPrint((char*)"[ ] creating process to hook");
CreateProcess(target,
nullptr,
nullptr,
nullptr,
FALSE,
NORMAL_PRIORITY_CLASS,
nullptr,
nullptr,
pStartupInfo,
pProcessInfo);
if (!pProcessInfo)
{
DbgPrint((char*)"[-] pprocessInfo fucked up");
}
if (!pProcessInfo->hProcess)
{
DbgPrint((char*)"[-] failed to create process");
return FALSE;
}
DbgPrint((char*)"[+] Created hook process\n");
DbgPrint((char*)"[ ] creating process hook");
auto hProc = SetWindowsHookEx(WH_CBT, // Installs a hook procedure that receives notifications useful to a CBT application
addr, // my proc symbol taken from the dll
hdll, // dll containing my proc
pProcessInfo->dwThreadId); // dword to the thread (something something windows store) RTFM
if (!hProc)
{
DbgPrint((char*)"[-] failed to hook process");
//This is where the code fails ie hproc is NULL
return FALSE;
}
DbgPrint((char*)"[+] hook injected");
UnhookWindowsHookEx(hProc);
return TRUE;
}
The dll that will be injected is as follows:
#include "stdafx.h"
#include<Windows.h>
LRESULT __stdcall print_successful_injection(int code, WPARAM w, LPARAM l)
{
MessageBox(0, L"Successfully Injected!", L"Hello", MB_ICONINFORMATION);
return (CallNextHookEx(NULL, code, w, l));
}
The def file is as follows:
LIBRARY "dll_to_inject"
EXPORTS
print_successful_injection
the DbgFunction works as follows:
VOID DbgPrint(char *msg)
{
#ifdef DEBUG
DWORD eMsgLen, errNum = GetLastError();//dword is unsigned int
LPTSTR lpvSysMsg; // __Out__ LPTSTR lpBuffer , A pointer to a buffer that receives the null-terminated string that specifies the formatted message
if (msg)
printf("%s: ", msg);
//FORMAT_MESSAGE_ALLOCATE_BUFFER -> The function allocates a buffer large enough to hold the formatted message, and places a pointer to the allocated buffer at the address specified by lpBuffer.The lpBuffer parameter is a pointer to an LPTSTR
//FORMAT_MESSAGE_FROM_SYSTEM -> The function should search the system message-table resource(s) for the requested message
eMsgLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL, errNum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpvSysMsg, 0, NULL);
//If the function succeeds, the return value is the number of TCHARs stored in the output buffer, excluding the terminating null character.
//If the function fails, the return value is zero.
if (eMsgLen > 0)
_ftprintf(stderr, _T("%d %s\n"), errNum, lpvSysMsg);
else
_ftprintf(stderr, _T("Error %d\n"), errNum);
if (lpvSysMsg != NULL)
LocalFree(lpvSysMsg);
#endif
}
I'm pretty new to stackoverflow so I hope I tried to provide as much as details necessary.
SetWindowsHookEx
fail if it called not for GUI thread. more exactly ifWin32Thread
field ofKTHREAD
is 0. you callSetWindowsHookEx
too early - thread yet not GUI thread (not initialized gui subsystem). so you need wait for this, before callSetWindowsHookEx
. not sure, are possible catch exactly moment (after thread callNtGdiInit
), when already possible callSetWindowsHookEx
, but simplest way callWaitForInputIdle(pi.hProcess, INFINITE)
with handle of new created process and only after it returnWAIT_OBJECT_0
callSetWindowsHookExW
also, as separate note - for what you allocate
STARTUPINFO
andSTARTUPINFO
from heap ? (and not free it late). simply declare it as local variables in function. alsoSTARTUPINFO
must be initialized, how minimum asSTARTUPINFO si = { sizeof(si) }
; also you not close process and thread handles