簡體   English   中英

使用注入的DLL從外部應用程序渲染OpenGL場景內部

[英]Render inside of OpenGL scene from an external application using an injected DLL

我已經能夠將DLL注入到應用程序中,例如鍵盤操作,但是如何掛鈎到OpenGL程序並繪制它? 我已經閱讀了許多“教程”和答案,但他們都概述了這樣做的想法,而不是如何實際做到這一點。 如果有人能指出我正確的方向,我會非常感激。

我打算做的是能夠從RAM中的第三方應用程序(注入dll)繪制疊加(或者可能在實際場景中繪制?這可能嗎?)。 我對OpenGL的唯一體驗是通過GLUT,但我願意學習,如果需要的話。

經過幾個小時的研究,我找到了一個開源應用程序,可以做我想要的,並查看其代碼,但似乎無法找到被掛鈎的方法或ASM代碼如何在該特定方法中更改。

是否在注入dll時定義要掛鈎的方法,或者在附加dll時是否執行此操作? 根據我的理解,你可以做任何一個,但是一個比另一個好嗎?

我正在尋找一個全面的教程,或者這樣一個簡單的例子。 如果有人能指出我正確的方向,那就太好了!

要理解的最關鍵的一步是,OpenGL是基於狀態的繪圖API,而不是場景圖。 因此,您不能假設,有一些場景可以添加一些疊加。 相反,你必須找到一個點,你知道你注入的程序是完成繪圖,你可以它上面繪制疊加。

這一點很容易識別的雙緩沖窗口:將呼叫wglSwapBuffers (或glXSwapBuffers基於X11系統, eglSwapBuffers基於EGL系統- Windows使用都沒有)。

所以你要做的是掛鈎調用SwapBuffers。 您將該調用重定向到您的疊加圖形代碼。

由於OpenGL是基於狀態的,因此您應該避免弄亂您所連接的程序的上下文。 沒問題,您可以根據需要創建任意數量的OpenGL上下文,並在同一個drawable中使用它們。 所以你的鈎子SwapBuffers看起來像這樣:

BOOL WINAPI (*host_SwapBuffers)(HDC);
HGLRC hook_last_rc_created = NULL; /* for context sharing */

/* C++ std::map for the lazy. */
std::map<int, HGLRC> hook_pixelformat_to_rc;

/* This function is called to setup per RC resources, i.e. things
 * that are not shared through the list namespace, like FBOs, VAOs
 * and such. */
void init_RC();

/* This function is called when the first hook OpenGL context is
 * created. This is to be used for one time initialization of OpenGL
 * objects that are shared among all contexts through the list namespace,
 * like textures, VBOs, PBOs and such. */
void init_GL();

/* The function that does the actual overlay drawing.
 * Must not call SwapBuffers when finished. The draw overlay has to set
 * up the viewport, projection and modelview transformations.
 *
 * rect gives the dimensions of the window we draw to, for
 * setting the viewport and stuff like that. */
void draw_overlay(RECT const *rect);

BOOL WINAPI hook_SwapBuffers(HDC dc)
{
    /* It's illegal to call SwapBuffers with a NULL dc. To keep Windows
     * error behavior we bail out, forwarding the call to the system
     * SwapBuffers if dc == NULL */
    if( !dc ) {
        goto terminate;
    }

    /* OpenGL RCs can be shared between DCs of compatible pixelformat. So technically
     * any number of pixelformat IDs could be compatible. But we just assume that
     * compatibility is only between pixelformats of the same ID, which is safe. */
    int const pixelformat = GetPixelFormat(dc);

    HGLRC hook_rc;
    /* we need to create a RC for our hook only one time and can reuse that
     * later. It can even be used for different DCs or windows, as long as
     * they have been created with compatible pixel formats. To make this
     * hook really robust there is to be a mapping from DCs to pixelformat IDs.
     * If no RC can be found for the given pixelformat, create one. */
    if( 0 == hook_pixelformat_to_rc.count(pixelformat) ) {
        /* the DC is of a window that already got everything set up for OpenGL.
         * All we have to do is create our own HRC if we don't have one already. */

        hook_rc = wglCreateContext(dc);
        if( !hook_rc ) {
            /* bail out, but forward the SwapBuffers call on error. Don't use
             * exceptions in hook DLLs, or very bad things may happen, if you're
             * not very, very careful. */
            goto terminate;
        }

        /* This could throw an exception... */
        hook_pixelformat_to_rc[pixelformat] = hook_rc;
        init_RC();

        /* If there was a RC created before, share its list namespace, so
         * that textures, VBOs, PBOs and so on are available among all the
         * contexts our hook uses. */
        if( hook_last_rc_created ) {
            wglShareLists(hook_last_rc_created, hook_rc);
        }
        else {
            init_GL();
        }
        hook_last_rc_created = hook_rc;
    }
    else {
        hook_rc = hook_pixelformat_to_rc[pixelformat];
    }

    /* Preserve the RC bound to the window before our hook.
     * May be NULL, but that's fine, this just means there was nothing
     * bound and we should return to that state at the end. */
    HGLRC const host_rc = wglGetCurrentContext();

    /* Find out which window the DC belongs to, so that we can query for its
     * dimension, which we need to properly setup a viewport region. */
    HWND const wnd = WindowFromDC(dc);
    RECT wnd_rect;
    GetClientRect(wnd, &wnd_rect);

    /* bind our own RC */
    wglMakeCurrent(dc, hook_rc);

    /* we can now draw the overlay */
    draw_overlay(&wnd_rect);

    /* Restore RC to DC binding */
    wglMakeCurrent(dc, host_rc);
terminate:
    /* host_SwapBuffers is a function pointer initialized to the address of the
     * system SwapBuffers function before hooking by the DLL injection code. */
    return host_SwapBuffers(hdc);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM