Tutorial How to Make a wxWidgets GUI In An Injected DLL

Hexui Undetected CSGO Cheats Sinkicheat PUBG Cheat

Neuromancer

Full Member
Apr 18, 2020
4
158
0
Game Name
Any Game
Anticheat
N/A
Coding Language
C++
This writeup will walk you through the process of creating a GUI for an internal game hack, i.e. an injected DLL, with the wxWidgets GUI framework on Windows. The full project file is available to download as a zip archive attached to the thread.

Step 1
Create a new project in Visual Studio, using the "Empty Project" template.

Step 2
Open your project properties, go to the "General" section, and change the "Configuration Type" option (which will have defaulted to "Application (.exe)") to "Dynamic Library (.dll)".

Then go to the Debugging section, and change the "Command" option to the program you want to attach to. VS will let you browse your filesystem for the target executable. (I'll be using Notepad in this example, but this process should work with any program). Change the "Attach" option to "Yes".

Step 3
I like to add a "src" directory at the root of the project, in case I have resource files (like images) which I want to keep separate from the source code. In this directory, create a dllmain.cpp file -- this will contain the entry point for your DLL.

Step 4
Add the following DllMain function:
DllMain function:
BOOL APIENTRY DllMain(HMODULE hModule,
                      DWORD ul_reason_for_call,
                      LPVOID lpReserved) {
    switch (ul_reason_for_call) {
    case DLL_PROCESS_ATTACH:
        CloseHandle(CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)HackThread, hModule, 0, nullptr));
    case DLL_PROCESS_DETACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
        break;
    }
    return TRUE;
}
You'll need to include Windows.h to resolve all symbols in this function.

This will cause the HackThread function to be called when the DLL is injected into the target process -- if you've spent any significant amount of time on these forums, chances are you've seen this piece of code before.

Step 5
Next, we need to add the HackThread function. This will just display a console window for now, since we want to verify that the DLL attaches properly to the target process. We'll add the GUI afterwards. Here's mine:

HackThread function:
DWORD WINAPI HackThread(HMODULE hModule) {
    // Create a console window for log output
    AllocConsole();
    FILE* file;
    freopen_s(&file, "CONOUT$", "w", stdout);

    // Get the base address of the module
    wchar_t* moduleName = (wchar_t*)L"notepad.exe";
    uintptr_t moduleBaseAddress = (uintptr_t)GetModuleHandle(moduleName);
    HANDLE processHandle = GetCurrentProcess();

    // Print the base address to the console we create
    std::cout << "Rise with the moon, go to bed with the sun" << std::endl
        << "Early to bed, and you'll miss all the fun" << std::endl
        << "Bring your wife and trouble, it will never trouble you" << std::endl
        << "Make her a member of The Midnight Crew" << std::endl;

    // Run an infinite loop waiting for a signal to terminate
    while (true) {
        if (GetAsyncKeyState(VK_END) & 1) {
            break;
        }

        Sleep(5);
    }

    // Clean up, free the console window we created, destroy the DLL thread
    fclose(file);
    FreeConsole();
    FreeLibraryAndExitThread(hModule, 0);
    return 0;
}
This is fairly straightforward. It allocates memory for a console window, launches it, gets the base address of the module it interested in from the process we attach it to ("notepad.exe" in this case), then outputs a haunting melody. When the console exits (i.e. we close it by pressing the "END" key and triggering the break condition in the infinite loop that keeps the console perpetually alive), then it cleans up after itself and destroys the thread.

The console window runs in a separate thread from the DLL itself, which is necessary for nebulous safety reasons which I don't feel like researching thoroughly enough to explain simply right now. This is left as an exercise for the advanced reader to complete in their own time.

The GUI we're going to launch will follow the same pattern, except wxWidgets will run its own polling loop for us behind the scenes, whereas we have to set up our own and listen for keypresses to trigger events.

