Over the past few years, we have seen an increase in the number of macOS environments we are asked to assess. While PoshC2 has “supported” macOS by way of Python since the very early days, increasingly Python support is changing in macOS. We wanted a way to run an implant that would be native to macOS, independent of the version of macOS in use, and would give more power than just running Python scripts. So, after months of development, we’re introducing JXA implants in PoshC2.

What is JXA?

JavaScript for Automation (JXA) is a scripting language in macOS which is a peer to AppleScript. Introduced in macOS 10.10, JXA enables writing scripts in a JavaScript format, but allows for interacting with Objective-C via an Objective-C bridge, bringing full C support within a scripting language.

Unfortunately, documentation on JXA is scarce, but there are a few sources to get you started learning the basics of JXA. Check out Apple’s developer site and the JXA-Cookbook.

JXA allows us to run on macOS environments from 10.10 (Yosemite) all the way to the latest release of BigSur (11.2).

PoshC2 + JXA

A new implant type has now been added to PoshC2. When starting your PoshC2 instance, you will notice the dropper_jxa.js payload added to the project payloads directory.

This dropper is our stage 1 and when run on the target it will reach out and execute the core implant functionality. The dropper contains the code needed for performing encryption/decryption, the check-in URI, and also performs some basic checks about the user and PID the implant is running under.

How do you run this on your target? I’ll leave most of that up to you, but one example is that JXA can be run by using osascript, a signed Apple binary used for running AppleScript and JavaScript code. osascript -l JavaScript dropper_jxa.js will get you started, but if you are interested in learning more about macOS tradecraft and executing on targets, stay tuned for our macOS whitepaper.

Once executed, you should see the implant in the PoshC2 Implant Handler.

Core functionality will allow for running basic shell commands, changing the beacon time, uploading and downloading files, and clipboard monitoring. As with all other implant types, run help to see a list of commands.

Some features of note:

  • beacon (set your beacon time)
  • clipboard-monitor (monitor the clipboard for changes for a length of time and return all strings)

  • upload-file / download-file (upload and download files)
  • Shell commands (any commands run on the implant that are not built-in commands in PoshC2 are run as shell commands. This will spawn /bin/sh to execute the command)

  • run-jxa (my favorite feature. See below for details)

We wanted to make sure that, as with the C# implant, the JXA implant is easily extensible and allows for you, the operator, to be able to add your tools without needing to re-write the server.

What this means is that if you have a favorite JXA script that you would like to run, you can simply drop in the resources/modules directory of PoshC2, then execute the function you want to run. An example of this is HealthInspector, by @its-a-feature. HealthInspector is a great script to perform situational awareness on a macOS environment. There are a load of functions within the script, but simply running run-jxa HealthInspector.js <function> you can obtain a ton of information without re-inventing the wheel.

Take a look below for a list of some of our favorite operational JXA scripts.

JXA Scripts

Defensive Enhancements

To ensure we empower our blue team friends, the following are some Indicators of Compromise (IoCs) specific to JXA implants.

Osascript spawns /bin/sh

When running a shell script within JXA, osascript spawns /bin/sh as a child process. This can be seen with Patrick Wardle’s Process Monitor app (https://objective-see.com/products/utilities.html#ProcessMonitor).

Running osascript to execute JXA scripts

Our initial dropper running using osascript could also be seen as an IoC. This is very much dependent on the environment, as JXA is used for legitimate purposes. If your organization does not use osascript, then checking for execution of osascript -l JavaScript as part of the command may help find malicious activity.

Also be sure to check out all the PoshC2 Indicators of Compromise (IoCs) at https://labs.nettitude.com/blog/detecting-poshc2-indicators-of-compromise


Apfel was used as inspiration for creating the JXA implant. We’d like to give a big shout out to @Its-a-feature and the developers of Apfel for the great work they’ve put into that project. We particularly found their approach to encryption and decryption useful.  Since documentation is scarce, Nettitude used some Apfel code to understand how these tasks would be performed in JXA to apply to the way that PoshC2 handles encryption/decryption. Apfel, which is part of Mythic, can be found at https://github.com/its-a-feature/Mythic.


With the addition of the macOS JXA implant, you can now use the C2 you know and love to operate against any macOS target. Grab the latest version of PoshC2 from https://github.com/nettitude/PoshC2 and give it a spin. As always, if you encounter any issues or have any suggestions on improving PoshC2, submit a ticket on GitHub or come chat with us on the PoshC2 Slack channel at https://poshc2.slack.com.