I'm trying to inject the DLL into my other program and hook the win32 API function SetConsoleTitle so I can read what parameters are being passed. Everything seems to work except that the strings appear to be unreadable.
When I was hooking my function (non winapi) everything worked just fine.
SetConsoleTitle export and hooked functions:
typedef BOOL(WINAPI* SetConsole)(LPCTSTR str);
BOOL SetConsoleHooked(LPCTSTR str)
{
//im checking the string here in the vs debugger
SetConsole s = (SetConsole)ConsoleAddress;
return s(str);
}
"Error reading characters of string"
The string is showing as nonreadable and I don't know how to access it.
And here is my DLLMain function:
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpvReserved) // reserved
{
if (fdwReason == DLL_PROCESS_ATTACH)
{
HMODULE hModule = GetModuleHandle(L"SomeFile.exe");
HandleAddress = (DWORD)hModule + (DWORD)0x51D05;
ConsoleAddress = (DWORD)hModule + (DWORD)0x55ACA;
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(LPVOID&)ConsoleAddress, &SetConsoleHooked);
DetourTransactionCommit();
while (true) {}
return true;
}
}
And lastly function from IDA that I've been trying to hook
Related
I'm working with MS detours 4.0, compiled in VS2005 on Windows 10 (Updating an older application).
I'm trying to detour the WriteProfileStringA function normally found in the kernel32.dll with a DLL injection.
The DLL injects just fine, I can debug the target process and can step through the detouring functions.
DetourTransactionBegin, DetourUpdateThread, DetourAttach and DetourTransactionCommit all pass with flying colours returning 0 each time.
typedef BOOL (__stdcall * WriteProfileStringAType)(CHAR *,LPCSTR,LPCSTR);
static WriteProfileStringAType OriginalWriteProfileStringA = NULL;
BOOL WINAPI DetouredWriteProfileStringA(CHAR * lpAppName,
LPCSTR lpKeyName,
LPCSTR lpString)
{
FILE* file = fopen("c:\\temp\\testdetour.txt","w");
fprintf(file,"DetouredWriteProfileStringA");
fclose(file);
return OriginalWriteProfileStringA(lpAppName,lpKeyName, lpString);
}
...
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved)
{
if (DetourIsHelperProcess()) {
return TRUE;
}
if (dwReason == DLL_PROCESS_ATTACH) {
...
DetourTransactionBegin();
long update = DetourUpdateThread(GetCurrentThread());
OriginalWriteProfileStringA = (WriteProfileStringAType)GetProcAddress(GetModuleHandle("kernel32"),
"WriteProfileStringA");
long attach = DetourAttach(&(PVOID&)OriginalWriteProfileStringA, DetouredWriteProfileStringA);
long commit = DetourTransactionCommit();
...
}
else if (dwReason == DLL_PROCESS_DETACH) {
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)OriginalWriteProfileStringA, DetouredWriteProfileStringA);
DetourTransactionCommit();
}
return TRUE;
}
BUT when the target application calls the WriteProfileStringA function, the registry is updated but the detour function is never called, break points are ignored and the testdetour.txt isn't created in the c:\temp directory(which does exist)...
Anybody have any ideas?
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 am trying to hook a function to cmd.exe process
the dll is injected just fine the problem is i can't get the cmd.exe to call my function
when im trying to enter the word "dir" on the command prompt it's showing me the same results instade of changing the first name to 'dan'
what am i doing wrong?
HANDLE WINAPI newFindFirstFileA(__in LPCTSTR lpFileName, __out LPWIN32_FIND_DATA lpFindFileData)
{
WIN32_FIND_DATA FindFileData;
HANDLE hFind = FindFirstFile(lpFileName, &FindFileData);
*FindFileData.cFileName = L'Dan';
lpFindFileData = &FindFileData;
return hFind;
}
BOOL APIENTRY DllMain (HINSTANCE hInst /* Library instance handle. */ ,
DWORD reason /* Reason this function is being called. */ ,
LPVOID reserved /* Not used. */ )
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
MessageBox(NULL,L"DLL Was injected!", L"Message" ,NULL);
/* Hooking function */
DWORD* dw = (DWORD*)GetProcAddress( GetModuleHandleA("kernel32.dll"), "FindFirstFileA" );
*dw = (DWORD)newFindFirstFileA;
break;
}
/* Returns TRUE on success, FALSE on failure */
return TRUE;
}
GetProcAddress does not return the pointer to IAT entry. Instead, it returns the location of the actual function. Thus, *dw = (DWORD) newFindFirstFileA would overwrite the prolog of the FindFirstFileA function, which would be disastrous. Refer to this article for detailed explanation for hooking an API
I wont to detour PlaySoundW function inside Minesweeper.
Game is crashing as soon as it calls PlaySoundW function.
If I uncomment Beep inside my code, game beeps and than crashes.
Now code is calling original function from hooked function so it should't do anything. But it is crashing anyway.
Can you tell me what is wrong?
After debugging app in Olly I found that when detour is active not all rubbish is popped out of stack.
How to fix it?
This is my code:
#include <Windows.h>
#include <tchar.h>
#include <detours.h>
namespace Hooks
{
BOOL(__stdcall *OrgPlaySoundW)(LPCTSTR pszSound, HMODULE hmod, DWORD fdwSound) = &PlaySoundW;
BOOL HookPlaySoundW(LPCTSTR pszSound, HMODULE hmod, DWORD fdwSound)
{
//Beep(1000, 250);
//return TRUE;
return OrgPlaySoundW(pszSound, hmod, fdwSound);
}
void DetourPlaySoundW(BOOL disable)
{
if(!disable)
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)OrgPlaySoundW, &HookPlaySoundW);
DetourTransactionCommit();
} else
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)OrgPlaySoundW, &HookPlaySoundW);
DetourTransactionCommit();
}
}
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch(fdwReason)
{
case DLL_PROCESS_ATTACH:
Hooks::DetourPlaySoundW(FALSE);
break;
case DLL_PROCESS_DETACH:
Hooks::DetourPlaySoundW(TRUE);
break;
}
return TRUE;
}
Try setting the calling convention of HookPlaySoundW to __stdcall (because the CC of PlaySoundW is also __stdcall (from Windows.h): WINMMAPI BOOL WINAPI PlaySoundW( __in_opt LPCWSTR pszSound, __in_opt HMODULE hmod, __in DWORD fdwSound);).
I have worked with detours before and after a casual glance everything looks correct except what I mentioned above. If this doesn't resolve your problem I'd be glad to do some further investigation.
The default setting for Visual C++ is __cdecl in which the call*er* cleans up the stack, but in __stdcall the call*ee* cleans up the stack. This is probably (i.e. might possibly be) the reason for all the "rubbish being popped off the stack".
Is there a way to progammatically detect when a module - specifically a DLL - has been unloaded from a process?
I don't have the DLL source, so I can't change it's DLL entry point. Nor can I poll if the DLL is currently loaded because the DLL may be unloaded and then reloaded between polling.
RESULTS:
I ended up using jimharks solution of detouring the dll entry point and catching DLL_PROCESS_DETACH. I found detouring FreeLibrary() to work as well but code must be added to detect when the module is actually unloaded or if the reference count is just being decreased. Necrolis' link about finding the reference count was handy for on method of doing so.
I should note that I had problems with MSDetours not actually unloading the module from memory if a detour existed within it.
One very bad way(which was used by starcraft 2), is to make your program attach to itsself then monitor for the dll unload debug event(http://msdn.microsoft.com/en-us/library/ms679302(VS.85).aspx), else you'd either need to IAT hook FreeLibrary and FreeLibraryEx in the process or hotpatch the functions in kernel32 them monitor the names being passed and the global reference counts.
Try using LdrRegisterDllNotification if you're on Vista or above. It does require using GetProcAddress to find the function address from ntdll.dll, but it's the proper way of doing it.
Maybe a less bad way then Necrolis's would be to use Microsoft Research's Detours package to hook the dll's entry point to watch for DLL_PROCESS_DETACH notifications.
You can find the entry point given an HMODULE (as returned by LoadLibrary) using this function:
#include <windows.h>
#include <DelayImp.h>
PVOID GetAddressOfEntryPoint(HMODULE hmod)
{
PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)hmod;
PIMAGE_NT_HEADERS pinth = (PIMAGE_NT_HEADERS)((PBYTE)hmod + pidh->e_lfanew);
PVOID pvEntry = (PBYTE)hmod + pinth->OptionalHeader.AddressOfEntryPoint;
return pvEntry;
}
Your entrypoint replacement could take direct action or increment a counter that you check for in your main loop or where it's important to you. (And should almost certainly call the original entrypoint.)
UPDATE: Thanks to #LeoDavidson for pointing this out in the comments below. Detours 4.0 is now licensed using the liberal MIT License.
I hope this helps.
#Necrolis, your link to “The covert way to find the Reference Count of DLL” was just too intriguing for me to ignore because it contains the technical details I needed to implement this alternate solution (that I thought of yesterday, but was lacking the Windows Internals). Thanks. I voted for your answer because of the link you shared.
The linked article shows how to get to the internal LDR_MODULE:
struct _LDR_MODULE
{
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID BaseAddress;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
USHORT LoadCount;
USHORT TlsIndex;
LIST_ENTRY HashTableEntry;
ULONG TimeDateStamp;
} LDR_MODULE, *PLDR_MODULE;
Right here we have EntryPoint, Window's internal pointer to the module’s entry point. For a dll that’s DllMain (or the language run time function that eventually calls DllMain). What if we just change that? I wrote a test and it seems to work, at least on XP. The DllMain hook gets called with reason DLL_PROCESS_DETACH just before the DLL unloads.
The BaseAddress is the same value as an HMODULE and is useful for finding the right LDR_MODULE. The LoadCount is here so we can track that. And finally FullDllName is helpful for debugging and makes it possible to search for DLL name instead of HMODULE.
This is all Windows internals. It’s (mostly) documented, but the MSDN documentation warns “ZwQueryInformationProcess may be altered or unavailable in future versions of Windows.”
Here’s a full example (but without full error checking). It seems to work but hasn’t seen much testing.
// HookDllEntryPoint.cpp by Jim Harkins (jimhark), Nov 2010
#include "stdafx.h"
#include <stdio.h>
#include <winternl.h>
#include <process.h> // for _beginthread, only needed for testing
typedef NTSTATUS(WINAPI *pfnZwQueryInformationProcess)(
__in HANDLE ProcessHandle,
__in PROCESSINFOCLASS ProcessInformationClass,
__out PVOID ProcessInformation,
__in ULONG ProcessInformationLength,
__out_opt PULONG ReturnLength);
HMODULE hmodNtdll = LoadLibrary(_T("ntdll.dll"));
// Should test pZwQueryInformationProcess for NULL if you
// might ever run in an environment where this function
// is not available (like future version of Windows).
pfnZwQueryInformationProcess pZwQueryInformationProcess =
(pfnZwQueryInformationProcess)GetProcAddress(
hmodNtdll,
"ZwQueryInformationProcess");
typedef BOOL(WINAPI *PDLLMAIN) (
__in HINSTANCE hinstDLL,
__in DWORD fdwReason,
__in LPVOID lpvReserved);
// Note: It's possible for pDllMainNew to be called before
// HookDllEntryPoint returns. If pDllMainNew calls the old
// function, it should pass a pointer to the variable used
// so we can set it here before we hook.
VOID HookDllEntryPoint(
HMODULE hmod, PDLLMAIN pDllMainNew, PDLLMAIN *ppDllMainOld)
{
PROCESS_BASIC_INFORMATION pbi = {0};
ULONG ulcbpbi = 0;
NTSTATUS nts = (*pZwQueryInformationProcess)(
GetCurrentProcess(),
ProcessBasicInformation,
&pbi,
sizeof(pbi),
&ulcbpbi);
BOOL fFoundMod = FALSE;
PLIST_ENTRY pcurModule =
pbi.PebBaseAddress->Ldr->InMemoryOrderModuleList.Flink;
while (!fFoundMod && pcurModule !=
&pbi.PebBaseAddress->Ldr->InMemoryOrderModuleList)
{
PLDR_DATA_TABLE_ENTRY pldte = (PLDR_DATA_TABLE_ENTRY)
(CONTAINING_RECORD(
pcurModule, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks));
// Note: pldte->FullDllName.Buffer is Unicode full DLL name
// *(PUSHORT)&pldte->Reserved5[1] is LoadCount
if (pldte->DllBase == hmod)
{
fFoundMod = TRUE;
*ppDllMainOld = (PDLLMAIN)pldte->Reserved3[0];
pldte->Reserved3[0] = pDllMainNew;
}
pcurModule = pcurModule->Flink;
}
return;
}
PDLLMAIN pDllMain_advapi32 = NULL;
BOOL WINAPI DllMain_advapi32(
__in HINSTANCE hinstDLL,
__in DWORD fdwReason,
__in LPVOID lpvReserved)
{
char *pszReason;
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
pszReason = "DLL_PROCESS_ATTACH";
break;
case DLL_PROCESS_DETACH:
pszReason = "DLL_PROCESS_DETACH";
break;
case DLL_THREAD_ATTACH:
pszReason = "DLL_THREAD_ATTACH";
break;
case DLL_THREAD_DETACH:
pszReason = "DLL_THREAD_DETACH";
break;
default:
pszReason = "*UNKNOWN*";
break;
}
printf("\n");
printf("DllMain(0x%.8X, %s, 0x%.8X)\n",
(int)hinstDLL, pszReason, (int)lpvReserved);
printf("\n");
if (NULL == pDllMain_advapi32)
{
return FALSE;
}
else
{
return (*pDllMain_advapi32)(
hinstDLL,
fdwReason,
lpvReserved);
}
}
void TestThread(void *)
{
// Do nothing
}
// Test HookDllEntryPoint
int _tmain(int argc, _TCHAR* argv[])
{
HMODULE hmodAdvapi = LoadLibrary(L"advapi32.dll");
printf("advapi32.dll Base Addr: 0x%.8X\n", (int)hmodAdvapi);
HookDllEntryPoint(
hmodAdvapi, DllMain_advapi32, &pDllMain_advapi32);
_beginthread(TestThread, 0, NULL);
Sleep(1000);
return 0;
}