Step 6
Now we're going to test the DLL. Open up Notepad (or whatever your target process is), then press "F5" in VS to build the DLL and attach the debugger to the target process. Then, launch your DLL Injector (I use the Guided Hacking Injector, which can be had for the very reasonable price of FREE from here: Guided Hacking DLL Injector) and inject the DLL into the process. The console window should launch and output some jaunty lyrics, then wait. If so, victory. If not, go back to step 1 and try not to fuck anything up this time around.

If you want to change your DLL's target, first change the target process in Project Properties > Debugging > Command so the debugger knows what to attach to. This part only applies when debugging, obviously. Then change the name of the target module in the string "moduleName". This can either be the main executable, or another DLL within the target process, as is the case with Pwn Adventure 3, for example.

Step 7
First off, you need a local installation of wxWidgets. Windows installation is pretty straightforward, just go to their website (wxWidgets: Cross-Platform GUI Library) and follow the instructions. This video will walk you through the process as well as give an overview of the framework, I used it to help me figure this process out, it's good. Neuromancer Seal Of Approval for sure. If you can't figure out how to install it with all these fantastic resources at your fingertits, then don't come back.

Once that's done, add:
$(WXWIN)\include; $(WXWIN)\include\msvc;
to your Project Properties > C/C++ > General > Additional Include Directories option.
Then add:
$(WXWIN)\lib\vc_lib
OR
$(WXWIN)\lib\vc_x64_lib
(depending on your target architecture)
to Project Properties > Linker > General > Additional Library Directories.
This ensures that your C++ compiler and linker know where to find all the framework components they need to compile your code. If you're hazy on how the compiler and linker work, then I strongly encourage you to get a clue before continuing with this tutorial. Trust me, it's worth your time, especially considering what your time must be worth for you to have read this far in the first place.

Step 8
Under my "src" directory, I have a "ui" directory, which you earn no points for guessing the purpose of. "Separation of concerns" in the programming catchphrase of the day here, look it up. Under this, create two directories, "app" and "main". "app" will contain the portion of the code which starts up the GUI, whereas "main" contains a class which actually represents the window we draw on screen. We'll create the "main" section first, since the "app" class will depend on it.

UIMain.hpp:
#pragma once
#include "wx/wx.h"

class UIMain : public wxFrame {
public:
    UIMain();
};
UIMain.cpp:
#include "UIMain.hpp"

UIMain::UIMain() : wxFrame(
    nullptr, // The parent window, which is null in this case because it's the master window
    -1, // The window's ID; -1 is shorthand for "no ID required"
    "Window Title", // The title of the window
    wxPoint(30, 30), // The coordinates the window should appear at; (0, 0) is the top-left corner of the screen
    wxSize(800, 600) // The size (width, height) of the window
) {}
Pretty much everything meaningful is described in the comments, so we'll just move on to the App class.
(Note: VS defaults to "*.h" filenames in the New Class wizard, but I prefer "*.hpp" for C++ code.)

UIApp.hpp:
#pragma once
#include "wx/wx.h"
#include "../main/UIMain.hpp"

class UIApp : public wxApp {
public:
    bool OnInit();
private:
    UIMain* m_frame1 = nullptr;
};
"m_frame1" is a pointer to an instance of the UIMain class, which, as you should recall, represents the main window of our GUI. In the "OnInit" function's implementation, we'll construct an instance of it.

UIApp.cpp:
#include "UIApp.hpp"

wxIMPLEMENT_APP(UIApp);

bool UIApp::OnInit() {
    m_frame1 = new UIMain();
    m_frame1->Show();

    return true;
}
"OnInit"'s job is fairly simple as described above, it just creates an instance of the window, then shows it. The real magic is done by the "wxIMPLEMENT_APP" macro, which, if you follow the implementations in VS (press F12 with your cursor on it), goes "wxIMPLEMENT_APP > wxIMPLEMENT_WXWIN_MAIN > WinMain". Thus, we have the WinMain function, and with it, the keys to the kingdom. From here we can go back to "dllmain.cpp" and launch our newly-created GUI by calling the WinMain function that the wxWidgets macro creates for us.

