Accessing Memory in DLL Injection results in Memory Access Violation - c++

I recently started trying to get into game hacking to develop my reverse engineering skills. I am running Windows 10. For now, I am trying to write a basic DLL Injection program that will let me read certain bytes from the game and print them out. Unfortunately, when I inject my DLL the game immediately crashes with the following log recovered from Windows Event Viewer:
Faulting application name: game_to_hack.exe, version: 2019.4.19.23316, time stamp: 0x6007d1a6
Faulting module name: IL2CppDLL.dll, version: 0.0.0.0, time stamp: 0x618dc9c6
Exception code: 0xc0000005
Fault offset: 0x0000000000248f48
Faulting process id: 0x8ca8
which seems to indicate a memory access violation on the given address.
The code for my DLL is relatively simple. There is a class which is supposed to scan the game for a certain pattern of bytes:
class SigScan
{
public:
// For getting information about the executing module
MODULEINFO GetModuleInfo(char *szModule)
{
MODULEINFO modinfo = { 0 };
HMODULE hModule = GetModuleHandle(szModule);
if (hModule == 0)
return modinfo;
GetModuleInformation(GetCurrentProcess(), hModule, &modinfo, sizeof(MODULEINFO));
return modinfo;
}
// for finding a signature/pattern in memory of another process
DWORD FindPattern(char *module, char *pattern, char *mask)
{
MODULEINFO mInfo = GetModuleInfo(module);
DWORD base = (DWORD)mInfo.lpBaseOfDll;
DWORD size = (DWORD)mInfo.SizeOfImage;
DWORD patternLength = (DWORD)strlen(mask);
char test = *(char*)base; // <- This is the memory access that causes the crash.
// TODO: Actually scan for the pattern
};
My dllmain.cpp then uses the above class to try and find the pattern:
void Run()
{
SigScan Scanner;
// It's a Unity game.
char proc_name[] = "gameassembly.dll";
char byte_sequence[] = "\x48\x8b\xc4\x48\x89\x58\x08\x48\x89\x70\x18";
char pattern[] = "xxxxxxxxxxx";
Scanner.FindPattern(proc_name, byte_sequence, pattern);
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
init_il2cpp();
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) Run, NULL, 0, NULL);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
My question is why does the crash happen and how can I fix it? I have confirmed that the MODULEINFO struct returned from the GetModuleInfo function is initialized to a non-null value, and the base address that I read from it seems legitimate. From reading other posts I understand that Windows will throw a memory access violation if you try to read another process's memory, but since my code is running in a DLL Injection my understand is that it should be able to read the memory without issue, since it is within the same process.
Any help is greatly appreciated! Thanks for your time.

I am a fool.
This line is the cause of all my issues:
DWORD base = (DWORD)mInfo.lpBaseOfDll;
This code is running on a 64-bit OS, whereas a DWORD is only 4 bytes, so it is presumably just taking the lower 4 bytes of the base pointer and using that, which results in invalid memory accesses as I am essentially looking at random addresses. Using a DWORD_PTR instead (8 bytes on a 64-bit OS) has solved all my issues.

Related

Access violation when unloading injected DLL via CreateRemoteThread

