Overthe past few weeks, I've seen a lot of discussion about whether or not the Epic Games' store is spyware. Unfortunately, the "proof" and "research" that has been shared is far from either of those things, and can only be described as an amateurish perspective. To clarify, I'm speaking about the technical analysis that's going around, and will not touch any legalese such ToS, EULA, and so on.
Now, don't get me wrong: I'm not here to hate on the analysis, dunk on poor understanding, or call out those that are, rightfully so, concerned about their privacy. To that same note, I'm not here to defend Epic Games. In the spirit of Mueller: this report does not exonerate Epic Games.
Instead, what I want to do is communicate just how much nuance goes into this type of research. It is very important to be thorough, and conclusions shouldn't be drawn by such high-level assessments. For that reason, I will expand on the research outlined in the Reddit thread, digging into everything on a much more intimate level so that everyone can have a better understanding. I will get pretty technical, but will do my best to put everything in layman's terms.
On the note of thoroughness, we come to why this won't be an exoneration: to say that there's nothing fishy going on would be to do a very, very in-depth analysis of a huge program. That would take hundreds of hours, and I don't have that. As I dig into the existing research, you should begin to understand exactly why this is the case.
Before we get started, let's talk about why you should trust my analysis. First and foremost, I don't have any bias: I don't play any Epic games, I hold no assets associated with them, and I have no interest in the current battle of exclusives going on between game stores. I also have no reason to dislike them.
In terms of credentials, I actually wrote the book on hacking games. Additionally, I have professionally worked on antivirus software for over 6 years and have an intimate understanding of malware analysis, malware detection, and reverse engineering.
Procmon doesn't inject, it intercepts events from inside the Kernel. Essentially, that means it tracks events from within the system's underlying infrastructure, and does not directly cause any behaviors inside of monitored user-mode programs. That means it is EGS doing enumeration, but that's not necessarily a bad thing. We'll get to it.
The very first thing to establish is that CreateFile doesn't necessarily create a file. It is simply how you open a file. We can even see Desired Acess: Read, which implies the code is only trying to view the file; this call isn't able to create or modify it. We can also clearly see the result NAME_NOT_FOUND. The file doesn't even exist.
This happened because EGS tried to load a library and Windows was attempting to locate it. Windows looks in various locations when loading executables or libraries. First, it checks in the calling process' working directory. If it's not there, Windows checks every directory in %PATH%, which is an environment variable containing a list of user-specified directories. The directory C:\fiddler\ is clearly in this user's %PATH%, and this event is simply part of the search for Shcore.dll. Yes, it is common for Fiddler to end up in %PATH%.
This person seems to think there is some significance to the Fiddler part of this, since that's an analysis tool he's using. Rest assured, however, it's simply a coincidence. This happens a lot, and we'll see it again with Procmon.
Secure communications are carried in part using asymmetric cryptography. This is a type of cryptography where there are two keys: a public key and a private key. The private key is only known to the server. Messages can be encrypted with this private key, and then decrypted by anybody with the public key. These keys aren't actually used to transfer data, though; symmetric cryptography does that. They are, however, used to establish identity before agreeing on a symmetric algorithm and setting up its keys. This identity establishment works because your computer, my computer, and most people's computers contain a list of trusted public keys. Only someone with a private key can generate a valid message for a given public key, and thus the whole system works. Rather than have millions of trusted keys, though, everything is set up so that we only have to trust a handful of Certificate Authorities. With their private keys, they can mark a public key as trustworthy, thus creating a chain of trust. It's a bit more complicated than this, but not much.
Knowing this, we can reasonably say that accessing the certificate store is a good thing. It means an application is validating who it is talking to and properly encrypting messages. This behavior exists in all modern browsers, and we can see that a browser is actually what's causing this:
Without getting into too much detail right now (don't you worry, we're gonna discuss exactly what this is later), this shows that the certificate events are happening through libcef.dll. That is CEF, the Chromium Embedded Framework, a library that can be used to embed a Chrome browser frame inside of an application. Epic is using this to have a portion of their UI deployed as a website. We can also see that the certificate store isn't even directly accessed by CEF. Instead, it is accessed by crypt32.dll, which is a Windows library for doing all sorts of cryptography.
I really hope that first bit is sarcasm. It is actually very, very common for applications to talk to themselves like this. This is what we call IPC, or Inter Process Communication. Software is becoming more and more distributed: multiple threads, multiple processes, and multiple machines. Yet these things all must communicate. Because of this, IPC mechanisms have become easy to use, fast, and stable. Even when speaking between threads in the same process, it can be better to use established IPC mechanisms as opposed to developing cross-thread messaging. There's nothing wrong with specializing inter thread communications, but if you have IPC already, there aren't really any disadvantages to repurposing it.
This really demonstrates the naivete of the poster. One tip I have for any aspiring reverse engineers: unless you're a relentless self-skeptic, learn to code first. You can tear apart an engine, but you'll end up confused if you don't know that oil lubricates and gas is combustible.
I use Pi-hole to stop all tracking and ads. It does this by essentially giving an empty response to DNS queries for known trackers and ad networks. Epic isn't on the blacklist by default, but custom blacklists are easy:
If you don't really know how Windows works under the hood, this prodding of Procmon may seem very sketchy. However, let's dig a bit deeper. If we double-click on an event in Procmon, we get a window with details. Within that window, there is a tab which shows the call stack. This is the chain of functions that lead up to the call being made, and can give us a lot of context:
A call stack is read top to bottom. Imagine Alice wants to know where Bob lives. Alice isn't sure, so she asks Paul, who checks his contacts to get the address. Paul then passes the address back to Alice. If we made a call stack for this event, it might look like this:
Paul may know a lot of information about Bob, but the only thing ever passed back to Alice is his address; Alice can't really peer into what Paul is doing or seeing without a lot of trickery.
To restate: after AliceAskPaul, everything is out of Alice's hands. What Paul does is up to him.
Additionally, when we talk about code, we use the word call. In this example, a call would be Alice deciding to ask Paul, then her Asking Paul, and so on. It is the invocation of a function.
In our case, EGS code loses control after frame 12. After that, what happens is up to QueryFullProcessImageNameW(), which is part of Windows. If we look at the documentation, we can get an idea of what's going on:
Effectively, this says: give QueryFullProcessImageNameW() a process handle (hProcess) and it will give you back the file name (lpExeName). Now things are becoming more clear: EpicGamesLauncher.exe doesn't even know that this is Procmon. That's literally what the code is asking Windows: "I have this process, can you tell me what it is?". All of the other things, including the event in question, are implementation details.
Next, we need to understand why it wants to know the process' name. If we dig into the Procmon trace, we can see that it's actually just looking up the name of every process. It's not targeting a specific process, not at this point. Once again we're left asking a question: why does it want to know the names of all running processes? Believe it or not, this is surprisingly common.
Note: when I say this is common, I mean it. Though it may not seem like it, there are so many reasons why programs do this. It's not a big cause for concern, and can't be leveraged for much value.
I'm still going to dive in to this, but not because I want to prove there's no wrong here. Rather, I think it's a good way to illustrate what analysis actually looks like. A good way to show that you can't just take a Procmon trace at face value.
Let's dig deeper. At frame 12, we see that the process scan is happening at PrintScriptCallstack + 0x60538. It may be tempting to assume that the code is printing some call stack of it's own, but that name is just a coincidence. The offset of 0x60538 is quite important. The number is quite large, which means the real code is unlikely to be a part of the function PrintScriptCallstack(). Instead, PrintScriptCallstack() is simply the nearest meaningful reference point that Procmon had for the code.
Except in certain cases, you don't ever get the actual code of a program running on your computer. Instead, you get what is called assembly code. This is the result of a compiler taking human-readable-and-writable code and transforming it into something a computer can execute. Thus, if we want to analyze this program, we use a tool like Binary Ninja to disassemble the machine code.
3a8082e126