Search code examples
c++visual-studio-2010dllhookdetours

Detours Hook: GetVolumeInformation Random Volume Serial


I'm trying to hook GetVolumeInformation, using Detours Express (3.0), to change the volume serial. The problem is each time the hooked function is called it returns a random volume serial.

#include <fstream>
#include <string>
#include <windows.h>
#include <detours.h>
#include <fcntl.h>
#include <stdio.h>
#include <io.h>
#pragma comment(lib,"detours.lib")
#pragma comment(lib,"ws2_32.lib")
std::string rcvBuf;

HANDLE CreateConsole();

HANDLE CreateConsole()
{
    int hConHandle = 0;
    HANDLE lStdHandle = 0;
    FILE *fp = 0;

    // Allocate a console
    AllocConsole();

    // redirect unbuffered STDOUT to the console
    lStdHandle = GetStdHandle(STD_OUTPUT_HANDLE);
    hConHandle = _open_osfhandle(PtrToUlong(lStdHandle), _O_TEXT);
    fp = _fdopen(hConHandle, "w");
    *stdout = *fp;
    setvbuf(stdout, NULL, _IONBF, 0);

    return lStdHandle;
}

HMODULE hLib = GetModuleHandle("Kernel32.dll");
typedef BOOL (WINAPI *HWIDPtr)(LPCTSTR lpRootPathName, LPTSTR lpVolumeNameBuffer, DWORD nVolumeNameSize, LPDWORD &lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength, LPDWORD lpFileSystemFlags, LPTSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize);
HWIDPtr pHWID = (HWIDPtr)GetProcAddress(hLib, "GetVolumeInformationW");

BOOL WINAPI MyHWID(LPCTSTR lpRootPathName, LPTSTR lpVolumeNameBuffer, DWORD nVolumeNameSize, LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength, LPDWORD lpFileSystemFlags, LPTSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize)
{
    printf( ("Real : %u"),&lpVolumeSerialNumber);
    return pHWID(lpRootPathName, lpVolumeNameBuffer, nVolumeNameSize, lpVolumeSerialNumber, lpMaximumComponentLength, lpFileSystemFlags, lpFileSystemNameBuffer, nFileSystemNameSize);
}

BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved)
{

if (DetourIsHelperProcess()) {
    return TRUE;
}

if (dwReason == DLL_PROCESS_ATTACH) {

    CreateConsole();
    DetourRestoreAfterWith();

    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());
    DetourAttach(&(PVOID&)pHWID, MyHWID);
    if(DetourTransactionCommit() == NO_ERROR)
               printf("Attached successfuly!@");
}
else if (dwReason == DLL_PROCESS_DETACH) {

    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());
    DetourDetach(&(PVOID&)pHWID, MyHWID);
    DetourTransactionCommit();
}
return TRUE;
}

any advise would be appreciated.


Solution

  • If you are referring to the fact that printf() call inside the hook function outputs random garbage - it makes perfect sense, since lpVolumeSerialNumber is an out parameter, and hence it may (and most probably will) contain garbage prior to the original function call. If you want to see the value returned by the original function, you should rewrite your hook function in the following manner:

    BOOL WINAPI MyHWID(LPCTSTR lpRootPathName, LPTSTR lpVolumeNameBuffer, DWORD nVolumeNameSize, LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength, LPDWORD lpFileSystemFlags, LPTSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize)
    {
        BOOL retval = pHWID(lpRootPathName, lpVolumeNameBuffer, nVolumeNameSize, lpVolumeSerialNumber, lpMaximumComponentLength, lpFileSystemFlags, lpFileSystemNameBuffer, nFileSystemNameSize);
        printf( ("Real : %u"), *lpVolumeSerialNumber);
        return retval;
    }
    

    Please note that I also changed the "&" to "*" - this is what you should use if you want to dereference a pointer rather than get its address.

    Hope this helps