Ready, set... hike!

The power of converting an adversary emulation playbook into a full-fledged security assessment

As the cybersecurity sleuth you are, you may have noticed that MITRE recently released a new adversary emulation plan, or playbook, for security practitioners to replicate the threat group menuPass.

menuPass is thought to be motivated by collection objectives that align with Chinese national interests. The group's targeting is consistent with China's strategic objectives as stated in the Five-Year Plan. While most of the group's targets have been located in the United States and Japan, the group has also been linked to intrusions in at least 12 other countries.

If you were like us, your first thought may have been, "can I execute this in my environment to see how vulnerable I'd be to an attack?"

You may be a red, blue or purple teamer looking for a realistic threat assessment for your next engagement. You may be in IT or InfoSec, without expertise or budget for a red team, and want to up your game. Or maybe you're a penetration tester, looking to extend into the seemingly murky and complex world of adversary emulation. In any case, let's see what we can do!

Learn thy enemy

First up is education. Isn't it always? We shouldn't get too far ahead without understanding our goals and our plan. Let's start with the goals.

To start, I'm looking for an extendable emulation plan that I can load into the Operator platform and run manually or on repeat, depending on my context (more on this later). Secondly, I'm looking for specific menuPass TTPs to incorporate in my plan because, well, I'm emulating the menuPass actor.

Now let's come up with a plan. Heading to The Center for Threat Informed Defense's GitHub page, I can read up on menuPass. Let's take a few minutes and head there now. I'll wait.


OK, we learned that MITRE has built two scenarios for replicating this specific threat actor, conveniently labeled Scenario 1 and Scenario 2. We'll start with Scenario 1 because it's first. After all, why make it complicated?

After reading the summary of this scenario, I conclude that there are 9 steps to a full emulation, according to MITRE:

Building the profile

Because we're planning on executing this test from the post-compromise position, we'll skip over the first two steps for now. We can come back later.

MITRE emulation plans are designed in the human-readable YML format. Storing attacks in this format allow you to read sequentially through an attack to get a feel for what could occur. This format also plays well with programmatic languages making it ideal for importing into command and control (C2) platforms.

Clicking into the YML representation of the plan, I scroll down to Scenario 1, Step 3: Discovery.

The first TTP I see is a discovery tactic implementation, intended to capture network shares.

Easy enough, this is intended to be run by the Windows command line executor.

Popping my Operator platform up, I immediately head to the Editor and build a procedure. After clicking save, I see:

Great! But wait, do you see that too?

Looking at the bottom right, I can see that there are already two TTPs in my database which are similar to my new one. Operator uses character distancing to point out procedures which could be duplication's (or helpful variations) of the same procedure.

Clicking on each, I can clearly see I already have this procedure, word-for-word. No problem, I can just delete my duplicate procedure. I should have checked first, I suppose.

Next, picking one of the variations, I choose to add it to a new adversary, titled menuPass.

Scrolling down the emulation plan, I can see another procedure. This time a T1018 procedure intended to test the network connectivity from one computer to another using PowerShell.

Having learned my lesson before, I start typing in "Remote System Discovery" in the Editor search bar to see if I already have this one. No dice! Going through the same steps as before, I write my TTP within Editor and add it to my (now existing) menuPass profile.

As I work my way down the playbook, I'm analyzing each command, trying to understand how it works, what the input and output of each may be and the impact each will have on a target system. I'm especially mindful of the variables inside each command, which I can spot by the #{variable} language.

A variable is meant to be replaced at runtime, whether manually or through some type of automated system.

Since I'm used to Operator, I'm well aware of how variables work!

So by the time I hit Step 6: Collection, I stumble across an interesting variable, copy_filename:

I can tell from the context of this command, that menuPass is attempting to copy a file from somewhere on the computer into the Recycle Bin. After tipping my hat to the creativity of the move - as it's likely to be an unusual place for a defender to look - I'm curious if I can fill that variable in automatically. I search the rest of the YML file for copy_filename but come up empty. Nothing indicates that another procedure will output the correct value. So I must supplement this profile.

Heading to Operator, I search for "file", which leads me on a rabbit hole of learning but I do stumble upon this:

I can work with this. I know that Operator will automatically parse files (among other Indicators of Compromise) from the output of procedures, so I can expect this particular TTP will output n-number of file.T1005 variables.

Heading back to the Editor section, I write the command like this:

