DRAFT - Beating EDR Detections

EDR 101

Anti-virus products used to search for static Indicators of Compromise (IOC), which typically took the form of an MD5 checksum, a url, or a filename. Well, referencing the “Pyramid of Pain” of IOCs, we can see that these are trivial for adversaries to change. It’s not unknown for APTs to change attack infrastructure in the middle of a campaign in order to foil any attempt at detecting their static IOCs.

Enter EDR. Endpoint Detection and Response (EDR) software is the next-generation of anti-virus products. They look at the behavior of programs and what they do instead of what they are. For instance, instead of looking for files named Malicious Document.docx, they can instead see that when Word opens Malicious Document.docx, a macro runs that launches Powershell.exe with a Base-64 encoded command-line argument.

The Research

I recently read a blog post by Christophe Tafani-Dereeper, “Building an Office macro to spoof parent processes and command line arguments”. The post shows research from Didier Stevens and Casey Smith on modifying process memory/data structures in order to spoof not only the command-line arguments, which has been a fairly standard procedure, but also the parent process, which I think is pretty cool.

However, in my own research of this technique I found something else: the a parameter of the process filepath of the new process spawned. As noted below, this didn’t pan out, though if someone finds a way to modify this, let me know!

The Technical Stuff

The magic lies in two data structures: the STARTUPINFOEXA.lpAttributeList which is of type LPPROC_THREAD_ATTRIBUTE_LIST, and the PEB (Process Environment Block).

The LPPROC_THREAD_ATTRIBUTE_LIST type contains attribute data for process and thread creation. Typically when you use CreateProcess, you’d set the STARTUPINFOEXA variable to NULL and not worry really worry about it (other than one size attribute). However, looking at the UpdateProcThreadAttribute, there’s clearly a plethora of attributes that can be modified before creation of the process, most notably, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS. Modifiying that specific attribute to a DWORD value of a valid PID will make it appear as if the new process was spawned by that parent.

The PEB data structure contains a member called ProcessParameters of type _RTL_USER_PROCESS_PARAMETERS, which in turn contains CommandLine. Modifying this Unicode string while the process is suspended upon creation will allow you to modify what appears to be the command-line arguments without actually affecting how the process is started. Interestingly enough, there is another member there titled ImagePathName. Unfortunately, after looking into it, I couldn’t find a way to successfully modify this value.

Adding it All Together

The original blog post had all the code, but I wanted to make it into a sort of kit so cybersecurity professionals could easily use this as a test in their own environment and see what the outcome is. You can find the code here.

Written on March 15, 2019