Game Vulnerability Researcher | Anti-Cheat Enthusiast
Here are some of my favorite projects I've worked on
Have you ever wanted to create an overlay for your cheats and wern't sure where to start? Keep reading, and I will show you how to setup your environment as well as the concepts behind creating an overlay.
Overlays are great because they can help cheat developers as well as potential users of a cheat keep up with specific values or toggled cheats. Allowing for more clarity on how the cheat operates and it's capabilities.
Disclaimer, this post will speak on the concepts behind creating an overlay for a game.
A future post will have code that you can follow along with!
Please hover over any words highlighted in purple to get a description of what they mean!
Things you need:
While some games may make the graphics API it uses obvious through launch options, checking the games imports, or by other means. Sometimes it can be difficult to identify what graphics API a game is using.
To address this issue, we can utilize MSI Afterburner. Which you can download from the official
MSI website.
You'll want to make sure to pay attention and install
Rivatuner Statistics Server during the installation process. As it is needed in order to use the overlay within MSI Afterburner
After it's been installed, you can follow these instructions to display the graphics API within the overlay:
Now the next time you launch a full-screen game, you'll see the graphics API displayed in the top left corner.
I learned this technique from "y4k ;; lucky doG" on Steam. Please feel free to check out their original post here: How to find out a game's rendering API with MSI Afterburner
You can download the SDK from here: Microsoft legacy SDK download
The SDK has already reached it's End of Life and is no longer supported. If you run into any issues installing the SDK it's usually because you already have a version of it installed.
You'll need to uninstall your current version and run the installer again so you can gaurentee you have DirectX 9 installed which is included with this installer
Within your IDE of choice (I use Visual Studio, so the following instructions are for that IDE)
These instructions assume you already have a solution created for your cheat.
Before we create our overlay it's important to understand how it works before hand!
Direct3D 9 is a Graphics API, that allows us to utilize commands to communicate and control a GPU in order to render images, 2D, and 3D graphics on our screens. Graphic API's vary depending on what operating system you are using as well as what specific software you're using.
For example, the Graphics API's utilized by Windows are Direct3D 9 - Direct3D 11.1 as well as OpenGL.
To create an overlay we first have to use Direct3D to render new graphics to our screen. So how do we do this?
I originally assumed that we would utilize the game's internal engine to render our overlay, which may be possible, but to my current knowledge is not how it works. Instead, we setup an environment very similar to how game engines utilize graphics API's and we interact with our GPU directly to render graphics on top of the game. As mentioned above, since graphics APIs can vary depending on the software of OS we want to make sure that whichever applications we are creating an overlay for uses the same API.
After we have confirmed that our application uses the same API, we have to gather information about the screen we're rendering to. That can look like something like this:
void Overlay::getGameWindowInfo()
{
windowInfo.gameWindowHandle = FindWindowA(0, "<Insert Game Window Name>"); // 0 is used to find any top-level window that matches the listed window name
if (windowInfo.gameWindowHandle)
{
GetWindowThreadProcessId(windowInfo.gameWindowHandle, &windowInfo.gameWindowProcID); // Gets Proccess ID of our targeted Window
gameHandle = OpenProcess(PROCESS_ALL_ACCESS, false, windowInfo.gameWindowProcID); // Gets the handle for the Process
GetWindowRect(windowInfo.gameWindowHandle, &windowInfo.rect); // Gets the dimensions of the window
overlayInfo.width = windowInfo.rect.right - windowInfo.rect.left; // Calculate window width
overlayInfo.height = windowInfo.rect.bottom - windowInfo.rect.top; // Calculate window height
MoveWindow(overlayInfo.overlayWindowHandle, windowInfo.rect.left, windowInfo.rect.top, overlayInfo.width, overlayInfo.height, true); // Used to move our overlay to the targeted area, and paint it over the current window
overlayInfo.margin = { 0, 0, overlayInfo.width, overlayInfo.height };
}
}
This function is responsible for grabbing information from our games screen, such as the process ID, handle, and the dimensions of our screen. This information will be used later to help us place our overlay properly on the screen.
In order to create our overlay we need to create a new Window that we will then show on the screen. We can do this using the CreateWindowEx
function. According to MSDN, this function creates an "overlapped, pop-up, or child window with an extended style."
We'd then want to utilize SetLayeredWindowAttributes
which allows us to set the opacity and transparency color keys of our newly created Window. Then we can show our window using ShowWindow
with the SW_SHOW flag.
The function to do this would look similar to this:
void Overlay::createAndShowOverlay()
{
overlayInfo.overlayWindowHandle = CreateWindowEx(WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_TRANSPARENT, L"Cheat Overlay", L"Cheat Overlay", WS_POPUP, 1, 1, overlayInfo.width, overlayInfo.height, 0, 0, hInstance, 0);
SetLayeredWindowAttributes(overlayInfo.overlayWindowHandle, RGB(0, 0, 0), 255, LWA_COLORKEY | LWA_ALPHA);
ShowWindow(overlayInfo.overlayWindowHandle, SW_SHOW);
DwmExtendFrameIntoClientArea(overlayInfo.overlayWindowHandle, &overlayInfo.margin);
}
We have to initialize Direct3D 9Ex to create an object which allow us to enumerate and retrieve capabilities of a device.
Next, we will go through and interact with a D3D (Direct3D) paramaters structure and set up the paramaters we want for our overlay.
Finally, we will create a device, which is how Direct3D communicates with our GPU. Giving it the information we gathered from previous functions along with the parameters we just set.
The code for this can look like this:
void Overlay::Direct3D9XInit(HWND hwnd)
{
hr = Direct3DCreate9Ex(D3D_SDK_VERSION, &m_pObject); // Creates an IDirect3D9Ex interface to create Direct 3D 9Ex objects
ZeroMemory(&m_D3DParam, sizeof(m_D3DParam)); // Initializes our D3DPRESENT_PARAMETERS with all zeros
m_D3DParam.Windowed = true; // If application (our game) runs windowed
m_D3DParam.BackBufferFormat = D3DFMT_A8R8G8B8; // Defines how color or depth information is stored
m_D3DParam.BackBufferWidth = overlayInfo.width; // Width of the new swap chain's back buffer in pixels (Our overlay's width)
m_D3DParam.BackBufferHeight = overlayInfo.height; // Height of the new swap chain's back buffer in pixels (Our overlay's height)
m_D3DParam.EnableAutoDepthStencil = true; // Makes Direct3D manage depth buffers for the application
m_D3DParam.AutoDepthStencilFormat = D3DFMT_D16; // The format of the automatic depth-stencil surface the device will create
m_D3DParam.SwapEffect = D3DSWAPEFFECT_DISCARD; // When rendering, this makes it present the back buffer, then discard it
// Creates a device to represent the display adapter
hr = m_pObject->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &m_D3DParam, 0, &m_pDevice);
}
The final step of our overlay process, rendering our overlay to the screen.
When rendering with Direct3D everything that we are going to render is going to be included between Device->BeginScene()
and Device->EndScene()
.
There are so many ways that you can render and draw to a screen and it would be too much to include here. I will include a link to the MSDN where you can see all a wide range of examples of all the things you can draw and make in the references.
For example, if we wanted to create a square overlay for our screen we could utilize the D3DXCreateLine()
function to initialize the drawing object, and then call the Draw()
function from that object.
One thing that can be complicated when creating shapes and text on our screen is that everything requires coordinates so that Direct3D can know where we want to draw each of our lines and the style of how we want to connect each vertex.
I will be covering rendering a lot more in my future post explaining the code behind creating a cheat overlay. So if you're interested in that, I hope you'll check out that post in the future as well!
The last thing we have to do after EndScene()
is to call PresentEx()
while swaps to the swapchain's next buffer. This enables us to swap out the currently rendered frame with a frame that has been rendered on the back buffer to avoid screen tearing.
Afterwards our user will see the newly rendered screen and then we will perform cleanup by calling the Clean()
function. Which according to MSDN, "Clears one or more surfaces such as a render target, multiple render targets, a stencil buffer, and a depth buffer".
Now we have officially rendered our overlay to the screen!
Now that I have a better understanding on the concept of how creating an overlay for a game cheat works. I will begin to work on creating my own overlay program! It was fun to learn about how much goes into creating an overlay, along with the process that graphic API's play. I hope whoever reads this blog was able to learn something as well!
If you have any feedback or want to share what you've created please feel free to reach out! You can contact me through Twitter/X or by the email listed in Contacts
Please take care, take some time to learn something new, and happy game hacking!
NitoTech
Documentation:
MSDN - Direct3D 9 GraphicsVideos:
Guided Hacking - Skyrim Overlay Example