Reverse Engineering: Binary Security

Totally_Not_A_Haxxer
73 min readJun 15, 2023

--

Binary Security | Introduction && Base Module Design

We have talked many times here about reverse engineering concepts and we just spent our time reversing a simple CrackMe and going through the steps of reverse engineering. However, what about security? How can developers protect themselves from zero days? The most honest question to that is whether they really can, zero days are just inevitable. Despite them being unavoidable directly, there are still many protection mechanisms that everyday reverse engineers can easily create in programs. In this article, we will be taking a real-world example of a program that uses a whole set of authentication systems, has drivers, and has thousands of more lines of code than that simple CrackMe we cracked! We have also talked quite a long time about game cheats, after all that is what this series is dedicated to. So, to satisfy this we will be taking a real-world example of a game cheat and exploit I was able to crack for Fortnite. This cheat was private, used APIs, was an external game cheat, and also used a TON of systems to authenticate clients or users of the program. Last time, we used a simple CrackMe but let’s actually step into the real world and this real-world experience might even give you much more experience in cracking software. Before we start the article, I also want to lay out a base for what this article will be talking about and note something.

Note about Length: Recently, I got a ton of comments and messages in discord and other various social media platforms telling me that I should stop calling these “things” articles, they are too long to be articles but instead are modules or lectures. So, For the remainder of this “article” we will be calling it a module.

Now, before we deep dive into the module of cracking code using real-world applications and going over basic security, it is about time we go over some basic terminology so you can be equipped!

  • Cracking Code / Applications: The process of cracking or breaking specific applications to bypass security systems such as login systems. When a cracker uses the term “cracking” they are referring to the factor that they were able to bypass login systems and use the application without a license.
  • Binary Exploitation: The process of exploiting vulnerabilities in binary applications such as buffer overflows or format string vulnerabilities.
  • External Game Cheat (EGC): External game cheat refers to a game cheat that operates and exploits the game from the outside without being injected into the game itself.
  • Internal Game Cheat (IGC): Internal Game Cheat refers to a game cheat that manipulates and exploits the internal system by being injected into the game’s process or operates in specific areas of the game internally.
  • Key Generation (KeyGen): A key generator is an application or algorithm that is designed to generate valid serial numbers, license keys, activation codes, strings, or text-based codes for bypassing software licensing systems.
  • Anti Debugging: Anti-debugging is quite popular, it is a technique that checks to see if a debugger is attached to the process which then will result in locking down the program if a debugger is present.
  • Code Integrity Checking: Code integrity checking is the process of checking code and ensuring that it was not tampered with by a reverse engineer, exploit developer, or other various engineers or other systems.
  • Code Injection: Code injection refers to the process of injecting code into an application’s process or binary to modify or alter its behavior and bypass security measures.

For this module, you will be learning terms throughout to better structure your understanding of cracking code and applications. But for now, these terms should allow you to get a good idea of what we will be talking about.

Binary Security | Real Life and Real World Applications

Source: onra2 on UC

Something interesting popped up in my previous article that I completely forgot to talk about. What exactly are the real world applications of reverse engineering and why might someone want to study software cracking? To be specific, there is no direct answer for this as the journey you take and the reason you choose RE is completely up to you. But, for a longer answer I have made some good bullet points as to where RE becomes handy.

Note: Most reading this might be familiar with cybersecurity organizations like Cybereason that protect us from ransomware. However, it may surprise you to learn that reverse engineering can be utilized for malicious purposes, allowing attackers to deploy their own versions of malware that can be mistaken for different variants. Malware analysis, one of the bigger fields in reverse engineering also plays a crucial role in the adversary’s tactics, techniques, and procedures, enabling them to leverage their understanding of the fundamentals for potentially nefarious purposes. This arsenal has gained significant importance and extends beyond exploit development. Let’s consider the case of Stuxnet as an example. You may have heard about the collaboration between the NSA and Mossad agents to sabotage the Iranian nuclear program. Companies like Kaspersky were able to obtain a sample of the worm-like malware and shared it with the public for study purposes, aiming to prevent its further spread. However, some nations took a different approach and weaponized the malware to infiltrate the facilities of other nations according to their own objectives.

  • Game Cheat / Exploit Development: One of the biggest markets to date is game exploit development and without a doubt it is one of the best fields to get into as it teaches you real world development and real world reverse engineering techniques. Most reverse engineer’s will start at game hacking because it shows again so many different things. Just within your first few months of REAL reverse engineering in the game hacking field you might learn how to build kernel drivers, how drivers in systems work, how to bypass massively distributed security systems, reversing industrial application, reversing network protocols, dissecting binary applications, exploiting security flaws on operating systems and binary applications and even some mathematics behind yourself as well! Many other things come with the game cheating and exploit development world, in fact there is so much that I could write a whole other article on just that but since we don't have the time we will not be doing that here right now. But, generally speaking, game cheat and exploit development are where RE is mostly used or commonly started with anyway. This is because exploit development requires binary analysis and a ton of understanding about the vulnerability and application you are trying to exploit.
  • Malware Analysis: The second biggest ( might be close to the first biggest ) applications of reverse engineering would be malware analysis. As malware becomes more and more common, the job rates for reverse engineers skyrocket. Why is this your asking? When unknown malware is released or sorry new malware that has yet to actually be shown on the web or been made public, reverse engineers are called to the task to immediately dig into that malware and see what they can find out about it. This can include reversing network protocols if they are custom, reversing the applications internals or malwares internal functions and many other primary targets for that malware. The reason some companies may hire reverse engineer’s to do this will vary but it mostly all boils down to research and to better protect their system by adding signatures unique to that malware to their systems or blocking specific actions or even training artificial intelligence. Malware analysis in itself is also a huge field and teaches you a lot. During MA you might learn about the windows and Linux internal suites, understand how windows works with specific calls and the primary difference between open sourced and closed source malware by understanding the techniques and new methods developers or teams might be using to bypass anti virus systems. Malware analysis also requires a ton of internal understanding about applications such as assembly, understanding system calls, understanding system internals and more among that list!
  • Digital Forensics: This is can tie into other fields but digital forensics is another amazing field where reversing can come into handy. Maybe you are not cracking code but you are definitely digging into the internals of files or applications. Digital Forensics is still a very well paying and high job that is talked about all the time in the cyber security industry. This can include pulling apart images, protocols, unknown files and even looking for specific symbols or keys or little clues to get you closer to your target. Here you might learn to apply reversing logic and concepts to different scenarios where instead of looking for exploits your trying to find specific pieces of information.
  • Intellectual Property Protection: This is not really a field but a job that is used amongst companies. Some companies may hire reverse engineers to go out and reverse technologies or even try and crack the companies applications to better harden their security surface. For example, sometimes in the game hacking industry ( as we will discuss in this module ), competition game companies will hire more reverse engineers or code crackers to help them leak or crack their competitors exploit or cheat to knock them off the market. This also happens outside of the game hacking world and sometimes may be used to help harden software protection mechanisms.
  • Legacy System Maintenance: Sometimes, people who work with legacy systems that have not been working with them since they were born will reverse those systems to get a better understanding of what the system is doing. Typically, when you are working with private legacy technology, documentation is VERY limited and typically outdated and poor. This leaves a reverse engineer up to the task of gaining information on undocumented parts of the software to create updates or patch issues within the code and be able to work with the protocols that may be undocumented

Regardless, reverse engineering is extremely helpful in cyber security as a whole. This is because it opens your mind up to entirely new deeper fields and without a doubt it is one of the harder fields to learn but brings you great skill and flexibility. Real world applications also can exist just simply because you can. When it comes down to the darker sides of reverse engineering such as dumping/leaking code, cracking software, breaking past login systems or dumping enterprise software, you realize the markets that this starts to become. RE is not popular just because its fun but because of the jobs and money that can be made from it especially in specific sets of activities like cracking software. Sure, it may take you quite a while to learn it and it may be frustrating to understand but over time when you master it you may just be able to pull some money from thin air.

Binary Security | Application / Programmatic Security

When you hop from CTFs that are RE-related to cracking or exploiting enterprise software, you will realize the stuff that CTFs never have and never will prepare you for; Private Security Mechanisms. When bigger companies become well-funded per se, more work goes into their security systems they may not even be using someone else’s and would rather be better off building their own. This happens because as we have discussed many times, working with third-party libraries, relying on third-party software or even relying on specific programming languages can become a huge risk to companies like Microsoft or Google. Some of these corporations go SO far as they make their programming language out of their assembly to build their anti-virus software and to build their security mechanisms. This is where Zero trust comes into play. Most people will tell you that zero trust exists, but let’s be completely honest here, zero trust barely exists. This is because whether or not you are building an anti-cheat system, writing plugins for other systems, or even building your database solutions, 9 chances out of 10 ( unless you are more than just a titan [ Microsoft, Apple, Google, etc. ] ) you are relying on a system fed library, system plugin, system setting or some form of third party vendor. This breaks the zero trust rule because you are trusting a verified but still third-party source into your open arms and just willingly allowing them to have control over specific parts of your program. If that provider then becomes vulnerable, your entire application is now at risk. When zero trust policies for corporations like Apple are put into place to develop an application, 99.9–100% of the software, protocols, files, plugins, and even programming language’s all belong to or were developed by Apple themselves. This means that they are trusting their software instead of relying on their own which is a good example of Zero trust. When this happens, CTFs become barely helpful since every custom protocol is undocumented, everything is black-boxed when you are reversing and they may have undocumented or unreleased security mechanisms that have not been reversed before or may even be using code obfuscation algorithms unique to only them. This is why real-world hacking and cracking code becomes useful. Most of your standard reverse engineers start in the game hacking realm which just makes sense, I mean, who wouldn’t want to make a small little Fortnite cheat? But the issue is how they can get up to that level. A ton of people always have this problem when transferring from CTFs which is why I want to bring a little bit of a real-world section to you. In this section of the module, we will be talking about binary security, how specific people will secure binary applications, and why people like game cheat developers NEED to protect their systems from other people. Below I have defined this section into sub-sections which have their sets of paragraphs under them.

  • Binary Security | User Input: A section that talks about how user input can be dangerous but how developers protect against it.
  • Binary Security | Fluff your strings!: A section that talks about the dangers of strings in the case of reverse engineering and cracking software.
  • Binary Security | Debuggers? LOL: A section that talks about anti-application techniques. In other words, ways that binary applications protect themselves against specific debuggers, disassemblers, etc.
  • Binary Security | An application is never safe: A wrap-up section that talks about how applications can never truly become “safe” and ends the primary application/programmatic security section of this module.

