Search code examples
winapihookdetours

How to use Detour hook and modify C++ console (cout) output?


Print.cpp

#include <iostream>
#include <Windows.h>
int main()
{
    while (true)
    {
        std::cout << "Hello World!\n";
        Sleep(500);
    }
}

Hook.cpp

#include "pch.h"
#include <detours.h>
#include <iostream>
#pragma comment(lib,"detours.lib")

BOOL(WINAPI* OriginalWriteFile)(
    HANDLE       hFile,
    LPCVOID      lpBuffer,
    DWORD        nNumberOfBytesToWrite,
    LPDWORD      lpNumberOfBytesWritten,
    LPOVERLAPPED lpOverlapped
    ) = WriteFile;
BOOL WINAPI HookedWriteFile(
    HANDLE       hFile,
    LPCVOID      lpBuffer,
    DWORD        nNumberOfBytesToWrite,
    LPDWORD      lpNumberOfBytesWritten,
    LPOVERLAPPED lpOverlapped
) {
    HANDLE stdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    std::cout << "HOOK" << std::endl;
    if (hFile == stdOutput) {
        const char* prefix = "[Hooked]: ";
        std::string newMessage = prefix + std::string((const char*)lpBuffer, nNumberOfBytesToWrite);
        return OriginalWriteFile(hFile, newMessage.c_str(), newMessage.size(), lpNumberOfBytesWritten, lpOverlapped);
    }

    return OriginalWriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped);
}
size_t(__cdecl* OriginalFWrite)(
    const void* buffer,
    size_t size,
    size_t count,
    FILE* stream
    ) = fwrite;

size_t __cdecl HookedFWrite(
    const void* buffer,
    size_t size,
    size_t count,
    FILE* stream
) {
    const char* prefix = "[Hooked]: ";
    std::string newMessage = prefix + std::string((const char*)buffer, size * count);
    return OriginalFWrite(newMessage.c_str(), size, count, stream);
}
std::ostream& (__cdecl* OriginalOstreamOperator)(std::ostream&, const char*) = nullptr;

std::ostream& __cdecl HookedOstreamOperator(std::ostream& os, const char* c)
{
    OutputDebugString(L"asdasdasd");
    const char* prefix = "[Hooked]: ";
    OriginalOstreamOperator(os, prefix); // Adding prefix
    return OriginalOstreamOperator(os, c); // Original call
}


BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        std::cout << OriginalWriteFile << std::endl;
        OutputDebugString(L"HOOK START");
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());
        std::cout << OriginalFWrite << std::endl;
        DetourAttach(&(PVOID&)OriginalWriteFile, HookedWriteFile);
        DetourAttach(&(PVOID&)OriginalFWrite, HookedFWrite);
        DetourAttach(&(PVOID&)OriginalOstreamOperator, HookedOstreamOperator);
        DetourTransactionCommit();

        break;
    case DLL_THREAD_ATTACH:

    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());
        DetourDetach(&(PVOID&)OriginalWriteFile, HookedWriteFile);
        DetourDetach(&(PVOID&)OriginalFWrite, HookedFWrite);
        DetourDetach(&(PVOID&)OriginalOstreamOperator, HookedOstreamOperator);
        DetourTransactionCommit();
        break;
    }
    return TRUE;
}

I also tried WriteConsoleA, WriteConsoleW and WriteFile. None of these methods work. It still outputs Hello World! How can I use HOOK to get the console contents or modify the contents?

I found that they were not being called. I did a breakpoint check with x32dbg and found that WriteFile and FWrite were called, but HOOK, which I programmed, was not.

Run:

759F3C50
776D6E80
Hello World!
Hello World!
Hello World!
Hello World!

Solution

  • I found the error. The reason is that I didn't write break in DLL_THREAD_ATTACH and DLL_THREAD_DETACH, so the HOOK was being detached.

    I added break to DLL_THREAD_ATTACH and DLL_THREAD_DETACH:

    case DLL_THREAD_ATTACH:
            break;
    case DLL_THREAD_DETACH:
           break;