使用注入的DLL从外部应用程序在OpenGL场景中呈现 [英] Render inside of OpenGL scene from an external application using an injected DLL

查看:339
本文介绍了使用注入的DLL从外部应用程序在OpenGL场景中呈现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经能够将DLLs注入到应用程序中,比如键盘操作,但是如何挂钩到一个OpenGL程序并绘制它呢?我已经阅读了许多教程和答案,但他们都概述了背后的想法,而不是如何实际做。如果有人能指出正确的方向,我非常感谢。

I've been able to inject DLLs in to applications for things like keyboard actions, but how does one hook in to an OpenGL program and draw over it? I've read many "tutorials" and answers, but they all outline the idea behind doing it, not how to actually do it. If someone could point me in the right direction, I'd much appreciate it.

我打算做的是能够绘制一个叠加层实际场景?可能吗?)从RAM中的第三方应用程序(注入dll)。我只有通过GLUT的经验,但我愿意学习如果需要。

What I intend to do is be able to draw an overlay (or maybe draw into the actual scene? Is that possible?) from a 3rd party application in RAM only (injected dll). My only experience with OpenGL is via GLUT, but I'm willing to learn if need be.

经过几个小时的研究,我发现一个开源应用程序可以做我想要的,并查看其代码,但似乎找不到什么方法正被钩住或者ASM代码如何在该特定方法被改变。

After hours of research, I have found an open-source application that can do what I want, and looked through its code, but can't seem to find what method is being hooked or and how the ASM code is changed at that specific method.

当注入dll时,是否定义hook方法,或者dll在附加时是否定义?从我的理解,你可以做,但是一个比另一个更好吗?

Is the method to be hooked defined when the dll is injected, or does the dll do it upon being attached? From my understanding, you could do either, but is one better than the other?

我正在寻找一个全面的教程,或这样一个简单的例子。

I'm looking for a comprehensive tutorial, or a simple example of such a thing. If someone could point me in the right direction, that'd be great!

推荐答案

要理解的最关键的一步是,如果有人能指出正确的方向, OpenGL是一个基于状态的绘图API,而不是一个场景图。因此,您不能假设有一些场景可以添加一些叠加。相反,你必须找到一个点,你知道你注入的程序是完成绘图,你可以绘制你的覆盖

The most critical step to understand is, that OpenGL is a state based drawing API, not a scene graph. Hence you must not assume, that there is some scene you can add some overlay to. Instead you have to find a point, where you know the program you injected is done drawing and you can draw your overlay over it.

很容易识别双缓冲窗口:在基于X11的系统上调用 wglSwapBuffers (或 glXSwapBuffers c $ c> eglSwapBuffers 对于基于EGL的系统 - Windows不使用它们)。

This very point is easily identified for double buffered windows: The call to wglSwapBuffers (or glXSwapBuffers on X11 based systems, eglSwapBuffers for EGL based systems – Windows uses neither of them).

所以你做的是钩到SwapBuffers 。

So what you do is hooking into the call to SwapBuffers. You redirect that call into your overlay drawing code.

由于OpenGL是基于状态的,因此您应避免混淆您嵌入的程序的上下文。没问题,你可以创建尽可能多的OpenGL上下文,你喜欢和使用它们在同一个drawable。所以你钩住的SwapBuffers看起来像这样:

Since OpenGL is state based you should avoid messing with the context of the program you've hooked into. No problem, you can create as many OpenGL contexts as you like and use them all on the same drawable. So your hooked SwapBuffers would look something like this:

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);
}

这篇关于使用注入的DLL从外部应用程序在OpenGL场景中呈现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