[英]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.