Tutorial How to debug effectively

Hexui Undetected CSGO Cheats Sinkicheat PUBG Cheat

timb3r

Semi-Retired
Dank Tier VIP
Jul 15, 2018
768
22,668
47
debug-header.PNG


Introduction:

This is going to be a quick little guide on how to effectively debug your own code and possibly a rant as well because I keep seeing the same mistakes made over and over again and it feels like I'm trapped in a time-loop. When I say over and over again I mean for the last 20 years this isn't a GuidedHacking specific thing, this is a programming thing in general. For whatever reason these days programming is a lot more accessible, there's tutorials, videos and books everywhere that will get you up and running in basically any language you want. Despite all this readily available information one thing still hasn't changed: people can't debug for shit.

Programming as a skill is in my opinion solely made up of three sub-skills working in unison. I've named them the three D's because it's funnier and easier to meme. Imagine a stool with three legs and each of these sub-skills are one leg each, if you take one leg away the stool falls over. If one leg is shorter the stool is woobly and will most likely cause you to spill beer everywhere and be screamed at by your partner or ML powered real doll.

The three D's are:
  1. Documentation.
  2. Debugging.
  3. Disassembly.
Documentation:

Programming is by it's nature language agnostic. Once upon a time most people were taught the basics of programming using something called BASIC (Beginners' All-purpose Symbolic Instruction Code). BASIC is exactly what it sounds like an incredibly basic language lacking complicated syntax to teach fundamental concepts like loops, subroutines and variables. The idea was that by mastering these basic concepts you could simply read the syntax for a more complicated language and easily move across to it.

C++:
10 FOR X=1 TO 10
20 PRINT "HELLO WOLRD"
30 NEXT X
If this doesn't make sense to you I've got some bad news.

This is the first D of programming: Documentation.

A good programmer understands that documentation (or lack of) is fundamental to grasping concepts required to effectively utilize a given language. They also understand that a computer language is just a tool for expressing their creativity. Good programmers will select the right tool for the job instead of just falling back on what is familiar or easy to use for them. As they say you never go crawling back to your ex: they might be familiar and easy to use but there's a reason you left them in the first place.

While we're on the topic of Documentation before you even put any code down you have know your target platform. Now I can hear you saying: "Uhhh timb3r it's Windows it's always Windows." yeah except for when it's not.

642045.jpg


Me personally I enjoy running my code on any device with a CPU. Phones, TVs, Routers, Nintendo 3DS?

gh-cube.png

So satisfying.

