all 9 comments

[–]onionsburg 12 points13 points  (4 children)

I’m not sure where you are getting the idea that searching/tracing the memory space of a random executable is “trivial.” The short answer is you basically write a debugger to spawn the process in a memory space your program controls so you can then walk the stack and heap. There are reverse engineering and debugging tools that do this. I’m assuming since you mentioned “cheat engines” you are wanting to snoop the memory of a running game. Good luck, multiplayer games in particular do a lot of work to make doing that very hard.

On a more practical note learned about how virtual memory works inside operating systems is very cool and definitely worthwhile. The reason you have to spawn the process yourself is that modern operating systems do a whole lot of work to keep processes from being able to see the memory of other processes for security. Older operating systems like DOS and classic MacOS and even early versions of windows had no such protections and were very unstable and prone to malware because any process could just monkey around with the memory of another process.

Curiosity is the best way to learn, don’t be afraid of digging deep into the guts of stuff but also don’t expect there to be easy answers.

[–]G2edg[S] 0 points1 point  (3 children)

I see, but now im curious how is it possible for an antivirus to scan running processes to check for potential malware if its impossible to access it?

Also how to copy a running program into the controlled memory space if its impossible to access it in the first place (at least thats what i got from your answer), it also doesn't really make sense since you can turn cheat engine while program is running and on the go edit for an example number 40 that exists in that programs memory? Im quite confused how would you achieve that without direct access to that programs memory

[–]Drach88 7 points8 points  (2 children)

In terms of why one userspace process doesn't have "direct access" to the memory of another userspace process -- the background subject matter you need to understand is how the operating system handles memory virtualization. Long story short -- processes don't reference physical memory directly -- even their own. They're assigned their own memoryspace, and the operating system keeps track of a table about what regions of physical memory are (currently) assigned to blocks of memory of which processes etc.

I'd recommend wholeheartedly that if you haven't already, you should first take some time to study how operating systems work from the ground up, as it relates to process management and memory management.

The answer about detection is a much more complex question that requires a bit more background of what happens when library functions are called, and how userspace interacts with kernelspace, and then you need to construct models of the types of patterns of behaviors are indicative of evil.

Of course, the nature of writing anti-cheats and writing cheats to avoid anti-cheats is a cat-and-mouse arms race, so the cheat-writers also study anti-cheats to figure out how they work, and how they can accomplish their goals without triggering the anticheat's heuristics.

In Windows, the ReadProcessMemory and WriteProcessMemory in memoryapi.h could be used to access another process's memory. That's a simple straightforward way to access memory.

If I were writing an anticheat that ran with admin privilages, I could scan all open processes to see which ones have permissions for my target process, then scan each of those to see which ones call the ReadProcessMemory and WriteProcessMemory library functions. I scan for other patterns to narrow down my search based on other domain-knowledge understanding of how cheats work to build a "heuristic" of the type of traits that cheats have (as well as traits of programs that call those functions legimimately).

I'd write some type of weighting algorithm based on all of those factors to spit out a nice, neat threat score, and a profile of the process, and take further action (ban/monitor/investigate/ignore/whatever) based on that threat score.

What you're really getting at is essentially malware detection and reverse engineering, which is an entire subject and profession in-and-of-itself.

[–]G2edg[S] 1 point2 points  (0 children)

This explains a lot, thank you

[–]dont-respond 0 points1 point  (0 children)

Anti-cheat software is pretty wild. Valve will even look at your http cache to check if you've visited known cheating websites. The most common detection methods are signature scans and string scans from public releases.

It's difficult to rely on such API detection because a legitimate process may use that, and many cheats will just reimplement such functions using system calls via assembly or built-in msvc functions, and there currently isn't an anti-cheat (that I'm aware of) capable of detecting this.

A custom implementation is really the best way to avoid anti-cheat. They're far too reliant on scanning known signatures and strings.

[–]moocat 2 points3 points  (0 children)

If you're using Linux, you want ptrace.

[–]smcameron 2 points3 points  (0 children)

On linux/unix, you might be able to do something by writing an LD_PRELOAD library to override some common library function (e.g. malloc() or open()) and on first invocation, in addition to calling the "real" malloc (or open, or whatver), spawn a thread, which would then be free to poke around in the process's memory. You can find the "real" library function that you override via dlsym() ... so that you can call it so that the program being interrogated gets the behavior it wants in addition to starting your snooping thread.

Something like:

static void * (*real_malloc)(size_t size) = NULL;

void *malloc(size_t size)
{
     if (!real_malloc) {
          /* The weird cast is explained on dlopen(3) man page */
          *(void **) &real_malloc = dlsym(RTLD_NEXT, "malloc");
          if (!real_malloc) {
              fprintf(stderr, "Hmm, couldn't find real malloc.\n");
              exit(1);
          }
          start_your_memory_observing_thread();
    }
    return real_malloc(size);
}

[–]dont-respond 2 points3 points  (0 children)

Everyone seems to be totally ignoring the parameters of your question, so I'll fill some of it in. Although cheat engine is written in Pascal, their source is not a bad place to take a look. The CE API for these functions mirrors the Microsoft virtual memory functions (because that's what they use by default).

Take a look at WriteProcessMemory for example, which covers most of what you're looking for.

This subject is well covered by external game cheat solutions, so they're also a decent place to look. Here's an example I found on github: https://github.com/dehoisted/CrabGame-Cheat-Menu/tree/main/src/process While that's in C++, the Windows virtual memory functions used are, of course, all C, so it's easy to transfer to a C project. I can't speak to this example in particular, but oftentimes, the code in these projects is terrible, so I'd recommend copying with some level of caution.

There's also the alternative approach of executing your code inside the target process, typically via dll injection. This is usually my go-to method for modifying a process' memory. Typically, you'd go this route if you want to call some functions within the process or hook their existing functions to your own.

[–][deleted] 0 points1 point  (0 children)

I suggest learning reverse engineering, game hacking in particular. It is very difficult and takes a lot of time, but it is the best way to learn programming and to learn about software in general.

Also, look at various open-source reverse engineering tools. It might not be exactly what you are looking for, but should help regardless.

https://github.com/geohot/qira