DetourDetach引发ERROR_INVALID_BLOCK错误

问题描述

我想将Bitblt函数与Detours库挂钩。

https://github.com/microsoft/Detours/blob/master/samples/simple/simple.cpp

通过参考上面的示例源,我成功创建了一个钩住Bitblt函数的dll,但是取消钩子无法正常工作。

当DLL与目标进程分离时,我希望恢复原始功能,但是DetourDetach函数引发ERROR_INVALID_BLOCK错误,并且发生对目标进程的访问冲突。

如何解决错误

下面是我写的源代码

#include <stdio.h>
#include <Windows.h>

void capture(HBITMAP* canvas);

int WINAPI WinMain(_In_ HINSTANCE hInstance,_In_opt_ HINSTANCE hPrevInstance,_In_ LPSTR lpCmdLine,_In_ int nShowCmd) {
    HMODULE hModule = LoadLibrary(TEXT("testdll.dll"));
    if (!hModule) return 1;

    int i = 0;
    while(1) {
        HBITMAP canvas;
        capture(&canvas);
        Sleep(2000);
        if (++i >= 1) 
            FreeLibrary(hModule);
    }

    //FreeLibrary(hModule);
    return 0;
}

void capture(HBITMAP* canvas) {
    RECT srcRect;
    HWND hSrcWnd;
    HDC hSrcDC,hDestDC;

    hSrcWnd = GetDesktopWindow();
    hSrcDC = GetDC(hSrcWnd);

    GetwindowRect(hSrcWnd,&srcRect);
    int SrceenWidth = srcRect.right - srcRect.left;
    int SrceenHeight = srcRect.bottom - srcRect.top;

    hDestDC = CreateCompatibleDC(hSrcDC);
    *canvas = CreateCompatibleBitmap(hSrcDC,SrceenWidth,SrceenHeight);
    SelectObject(hDestDC,*canvas);

    for (int y = 0; y < SrceenHeight; y += 50) {
        BitBlt(hDestDC,y,50,hSrcDC,SRCcopY);
        Sleep(2);
    }

    ReleaseDC(hSrcWnd,hSrcDC);
    DeleteDC(hDestDC);
}

#include "pch.h"

BOOL(WINAPI* originFunc) (HDC,int,HDC,DWORD);
BOOL(WINAPI* detourFunc) (HDC,DWORD);

DWORD WriteLog(LPCTSTR format,...) {
    TCHAR szLog[500];
    DWORD dwBytesWriten;

    va_list args;
    va_start(args,format);
    _vstprintf_s(szLog,500,format,args);
    va_end(args);

    WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),szLog,_tcslen(szLog),&dwBytesWriten,0);

    return dwBytesWriten;
}

BOOL WINAPI MyBitBlt(HDC hdc,int x,int y,int cx,int cy,HDC hdcSrc,int x1,int y1,DWORD rop) {
    WriteLog(TEXT("Function called : Bitblt(0x%X,%d,0x%X,0x%X)\n"),(DWORD)hdc,x,cx,cy,(DWORD)hdcSrc,x1,y1,rop);

    return originFunc(hdc,hdcSrc,rop);
}

BOOL APIENTRY DllMain(HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved) {
    if (DetourIsHelperProcess())
        return TRUE;

    originFunc = BitBlt;
    detourFunc = MyBitBlt;

    LONG error;
    switch (ul_reason_for_call) {
    case DLL_PROCESS_ATTACH:
        AllocConsole();

        DetourRestoreAfterWith();

        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());
        DetourAttach(&(PVOID&)originFunc,detourFunc);
        error = DetourTransactionCommit();

        WriteLog(TEXT("Detour result(Attach) : 0x%08X\n"),error);

        break;

    case DLL_PROCESS_DETACH:
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());
        DetourDetach(&(PVOID&)originFunc,detourFunc);
        error = DetourTransactionCommit();

        WriteLog(TEXT("Detour result(Detach) : 0x%08X\n"),error);
        Sleep(500);

        FreeConsole();

        break;
    }

    return TRUE;
}

#include "framework.h"
#include <stdio.h>
#include <stdarg.h>
#include <tchar.h>
#include <detours.h>

error detail

(本文已由Google翻译翻译。)

解决方法

我发现了问题所在!

for (i in colors.indices) {
            var oldColor = Color.valueOf(colors[i])
            var red = (oldColor.red() + 0.2f) % 1.0f
            var green = (oldColor.green() + 0.2f) % 1.0f
            var blue = (oldColor.blue() + 0.2f) % 1.0f
            colorsNew[i] = Color.argb(1.0f,red,green,blue)
        }

确保在挂接前仅将originFunc初始化一次。 (因为CopyOnWrite)

(本文已由Google翻译翻译。)