These sections may go a bit deeper so buckle up buckaroo, cause we are going for quite the ride!

Binary Security | User Input

When it comes to cyber security in general, you should know by now that working with user input can be bad on so many levels. This can include giving the user full control over the behavior of an application during execution. If you are not aware of this, then let’s talk about it deeply. Say you have a program that is in binary format something like a game cheat for example and you require the user to enter their license key. Well, when we do that we need to use something like std::cin in C++ to get the users’ input unless we are taking that from a GUI or some framework to make a different input control. Either way, usually we are also adding text to that so our prompt looks something like this.

As someone who may not think correctly, you might be wondering, how exactly can this be bad? Well, if this tells us anything, two things could be happening in this application, one which we can talk about now and the other one we will talk about later.

  • Unencrypted / Hidden strings: This is bad for multiple reasons, again we will get back to this in the “Binary Security | Fluff your strings!” section.
  • Allowing user input with no control: Now we can not infer that the application is not limiting the amount of data we can put into the application but we do know it allows us to input data. If there are no proper protection mechanisms in place, then a random user who is smart enough to google “ how to exploit binaries with user input “ can easily stumble across a payload or even nowadays with the right prompt ChatGPT that payload up!

Either way, this can be bad IF there are no security controls or mechanisms put into place to stop users from abusing the binary. The most common vulnerability in applications that are based on user input is typically a buffer overflow. In shorter terms, buffer overflows are when a developer doesn’t exactly safely use buffers in programming languages or does not monitor the amount of data or type of data a user can input. For example, the following pseudo-code shows two scenarios; one is an example of a vulnerable application without security controls, and one with security controls.

  • Application 1
UserInput [12];
UserInput = input("Enter system command");
system_run_command(UserInput)
  • Application 2
UserInput [20];
UserInput = input("enter system command");
if (len(UserInput) < 20) {
system_run_command(UserInput)
} else {
println("bad length")
}

Now, both applications are still bad because they are calling user input in the most unsafe way possible or rather storing it but application 2 at least does its best to prevent users from purposely overflowing that code. This is an example of a small and simple security system that can be implemented to prevent users from overflowing specific points in the program to prevent BOF attacks. Regardless, binary applications still should limit how much user input they use but if they need it, implement the strongest security mechanisms possible. Have you ever heard of blacklisting or whitelisting? Well, this exists in programs that require user input as well. In an application, one of the ways developers can prevent RCE attacks ( Remote Code Execution ) or exploit buffer overflow vulnerabilities (BOFs) is by whitelisting or blacklisting specific sets of characters.

  • BlackListing: Blacklisting is considered to be more dangerous to implement, this is because you are only specifying a specific amount of characters or sets of characters a user can not use. The following program below demonstrates this.
BlackList = []string{
"||",
"!",
"()",
`'`,
"@"
}

