Video Tutorial OpenGL Hooking, Drawing & Text Rendering Tutorial

Hexui Undetected CSGO Cheats PUBG Accounts

ZleMyzteX

I have no idea what I'm doing
Fleep Tier Donator
Trump Tier Donator
Dank Tier Donator
Full Member
Nobleman
Mar 10, 2020
90
2,073
0
Well, I have the exact same problem with the exception... reset everything, still didn't help. :(
 

BDKPlayer

No hack no life
Dank Tier VIP
Dank Tier Donator
Oct 31, 2013
393
13,758
36
Thank you for the great tutorial @Rake . I recently wanted to hook some OpenGL games and having a working version for AssaultCube kept me somewhat sane.

I couldn't get it to work in other games such as "Brink", "OpenArena" and a couple of others. You mention in your tutorial that its probably because I have to tweak the values in SetupOrtho(); to fit the game but I wanted a more universal solution.

So after digging some chinese forums (lmao) it turns out you can just create your own OpenGL context once and then use it whenever you want to render something and after restore the original context. This method has worked for every game I've tested (including AssaultCube) and also avoids to do the entire "SetupOrtho" stuff every frame.

Here is some hot sauce:

C++:
bool contextCreated = false;
HGLRC myContext;
HGLRC gameContext

//hooked SwapBuffers. This is x64 but it also works for x86
int64_t HkHwglSwapBuffers(HDC hdc)
{
    //Save the games context
    gameContext = wglGetCurrentContext();

    //Create our own context if it hasn't been created yet
    if (contextCreated == false)
    {
        //Create new context
        myContext = wglCreateContext(hdc);
       
        //Make thread use our context
        wglMakeCurrent(hdc, myContext);
       
        //Setup our context
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0.0, 640, 480, 0.0, 1.0, -1.0);  //might want to make these your actual screen resolution
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glClearColor(0, 0, 0, 1.0);
    }
   
    //Make thread use our context
    wglMakeCurrent(hdc, myContext);
   
    //Draw something (a rectangle here)
    glColor3f(1.0f, 0, 0);
    glBegin(GL_QUADS);
    glVertex2f(0, 190.0f);
    glVertex2f(100.0f, 190.0f);
    glVertex2f(100.0f, 290.0f);
    glVertex2f(0, 290.0f);
    glEnd();

    //Make thread to use games context again
    wglMakeCurrent(hdc, oldContext);

    //return to orginal swapbuffers
    return oOpenGLReturn(hdc);
}
 

Rake

I'm not your friend
Administrator
Jan 21, 2014
13,031
79,068
2,469
Thank you for the great tutorial @Rake . I recently wanted to hook some OpenGL games and having a working version for AssaultCube kept me somewhat sane.

I couldn't get it to work in other games such as "Brink", "OpenArena" and a couple of others. You mention in your tutorial that its probably because I have to tweak the values in SetupOrtho(); to fit the game but I wanted a more universal solution.

So after digging some chinese forums (lmao) it turns out you can just create your own OpenGL context once and then use it whenever you want to render something and after restore the original context. This method has worked for every game I've tested (including AssaultCube) and also avoids to do the entire "SetupOrtho" stuff every frame.

Here is some hot sauce:

C++:
bool contextCreated = false;
HGLRC myContext;
HGLRC gameContext

//hooked SwapBuffers. This is x64 but it also works for x86
int64_t HkHwglSwapBuffers(HDC hdc)
{
    //Save the games context
    gameContext = wglGetCurrentContext();

    //Create our own context if it hasn't been created yet
    if (contextCreated == false)
    {
        //Create new context
        myContext = wglCreateContext(hdc);
      
        //Make thread use our context
        wglMakeCurrent(hdc, myContext);
      
        //Setup our context
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0.0, 640, 480, 0.0, 1.0, -1.0);  //might want to make these your actual screen resolution
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glClearColor(0, 0, 0, 1.0);
    }
  
    //Make thread use our context
    wglMakeCurrent(hdc, myContext);
  
    //Draw something (a rectangle here)
    glColor3f(1.0f, 0, 0);
    glBegin(GL_QUADS);
    glVertex2f(0, 190.0f);
    glVertex2f(100.0f, 190.0f);
    glVertex2f(100.0f, 290.0f);
    glVertex2f(0, 290.0f);
    glEnd();

    //Make thread to use games context again
    wglMakeCurrent(hdc, oldContext);

    //return to orginal swapbuffers
    return oOpenGLReturn(hdc);
}
That's awesome, this is way easier than I thought.
 

Rablidad

Full Member
May 2, 2020
29
513
2
thanks, just a little question, I've hooked SwapBuffers from gdi32.dll instead of the one from opengl32.dll, the hook occured succesfully, its first executing my own SwapBuffers and then returning originalSwapBuffers, but it doesn't seem to draw to the screen, do I have to strictly hook it from opengl32.dll instead of gdi32.dll, wondering that because you said in your video that it's actually exported from gdi32.dll, anyway, I'll try both cases, thanks.
 
Last edited:

Rake

I'm not your friend
Administrator
Jan 21, 2014
13,031
79,068
2,469
thanks, just a little question, I've hooked SwapBuffers from gdi32.dll instead of the one from opengl32.dll, the hook occured succesfully, its first executing my own SwapBuffers and then returning originalSwapBuffers, but it doesn't seem to draw to the screen, do I have to strictly hook it from opengl32.dll instead of gdi32.dll, wondering that because you said in your video that it's actually exported from gdi32.dll, anyway, I'll try both cases, thanks.
do it the way I did it, for assault cube, and it will work