I'm trying to cleanly inject DLL into foreground window's process, call simple function from this DLL and then cleanly unload the DLL. My injection code:
HWND fgwnd = GetForegroundWindow();
DWORD cur_thread = GetCurrentThreadId();
DWORD fg_pid = 0;
DWORD fg_thread = GetWindowThreadProcessId(fgwnd, &fg_pid);
BOOL res = 0;
const char* inj_path = "C:\\Users\\pc\\source\\repos\\hothook\\x64\\Debug\\fground_injector.dll";
// Get process handle to victim
HANDLE victim = OpenProcess(PROCESS_ALL_ACCESS, FALSE, fg_pid);
// Find exact adress of LoadLibraryA function from text space of kernel32.dll loaded by the OS
// and used by victim
PVOID llib = (LPVOID)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryA");
PVOID flib = (LPVOID)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "FreeLibrary");
// Allocate memory inside victim's address space
LPVOID inj_path_victim = (LPVOID)VirtualAllocEx(victim, NULL, strlen(inj_path)+1,
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
// Write inject dll's adress into victim
SIZE_T written;
res = WriteProcessMemory(victim, inj_path_victim, inj_path, strlen(inj_path)+1, &written);
// Finally, inject DLL into victim!
// Spawn thread in remote process ================================================================
HANDLE inj_llib_thread = CreateRemoteThread(
/*I*/ victim, // Handle to process where thread will be created
/*I*/ NULL, // SECURITY_ATTRIBUTES for new thread
/*I*/ 0, // Initial stacks size, bytes. 0 -> default size
/*I*/ (LPTHREAD_START_ROUTINE)llib, // User defined callback LPTHREAD_START_ROUTINE
/*I*/ inj_path_victim, // Ptr to variable to be sent as func parameter
/*I*/ 0, // Creation control flags. 0 -> immediate start
/*O|O*/ NULL); // Ptr to variable that recieves thread ID
// ===============================================================================================
// CANNOT WAIT FOR THREAD IN OTHER PROCESS.... OR CAN I?! I CAN!
// Wait for DLL to get properly injected into victim
res = WaitForSingleObject(inj_llib_thread, INFINITE);
// Get executable base address of the loaded DLL
DWORD llib_exit;
res = GetExitCodeThread(inj_llib_thread, &llib_exit);
// Free previously allocated remote memory
res = VirtualFreeEx(victim, inj_path_victim, 0, MEM_RELEASE);
// Call injected DLL's function
HMODULE fg_inj = LoadLibraryA(inj_path);
PVOID inj_t_proc = (LPVOID)GetProcAddress(fg_inj, "injectThread");
PVOID ulib = NULL;
// Spawn thread in remote process ================================================================
HANDLE inj_thread = CreateRemoteThread(
/*I*/ victim, // Handle to process where thread will be created
/*I*/ NULL, // SECURITY_ATTRIBUTES for new thread
/*I*/ 0, // Initial stacks size, bytes. 0 -> default size
/*I*/ (LPTHREAD_START_ROUTINE)inj_t_proc, // User defined callback LPTHREAD_START_ROUTINE
/*I*/ NULL, // Ptr to variable to be sent as func parameter
/*I*/ 0, // Creation control flags. 0 -> immediate start
/*O|O*/ NULL); // Ptr to variable that recieves thread ID
// ===============================================================================================
// Wait before injected DLL's thread finishes before extraction
res = WaitForSingleObject(inj_thread, INFINITE);
// Extract injected DLL from victim
// Spawn thread in remote process ================================================================
HANDLE inj_flib_thread = CreateRemoteThread(
/*I*/ victim, // Handle to process where thread will be created
/*I*/ NULL, // SECURITY_ATTRIBUTES for new thread
/*I*/ 0, // Initial stacks size, bytes. 0 -> default size
/*I*/ (LPTHREAD_START_ROUTINE)flib, // User defined callback LPTHREAD_START_ROUTINE
/*I*/ (LPVOID)llib_exit, // Ptr to variable to be sent as func parameter
/*I*/ 0, // Creation control flags. 0 -> immediate start
/*O|O*/ NULL); // Ptr to variable that recieves thread ID
// ===============================================================================================
// Wait untill injected DLL is fully extracted from the victim
res = WaitForSingleObject(inj_flib_thread, INFINITE);
DWORD flib_exit;
res = GetExitCodeThread(inj_flib_thread, &flib_exit);
// Extract injection DLL from host
FreeLibrary(fg_inj);
// ^^^ This actually does not unload DLL from host app, even if I call it 100 times in a loop...
// Clean up by closing all utilised handles
CloseHandle(victim);
CloseHandle(inj_llib_thread);
CloseHandle(inj_thread);
CloseHandle(inj_flib_thread);
My injection DLL is truly bare-bones:
BOOL APIENTRY DllMain(HMODULE hm,
DWORD call_reas,
LPVOID reserved)
{
switch(call_reas)
{
case DLL_PROCESS_ATTACH:
{
DisableThreadLibraryCalls(hm);
// I thought that threads calling DllMain with case 2-3 cause crash
// But no, same crash with or without this call
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
DWORD injectThread(LPVOID p)
{
//AllowSetForegroundWindow(ASFW_ANY);
// This is what it originally suppose to do
// Let the host "steal" foreground window status from victim
// But even commenting this out results in the same crash
return 0;
}
The crash happens after I create FreeLibrary remote thread to unload injected DLL. This is as much crash details as I could get, as it happens in the system kernel it seems:
Exception thrown at 0x00007FFE598C7170 in maudswch.exe: 0xC0000005: Access violation executing location 0x00007FFE598C7170.
00007ffe598c7170()
kernel32.dll!00007ffe9ac47034()
ntdll.dll!00007ffe9c682651()
Not Flagged 50864 0 Main Thread Main Thread win32u.dll!00007ffe99e51104
Not Flagged 47548 0 Worker Thread ntdll.dll thread ntdll.dll!00007ffe9c6d0794
Not Flagged 41096 0 Worker Thread ntdll.dll thread ntdll.dll!00007ffe9c6d0794
Not Flagged 43456 0 Worker Thread ntdll.dll thread ntdll.dll!00007ffe9c6d0794
Not Flagged > 29820 0 Worker Thread Win64 Thread 00007ffe598c7170
I tested this on many "victims". CMD, Notepad, my other custom GUI program. The result is the same. DLL gets successfully injected, DLL function gets executed, but when unloading it crashes "victim". One more detail, is that FreeLibrary remote thread takes quite long time to finish, about 1.5 seconds sometimes even 7 seconds!
I'm trying to solve this puzzle for days now, I searched all the Internet, but all other similar cases seems to be non-related... And at this point I have no idea what is going on and how to fix this. Of course, I can just bite the bullet and never try to unload my injected DLL, after all it works. But I don't want to leave useless DLLs in other processes after it finished it's job.
Edit:
Some debug prints. As you can see, hm: and func addr: is outputted in DllMain PROCESS_ATTACH. As you can see, I'm lucky to have base DLL address and function address to be exactly the same in host and victim processes. However, passing full base address to FreeLibrary external thread results in exactly the same crash, so truncated base address was not the real reason behind the crash...
Using GetExitCodeThread() to retrieve the HMODULE returned by LoadLibraryA() in the target process will work only if the victim is a 32bit process. Otherwise, the HMODULE will be too large to fit in the remote thread's exit code, so you will have to use a different mechanism to get the DLL's base address in the target process, such as using EnumProcessModules()+GetModuleFileNameEx() or CreateToolhelp32Snapshot()+Module32(First|Next)(), or even injecting stub code that calls LoadLibraryA() and saves the HMODULE into a variable that the injector allocates and can read from via ReadProcessMemory().
More importantly, the way you are calling the DLL's injectThread() function in the target process is wrong. You are using LoadLibraryA()+GetProcAddress() to get a pointer to the injectThread() function within the injector's process, and then you are assuming that the function is located at the same address in the target process. But the DLL in the target process may have been loaded at a different base address than the DLL in the injector process (especially in light of technologies like ALSR, DLL rebasing, etc).
The correct solution is to get the offset of the injectThread() function within the DLL (which the injector can calculate by subtracting its DLL's base address from the function's address), and then add that offset to the base address of the DLL in the target process.
Also, make sure your injectThread() function has the correct signature that CreateRemoteThread() is expecting. What you showed is missing a calling convention specified, so it will use whatever the compiler's default convention is, which is usually __cdecl. But CreateRemoteThread() requires __stdcall instead.

64-bit Code Cave Returning Incorrect Entry Point Location

I have been attempting to run a 64-bit DLL purely in a processes virtual memory without 'manually mapping' it (i.e. manually resolving relocations/imports).
The plan was to inject code into the target application and load the module via conventional means, such as LoadLibrary.
I was under the assumption LoadLibrary would fix the module relocations/imports on it's own, as that's what it is designed to do.
After loading the module, the injected code would obtain information regarding the module with GetModuleInformation, transfer it to a temporary memory buffer, free the module, allocate memory at the same address it was originally loaded at, write it back, and execute the entry point.
That last step is where I believe the error is occurring.
In order to test this theory, I have hard-coding entry point addresses, debugged the remote application via Visual Studio's 'Attach to Process' feature, emulated a similar environment to correct bad pointer arithmetic, all in order to gain a bit more information on what the error might be.
Here is some general information which may or may not be useful:
Both applications (the injector, and DLL) are compiled to run in 64-bit architectures
The test application I have been using to test the injection method is the windows update applicaiton (wuauclt.exe - located in /System32/), it is of course compiled to run as a 64-bit PE
Host machine: Windows 7 Home Premium (system type: 64-bit operating system)
As far as information relating directly to the injector goes:
The primary code injection method works (as far as I can tell), and I have proven this via caveman debugging with MessageBoxA
The project is using a multi-byte character set with code optimizations disabled. The code was compiled using VS 2013 Ultimate (both projects built for Release x64)
SDL checks are off since unsafe functions are used (strcpy and friends)
The injector is debugged with elevated privileges (as high as SE_DEBUG_PRIVILEGES) every time its ran.
Code Preface:
The code exhibited below is not in any which way meant to look pretty or exhibit good programming practices. Keep this in mind when viewing the code. It was specifically designed to test a code-injection method to verify it works. If you have issues with the program layout, structure, etc, feel free to correct them and/or restructure them on your own. It's not the reason I'm here. Unless it is what resulted in the error, then it is entirely the reason I'm here :)
The code for the injector: http://pastebin.com/FF5G9nnR
/*
Some of the code was truncated (functions not pertaining to the injection), but
I have verified the code compiles and works correctly with it's injeteme.dll counterpart
*/
#include <Windows.h>
#include <Psapi.h>
#define TARGET_PID 1124
typedef BOOL(WINAPI* pFreeLibrary)(HMODULE);
typedef HMODULE(WINAPI* pLoadLibraryA)(LPCSTR);
typedef HANDLE(WINAPI* pGetCurrentProcess)(void);
typedef BOOL(WINAPI* DLL_MAIN)(HMODULE, DWORD, LPVOID);
typedef HANDLE(WINAPI* pOpenProcess)(DWORD, BOOL, DWORD);
typedef BOOL(WINAPI* pVirtualFree)(LPVOID, SIZE_T, DWORD);
typedef int(__stdcall* pMessageBoxA)(HWND, LPCSTR, LPCSTR, UINT);
typedef LPVOID(WINAPI* pVirtualAlloc)(LPVOID, SIZE_T, DWORD, DWORD);
typedef BOOL(WINAPI* pGetModuleInformation)(HANDLE, HMODULE, LPMODULEINFO, DWORD);
typedef BOOL(WINAPI* pWriteProcessMemory)(HANDLE, LPVOID, LPCVOID, SIZE_T, SIZE_T*);
//////////////////////////////////////////////////////////////////
struct IINFO
{
LPVOID stubAddr;
LPVOID retStatusPtr;
char fullModulePath[MAX_PATH];
DWORD pId, sizeOfCurrStruct;
// DEBUG
pMessageBoxA messageBox;
pOpenProcess openProcess;
pVirtualFree virtualFree;
pFreeLibrary freeLibrary;
pLoadLibraryA loadLibrary;
pVirtualAlloc virtualAlloc;
pGetCurrentProcess getCurrProc;
pWriteProcessMemory writeMemory;
pGetModuleInformation getModInfo;
};
static DWORD WINAPI stub(IINFO *iInfo)
{
HMODULE hMod;
MODULEINFO mInfo;
DLL_MAIN dllMain;
LPVOID lpNewMod, lpTempModBuff;
PIMAGE_DOS_HEADER pIDH;
PIMAGE_NT_HEADERS pINH;
iInfo->messageBox(NULL, iInfo->fullModulePath, NULL, 0);
hMod = iInfo->loadLibrary(iInfo->fullModulePath);
if (!hMod)
return 0;
if (!iInfo->getModInfo(iInfo->getCurrProc(), hMod, &mInfo, sizeof(MODULEINFO)))
return 0;
lpTempModBuff = iInfo->virtualAlloc(NULL, mInfo.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!lpTempModBuff)
return 0;
if (!iInfo->writeMemory(iInfo->getCurrProc(), lpTempModBuff, mInfo.lpBaseOfDll, mInfo.SizeOfImage, NULL))
return 0;
if (!iInfo->freeLibrary(hMod))
return 0;
lpNewMod = iInfo->virtualAlloc(mInfo.lpBaseOfDll, mInfo.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!lpNewMod)
return 0;
// using wpm since we have already acquired the function
if (!iInfo->writeMemory(iInfo->getCurrProc(), lpNewMod, lpTempModBuff, mInfo.SizeOfImage, NULL))
return 0;
if (!iInfo->virtualFree(lpTempModBuff, 0, MEM_RELEASE))
return 0;
/*if (!iInfo->virtualFree(iInfo, 0, MEM_RELEASE))
return 0;
iInfo->messageBox(NULL, NULL, NULL, 0); */
pIDH = (PIMAGE_DOS_HEADER)lpNewMod;
if (!pIDH)
return 0;
pINH = (PIMAGE_NT_HEADERS)((LPBYTE)lpNewMod + pIDH->e_lfanew);
if (!pINH)
return 0;
dllMain = (DLL_MAIN)((LPBYTE)lpNewMod + pINH->OptionalHeader.AddressOfEntryPoint);
if (!dllMain)
return 0;
iInfo->messageBox(NULL, NULL, NULL, 0);
dllMain((HINSTANCE)lpNewMod, DLL_PROCESS_ATTACH, NULL);
return 1;
}
static DWORD WINAPI stubEnd(){ return 0; }
//////////////////////////////////////////////////////////////////
int main()
{
HANDLE hThread = 0;
DWORD dwStubSize = 0;
int sucResp = 0, count = 0;
HMODULE hUser32 = 0, hNtdll = 0;
char fullPathName[] = "C:\\injectme.dll";
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, TARGET_PID);
if (!hProc || hProc == INVALID_HANDLE_VALUE)
return 0;
__int64 SizeOfStub = (LPBYTE)stubEnd - (LPBYTE)stub;
LPVOID lpStub = VirtualAllocEx(hProc, NULL, SizeOfStub, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!lpStub)
return 0;
hUser32 = LoadLibraryA("user32.dll");
if (!hUser32)
return 0;
hNtdll = LoadLibraryA("kernel32.dll");
if (!hNtdll)
return 0;
IINFO iInfo = {};
iInfo.retStatusPtr = &sucResp;
strcpy(iInfo.fullModulePath, fullPathName);
iInfo.sizeOfCurrStruct = sizeof(IINFO);
iInfo.stubAddr = lpStub;
iInfo.pId = GetCurrentProcessId();
iInfo.messageBox = (pMessageBoxA)GetProcAddress(hUser32, "MessageBoxA");
iInfo.openProcess = (pOpenProcess)GetProcAddress(hNtdll, "OpenProcess");
iInfo.virtualFree = (pVirtualFree)GetProcAddress(hNtdll, "VirtualFree");
iInfo.freeLibrary = (pFreeLibrary)GetProcAddress(hNtdll, "FreeLibrary");
iInfo.loadLibrary = (pLoadLibraryA)GetProcAddress(hNtdll, "LoadLibraryA");
iInfo.virtualAlloc = (pVirtualAlloc)GetProcAddress(hNtdll, "VirtualAlloc");
iInfo.getCurrProc = (pGetCurrentProcess)GetProcAddress(hNtdll, "GetCurrentProcess");
iInfo.writeMemory = (pWriteProcessMemory)GetProcAddress(hNtdll, "WriteProcessMemory");
iInfo.getModInfo = (pGetModuleInformation)GetProcAddress(hNtdll, "K32GetModuleInformation");
LPVOID lpStubInfo = VirtualAllocEx(hProc, NULL, sizeof(IINFO), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!lpStubInfo)
return 0;
if (!WriteProcessMemory(hProc, lpStub, stub, SizeOfStub, NULL))
return 0;
if (!WriteProcessMemory(hProc, lpStubInfo, &iInfo, sizeof(iInfo), NULL))
return 0;
hThread = CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)lpStub, lpStubInfo, 0, NULL);
if (!hThread || hThread == INVALID_HANDLE_VALUE)
return 0;
WaitForSingleObject(hThread, INFINITE);
return 1;
}
The code for the DLL to be injected: http://pastebin.com/8WXxcpu1
#include <Windows.h>
BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpParam)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
{
MessageBoxA(NULL, "Hello from injectme.dll!", "", MB_OK | MB_ICONINFORMATION);
break;
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
The error when running the code above verbatim (assuming you also applied the settings above and have a similar environment) in VS2013's debugger is as follows:
"Unhandled exception at 0x000007FEEA5125D4 in wuauclt.exe: 0xC0000005: Access violation executing location 0x000007FEEA5125D4."
Upon viewing the process "wuauclt.exe" in Process Hacker, I can clearly see the module was allocated originally (upon being loaded via LoadLibrary) at 0x7fef67c0000. This is shown in the context menu->under miscellaneous->unloaded modules.
Once double-clicking "wuauclt.exe", you can browse over the application's virtual memory to ensure everything is working as it should be. I can confirm for this current session, an RWX memory buffer has been allocated at 0x7fef67c0000 with the exact size of the unloaded module, containing the injectme.dll module. When digging into injectme.dll with CFF Explorer, then entry point RVA seems to be 0x132C, which does not add up, considering the error is much further away in memory. Additionally, I can verify two more RWX memory buffers containing the code injection stub, and information structure. Looking back the information structure probably doesn't need RWX. Anyway, I can't for the life of me figure out the error.
I'm hoping one you may be able to assist me. I am extremely grateful for your time.
My gut feeling is that you're lacking the fundamental understanding for such a challenging project. You're mixing concepts from rather distinct realms.
Windows itself cares very, very little about the programming language you used in development. Either you get CLR code (.Net) or native code. In this case it's x64. But Windows really doesn't care about strcpy or SDL checks. That's for the compiler to deal with, not the OS. Chances are strcpy wouldn't even survive, when its code is fully inlined. But you apparently have optimizations turned off, for some strange reason - again a compiler versus OS confusion.
However, Windows does care about other concepts that you don't mention. Chiefly those would be ASLR and DEP - Address Space Layout Randomization and Data Execution Prevention. They're techniques to keep hackers out, and you're hacking. So that's not really a surprise.
I'm not sure if by "RWX" you mean Read Write Execute" because you should know that's asking for problems. DEP is inspired by the more aptly named W^X, Write XOR eXecute.
The more likely culprit is ASLR, though. Windows by design tries to load DLL's at unpredicatble addresses, as that eliminates an entire class of hacks. It appears you're assuming a load address, while Windows really is using another address.
A final mistake might be that you're failing to understand where the relocations are done. To improve the amount of shareable pages, relocations are done on the Import Address Table, not the code itself. The IAT is a trampoline table, and therefore executable. Your failure might also be a missing IAT.

Detours: Prevent task kill of my software via another software

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;
}

