Hooking RtlCopyMemory crash

c++ / delphi package - dll injection and api hooking
Post Reply
wineggdrop
Posts: 19
Joined: Mon Nov 18, 2019 6:18 am

Hooking RtlCopyMemory crash

Post by wineggdrop »

VOID (WINAPI *Real_RtlCopyMemory)(PVOID pDestination,const PVOID pSource,SIZE_T iSize);
VOID WINAPI Detour_RtlCopyMemory(PVOID pDestination,const PVOID pSource,SIZE_T iSize);

void InstallHook()
{
LPTSTR lpModule = "ntdll.dll";
LPTSTR lpAPIToHook = "RtlCopyMemory";
HookAPI(lpModule,lpAPIToHook,Detour_RtlCopyMemory,(PVOID*)&Real_RtlCopyMemory);
}

VOID Detour_RtlCopyMemory(PVOID pDestination,const PVOID pSource,SIZE_T iSize)
{
OutputDebugPrintf("RtlCopyMemory Called");
return Real_RtlCopyMemory(pDestination,pSource,iSize);
}

when the dll injects into any process(tested on notepad.exe,mstsc.exe or other application),the process crashes with c0000005 error.no problem Hooking RtlCompareMemory.
test platform: windows 7 x64 and windows server 2012 R2
Last edited by wineggdrop on Tue Nov 19, 2019 12:39 am, edited 1 time in total.
iconic
Site Admin
Posts: 1065
Joined: Wed Jun 08, 2005 5:08 am

Re: Hooking RtlCopyMemory crash

Post by iconic »

Your detour callback is missing WINAPI (__stdcall) calling convention

--Iconic
wineggdrop
Posts: 19
Joined: Mon Nov 18, 2019 6:18 am

Re: Hooking RtlCopyMemory crash

Post by wineggdrop »

VOID (WINAPI *Real_RtlCopyMemory)(PVOID pDestination,const PVOID pSource,SIZE_T iSize);
VOID WINAPI Detour_RtlCopyMemory(PVOID pDestination,const PVOID pSource,SIZE_T iSize);

void InstallHook()
{
LPTSTR lpModule = "ntdll.dll";
LPTSTR lpAPIToHook = "RtlCopyMemory";
HookAPI(lpModule,lpAPIToHook,Detour_RtlCopyMemory,(PVOID*)&Real_RtlCopyMemory);
}

VOID WINAPI Detour_RtlCopyMemory(PVOID pDestination,const PVOID pSource,SIZE_T iSize)
{
OutputDebugPrintf("RtlCopyMemory Called");
return Real_RtlCopyMemory(pDestination,pSource,iSize);
}

same result with the WINAPI convention.
iconic
Site Admin
Posts: 1065
Joined: Wed Jun 08, 2005 5:08 am

Re: Hooking RtlCopyMemory crash

Post by iconic »

Does Real_RtlCopyMemory have WINAPI? Both callback and real hook definitions need the same calling convention, otherwise you crash

--Iconic
wineggdrop
Posts: 19
Joined: Mon Nov 18, 2019 6:18 am

Re: Hooking RtlCopyMemory crash

Post by wineggdrop »

iconic wrote:Does Real_RtlCopyMemory have WINAPI? Both callback and real hook definitions need the same calling convention, otherwise you crash

--Iconic
I have tried both with/without WINAPI conversion,same result.I even tried the __cdecl conversion,same result.BTW,it won't only happen in madcodehook,it happens in microsoft's Detours,and minhook library.
iconic
Site Admin
Posts: 1065
Joined: Wed Jun 08, 2005 5:08 am

Re: Hooking RtlCopyMemory crash

Post by iconic »

Make sure you're calling InitializeMadCHook() before anything else. My quick test code worked fine here with a hook on ntdll RtlCopyMemory
RtlCopyMemory.png
RtlCopyMemory.png (41.83 KiB) Viewed 16573 times

Code: Select all

typedef void (WINAPI *_RtlCopyMemory)(PVOID Destination, PVOID Source, SIZE_T Length);

void (WINAPI *Real_RtlCopyMemory)(PVOID Destination, PVOID Source, SIZE_T Length);