you can answer your question by debugging SwapBuffers
 

SuperNewbie

i wanna be your friend
Fleep Tier Donator
Dank Tier Donator
Nobleman
May 5, 2020
55
838
0
Thank you for the great tutorial @Rake . I recently wanted to hook some OpenGL games and having a working version for AssaultCube kept me somewhat sane.

I couldn't get it to work in other games such as "Brink", "OpenArena" and a couple of others. You mention in your tutorial that its probably because I have to tweak the values in SetupOrtho(); to fit the game but I wanted a more universal solution.

So after digging some chinese forums (lmao) it turns out you can just create your own OpenGL context once and then use it whenever you want to render something and after restore the original context. This method has worked for every game I've tested (including AssaultCube) and also avoids to do the entire "SetupOrtho" stuff every frame.

Here is some hot sauce:

C++:
bool contextCreated = false;
HGLRC myContext;
HGLRC gameContext

//hooked SwapBuffers. This is x64 but it also works for x86
int64_t HkHwglSwapBuffers(HDC hdc)
{
    //Save the games context
    gameContext = wglGetCurrentContext();

    //Create our own context if it hasn't been created yet
    if (contextCreated == false)
    {
        //Create new context
        myContext = wglCreateContext(hdc);
     
        //Make thread use our context
        wglMakeCurrent(hdc, myContext);
     
        //Setup our context
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0.0, 640, 480, 0.0, 1.0, -1.0);  //might want to make these your actual screen resolution
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glClearColor(0, 0, 0, 1.0);
    }
 
    //Make thread use our context
    wglMakeCurrent(hdc, myContext);
 
    //Draw something (a rectangle here)
    glColor3f(1.0f, 0, 0);
    glBegin(GL_QUADS);
    glVertex2f(0, 190.0f);
    glVertex2f(100.0f, 190.0f);
    glVertex2f(100.0f, 290.0f);
    glVertex2f(0, 290.0f);
    glEnd();

    //Make thread to use games context again
    wglMakeCurrent(hdc, oldContext);

    //return to orginal swapbuffers
    return oOpenGLReturn(hdc);
}
Hi, I know it's been like four months since you posted this but I was wondering if you could explain some of your code to me, especially relating to how you set up the newly created rendering context. I'd appreciate it.

The code definitely works as it stands but I've been messing around with it and I was wondering why you were changing the MatrixMode back to GL_MODELVIEW and setting it to the identity matrix. I commented out the GL_MODELVIEW line, the following glLoadIdentity(), and the glClearColor and noticed no discernible difference. Also, why is glClearColor being called here without glClear(GL_COLOR_BUFFER_BIT)? Using glClear(GL_COLOR_BUFFER_BIT) doesn't actually do anything either, which is odd. Are we/the game drawing over the clear?
 

BDKPlayer

No hack no life
Dank Tier VIP
Dank Tier Donator
Oct 31, 2013
393
13,758
36
Hi, I know it's been like four months since you posted this but I was wondering if you could explain some of your code to me, especially relating to how you set up the newly created rendering context. I'd appreciate it.

The code definitely works as it stands but I've been messing around with it and I was wondering why you were changing the MatrixMode back to GL_MODELVIEW and setting it to the identity matrix. I commented out the GL_MODELVIEW line, the following glLoadIdentity(), and the glClearColor and noticed no discernible difference. Also, why is glClearColor being called here without glClear(GL_COLOR_BUFFER_BIT)? Using glClear(GL_COLOR_BUFFER_BIT) doesn't actually do anything either, which is odd. Are we/the game drawing over the clear?
The code is the result of me trying to get it to work in like 5 games I tested. There may be some lines that aren't required for many or even any games. Since this context only needs to be setup once with this method there is really no big penalty. I don't have any interest in optimizing intermediate mode OpenGL tbh since its legacy anyway. This is just supposed to work :D
That being said if you can provide an implementation that works with fewer lines of code and maybe even explain why some of my stuff is not required that would be a nice contribution :)
 
  • Like
Reactions: SuperNewbie

Meow

Gimme food hooman.
Meme Tier VIP
Fleep Tier Donator
Apr 24, 2020
213
5,568
7
The code is the result of me trying to get it to work in like 5 games I tested. There may be some lines that aren't required for many or even any games. Since this context only needs to be setup once with this method there is really no big penalty. I don't have any interest in optimizing intermediate mode OpenGL tbh since its legacy anyway. This is just supposed to work :D
That being said if you can provide an implementation that works with fewer lines of code and maybe even explain why some of my stuff is not required that would be a nice contribution :)
Great job I didn't noticed that post and it solved some issues for me hooking another game than assault cube. It's also great if you want to set your own ortho.
btw. I guess you forgot to set `contextCreated` in your code?

Thats how my hook looks in nim and it works great. I also skipped the glClear

Code:
  let gameContext = wglGetCurrentContext()
  if HackContext == 0:
      HackContext = wglCreateContext(hdc)
      wglMakeCurrent(hdc, HackContext)
      glMatrixMode(GL_PROJECTION)
      glLoadIdentity()
      glOrtho(0, Resolution[0].GLdouble, Resolution[1].GLdouble, 0, -1, 1)
      glMatrixMode(GL_MODELVIEW)
      glLoadIdentity()
  wglMakeCurrent(hdc, HackContext)
  hackLoop()
  wglMakeCurrent(hdc, gameContext)
  result = oglSwapBuffers(hdc)
 
Community Mods