Step 9
Head back to your "dllmain.cpp" file, and modify the HackThread function thusly:
HackThread function calling WinMain:
DWORD WINAPI HackThread(HMODULE hModule) {
    // Get a handle to the target module
    wchar_t* moduleName = (wchar_t*)L"notepad.exe";
    uintptr_t moduleBaseAddress = (uintptr_t)GetModuleHandle(moduleName);
    HANDLE processHandle = GetCurrentProcess();

    // Call the WinMain function that the wxWidgets macro provides
    WinMain((HINSTANCE)processHandle, NULL, NULL, 0);

    // Clean up after the UI thread exits
    FreeLibraryAndExitThread(hModule, 0);
    return 0;
}
That's all there is to it. It calls the WinMain function that was provided for us by wxWidgets, which will eventually call your "OnInit" function, which will create an instance of your Main window and show it. Launch, compile, inject, verify: you should now be staring at an entirely blank window, 30 by 30 pixels from the top-left-hand corner of the screen, 800 pixels wide and 600 pixels high, with the window title of "Window Title". Unless you changed any of those details in "UIMain.cpp", which I encourage you to experiment with.

That's it that's all. You're on your own now, the video I linked before is an excellent source of information on wxWidgets, as is the documentation on their website, which was also linked above.

If there's anything here you can't quite work out, then either pay Rake boatloads of money to explain it to you or get a brain transplant, just don't come crying to me.

If you spot any genuine mistakes or have ideas for improvements, then either respond to the thread or message me. I know that everything here works because I went through the process at the same time as I was writing about it, Hunter-S-Thompson-style, which means my method is correct. It doesn't really do any favors for the brain transplant crowd, though. I hear the waiting lists are long.

Zip archive of the completed project is here. It was too large to attach here, so I posted it to an external file host, let me know if it goes down. Also, for the love of Allah, if you're a beginner, then use it as a reference implementation and write your own from scratch. Even if they end up being largely identical, still do it. If pasting leads to brain damage, then using an entire downloaded project template probably gives you radiation poisoning.

Sorry boys and girls, Rake has spoken, so I've had to remove the download link. I could fairly easily provide a Git link with a well-known provider, but I actually prefer it this way. If you give people a way to cheat, god knows they're going to use it, regardless of whether or not it's to their own detriment. Thanks Rake, you're a real bro. I appreciate the endorsement and feedback.

Remember skids, if you stay in school, then you stay off the Wall of Shame. Ciao.
 
Last edited:

Rake

Cesspool Admin
Administrator
Jan 21, 2014
12,152
78,998
2,396
offsite download links and 188mb zip files are not allowed on the forum, please update as needed

also your video links will all expire next month

Thank you for sharing this nice tutorial
 

Neuromancer

Full Member
Apr 18, 2020
4
158
0
offsite download links and 188mb zip files are not allowed on the forum, please update as needed

also your video links will all expire next month

Thank you for sharing this nice tutorial
I've made the changes you asked for, plus a couple of minor edits to clear up parts I wasn't completely happy with. Thanks for the input. I'm not considering a career as a technical writer any time soon, but I hope this can help a few people out.
 
  • Haha
Reactions: Rake

Neuromancer

Full Member
Apr 18, 2020
4
158
0
Update (again):

I've decided to make a short series of tutorials regarding custom UIs for hacks, with this being retroactively labeled Part One. The code sample for Part Deux has already been written, and the corresponding post should appear in the next day or two.

As such, I've decided to make all the code for all parts available. The project for this post can be found here: RocketGit, and the code for part two is already available on the same Rocketgit account. See you all soon. <3
 
Attention! Before you post:

Read the How to Ask Questions Guide
99% of questions are answered in the Beginner's Guide, do it before asking a question.

No Hack Requests. Post in the correct section.  Search the forum first. Read the rules.

How to make a good post:

  • Fill out the form correctly
  • Tell us the game name & coding language
  • Post everything we need to know to help you
  • Ask specific questions, be descriptive
  • Post errors, line numbers & screenshots
  • Post code snippets using code tags
  • If it's a large project, zip it up and attach it

If you do not comply, your post may be deleted.  We want to help, please make a good post and we will do our best to help you.

Community Mods