You can't just open Visual Studio and select a new Nintendo 3DS project. You've gotta configure a build environment and the homebrew SDK (not to mention jailbreak the actual hardware if you're not using an emulator). How do you learn how to do all this stuff? Well you post on a forum and ask to be spoon fed:


WRONG!

You read the documentation that some asshole wasted hours of their life putting together so their forum wouldn't become filled with questions like "How2Do". Now to focus this back on Windows again. Where should you go if you want to interface with the Windows operating system? MSDN. What about Linux? MAN. Want to know how the Intel Processor works? Go check out the SDM.

I don't know how else to convey this to new programmers all the answers are in a manual somewhere. No matter what the issue is 99% of the time it is documented somewhere. So before you ask go check out the documentation first.

Debugging

This is the meat of this article because this seems to be the biggest issue most people are having. Visual Studio is an IDE not a "compiler". IDE means Integrated Development Environment meaning it's a collection of tools working together. One of those tools (arguably the most important and under used) is the debugger. The debugger allows you to inspect your code at run-time and locate bugs quickly and effectively.

Lets use a real example I see constantly all over this forum EXCEPTION_ACCESS_VIOLATION (0xC0000005).

debug1.PNG

This is what you'll see when you hit F5 or click the green play button in Debug mode.

What does all this information mean? You're a programmer you tell me! Let's break it down:

The first thing to note is line that debugger is highlighting is not actually the line where the exception occurred as the exception occurred outside our module this is best guess for the compiler. How do we know it occurred outside our module? The first line of the Exception box tells us this: Exception thrown at: 0x00007FFC382CD942 (ucrtbased.dll). So immediately we know that it must be an inter-module call that's causing the issue for us. We only have two calls so the problem must be with strcpy.

Examining strcpy we can see that yes: our code is correct. We have provided the correct number of parameters so the issue must be further back in the code. Now let's look at the next part of the exception message: 0xC00000005 Access violation writing location 0x0000000000000000. Access violations occur typically when you're attempting to write to memory that you don't have access to or an invalid memory address.

Checking MSDN confirms this:
avio.PNG


So we're trying to write to an invalid memory address so the actual problem is our pointer you'll notice we forgot to allocate it before using it! So while the exception is triggering in ucrtbased.dll it's actually our fault it's happening. Now imagine your code wasn't 5 lines of code it was 5000 lines of code how hard would you think it would be to track down this type of error without using a debugger? The answer is pretty fucking hard.

Here's another example of something similar:

C++:
DWORD entity = *(DWORD*)(game + entityList);
Why is this code bad? It's de-referencing a pointer which means it must be some type of internal hack however this is unsafe code.

onedoesnot.jpg


The code assumes that game and entityList are both non-zero values and are pointing to a valid pointer. That's ALOT of assumptions to make in one line of code it's very rarely a good idea to do this unless you've got some additional code doing sanity checks. If you're using the "typical" template of DllMain / CreateThread / Hackloop and you're just endlessly looping then I can almost guarantee you're heading for an access violation.

When I was designing my MK Bot AI bridge I couldn't afford any crashes or I'd risk loosing hours of evolution due to something failing it needed to be fault tolerant as shit.

C++:
uintptr_t MK_GetP1BaseAddr()
{
    uintptr_t* playerBase = (uintptr_t*)(moduleBaseAddress + 0x03302038);
    if (!playerBase || !*playerBase)
        return NULL;
    return *playerBase;
}

float* MK_GetP1HealthPtr()
{
    if (!moduleBaseAddress)
        return NULL;

    uintptr_t playerBase = MK_GetP1BaseAddr();
    if (!playerBase)
        return NULL;
    return (float*)(playerBase + 0xA38);
}

float MK_GetP1Health()
{
    if (!moduleBaseAddress)
        return 0.0f;

    float*f  = MK_GetP1HealthPtr();
    if (f == NULL)
        return 0.0f;

    return *(float*)(f);
}
Overkill? Perhaps. But how many times did it crash? Fucking never it's the stablest piece of code I've written in years. The reason it needed so many sanity checks was so I could inject the DLL whenever I wanted. It didn't matter if the game state was initialized the code would just wait until the game state became valid before attempting to read things like player health or distance.

If you're working on something with frequent updates like CSGO or the like then offsets will change and your code will break. Before your hack even runs you should be performing a check to make sure its a known safe version before attempting to read anything. How you do this differs by game but there's usually a build number you can pull out of memory to check.

But there's also another cooler technique you can use Vectored Exception Handling.

VEH

Take our scag code from before we can throw in a VEH and trap the exception before we explode the host program:

C++:
#include <Sddl.h>
#include <intrin.h>
#include <stdio.h>

LONG WINAPI HandleExceptions(EXCEPTION_POINTERS* ExceptionInfo)
{
    if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
    {
        printf("EXCEPTION_ACCESS_VIOLATION occured at: %p\n", ExceptionInfo->ContextRecord->Rip);
        ExitProcess(-1);
    }
    return EXCEPTION_CONTINUE_SEARCH; // Pass to the next handler
}

int main()
{
    LPVOID pHandle = AddVectoredExceptionHandler(1ul, HandleExceptions);
    if (!pHandle)
        return -1;

    char* buffer = NULL;

    strcpy(buffer, "This is a test string.\n");
    printf("%s\n", buffer);

    delete []buffer;

    RemoveVectoredContinueHandler(pHandle);

    return 0;
}
If you run this with a debugger it will catch the exception, however if you run it without a debugger attached CTRL+F5 you'll notice instead of crashing this happens:

EXCEPTION_ACCESS_VIOLATION occured at: 00007FFC8320D942

D:\Code\CpuID\x64\Debug\CpuID.exe (process 10924) exited with code -1.


There's another benefit doing this as well if you crash a game it can generate a crash log, the crash log can contain a lot of detailed information you might not want the developers to see: particularly as the crash is occurring outside their code in some unknown module which they do not have symbols for something they might be interested in sending to their AC provider.

Remote Debugging

The last thing I'm gonna talk about debugging wise is remote debugging. Visual Studio will actually allow you to debug an injected DLL this feature alone makes it worth giant pain in the ass that it's turned into.

In order to get this to work you're going to have to configure GH injector like so:

ghinj-1.PNG


Under advanced options you need to uncheck "Unlink PEB" otherwise visual studio will not be able to locate your module. Go ahead and inject your DLL into the target process.

In Visual Studio setup your desired breakpoints then click Debug -> Attach to Process and locate the game module. If you've done everything correctly you can now step through your injected DLL just like normal. There's a few issues however if you're relying on the injector to mask or hide your DLL from some type of AntiDebug or Anti-Cheat this method wont work well for you but luckily we still have one more D to cover.

Disassembly

What ever language you choose to spend all your time learning and ignoring the opposite sex damning the rest of to live in a world populated by idiots and trailer trash at some point it will be be expressed as processor specific byte code. Since humans don't typically like reading numbers we invented a symbolic language which was fair easier to read and understand. The most popular one is the Intel syntax which is what Visual Studio uses, there's also AT&T syntax if you have a fetish for % symbols. Low powered ARM CPUs have become increasing popular and they have their own symbolic language as well.

If you're going to write code you're going to have to get familiar with disassembly and if you're going to debug or reverse engineer game code then you're going to have really like disassembly (as in relax those throat muscles and put a smile on that face). If you don't want to learn disassembly that's fine too I'm sure begging on forums will eventually get you the answer you want (eventually).



I'm not going to explain disassembly to you there's enough tutorials already I even wrote one. But I am going to stress the importance of knowing and understanding it. Since you love documentation now I'm sure you're already off and reading as much as you can. There's a passive learning technique you can use to teach yourself without actually spending hours and hours of time and you can do it from inside visual studio.

By pressing ALT+8 or some convoluted menu navigation (see below) you can open the disassembly window:

Use the Disassembly window
To enable the Disassembly window, under Tools > Options (or Tools > Options) > Debugging, select Enable address-level debugging.

To open the Disassembly window during debugging, select Windows > Disassembly or press Alt+8.
The cool thing about this is you can have your C code right next the equivalent assembly code. Just by having this code visible when you debug you'll begin to understand how the compiler expresses code, how functions look, how different registers interact with each other and you don't even need to do anything except write code. Another cool thing you can do is mess with different calling declarations and see exactly how they are expressed in code. This combined with the Intel manual will teach you better and quicker than any course on the internet and it's all passive.

Outro:

With all these tools and resources at your fingertips it's damn near impossible to not be excellent so be excellent.



How to use the debugger:
https://docs.microsoft.com/en-us/vi...g-through-code-with-the-debugger?view=vs-2019

Reverse engineering & assembly:
https://guidedhacking.com/threads/beginners-guide-to-reverse-engineering-tutorial.13446/

Documentation:
https://guidedhacking.com/threads/start-here-beginners-guide-to-learning-game-hacking.5911/
 
Last edited by a moderator:

Rake

Cesspool Admin
Administrator
Jan 21, 2014
11,537
78,998
2,310
Fun read and I learned how to use VEHs, nice!

I added my video link at the bottom for our debugging video too
 
  • Like
Reactions: Zanzo420 and Kage

Zanzo420

Full Member
Aug 13, 2018
2
134
0
Excellent video tutorial, taught me a few debugging tricks that should come in handy! Thanks!
 
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 League of Legends Accounts