void WINAPI Detour_RtlCopyMemory(PVOID Destination, PVOID Source, SIZE_T Length)
{
	Real_RtlCopyMemory(Destination, Source, Length);
	if (Length == 5 && lstrcmpA((char *)Source, "Hello") == 0)
	{
		printf("Calling RtlCopyMemory(0x%p, 0x%p, 0x%x) <-----\n", Destination, Source, Length);
	}
	else
	{
		printf("Calling RtlCopyMemory(0x%p, 0x%p, 0x%x)\n", Destination, Source, Length);
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	InitializeMadCHook();
	char a1[MAX_PATH] = {0};
	char a2[MAX_PATH] = {0};
	_RtlCopyMemory pRtlCopyMemory = (_RtlCopyMemory)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlCopyMemory");
	lstrcpyA(a1, "Hello");
	HookAPI("ntdll.dll", "RtlCopyMemory", Detour_RtlCopyMemory, (PVOID*)&Real_RtlCopyMemory);
	pRtlCopyMemory(&a2, &a1, 5);
	getchar();
	return 0;
}
--Iconic
iconic
Site Admin
Posts: 1065
Joined: Wed Jun 08, 2005 5:08 am

Re: Hooking RtlCopyMemory crash

Post by iconic »

Just tested a 32-bit build of the same code on Win7 x64. The WOW64 version of ntdll does *not* export RtlCopyMemory at all. RtlCompareMemory() however *is* exported

--Iconic
wineggdrop
Posts: 19
Joined: Mon Nov 18, 2019 6:18 am

Re: Hooking RtlCopyMemory crash

Post by wineggdrop »

your code works fine,but it's an exe file,I am talking about the hook in dll,inject the dll into a running process like notepad.exe,mstsc.exe and etc.

64 bit ntdll.dll exports RtlCopyMemory,and 32 bit ntdll.dll won't export that api,I am sure about it.
iconic
Site Admin
Posts: 1065
Joined: Wed Jun 08, 2005 5:08 am

Re: Hooking RtlCopyMemory crash

Post by iconic »

Please upload “your” library project code. I’ll test as soon as I receive it.

—Iconic
wineggdrop
Posts: 19
Joined: Mon Nov 18, 2019 6:18 am

Re: Hooking RtlCopyMemory crash

Post by wineggdrop »

#pragma warning(disable : 4995)
#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <stdio.h>
#include "MadHook.h"


#if defined _M_X64
#pragma comment(lib,"madHookx64.lib")
#elif defined _M_IX86
#pragma comment(lib,"madHookx32.lib")
#endif

VOID (WINAPI *Real_RtlCopyMemory)(PVOID pDestination,const PVOID pSource,SIZE_T iSize);
VOID WINAPI Detour_RtlCopyMemory(PVOID pDestination,const PVOID pSource,SIZE_T iSize);

void InstallHook();
void OutputDebugPrintf(const char* strOutputString, ...);

extern "C" __declspec(dllexport) void MadCodeHookTest(){return;}

BOOL WINAPI DllMain(HINSTANCE hDLL,DWORD fdwReason,LPVOID lpReserved)
{
switch(fdwReason)
{
case DLL_PROCESS_ATTACH:
InstallHook();
break;
case DLL_PROCESS_DETACH:
FinalizeMadCHook();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}

void InstallHook()
{
InitializeMadCHook();

LPTSTR lpModule = NULL;
LPTSTR lpAPIToHook = NULL;

lpModule = "ntdll.dll";
lpAPIToHook = "RtlCopyMemory";
if (HookAPI(lpModule,lpAPIToHook,Detour_RtlCopyMemory,(PVOID*)&Real_RtlCopyMemory))
{
OutputDebugPrintf("Mad Hook %s Successful",lpAPIToHook);
}
else
{
OutputDebugPrintf("Mad Hook %s Failure",lpAPIToHook);
}

}

VOID WINAPI Detour_RtlCopyMemory(PVOID pDestination,const PVOID pSource,SIZE_T iSize)
{
OutputDebugPrintf("RtlCopyMemory Called");
return Real_RtlCopyMemory(pDestination,pSource,iSize);
}

void OutputDebugPrintf(const char* strOutputString, ...)
{
char strBuffer[4096] = { 0 };
va_list vlArgs;
va_start(vlArgs, strOutputString);
_vsnprintf(strBuffer, sizeof(strBuffer)-1, strOutputString, vlArgs);
va_end(vlArgs);
OutputDebugString(strBuffer);
}

tested on X64 version of windows 7 and windows server 2012 R2(compiled DLL is 64 bit)
iconic
Site Admin
Posts: 1065
Joined: Wed Jun 08, 2005 5:08 am

Re: Hooking RtlCopyMemory crash

Post by iconic »

If you remove the variable arg functionality in your code (which use CDECL and can be very bad inside an STDCALL hook callback) to use the normal WIN32 API OutputDebugStringW("RtlCopyMemory Called"); which is also STDCALL does the issue continue to persist? I'd advise you do not use c run-time functions inside DLL hook callbacks, sometimes you can get away with them, other times you can't.

--Iconic
iconic
Site Admin
Posts: 1065
Joined: Wed Jun 08, 2005 5:08 am

Re: Hooking RtlCopyMemory crash

Post by iconic »

Alright, I can confirm the issue, but as you mentioned previously this happens with any other hooking library you have tried so it's not an MCH issue directly.
If you simply just call the *real* function inside your callback the issue disappears here. I've tested with Notepad. To make sure it was being called I
created a secondary thread to poll a global counter to see how often RtlCopyMemory() was being called for 60 seconds, updating the value output every
5 seconds and then sleeping. You'll need a different method for letting other code know that the callback has been called, most other methods I've tried
will actually deadlock.
Internal_Hook_Callback_Count.png
Internal_Hook_Callback_Count.png (69.54 KiB) Viewed 16552 times
--Iconic
iconic
Site Admin
Posts: 1065
Joined: Wed Jun 08, 2005 5:08 am

Re: Hooking RtlCopyMemory crash

Post by iconic »

@wineggdrop

Can you please confirm that simply calling the *real* function inside your callback works without trouble?

Code: Select all


VOID WINAPI Detour_RtlCopyMemory(PVOID pDestination, const PVOID pSource, SIZE_T iSize)
{
    return Real_RtlCopyMemory(pDestination, pSource, iSize);
}
I ran some further tests today and was able to pass all params (dest, src, size) to another worker thread just fine via APCs and then used WriteFile to create a log.
Unsurprisingly, due to the heavy API call volume, the log became rather large quickly here but nonetheless worked fine. OutputDebugString, SendIpcMessage,
mailslots etc. all locked up for me so I turned to APCs (NtQueueApcThread) which allowed all 3 parameters to be effortlessly passed on and logged from a different
thread context. Hopefully that can be helpful to you in some way.

--Iconic
wineggdrop
Posts: 19
Joined: Mon Nov 18, 2019 6:18 am

Re: Hooking RtlCopyMemory crash

Post by wineggdrop »

it works if removing the OutputDebugPrintf("RtlCopyMemory Called");
Post Reply