最近有用到detour,属于一种api拦截的方式了,是微软研究院出的一个库(可以网上下载,是源码形式,有makefile,可用vs的命令行工具来编译出来)。可以替换掉我们关心的api,进入到我们的处理中。

当然,api拦截,首先需要借助Dll注入,才能够去影响你想改变的进程,这可通过上篇文章中全局hook来实现:可在hookProc回调中,进行detour,然后在DLL的proc_detach中undetour就可以了。

其实detour的使用倒是很简单了。直接几个接口就可以了,具体看下面代码。

static bool _apihooked = false;

static int (WINAPI *SysMessageBox)(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
= MessageBox;

// detour function that replaces the MessageBox API
int WINAPI HookMessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
{
    using namespace std;
    wofstream ofs(L"record.txt", ios::app);
    ofs.write(lpText, _tcslen(lpText));
    ofs.close();
    return SysMessageBox(hWnd, lpText, lpCaption, uType);
}

static bool _detourStart()
{    
    DetourRestoreAfterWith();//

    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());

    DetourAttach(&(PVOID&)SysMessageBox, HookMessageBox);

    LONG ret = DetourTransactionCommit();
    if (ret != NO_ERROR)
    {
        assert(false && "detour start failed");
        return false;
    }

    return true;
}

static bool _detourStop()
{    
    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());

    DetourDetach(&(PVOID&)SysMessageBox, HookMessageBox);

    LONG ret = DetourTransactionCommit();
    if (ret != NO_ERROR)
    {
        assert(false && "detour stop failed");
        return false;
    }

    return true;
}

bool DetourStart()
{
    if (!_apihooked)
    {
        if (!_detourStart())
            return false;
        _apihooked = true;
    }

    return true;
}

bool DetourStop()
{
    if (_apihooked)
    {
        if (!_detourStop())
            return false;
        _apihooked = false;
    }

    return true;
}