I add this, along with the Find recent files TTP, to my menuPass adversary. This ensures I'll automatically locate recently modified files to satisfy this specific collection procedure in the emulation plan. Of course, I could fill this in manually by running each command and analyzing the output myself.. but isn't that what automation is for?

As I wrap up my emulation plan, I look back at the procedures I've added and modified. Instead of taking each command, word-for-word, I've made slight tweaks (such as swapping the copy_filename variable) in order to create a more powerful security test, specific for my goals.

Let's take a quick pause and thank The Center for Threat Informed Defense. Those working in the public interest, putting free and open-source data & tools into the industry, deserve praise for contributing.

The exercise

With my newly minted menuPass profile, it's time to get to work. Before we continue though, we should determine exactly what we're hoping to accomplish.

  • I could run my adversary as part of a larger red team exercise, executing my profile automatically with my defensive team unaware of what I'm doing.

  • I could team up with my blue team to engage in a healthy purple team engagement, with them watching my every step and checking their detection capabilities along the way.

  • I could replace the variables I so diligently wrote with hard-coded values and run a scripted penetration test.

I think I'll go with the first.

In red team engagements, I recommend working with a team to build your manual and automated attack plan. This coordination should include steps like writing rules of engagement to set expectations, determining how much knowledge the blue team will have of your plan or overall presence and ensuring you have the proper permission to test the machines you are infecting.

Gaining access

So now, I have an adversary and an exercise plan. So how should I kick things off?

Previously, I decided to skip the initial access and command-and-control steps of the menuPass playbook because I wanted to focus on post-compromise behaviors. No worries, I'll incorporate something different: a rubber ducky attack.

Whipping up a quick ducky script, I now have an alternative initial access plan. This script will download a Pneuma agent from a remote server (stubbed out at to a target system when a USB is plugged into an unlocked computer.

I compile my script and my payload delivery mechanism is complete!

Heading out of my cubicle, I stretch my legs and wander down the hallway. I see a cluster of laptops - unlocked, against company policy - and I saunter over. Plugging the ducky in for a quick second, I snatch it back out and quickly walk away. Delivery complete. As I head back to my workstation, I check out Operator in anticipation and...

Bingo! Two of the laptops are now checking into my platform!

With Remote Code Execution (RCE) established through Pneuma, I must tread carefully not to get caught. I could go through a few steps to ensure persistence on the machines or laterally move to extend my footholds, but I have menuPass on the brain today.

Let's take a look around. Clicking into one of the agents, I open the reverse-shell and run a few commands to understand where I am (on the network) and whose computer I've compromised.

I could then pivot into slowly executing the menuPass procedures manually, entering them into my shell, pausing to consume the output manually and leveraging that to make additional decisions about what TTP to execute when. But I'm not worried about getting caught in this test, as the stakes are low, so I'll speed things up.

Clicking into the Emulate section, I launch my pre-built adversary profile after double-checking that my agent has a jitter time of an hour per beacon (check in), just to avoid too much noisy traffic. Over the next several hours I watch as my compromised machines execute a handful of discovery procedures.

Then, I notice the following message on one of my agents, indicating it is unable to resolve a host_address variable:

Nothing within the playbook seems capable of discovering matches to the host_address variable, so the procedure is being skipped. I could do nothing, and accept it as a loss but I'm rather curious what the output of the TTP would be. I pop open the agent facts modal and enter in a host address I found while working with the reverse shell manually.

After saving, I see the agent pick up the new knowledge on its next beacon. Perfect.

As the emulation continues, I notice my Find recent files procedure successfully located a handful of files, dumping the values to standard out and feeding them as input into my collection procedure, which stores them in the recycling bin for later exfil.

Hopping back to the reverse shell, I can check out my stash and execute a manual exfiltration of the files if I'm interested. I could have put this step into the emulation plan, to do it automatically, but I haven't added all the menuPass exfiltration TTPs yet, so I'll do that myself from the shell this time around.

As the exercise concludes, I realize no one has caught on to me yet. I've had footholds in the network all day and the defense hasn't caught on. Time to brief them.

I hope you enjoyed this exercise, taking Cyber Threat Intelligence (CTI) data and transcribing it into an executable playbook. In this case, we walked through the new MITRE menuPass playbook but the steps would be the same regardless of the threat actor.

After the building process was complete, I went through the steps to construct an Operator adversary and perform a full-fledged security assessment in my organization. Of course, as an example, I left out many of the details I'd normally go through to work within the parameters of security testing but hopefully this left you with a taste for what is possible.

Happy hacking.