void main() {
var input [23];
input = GetUserInput("enter your name")
for char in BlackList {
if input.contains(char) {
println("BAD CHARACTER, SECURITY SIGNAL")
exit(0)
}
}
println("hello", input")
}

This program takes user input and will then check the blacklist. If any character is contained in the text that was entered, the security system will trip and the program will exit. But you notice how not every single character was blacklisted? How words were also not blacklisted? A user could still very well use symbols such as && or; and | since the blacklist did not contain those characters. This is faulty because any hacker ( in a more realistic scenario ) could take advantage of this and just write a more complex bypass.

  • Whitelisting: Whitelisting is a much safer method because instead of telling the user what they CAN NOT input you are telling them what they CAN input. Consider the following pseudo-code program.
WhiteList = []string{
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"0",
}

void main() {
var input [23];
input = GetUserInput("enter a single number")
for char in BlackList {
if input.contains(char) {
println("sum! -> ", 2 + int(num))
exit(0)
}
}
println("SECURITY SYSTEM TRIPPED- NO NUMBER USED")
exit(0)
}

In this example, the program checks if it does contain a character within the whitelist, and if it does then it will just continue to go on but if not it will trip a security system and not create or execute the equation. Whitelisting is again considered to be much safer and you see it all the time in applications such as banking applications that only require you to input card numbers or other numerical only information. Now, user input can not always be protected but there are some INTENSE security mechanisms out there that can prevent hackers from getting passed. Of course, when it comes to this level most of the vulnerabilities are not actually in the user input but in the security mechanisms themselves.

Binary Security | Fluff your strings!

In our previous article, about cracking code, we talked a TON about reversing theory and then took a small CrackMe challenge and threw it into X32DBG and well easily found a string and traced it to a compare statement and so forth, patched then cracked it. When I was saying how deadly strings are, I was being serious, strings are DEADLY to a developer if you are not backing your systems. You might be asking, why is this so bad? Well, if we are not properly protecting our systems from debuggers, memory readers, memory writers, disassemblers, process explorers, etc, people can easily dump the application to something like a .dmp [dump] file and just pop open something like IDA and find every string you place. If you recall, when we worked with Lafarge’s CrackMe, we were able to easily figure out that the program must have been using strings, we popped open a debugger (X32DBG) and were able to easily find the direct location of where the input was made because most typical CLI and GUI based inputs all have text asking you what it wants. If this string was encrypted in some shape or form or even encoded then yeah there would still be a chance we might not be able to find it as easily through a debugger. This still does not mean it is safe, even code obfuscation won’t save you here. This is because really good reverse engineers can just pop open a hex editor that allows memory reading and just read the program in RAM during its execution and uncover the strings. This is because no matter what if you are printing it to the screen, it still has to be decoded. Take the following two programs as an example.

  • Program 1: This program makes no effort to protect itself, it just simply asks for an input key and checks if its the correct key.
#include <iostream>
#include <string>
#include <Windows.h>

int main() {
std::string key;
std::cout << "Enter license key>> " << std::endl;
std::getline(std::cin, key);
if (key == "LicenseKeyA") {
std::cout << "You got access!" << std::endl;
Sleep(100000000);
}
else {
std::cout << "Unauthorized..." << std::endl;
Sleep(100000000);
}
}

If we look at program one in a debugger and search for the string Enter license key>> then we get the following result.

We can clearly see where our input starts and where everything is in the block where we are getting input. Now, lets' look at this a bit more, we know that we are trying to get the line count. Well, if we look at this deeper we can find the function which is comparing everything since it is comparing a string.

Two things are going on here. We don’t even actually have to crack this program anymore or even bother finding the loop or compare statements. Because we have already found what the check is going for, we can just exit the debugger and now use LicenseKeyA as a valid license key input. Now this is where things get even weirder because we can still crack the program. Realistically a program won’t always be doing this and will not check. So what exactly is a weirder security mechanism that we can do to prevent that easy searching? Well, if we wanted to go dark we can do what program two does.

  • Program 2: This program takes things a bit differently, instead of just simply placing text inside of the loop, the program will take an array of bytes and then use that as the “string”. This is done by taking the bytes within the array and calling a function to convert the bytes to their respective ASCII position.
#include <iostream>
#include <string>
#include <Windows.h>

std::string Decoder(const unsigned char* begin, const unsigned char* end) {
std::string decoded;
for (const unsigned char* ptr = begin; ptr != end; ++ptr) {
decoded += *ptr;
}
return decoded;
}


int main() {
std::string key;
unsigned char bytes[] = { 76, 105, 99, 101, 110, 115, 101, 75, 101, 121, 65 };
unsigned char okmessage[] = {89, 111, 117, 32, 103, 111, 116, 32, 97, 99, 99, 101, 115, 115, 33};
unsigned char unauthorized[] = { 85, 110, 97, 117, 116, 104, 111, 114, 105, 122, 101, 100, 46, 46, 46 };
const size_t numBytes = sizeof(bytes) / sizeof(bytes[0]);
const size_t numok = sizeof(okmessage) / sizeof(okmessage[0]);
const size_t numunauth = sizeof(unauthorized) / sizeof(unauthorized[0]);

std::cout << "Enter license key>> " << std::endl;
std::getline(std::cin, key);

// Check license key
if (key == Decoder(bytes, bytes + numBytes)) {
std::cout << Decoder(okmessage, okmessage + numok) << std::endl;
Sleep(100000000);
}
else {
std::cout << Decoder(unauthorized, unauthorized + numunauth) << std::endl;
Sleep(100000000);
}
}

This program is much more secure than the last, without a doubt it is still easy to reverse with the right techniques and inspection frameworks but what we have here is a bunch of byte arrays that hold specific messages.

  • bytes[] → This byte array holds the actual key we are going to be checking which converted to ASCII is LicenseKeyA .
  • okmessage[] → When working with this array this is the byte array that says we have gained access to the program and that the key was valid. When we convert this to ASCII we get You got access! .
  • unauthorized[] → This will display the unauthorized message when converted to ASCII.

When we look at this in a debugger we can go to look for strings in the program so lets see if we can find any.

At the very bottom you can see we searched for LicenseKeyA which means our program has correctly hid the string from anyone from directly seeing it. The issue with this? Sometimes this can be very ineffective, for example, say the program doesn't want to hardcode every single word or phrase it wants to output and just leaves the encoder for the byte list directly into the program like the one shown below.

#include <iostream>
#include <string>
#include <vector>
#include <Windows.h>

std::vector<unsigned char> StringToByteArray(const std::string& str) {
std::vector<unsigned char> byteArray;
byteArray.reserve(str.size());

for (char c : str) {
byteArray.push_back(static_cast<unsigned char>(c));
}

return byteArray;
}

std::string Decoder(const unsigned char* begin, const unsigned char* end) {
std::string decoded;
for (const unsigned char* ptr = begin; ptr != end; ++ptr) {
decoded += *ptr;
}
return decoded;
}


int main() {
std::string key;
// Create vectors
std::vector<unsigned char> LicenseKeyArray = StringToByteArray("LicenseKeyA");
std::vector<unsigned char> okmessage = StringToByteArray("Proper License key!");
std::vector<unsigned char> unauthorized = StringToByteArray("Unauthorized...");
// Get sizes for calculation
const size_t numBytes = LicenseKeyArray.size();
const size_t numok = okmessage.size();
const size_t numunauth = unauthorized.size();
// Get license key
std::cout << "Enter license key>> " << std::endl;
std::getline(std::cin, key);
// Check license key
if (key == Decoder(LicenseKeyArray.data(), LicenseKeyArray.data() + numBytes)) {
std::cout << Decoder(okmessage.data(), okmessage.data() + numok) << std::endl;
Sleep(100000000);
}
else {
std::cout << Decoder(unauthorized.data(), unauthorized.data() + numunauth) << std::endl;
Sleep(100000000);
}
}

This program takes a lazier approach, instead of just manually encoding everything properly it still manages to call a function with the input of type string to encode the bytes then decode them. Lets see what happens when we debug our program.

There are our strings once again. This is what happens when programmers are not thinking properly. Now, even the previous program that uses the raw byte representations in the program is still not safe. This is because the data is still being decoded, returned as a string, and printed to the screen. Now, without doing a live debug on the program where we set breakpoints and step through the program we wouldn’t be able to find the strings in the previous program but we could still find it with the correct programs. Now, let’s walk through something even deeper and talk about the bigger issue. Even if the program2 didn’t implement the StringToByteArrayfunction and still hid its strings, the issue is the developer in this case still left user input wide open which requires a string and they would have to write a whole other encoding function for this as well. If a reverse engineer is smart enough they could easily find the exact point where you start the input based on just activating the program and trace function calls especially if they know the language you used. Either way, strings even if they are thrown through a decoder or obfuscator are still extremely dangerous, but in the end, it is all about making the reverse engineer’s job harder to crack your program and leak it. This is where anti-cheat systems come into play. Everyone complains or most gamers complain about how anti-cheat systems are just not good enough at catching people who are cheating, but like the programs and demos we have shown here; it does not matter what security mechanism you put in place, it does not matter how strong you think your program is or how protected and locked down your binary is, reverse engineers are impossible to prevent and will ALWAYS find a new way around a new even undocumented security mechanism. Not to mention, programmer error happens every day and always will, even the best most flexible developers always make mistakes and are BOUND to mess something up. Concluding this section, when you develop applications, make sure you know what you are doing and make sure that when you do write code you make it secure as possible and stay away from strings as much as you can unless it is just impossible for you then try to secure your application with code obfuscation.

Binary Security | Debuggers? LOL

We have talked a ton already about bad and good examples of binary security and previous articles on cracking software using X32/64DBG to debug, patch and inspect applications. We have even gotten used to cheat engine when working with games and even used process monitor to understand how a specific process is working with the environment outside of itself. But what if we try to open something like a game that has a powerful anti-cheat like EAC? When we open Fortnite without spoofing it, creating some form of driver, or loading our systems and modules, you will notice that EAC will throw an error saying an anti-cheat violation has been triggered and your debugger-like cheat engine will go ahead and just drop or if you open process hacker will automatically become terminated by EAC. This is because anti-cheat systems that sit at ring0 or the kernel level of your operating system can read and write to the system’s memory telling it what it can and can not do while the driver is active in the system. This is one primary way anti-cheat systems will work and how binaries become more secure. When someone develops a login application similar to the one we have shown in the section before, they typically will implement anti-application techniques if that makes any sense. They will create a whitelist or blacklist of specific names on the system that are allowed, specific prefixes that are known to be used to actively debug the application or dump it. This is the bigger world of security, if you can not directly prevent someone from reversing your binary or application, prevent them from even reaching your application with other programs that can be used to dump it. A few methods are shown below that are commonly used within production systems.

  • Checking Names: Checking names of processes and matching them with “Cheat Engine”, “IDA”, “Ghidra”, “Hacker”, “Process Explorer”, “Monitor”, “DBG”, and various other names are one great way to prevent your application from being attached to a debugger, but one major issue with this is that any cheat or good developer can write a program to change its title name to something random or a specific pattern that is not detected by systems like this. Of course, the issue here is that we still can not use standard debuggers without using our own or finding a way to bypass systems that may be detecting tools that are just better than the ones we create.
  • Checking Process Attaching: Let’s say we want to open up a cheat engine or make it even better, our amazing debugger and get things started! To properly debug a process we need to tell our program to attach a debugger to it but oh no! The application has blocked any form of debugger from being attached to the process. This is another common security mechanism for binary applications, some of them will include entire systems to not only block specific applications by name but also protect their applications by also disallowing any form of attaching to the process directly which means if any debugger was detected but not shut down, the secondary mechanisms would just prevent them from happening. This still becomes an issue because we can always tell a program to just write a .dmpfile which can be inspected by frameworks like IDA without the application actively running.
  • Anti-Tampering Mechanisms: One of the major things that software cracking includes is making changes to the code directly by disassembling the file, patching at specific memory addresses then wrapping everything back up in an executable. If all goes well then anti-tampering mechanisms will employ specific techniques such as checksum verification, digital signatures, or encryption to protect the integrity of the application or applications sub files that it uses. Hackers can still manage to bypass this by breaking or even leveraging vulnerabilities in those systems and manipulating them directly.
  • Anti-Network Tampering Mechanisms: Some games or applications communicate externally with other various systems and APIs. This is typically included to add more functionality to the application, check for logins, and so on from there. More advanced reverse engineers especially your good game cheaters will sandbox that one specific application and inspect all of its networking by using specific protocol analyzers and system frameworks or utilities. They will then continue to tamper with the protocols and intercept communications to better understand how the program interacts outside of itself with other resources, they can then leverage this by writing programs to automate the exploitation/sniffing process and reconstruct custom packets to manipulate the control flow of the application or even exploit vulnerabilities. Most modern systems will not be able to prevent this as it requires an INSANE amount of control over the users’ computer that even most anti-cheat systems in modern games could not handle. There is only a very few select amount of programs that can help with this but even then fail at protecting against ZeroDays within the program, especially on the network side. The reason is that if we are being honest, it is quite rare to see a game protect its network due to how rare it is to see a game cheater publicly sell an exploit within the program that can manipulate the network directly and leverage ZeroDays. They do still protect against it but sadly do not make it much of a priority because again, they just assume that not many people are doing it.
  • License Verification: When it comes to using enterprise software, 9 chances out of 10 you are more than likely going to have to provide a valid license key. Most systems will interact with databases on the cloud to validate the license key which means it connects to somewhere outside of the program, but as we have discussed this in itself can become an issue. From personal experience, reversing game cheats that use KeyAuth as a primary system for logins are always going to be bypassable because all they manage to check is the username and if the API responded with the correct status code. The most secure program I have seen with license verification was one that would compare the API response every single time you even wanted to open the smallest tab, that in itself took an INSANE amount of reversing and in the end is just tedious to get through. License verification is one of the most common techniques but is still very attackable and who knows, maybe the API provider themselves also have an issue in their system that can result in everyone using your application for free.
  • Server-Side Validation: Most modern-day applications will validate licenses, users, connections, addresses, and more all within a server. The issue with this? That it can still be attacked by other hackers who know what they are doing when it comes to reverse engineering the game. Most people do not like storing their API secrets/keys directly in the binary so they store some form of sub-authentication hidden within a binary and obfuscate the code and use that API to reach another API and so on from there to validate the information. As we said before, this can not directly protect the application because the data has to be pulled from somewhere. In the case that someone bypasses your security mechanisms, they can easily spin up a program to read a dump file and just pull all of the active API endpoints, licenses, or information you have that is active during runtime. Server-side validation is cool and also works for a ton of applications like games but is still an issue if you are using it to validate specific information and only using it for very specific purposes.

Many other binary security techniques are put in place but those are just the most basic ones. Note how I mention that even these applications with the most secure systems are reversible. Well, that brings us to our next section.

Binary Security | An application is never safe & A singular Ending Note

As we have clearly talked about in this section and demonstrated, a application is never truly safe just as zero trust truly never much exists. This is because no application can possibly be just to the upmost secure or implement every single security system in the world simply due to collision issues, compatibility issues, implementation issues and as long as humans and even machines are alive, code will always find some way to become vulnerable and just like for every security mechanism put into place there is a hacker out there that is bound to break it. This is where people still fall short and say that “ our applications are the most secure “ because they may be the most secure but never are 100% secure down to the exact percentage especially if they are using bad security systems. The world of hackers is also every growing and evasion techniques are bound to happen especially in the case of games as its already shown. In this section we talked a lot about how applications are most likely going to be vulnerable, how they can protect against it and how applications can also fight against these but also how hackers can bypass them. We are now ending on a note saying that applications are simply just never safe, but we can do the best we can to secure an application and make it harder for reverse engineer’s to reverse security systems to build working bypasses for those systems.

Binary Security | Where Code and Hacking Collide

One of the biggest problems within cyber security and getting started is that people do not exactly know where to start, when it comes to reverse engineering and application security this step is 100% essential for you to know. It is important that reverse engineers know their ways in and out of systems not just by reversing applications and attacking them but building them as well. We will not get into red team and blue team directly and their own methodologies but we will rather be exploring why it is important to understand as a reverse engineer how to break and build systems, where this can be beneficial to you, understanding both roles in your exploit development. In this section of the module we will be talking about the following.

  • Binary Security | Becoming a Theorist: A section that talks about security theory, why becoming a theorist is important in the field of RE and where it will help you most.
  • Binary Security | Why learning programming is important: A section that talks about why programming is important in the field of RE, why it can help you become a better reverse engineer and where it can benefit people who develop zero days.
  • Binary Security | Utilizing Your own Tools: This section talks about programming and its own implementations to you as a hacker and where it can help you with your own programs.
  • Binary Security | A Final Note: A final note on Where Code and Hacking Collide and then a phase transition into real world examples.

Binary Security | Becoming A Theorist

Most of my RE ( Reverse Engineering ) articles have all been theory based, we have explained deep into theoretical concepts, mathematical concepts, programmatic concepts, exploitation concepts and more. By now you may still be asking, if we only need to know HOW to do something on a specific application, why are we even learning or going to bother with theory? Truth being told, if someone tells you HOW to do something, there is a heavy chance that it might only apply to specific circumstances. For example, someone can teach you how to execute Blind SQL injection, scan for it and understand that specifically and just how that specific vulnerability works but when you go to Boolean Based SQL Injection your not going to be able to execute it the same and will have to re learn the process all over again. Theory is the very thing that powers our world, everyday people who work with computers, computer engineers, developers, security researchers are using theory in some shape or form, instead of just specific fields every single human in any profession or in general uses theory in their regular life even if they aren't the ones building it. Becoming a reverse engineer is not just like solving a simple puzzle, its more than that, not to mention any good reverse engineer knows their way in and out of a system they have never discovered before. How can this be possible you ask? Well, they may not know the direct ins and outs, but they may know where to start and direct their research all because of the theory they have learned. If you learn the theory of how an SQL injection attack works ( for example ) and then learn how different variants such as time or Boolean based attacks work then you can easily build a foundation for newer forms of SQL injection you have never learned before since you were able to build a direct base of how SQL injection attacks work and how SQL works. The same falls for reverse engineering. You are not going to be able to make a keygen for a program after cracking a simple CrackMe challenge, you need to build an entire base of theory for RE before you can even jump to that stage and then understand various factors to be able to do it. In this case of my modules, they teach you the concepts behind game cheats, specific fields of exploits and even teach and educate about specific topics in RE. When we look at some of the articles that talk about game cheating and in the case of “Reverse Engineering:Conceptual Logic” if you read that entire article you get a giant base theory of how the actual game cheats work and understand that they mostly all stay the same in and out. ESP is a type of cheat that gives the current player or game pawn on the client side extra sensory perception about the game world around them or more information such as seeing players from the walls. The concept of building that cheat is the same, we need to get all the players in the map, get all their locations, use specific algorithms like linear transformation algorithms to take a 3 dimensional position and convert it to a two dimensional position on the screen and then draw a bunch of boxes or information of that player in that position in the game onto the screen. This concept DOES NOT change and is only modified slightly but will not change just because the game changed. However, if I told you that Valorant ESP requires that we build a KM ( Kernel Mode ) driver to request Read and Write permissions to the process and then have to scan at memory address 0x10 for the players current world position and so on from there, then that theory would not exactly be theory, it would rather just be me telling you what you need to do to cheat in the game Valorant. Theory, will take you a ton of places, you do not need to understand the most advanced concepts as well if you have that theory to back you simply because it is the building blocks of everything around us. Becoming a theorist is hard in todays world because there is not nearly enough resources out there to get theory down but that's okay because enough practice and knowledge and you can start actually building your own road paths and theory for your own work and then eventually figure the path on the side that you need to work on. For now, since we have gone over enough theory we will not really be talking about that here today. I just wanted to take a second and be able to explain to you why we actually use theory, why it is not required but why it actually becomes extremely useful! Now we can move onto the more in depth sections.

Binary Security | Why learning programming is important

One thing we always tend to forget as hackers is how important programming is. Many say you do not need to master it, and that is true; however, similar to theory it is extremely helpful! When it comes down to reverse engineering you are definitely going to need it to actually understand what's happening. In the last article, we talked about assembly a little bit and how programming language’s work as well as went deep into how applications work on the backend and interact with a system and their environments. When we got to the CrackMe challenge you probably already had a general layout of how we were going to crack it, what we were going to do, what we were looking for and generally what we seriously needed to get done before we even started to work on patching that compare and jump statement. Because of us learning the very basics of programming and applications even using a small crash course of X64_86 assembly, we were able to easily grasp what our program was doing when looking at specific sections. Obviously, when you get more into software cracking and understand the base fundamentals of everything we are going to need to learn more about development, how writing plugins for applications like Cheat Engine, Ghidra, IDA and so forth can actually help you and where writing your own exploits, utilities and drivers become a major handout. So, this is why keeping programming in the back of your head will help you. Not only will it help you understand how the application is working but even during the phase of attack planning we can already design and layout what the program is doing in our heads. For example, say we know a program is asking for key user input that is only digits and it then compares that to a given length based on the error message, we can draw out a flow that works in our head and then draw out some pseudo code which is of the following.

if len(user_input) == 12 {
// check if its char only
if user_input == DigitOnly {
Authenticate(user_input)
} else {
throw ERROR_VALUE_MUST_BE_INTEGER
}
} else {
throw ERROR_VALUE_MUST_BE_EQUAL_TO_12_NUMBERS_EXACTLY
}

Just because we have laid out exactly how our system works we can better understand what we are going to look for and what we need to target most to help ourselves actually exploit the application. When it comes to development, like mathematics and most field, doing base theory is going to be your best friend and then learning languages like Assembly, C++, Rust, Go, etc, will all be good ones to choose where to learn. Real world reverse engineering typically has you either working with C++, Go, Rust or in some interesting cases Java or Python binaries. Of course that is a different world and reading that kind of translation is a bit wacky but most of what you will see in RE is going to be assembly from disassembling and debugging. Regardless, programming is extremely helpful especially when working with more secure protocols, frameworks, applications, security systems and other big boy things. Now when we get deeper into things you may also know that some reverse engineers leak code to specific programs such as game cheats. You might be asking, how can a reverse engineer just convert machine code to the original applications native language? Truth being told is that they cant. This is also where learning programming may aid you as a reverse engineer. When reverse engineers come into more complex cases of cracking code and leaking it, they typically use frameworks like Ghidra or IDA both have unique versions that support the use to decompile programs. The process of decompiling typically revolves around identifying the native programming language of the application, taking the disassembled output and converting it to the closest representation of its native language. For example, say you have a simple login and authentication application written in C++. Any reverse engineer could pop open IDA pro, disassemble the program, spectate and understand how the program works through static and dynamic analysis and directly decompile that program to pseudo code. Below is an image that demo’s what decompiled output may look like.

When you have not only a knowledgeable reverse engineer, but one that also knows DEEPLY about programmatic theory and understands easily what they are trying to exploit, they can take this code and just re make it in their own form. For example, in the screenshot above, any direct reverse engineer with deep programmatic theory and development knowledge in C++ could easily patch that program up, refine it inside of an IDE, make it all pretty, document some of the code and just leak the source code. Now, some frameworks exist to take code like this and just convert it using specific code sequences using specific algorithms but those frameworks are not publicly known and are not directly released out to the public. In other cases, some reverse engineers that notice the code might be obfuscated or packed will find unpacking utilities to unpack or reverse the obfuscation of the program, then convert it to pseudo code and finally refine the program in the own development environments. Code / Application leaks do not always work this way, some may not even reverse engineer the application but rather find endpoints exposed in the binary application that lead to some production server that may have a vulnerability in it allowing non authenticated users to access the source code. Despite this still being possible that is a whole other chain of attacks that do not fall into RE and rather fall into web application hacking. This is a good example of where actually understanding programming comes into handy. It can deeply advance your skill and exploitation process as it allows you to understand the result from decompilers, understand specific calls, understand how to scan and read specific values in disassemblers and also understand how to patch programs directly. Because without the knowledge of assembly, how would we even know what direct statement we need to patch? Or what about without programmatic theory how could we even spot the brick or know what we are looking for in a debugger or RE framework like IDA? We just simply couldn't. Say in a world we do not exactly directly need programming for reverse engineering or need knowledge of language’s like assembly. The theory, the understanding of those concepts go a really long way and plus, what is the hurt of trying to learn something new anyway? It cant be that hard right? Especially if you are a reverse engineer and working on a lower level of computers. This actually leads us into our next section. Asides from just patching code in debuggers or frameworks, understanding specific system calls, understanding specific parts of a dump or memory section, where does programming and development help reverse engineers?

Binary Security | Utilizing Your own Tools

In the previous section we talked much more about how programming can help you as a reverse engineer and how it can make your skill much more versatile and flexible. However, we have yet to talk about how it can be USEFUL and directly apply to you other than just understanding how programs work and mapping them out a bit more. Lets talk about game cheating. When a game cheater who knows what they are doing and isn't pasting code wants to build a game cheat, they typically go through the process of doing research on their target game. Since it fits well for the current state of this article, lets say the users target is Fortnite. The reverse engineer would first start by understanding the security mechanisms of the game, understand what they can and can not do at the user level of the application and then understands how they can actually reverse everything properly. In order to build their game cheat they not only need to build the actual exploit but understand specific topics and choose how they are going to actually build a cheat that can work with everything. Remember how we talked about the security systems in games like Fortnite or Apex Legends and how they will easily drop systems or drop itself if it detects a debugger active on your system or a specific framework? Well, this makes the reverse engineers job much more harder and they cant really choose how they are going to build the cheat if they cant even get their own arsenal to load in the game. By this point, this is where programming can come in handy for a reverse engineer as they can take two steps to this approach.

  • Build A Spoofer: Typically which this is a rare step in the process, but sometimes spoofing system services or system security measures on the client side of the reverse engineer will help momentarily bypass security measures. Spoofers basically help by “spoofing” the hardware address and various other parts of the system that actually prevent anti cheat systems from detecting weird activity from the same exact address over and over again. This can also help the reverse engineer test the security systems without fully getting banned as the spoofer just momentarily masks the data that a specific anti cheat system would ban.
  • Customized Software & Drivers: Drivers are- one of the more common ways most modern and powerful game cheats are developed. Drivers are basically programs that can assist a operating system with interacting with a specific program. In this case, exploit drivers typically sit on the kernel level and request specific permissions from the operating system to read and write data to a specific process and load modules. Drivers are commonly used to evade anti cheat systems and other various security systems in games, this is because they sit at a level that some anti cheat systems just do not have access to like VAC. When it comes to games like Fortnite in this case which use BattlEye AC and Easy AC they can become more frustrating because all of them sit at the kernel level of your operating system and require much more further evasion techniques. Either way, the reverse engineer is typically developing their own driver because pulling any random driver from GitHub is bound to become detected and may not be signed which is a whole different world we will get into in another article. But the driver is only the beginning of this road path as the reverse engineer has to build their own programs to work and operate with the systems or build a program that can momentarily bypass security measures so they can use tools. Typically when exploits are made for games and other various applications, a game cheater may actually use fully customized software they made to continue specific operations. For example, say a game cheater wants to read the players health no matter what update the game is in. Well, In memory the hacker has to first build a program that can read from the memory location of the players health such as 0x133BF and then they have to read those values back and store them in a variable or some area in the program that the program can refer to. Well, this value is not static and most of the times when a game updates, the issue with it becomes when the user tries to read that same memory address and it just doesn't exist. Now, they need to build a program and scanner that is undetected by the security system, bypasses other security measures and reads from the game itself to fetch the location of a specific set of bytes in memory. Woah woah woah stop there for a second, that was kind of run on. I know that might be a bit confusing to sink in but it shows the point that reverse engineering and building exploits will require some decent knowledge of programming. This is really just going to say that even when you do some reversing and do not have much knowledge of programming that sometimes working with your own tools is going to be something that benefits you in the long run especially save you time and effort trying to use system commands or controls to bypass or disable the security mechanisms in specific applications. Now, either way the process is very tedious but building your own tools, own drivers, own debuggers, own sniffers can also help you perform much more accurate recon that just assuming what a system has because you couldn't launch X64DBG or ProcessHacker.

When it comes to reverse engineering, in general the second path is going to be chosen. This is because when a programmer really has the power to do something, they would rather much end up building their own tools for the current state instead of walking through the same process for every singular target they choose. If we choose a spoofer road path that means the developer has to build a spoofer for every single possible application instead of just building a driver that could possibly be universal for most systems and using their own frameworks that can take advantage of privilege's on the operating system to just plugin their own frameworks and tools which may be bound to work on most systems instead of having to reconstruct them, write a whole new program, port the framework and so on from there. Not to mention, even if they could get away with spoofing the system and only use it once they still have to develop a working exploit anyway and automate those without a spoofer since every client may not have a working spoofer on their end. In a realistic scenario the reverse engineer may just build their own spoofer and build it INTO the program itself rather than just leaving it up to the clients. Regardless its still a painstaking road to go through and just using a spoofer overcomplicates things when the attacker could easily just build a few systems to automate the process of exploitation. This is also very common to see within communities like the game moding/cheating communities, exploit development communities, malware development communities and so on from there.

Binary Security | A Final Note

Since we are ending this section in the module, I wanted to make a final note on something. A ton of people will tell you that you need this and that or you need so and so amount of credentials and information but I am going to be honest with you- you can only do what you truly want to do. Sometimes, binary applications can be as easy as googling a simply payload, injecting it into user input and then getting root access, other times it can take someone an entire month to exploit and understand. What you do with my articles, however you may take them is fully on you. If you feel like you can be a better security researcher by understanding the primary fundamentals of programs, programming in itself, the frameworks you use and even becoming a wizard at programming which will all help you. I also want to say that no matter how hard you try, what systems you implement, what you do, binary applications will never be safe. We have gone over a bunch of security mechanisms and controls that can make reverse engineering harder but also mentioned how even if we do make it nearly impossible, there is still a high chance that it is still very crackable and exploitable. Some frameworks are even exploited without the public knowing since it can be quite the legal limitations that prevent hackers from doing it. Either way, it may be cracked but not all the time will it be. It is also important to note that choosing one side and mastering one side of the trade is not the best of the options. As a reverse engineer or exploit developer or even a malware developer it is important that you study how to attack applications including your own while also how to defend against it. Most licensed software out there is pushed without even testing its limits unless its a security system typically in the web application but not many seem to think about the application itself and where it can abused or taken advantage of. Always, secure your programs.

Binary Security | Real World Software Cracking

We have talked many times before about what software cracking is, after all that is how we have decided to start in reverse engineering and powering this course off right out of the gate! So, to finish this article up, I want to give you a brief introduction to real world software cracking and give you a primary example of what you might come across. For context, I will not be showing any enterprise software but rather explain my experience in the game hacking world, targeting hackers who work underground to produce exploits for games like Fortnite, COD, Apex Legends and other games as well as bypassing security systems like EAC ( Easy Anti Cheat ( , BE ( BattleEye ), and other various anti cheat systems. Below I have listed a few sections that this part of the module will be split into.

  • Binary Security | Where Cracking and Nuts Collide: A section that introduces you to how criminal software crackers can help game companies out and how real world software cracking comes into play.
  • Binary Security | Choosing Our Target: A section that gives a good background into my personal experience, why I chose the game hacking community, why targets are chosen, why I chose to crack this program and also going into the game cheat community as a whole.
  • Binary Security | Drawing Out A Plan: A section that talks about going through the steps of making a game plan, how will we attack? what are we looking for? What will our whiteboard of attack paths look like?
  • Binary Security | Executing The Plan: A section that talks about executing our game plan including continuing to execute static and dynamic analysis of the program going through the steps.
  • Binary Security | Cracking The Program: A section that executes the actual programmatic cracking where we execute the plan and fully crack the program tracing back calls and information.
  • Binary Security | Real World Cracking — Conclusion && Summary: Section will sum up everything in this article and then finally talk about how everything comes together and more deeper scenarios. This will also talk about real world hacking and its limits, what happens and what is considered to be legal and illegal in this scene.

Binary Security | Where Cracking and Nuts Collide

Yes, the pun was intended. In this section of the module, we will be talking about where the line of cracking becomes- just justified. In software cracking, I like to call your average reverse engineer’s that just crack basic CrackMe challenges crackers, they are the ones that are getting started or are just bored with nothing to do. Meanwhile, you have your schizo’s and your nuts which are people that can sit here and just crack enterprise software and leak even the most protected programs in literally days. For some people it can take years to reach that, but why become a schizo? where exactly does becoming a complete nut come helpful to you? Well, two things.

  • Who Doesn’t want to just open a bunch of cool hacking terminals and crack their favorite application in two days?
  • Who doesn’t want to be able to just be that fast?

Now, without a doubt, software cracking even for the nuts and schizos can take months or even years to successfully crack and walk through and some programs never even get cracked. Regardless, it is cool to be a part of those people because it can seriously help you collaborate with other teams, pull together unique organizations and even educate people on the world of software cracking much better plus, most of your nuts understand everything about the application they are cracking, how to protect the application better and so on from there. Cracking and Nuts start to collide when each of their unique skill is just brought together, where instead of just software cracking you have development, security system design, backend and frontend design, and so on from there! But what about game companies? How can these nuts help out the game companies? Well let us think about it for a second, when someone who is a complete addict to hunting and cracking other game cheats then leaking them, game companies will send out people to look for that code so they can better understand how to drive it or maybe the company might even be hiring software crackers to go knock off competition. For example, I was once contracted by a smaller end startup that had an issue with their game, a hacker kept exploiting their game over and over again and they were making INSANE amounts of sales from it. They hired me along with a few other people to collaborate and crack the cheat and then sell the crack for less money while also feeding it to the same company so they could better study how the application worked. There was much more to this but either way, the point being from even my personal experience, software cracking goes a long way and it may not even help direct game companies but help everyone in general. Take into consideration the amount of malware that uses custom signatures and bypass rules, if reverse engineers didn’t exist companies or firms or governments would not be able to protect their systems without them since reverse engineers dig DEEP into a program and deeply understand how to detect it and how to work around its bypass mechanisms so they can also add signatures into AV ( Anti Virus ) systems. Now, let’s dig a bit deeper into things, lets' crack this god-for-saken cheat.

Binary Security | Choosing Our Target

I told you that this cheat had a personal background and reason for being chosen, so what I am going to do is tell you why I did what I did from the attackers perspective and then tell you how other reverse engineers may choose a target. Me and a few other people who I will refuse to name were working on something for a game- we will say Fortnite in this case since it actually was Fortnite. We were just messing around figuring out how to do some things with the anti cheat system and also using it as a “educational” side to teach people where anti cheat systems were flawed since all it takes to bypass EAC is a little bit of programming knowledge and its easy to get it done. Within this set, we had someone who took the source code from us and was actually trying to sell it. THIS WAS BAD because two things happen when someone takes code like that and uses it for nefarious purposes and then tries to sell it off of people for hundreds of dollars a day-

  • EAC will find you- and they will hunt you down
  • You now have someone who just took all your hard work

So, what we decided to do was wait until he came to sellers we knew. At this point, he was reaching out to resellers which are basically people that take game cheats and re sell them for a higher price and make money off it which is how game cheat companies make their money and also how other people get their cheats out there more. In this case, this guy went to the reseller we knew personally and tried to make a deal. The cheat had some issues and wasn't being pushed to production but he was bragging about how good it was. For context, below is a screenshot of what the cheat looked like in game.

ESP mid game

This was a singular lobby that was showing and drawing the direct locations of the characters in the map. The next image shows what it looks like in lobby.

Client Side External Game Exploit Demo | Character[1568 meters away from client camera] + FOV aim range

Then the next image is a more clear photo of what the skeleton looked like.

ESP skeleton — 10 meters away

I was super annoyed at this, who the heck was this guy thinking he could come in here when I and someone else are trying to sit there and produce quality education and security research, RIP ALL of our hard work away from us, brag about how secure it was and then just sit there and scam people with it? NOT someone I want to be affiliated with and someone I wasn’t going to just watch. I typically do not engage with this, but this person was trying to take exploit code that can be used for nefarious purposes and then continue to scam people AND hurt the communities I spent this entire year building and damaging relationships so I HAD to do something about it. I waited and waited until this guy would eventually slap the binary and loader into the chat and only privately send keys. My alt account in the reseller chat was sitting there and just watching, he then sent us all keys and told us that this is how the cheat works. So, by then I had my target, left the chat, took the binary, and did some research. I was able to choose my target because they wanted to do something harmful to not only me but the people that worked on this, communities, and people that were also going to get scammed from that. This cheat was a very simple demo as well it was never meant for production and this dude just wanted to shove it out into the open. This was one of the better reasons to crack code but other reverse engineers might have a more legit reason as to why they want to do this kind of activity if you will. Some crackers might choose their target by understanding their limits, some crackers might go based on their enjoyment and some may just be in it for the money since software cracking makes an insane amount of money if you are good at it. You may notice a common thing in black hat and even white hat hacking- targets are chosen for thousands of reasons but always have some motive even if it’s some weird one like “because we can” it is still for some random reason or aimed towards political motive. Either way, choosing a target is going to be completely up to you and what you want to do, and who you want to target. However, note that when you do go to attack an application if you attack it for any other motive that is negatively forced you are bound to get in trouble, be careful and I do NOT condone illegal activity. I am simply here to educate and inform the world about topics like game hacking, software cracking, and more simply for fun.

Binary Security | Drawing Out A Plan

Alright, let’s talk logistics. We have already laid out who and what exactly we are targeting but now we need to draw out a game plan. What exactly should our game plan include? what even is a game plan? Every hacker has some mental or physical hit list that represents a game plan. A game plan in our case is a plan of discovery, attack, road paths, and systems we will attack first or some form of understanding of how we will attack it. You might be asking, why are these logistics important? In say enterprise software cracking, you may need to remember sets of data, organize information, organize target information, and plan out everything that you want to target. Since this is not enterprise software and is just a very simple protection against it, we can see how it works. Logistics help in many areas, in this case even if we are not directly targeting enterprise software or targeting larger systems, it is still good to practice mapping out our game plan to better exercise logical processing in our head! If you are new to this sort of thing, it may help you collect information and understand exactly what we need to do, and execute it without an issue. So, since most of this is logic planning, I will be going over a few bullet points and sub-sections that will all talk about what we can expect from this program.

Drawing Out A Plan → Mapping everything out

When it comes to software cracking, every single bit of knowledge about our program seriously will help during the cracking process. Right now since we are in the first stage of things we need to directly understand exactly what our program is and what it is supposed to be. Currently, we know the following.

→ The developer: We know that the developer stole the same source code from us and knowing how petty and baggy about it he was we can infer that he directly was not good at what he was doing especially given he went straight to trying to sell it and push it to production after switching just a few things 5 hours after stealing it. This information can help us seriously narrow down our target.

→ The cheat was in testing: When taken, the cheat was barely even able to be pushed to prod or even beta testing as it was just a very small experiment. Since we are going to be trying to black box this scenario we will say we know nothing about the program other than the fact that it was stolen and it was in testing. Knowing that it was in testing and then immediately pushed to production 5 hours later helps us understand that our target is BOUND to have a few weaknesses inside of it and is not very well protected. ( Time is everything in RE and inspection ).

→ The target came from the game cheat community: I typically never talk like this but I will say from personal experience I know that about 90% of the game hacking community is filled with people that open-source game cheats or people that take open-sourced cheats, paste them and release them into production with barely any security. This means that the code they are using may be outdated and still used, a driver may not be exploiting things properly or hidden properly, debug information may be active, text might not be encrypted and everything might be seen at runtime using specific utilities. We also know that based on some videos and demos and base knowledge of private game cheats that this exploit 100% includes some form of licensing especially if they are checking it.

Because of this information, we can start mapping everything out, now what we need to do is say exactly what we are looking for before even opening the program using the examples above as a base for building our attack plan. Keep in mind that all of this can happen within seconds if you know the person or thing you are targeting. So now we can move on to our secondary step.

Drawing Out A Plan → Advancing The Knowledge

Now that we have collected a base of information about our target and our knowledge we can now pull what we are looking for together. We know that the system is going to use some key authentication which means two things; the program either uses some form of user input either through a CL or GU interface or is accepting command line arguments. Typically, these programs are GUI based and are one click for users given that it is a cheat for people that also may not know much about piping and command line arguments. I can also infer that this system is going to be popular, it may be keyauth since that is popular but maybe some of the other mainstream authentication systems. Either way, we can expect to find some form of network activity because anyone who programs a built-in login system HAS to be out of their MINDS to be doing that. Not to mention that APIs like KeyAuth allow programs to fetch hardware information of the client, grab the IP address, Network Type, and so on from there. Now that we have this base knowledge we can lay out the following of what we are looking for.

  • API Secrets / API Activity: In some cases, we may be able to find network activity or some form of connection-based activity with an API during dynamic analysis. You might be asking, how can we test that? Given this is a client-based exploit and is a program that only runs on the client side and is for an online game we can assume that the developer does not expect people to use this exploit or program offline, thus allowing for the idea of forward connection. If there is an API then that means there is an API license present somewhere in the program or with a remote location. If the application does not have the correct security measures or does not implement HTTPS we can assume that we can use a set of tools like WireShark or other programs to sniff out data during runtime and test specific environments. For example, if we try to sign in without a network connection and the license we used is valid, this means that it is most likely using a singular API but if it works just fine without a network connection then we know it’s NOT using an API. This ALSO means that when we go to our static analysis step of the program we can try to look for API keys and software licenses and even look online for demo license keys to match them with API providers.
  • PlainText Debugging information or General Output: When collecting user input, the CL or GU interfaces are bound to be using text to notify the user of what the application wants. This is simply just basic UX design. So, when we go to debug, dump or analyze the binary we can assume there might be some text that is not correctly hidden such as the console log and message for text. You might be asking, why are we even looking for the message put out by the program to prompt input? This is because when using languages like C++ or even libraries like ImGui for C++ we notice that typically before std::cin (C++ input call) or ImGui::Input ( ImGui user input box ) is called there is usually some print statement or output statement or call like ImGui::Text() that lets the user know what the input is asking for. If we can directly find the location of this text, we can assume that directly after that call or a few lines after that the function is being set up to call user input and then capture and parse the user input. When we go to this line in our disassembly we can track down the function that is comparing the result of some API or user track or even key length for requirements.
  • Security Mechanisms: Now we know our target is most likely a person that doesn’t know what they are doing, but those same people know how to paste properly so we can assume that this person might have gotten some form of knowledge behind their belt about securing applications or maybe even used ChatGPT to auto-generate them a program that prevents debuggers. So, we are going to try to activate the program and then check for security mechanisms by opening up applications like X32/64DBG, ProcessHacker, ProcessMonitor and if they trigger or trip a security mechanism then we are just going copy the EXE file for those programs and just rename them as there is a high chance the program is going based on names rather than brute forcing every process ID and checking what it’s doing.
  • Error Systems and Debug Information: When we get to test the application, one primary thing that will help us better analyze the binary and the systems inside of it is understanding its error systems. In this portion similar to the process of binary exploitation, we will be testing random junk, pushing a bunch of random characters, trying numbers only, and going based on sets of characters. We want to try and purposely trigger the error system so we can get used to some specific message that may be static in the application or more advanced scenarios we may see a customized code system that tries to compare the error in a map and return the message associated with a code. At the first step when logging in we can imagine that the cheat itself is going to get the values and error messages from the API provider. This is because the API provider may already have its custom code system and may just return a status.
  • External Environment Activity: This is a huge one in more advanced scenarios, we will be trying to see if we can find any other information within the application by just listening to what the process is doing outside of itself other than networking as well. Since we are already expecting an API to be used, we may want to look to see if it’s writing to a file, making controls, or doing something with our OS. This will help us analyze any other files that can give us a bunch of information on the application or maybe even something that can help us crack it easier!

Now that we have everything laid out for what we are looking for, we can now deeply construct some form of attack flow to look at this binary which is our next step.

Note: I just want to clarify that you do not always have to go this deep into making a game plan for something as simple as this. By this time of creating a plan I already knew what I was going to crack, for the sake of this module I wanted to include it in here to actually give you some decent world experience and explain that sometimes; game plans can seriously come in handy! The next step will require a notepad or some form of thing to write on- I will be using a whiteboard.

Drawing Out A Plan → Finishing The Full Plan

Now, I am going to organize this plan a bit differently and rule things out completely in graphic form. So lets start with the sub things of what we are looking for. Each bullet point will remain a new path of drawing along with a photo result.

  • Task List / What we are looking for: We mentioned that we are looking out for multiple things which is Login Systems, Error Systems, Error Messages, Text, Output, Debug information, Network Connections, External resources and so on from there. So I will take to the right side of my whiteboard and place the task list like so.

With this in hand, we now have a decent task list of what we are looking for. At any time we need to look back we can knock off what we have already seen in the application or look back on what we have not seen yet.

  • Flow Chart / Road Path: This is going to be much more visual, it will basically take everything and map it all out- more or less an attack flow. Something that helped me in the field was to predict what I was going to come across and then think of everything bad that could go wrong- errors and then create a path based on what I was doing to counteract those errors. For example, say I am working on a bigger software crack than this, I predict that I am going to run into some form of security against debuggers. That being predicted I would then say okay if I actually can use a debugger let me just look for a few things and if I cant then lets try to open process monitor, create a dump file while running the application and disassemble it in IDA or some other RE framework and if that doesn't work take a different control. This type of understanding and logical processing helped me a ton when working with applications and is why I was able to crack specific applications on a very simple level a lot more quicker than just generating a road path then. Think of our brains like one giant conditional block, we can re program ourselves to generate more conditional statements that act based on a condition being true or false. In this case, below is an example of what I was able to draw with this game plan.

I figured I would try to add humor so I called it “Schizo crack” for fun since this was also one of the fastest cracks vie ever made on a game cheat before. As you can see there are two road paths all set for their own thing and what I was looking for.

  • Dynamic Analysis Road Path: The dynamic analysis road path will be the first thing we attempt to do on the actual application. This will help us identify the systems within the application. You may notice that on that side I am going to look for status strings, or some form of output that would resemble a status mark, status code, etc. I assume status just because keyauth applications or applications alike will always have “Status” this is just an assumption and nothing more. The second thing I expect is going to be user input.
  • Static Analysis Road Path: The static analysis will include opening debuggers or specific frameworks to statically analyze this program and what its doing on the inside. You can see the first top most thing I pinpoint is that IF there is no anti debug system, to continue searching for the highest most likely thing which in this case is plain text information. If a application has no anti debug there might be a high chance that we can use that debugger to analyze any secrets we might come across. If we can not find raw text then we shoot to the secondary most likely thing which is to check for any form of security. If there is no actual application security that would halt us from opening hex editors or other frameworks then we can analyze it during run time with applications like HxD and search for API secrets, API endpoints that the program may be using and in the case of a debugger we would analyze compare statements. Then going back to the road we have our next step.

You then notice that they all actually go deeper into the final stage which is cracking the application and possibly using information from both stages of analysis. Now that we have everything drawn out lets actually go to the final step.

Binary Security | Cracking The Program

You might be asking why this is counted as a direct section of this module, but I figured I would separate it just because of how detailed this section might be. Either way, lets stop talking and get into it. We have now talked about everything we need to look out for, explored routes and different ways hackers can defend against other hackers, so lets actually attack this program and see what we can do to it.

  • Dynamic Analysis: The first thing we need to start it actually look at the program inside of its live state, lets see how the program works and what it is currently doing.

Upon opening the program we get this output.

Okay interesting, the program says its connecting but what exactly is it connecting to? There could be multiple things going on here so lets actually see if we can cut our internet connection and execute the program.

Huh, when cutting internet connection from our program it seems that the program is actually seriously trying to connect to something. This program once it receives an error will start a timer and then instantly output the primary issue. Lets go deeper into this and see what we get when we enter a license name. For the testing purposes of this program, even though I have a valid license key I would like to mimic a situation where we only have access to the loader.

Okay, so far we have a few things to note.

  • The program is obviously accepting user input
  • The program is validating licenses
  • The program has an error system for the users

This doesn't tell us much right now, but lets see if we can overflow it. Right now I am not searching for a buffer overflow, while this is possible we are focusing on just testing what we can find and if this is being passed to an API provider then from there we can actually assume more information about the program. For this scenario I am going to throw 1,000 ‘A’s through the input and created a simple go program to generate it.

package main

import (
"os"
"strconv"
"strings"
)

var data int

func init() {
data, _ = strconv.Atoi(os.Args[1])
}

func main() {
println(strings.Repeat("A", data))
}

Our output we get

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

when we feed this into the input the program shows us the following.

Right, our program doesn't overflow which means its input is not being stored improperly but most importantly we get something that can give us more information on the system. The key MUST be shorter than 70 characters and would you also notice that the Status: is the exact same. This can verify one of two things.

  • 1: The program is actually using a API provider for authentication
  • 2: The program is just using the same status message over and over

1 is more likely because typically an API response is just specific requirements the API wants and sure the program could be checking it but the factor that “status” is typically used to show the response status of a specific request but also how the program says “Connecting” AND requires system commands shows a ton more about the program. I want to also note that after trying not only the letters but just numbers, a mix and pattern of numbers, commands etc. This all can verify that we just are passing this to an API rather than using it to run a system command or something weird like that. So far we have actually knocked a few things off the list here, we have found that there is text and output to check for, we know there isnt a direct error system but a status system, we know the program requires network connection but we have yet to check security systems. If we open the debugger like X64 DBG and load the program into the debugger, here is what happens.

Jeez- not even a single warning and the program refuses to quit as well- man what kind of security does this program even have? None. This is actually a good thing because instead of trying to analyze everything within memory we can go ahead and inspect everything. My first instinct given that there was text based output is to look for all string references and find some form of data. When we go to our string references in every single module, this is what our debugger gives us. We can now actually move onto our next step.

  • Static Analysis: Since we figured out we can open a debugger, we can now actually figure out some other unique things about this program!

To major things I found that were already a MASSIVE win for me hahaha. Lets see what we have here when we zoom in in case you cant see directly.

We have some information that can be extremely useful here.

  • 1: From my experience, that key and set of characters and numbers there seems to be an API license or key for what I can only assume is keyauth.
  • 2: We now know the program is 100% using an external API for its login system and we know the name as well.

what can we do with this information? Well from my knowledge I am 100% sure that is the license or API key the developer was using for keyauth but before I do so I need to verify this. What we can do now is go to google and search up C++ code examples using keyauth which gives us the following results.

When we click on the REPO and start reading the ReadMe file we can 100% verify that the person who wrote this cheat NOT ONLY pasted code and set it in production but also used keyauth and that is his API secret because when we go to the README we can see this block.

This image shows us that he used the same \n Status: message and did use his own application secret or the token for the API WHILE ALSO storing the ownerID in plain text! What that's crazy! We have yet to even crack the program but was able to get ahold of license information.

We can verify that this is the same information used when we see this

42b9ce3abd23da997c560b99c8f7318c9a81a1a51439828++++++++++++++
31XNZxg+++

and we can compare the length of the keys and data compared to our screenshot above! Now we can probably assume that we can search for input here because if this person is willing to just store everything in plaintext then they are definitely going to plain text user input.

And as we predicted- we were able to find the user input prompt. Now if you recall to our CrackMe challenge, we should be able to do something similar correct? You are very correct on that, but this one seems to take a different route. Lets follow this in the debugger and see what brick of assembly we get this time.

That is a very weird set of functions- lets zoom in a bit.

So looking at this code we have a few things we see that alerts us right away on the right side of the debugger. We see the enter license prompt, we then see the status message which means there is some jump telling it to compare if the status was good or valid or even bad and finally it looks like the program will make a system call system("cls") to clear the screen. This is something that will actually help us a TON when working since we know what to expect in the program. You will notice that this program is much more different than the crack me we did before. Instead of just comparing the key and license directly this program is not only setting up a backend API function but also calling for standard inputs and calling hundreds of different functions. So how will we go through this? Well, if you recall from previous cracking, we always went below the output of the input and checked there first but remember, our program here will ONLY CALL AND OUTPUT Status when the input is successful. Right away you may also notice we see a few sets of assembly conditions which the most noticeable one is

00007FF6CA5F0E44 | 75 35                    | jne privatefortniteexternal.7FF6CA5F0E7 |

right before the Status message is called. A cool feature with debuggers like X32/64DBG is that we can hover over the bricks and click on it. For example, if we hover over a function call like the one shown below

00007FF707970DF6 | E8 1593FEFF              | call privatefortniteexternal.7FF70795A1 |

we will get the following output from the debugger in a small pop up window.

For the sake of the article I just double clicked on the function call but hovering over it will also produce a good result. In our case, we are going to assume that a user like this based on their behavior is more likely to actually make the input call RIGHT after the prompt is put or a few lines after. The output and trace in the debugger of the first function called is also similar to other input calls that if you recall we have seen before. Of course this will be fluid or change all throughout the development as there are hundreds of different methods to grab input but its a good starter to look out and check functions after. If we go to the next function below and the second call and trace it we get the NEXT output.

This output is much larger than one might expect but since this is a bigger scenario it only makes sense. This is hard to walk through so lets start with the most obvious factor. Since we are looking for some form of condition here after the input, we spot multiple call functions then a je or jump if equal condition at

0x00007FF707959A1C

this seems to be calling another function. Let’s think about this a bit more logically and just branch this out in our heads. Say we have a brick of input that then calls another function, what can you imagine that input block MAY be doing after the input is called? We have a few things.

  • Checking Specific Requirements: If there is a specific requirement a provider such as an API provider may be working on then the developer might check that as well. They might also check the type of Unicode, they could also chomp specific values or cut values from the string if they are considered malicious and a bunch of other things.
  • Passing it directly to the API provider: From our current knowledge, the application seems to be placing the status message saying if the key is too long if the system requires specific character sets, and more. We can assume that the developer might just directly be calling a function on the backend for the keyauth application which would indicate that they are passing it directly to the API provider.

Now, there are a few steps we can take here. Right now, I can only assume that the person who wrote this cheat is just calling the backend code which also tells us that the jump if equal loop might be a status check. How can we verify this more? Well, we can go back to the key auth repo and we can check the source code for any occurrences of a Boolean value. Because since there was no initial cmp assembler call or any form of data compare we can assume that the developer is checking or possibly checking a Boolean value. If we go to the repo, the same one we went to before we can come across this code snippet.

 std::string key = ReadFromJson("test.json", "license");
KeyAuthApp.license(key);
if (!KeyAuthApp.data.success)
{
std::remove("test.json");
std::cout << skCrypt("\n Status: ") << KeyAuthApp.data.message;
Sleep(1500);
exit(0);
}

This is a good code snippet because it shows exactly what we figured! Because we can see that this program checks a Boolean value which is the data.success which actually means that we can verify that the JE condition in the function we viewed might be something we can patch. Lets try something real quick. If we go and patch that to jmp lets see what happens.

The instruction was also properly encoded which means that the instruction is valid and we can go ahead and save that and patch the file. When we save the patched file we get the notice saying there was 4/4 patches made successfully!

When we go ahead and run the EXE file and try the same process of just entering an invalid key we may possibly see the following.

Now, we notice that the patch has actually worked but not in the way we want it to work. Remember we are trying to bypass full login and after the status returned to be the API status failing, we seem to also have tripped another system which means we are not exact on the point we needed to patch. If we look back to the original trace we might actually be able to bypass the system. If we recall going back, we actually missed something when exploring. If we go back to the original user input location in the disassembly we can see that there is another jump statement / condition.

In this code at the address section that ends with 70E44 we can see a jump if not equal and then from that jump on the far left see that it jumps to a CLS system command. By now we can assume the code looks something like this.

user_input = std::getline(std::sin, "Enter License");
KeyAuth.App.Init()
result = KeyAuth.CheckLicense(user_input);
if (result != false) {
system("cls")
// execute other function calls
}

Of course the code is going to be much more different and structured but thats a good idea at least. So all we actually have to do now is patch that sneaky little JNE instruction to a jmp instruction so no matter the status it will continue to go forward.

Ah yes! Our jump statement was encoded successfully! This is great for us. Lets see if we can try to repatch the file and see if we actually bypassed the login system this time!

Patch, and now execute!

AWESOME! Hahaha even if we made a small mistake we were still able to easily crack this exploit and bypass login requirements as far as we know anyway. Now in a more realistic situation, we might have to do more and check if the cheat works without using a valid API login but we will get into that in just a second.

What exactly can we take away from this? What mistakes did the developer make? Why was it so easy? Let us hit those bullet points one by one.

  • Mistake 1 → STRINGS: One thing we heavily discussed was the use of strings and how bad they can be if we are not directly picking anything up. One way the developer could have made it hard for us was to encode strings or use specific algorithms to better hide the strings so a debugger could not find them as easily. In this case, he could have used the ASCII encoding and decoding technique we mentioned before but even that would be easy to bypass as we also talked about and will explore in another article.
  • Mistake 2 → No framework/application protection: Another thing that made this application easier was the fact that we were EASILY able to just pop open a debugger. The best security would tell you to close the debugger ( like EAC, BattlEye, etc anti-cheat systems do on games ) before you can use or execute the program properly.
  • Mistake 3 → No code was obfuscated or even hidden: Now of course, everyone might not go through this trouble but using a packer or some form of code obfuscation is going to help people like this ALOT in the long run.
  • Mistake 4 → Using the same system to output the status of a failed API response: If the developer was a bit smarter they would have a custom code system to prevent users from easily being able to piece the logic together on where exactly their errors are coming from.
  • Mistake 5 → The developer hid secrets within the application in plain text and also just tried to place them or hide them in the applications: Typically, it is much safer to store a set of keys such as API keys, License information, application secrets and more on a remote CDN or server that has to go through a series of its authentication before being executed.

These are all major takeaways, but, I won’t go anymore deeper than I already have on this end of things so let’s end this article and stuff some more info in your brain XD!

Binary Security | Real World Cracking && Conclusion

The program in this article we cracked was a bit more real world, it wasn’t enterprise software but it was definitely real world and is sadly something I see every day in the field. It might also not be cracking game cheats but also cracking black hat frameworks, simple C2 servers, and even private programs that want to charge you a ton. Other times I may come across a cheat that is quite well-packed, well-developed, well-written and well secure but even the developers still manage to make mistakes. Take the following security mechanism for example.

When I was debugging a cheat I saw this ENTIRE list of debug information and also saw this giant wall text of system commands that looked like the one shown below.

This cheat I exploited here recently and with the simple runtime viewer was able to view all of the strings. What are the issues here? Well, the set of commands is killing any process with a name that starts with the specified name such as “taskkill”. The /FI flag is used to specify a filter for the taskkill command. The /IM flag is used to specify the image name (process name) to terminate. The /F flag forces the termination of the process, and the /T flag terminates all child processes started by the process. The >nul 2>&1 part redirects the command’s output to the null device, finally discarding any output or error messages. This is okay security and it makes sense why someone would think this would stop me but why wasn’t it stopping me? The issue lies in the fact that they are killing the process by name. C++ has a TON of built-in features that allow you to build your protection system where you essentially just take the current application, start a thread and check if anyone attached a debugger to the process, wrote or read memory to the application externally, or is using other external processes to send data to your application. This would be much more effective than just running a system command plus there are many different issues that come with this. Real-world cracking may include other systems as well and I have seen some- intense systems but in the end, they all can be bypassable if you have the right skill. In other cases you may not be able to fully break the program instead you would have to build a keygen if everything was hardcoded into the application and take a million different routes. This all can be quite confusing for someone but that is what most of your real-world cracking. Mostly boiling down to protecting and bypassing those protection methods for instance the one above I would be able to just copy the .exe file of say X64DBG and just rename the tool and then run it and POW it would just fine as it did in that case. You may also notice that real-world software cracking comes off quite frustrating at times where it can take you weeks to crack the application, but remember, similar to what we did here, you may be overlooking and over thinking a specific situation, and in other cases you may need to overthink things.

This article spits out a ton more than you were expecting but I also feel that it would be cool if we could slowly build up to real-world cracking I even have a few frameworks that are being illegally sold that I could crack and reverse without any issues and go deeper into different protection methods used by developers especially offensive developers. I also want to mention that everything done in this post was completely ethical and legal. The source contained an exploit for a specific game company and game and it was then up to us to crack the source and prevent the user from selling it which we did. In the end, the person that sells this cheat will now be completely out of money the second he tries to sell it and may only be able to get a few hundred out of the few grand if he sold to more users especially if his program becomes cracked.

--

--

Totally_Not_A_Haxxer

Cyber Security Educator, Developer, Social media manager, Author, youth education, content creation, engineering, ui/ux, RE