process crashes when I read/write memory with dll injection

I wrote a hackme program and I want to hook it and make bruteforce to crack it (with dll injection).
the problem is when I'm trying to write or read the memory, the process crashes (its happens to me not only with the hackme program, but every program), although I give myself writing and reading privilleges with VirtualProtect.
If I add messagebox to the dll, the messagebox works.
here is the dll that supposed to prevent from the process to print something (with NOPing):
#include "DLL.h"
#include <windows.h>
#include <tlhelp32.h>
BOOL APIENTRY DllMain(HINSTANCE hInst, DWORD reason, LPVOID reserved)
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
DWORD threadId;
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&ThreadProc, NULL, 0, &threadId);
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return true;
}
DWORD ThreadProc(LPVOID lpdwThreadParam)
{
VirtualProtect((LPVOID)0x00417D10, 5, PAGE_EXECUTE_READWRITE, NULL);
*(char *)0x00417D10 = 0x90;
*(char *)0x00417D11 = 0x90;
*(char *)0x00417D12 = 0x90;
*(char *)0x00417D13 = 0x90;
*(char *)0x00417D14 = 0x90;
return 0;
}
here's the information about the address in the process that I'm writing to:
http://prntscr.com/2bveja (with IDA)
the dll, the injector and the hackme are compiled for 32bit.
I'm using win7 64b.
There were 2 problems:
VirtualProtect can not receive NULL in the last parameter (old privilege).
Therefore I gave it pointer to DWORD variable.
I gave the VirtualProtect a permanent address, but it was not good, since in windows 7 the image base changes every execution, so I found out the process image base and added it the offset 0x12d1.
HMODULE hand = GetModuleHandle(L"HackMe.exe");
VirtualProtect((LPVOID)((DWORD)hand + (DWORD)0x12d1), 6, PAGE_EXECUTE_READWRITE, &oldp);

Detect when a Module (DLL) is unloaded

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;
}