Thursday, June 20, 2019


I have been pretty busy helping organize HackTheSea for DEF CON 27.  This will be the first ever maritime and ship hacking village at DEF CON.  We are going to have a team CTF on a very nifty "ship" environment provided by Fathom5.  There will also be a series of workshops for n00bs to maritime ICS/OT with lots of gear available for hacking practice.  Our CFP is currently open, but closing soon for those doing original research in high seas hacking.  In keeping with the DEF CON theme this year, Technology's Promise, we will also have Seasteading Institute on hand to talk about living at sea and to kick-off a hackathon challenge for the Seasteading Community.

Plus, lot's of pirate meme stuff.

Saturday, March 2, 2019

BSides NOVA was great.  Got a lot of interesting questions and feedback on my malware analysis training.  Taught lots of new lock-pickers at the LPV with TOOOL. Saw some great talks and Watched War Games with an audience of hackers and I Am The Cavalry.

Saturday, February 23, 2019


For anyone attending the malware training, you will need a hex editor installed for one of the labs.  It doesn't matter what editor you choose, we won't be using it much.

Friday, February 22, 2019

BSides NoVA Training

For anyone attending my malware analysis workshop, No Disassembly Required, next week at BSides NoVA here is the very brief list of what to bring and prerequisites.


Enough available memory and storage to run a Windows 10 VM
Hypervisor of your choice installed (Hyper-V, VirtualBox, VMware, whatever)
WiFi enabled
*Wired Ethernet adapter if needed (example, Thunderbolt to Ethernet) just in case

Windows VM

Configured with NATed or Bridged network access


Willingness to learn and a basic familiarity with a Hypervisor software and VMs.  The course is designed  to let students work at their own pace on the labs, with progressively more difficult challenges to complete. 

Wednesday, October 17, 2018


After a bit of a hiatus I hope to start blogging more regularly, or at least to get caught up on posting about various topics I have spoken on at recent conferences.  For those who missed it I spoke on script based malware including so-called "fileless" intrusions, and taught a related training at BSides-Pittsburgh in June.  Last week, I co-presented a talk at DerbyCon about hacking maritime SCADA.  I will be working on some posts related to those talks, both technical deep-dives, and sharing some of my experiences with "soft-skill" topics like presenting at conferences, writing CFP responses, talking to reporters, and coordinating ethical disclosure of vulnerabilities.

Friday, April 20, 2018

Part Three: Triage With Osquery and Obtaining Indicators

In this post, I’ll go more in-depth about how I used osquery to find the indicators in part two, and how to use the same technique for threat hunting on macOS.

Osquery Logs

There are two styles of results logs in osquery, snapshots and differential logs.  Snapshots are exactly what the name suggests, results of queries executed at a single point in time.  Differential logs only add a row when results of a query change.  As a simple example, I have created an osquery.conf file with scheduled queries for listening_ports and launchd tables.  Applying these configs gives us a differential log.

The first set of entries from launchd are the baseline.  This log can be saved or discarded.  For our purposes we just need the subsequent changes, which will list any new property lists added to the launchd paths.  We could get the same information without using osquery by running "launchctl list" and writing a script to parse it, but osquery is a convenient tool to use for this purpose.

The next step is to take a snapshot on my virtual machine, and then run the trojan PDF from part one. After the Mach-O binary executes, we see the decoy document appear.

Checking our osqueryd.results.log again, we can see we have a new row in our log.  Reading through the results we can see that indeed the malware has added a property list to our launch directory for persistence.  We can also see the paths we need to locate the property list, which will in turn yield the path to the persistent executable, as we saw in part two.

This is an extremely simple example of dynamic analysis.  The technique could be automated further with scripting to create our own custom "sandbox". With it we could quickly find low-hanging fruit indicators from our macOS malware sample, or from suspected phishing email attachment.  Additional tables can be added to monitor other potential persistence mechanisms like crontab, or even more stealthy methods like @xorrior's emond based persistence.

I am still exploring the capabilities of osquery for ways to detect other malicious behavior and indicators.  For example, I've been exploring the best way to capture network information using only osquery tables.  I experimented with the listening_ports table and found that it does indeed log processes listening on a port.  I am able to see, for instance the mDNSResponder service listening as expected on UDP port 5353.  Unfortunately, listening_ports does not address reverse-shells or other backdoor and C2 mechanisms.  

Another interesting table I have experimented with is file_events, and it seems to have some cool possibilities. One use case would be to create a substitute for Windows Security Event ID 4663, and use it for something like @neu5ron's canary files.  I'll keep exploring, and keep blogging about what I find. 

Monday, April 16, 2018

Part Two: Writing the Rules

Query Rules

As I said in part one, I began by checking the osx-attacks pack for existing rules.  While there were no rules to detect the newest APT32 associated variants, I used the pack as a template for writing my own.  Packs have only a few necessary elements.  The first element in the osx-attacks pack is a platform key that specifies the value for macOS ("darwin").  The next element, "queries", quite naturally contains the rules we want applied, formatted as a series of SQL queries.

Looking at the first rule, "Wirelurker", we see that it consists of a query selecting all columns from the table "launchd" where the row has a name value that ends in ".plist".  The other keys in the Wirelurker rule are pretty straight forward.  "Interval" specifies in seconds how often to run the query.  The "version" key is the minimum version of osquery compatible with this rule.  The two remaining fields, "value" and "description" are just optional meta-data for informational purposes.

Before going any further, a brief note on the syntax.  The osx attacks pack includes a bash-style backslash to indicate line continuation. Other example configuration files from the Facebook osquery repository include C-style comments (//).  These elements were compatible with the json parser in earlier versions of osquery, but may not be compatible with newer versions. The parser in version 3.1.0, the latest version installed by Brew as of my writing this post, throws errors on these non-compliant elements.  I have confirmed this via experimentation and talking to osquery developers via the Slack channels.

Now let's go back to that table "launchd", and answer "what is a .plist?" and "why are we looking for them?"  For additional information you can always check out my talks from BloomCon 2018 and BSides Columbus 2018.  The short answer is that property lists (.plist) and launchd are the way at least half of macOS malware variants, according to my own completely un-scientific estimate, achieve persistence.

 The more complete answer is that launch daemon (launchd) is the process started by kernel_task (pid 0) on startup (as pid 1) to ensure that other processes that need to run on startup on macOS get run.  Launchd accomplishes this by walking a set of special directories and parsing a set of special xml files, which are the startup "property lists".  These directories and property lists serve much the same function as the Windows' "run" and "run once" registry keys.

Within the .plist file for the APT32 variant shown here, a "RunAtLoad", "true" key-value pair ensures persistence through a shutdown or restart, while "KeepAlive", "true" key-value pair ensures the process is restarted if stopped.  Lastly, the "ProgramArguments", "/Users/thewoz/Library/Containers/" key-value pair gives us the full path of the Mach-O binary "hidd", which is written to disk in the victim's ~/Library/Containers folder and concealed with a "hidden" xattribute, which launchd is required to run on startup.

Using this information, we can create two rules for query pack.  The first will follow our osx-attacks pack template and query the launchd table to detect the presence of "", a good indicator of this variant.  The second rule will query the "file" table for that persistent Mach-O binary.  Results can either be logged locally to the default /var/osquery/log/osqueryd.results.log, or can be aggregated for ingestion by Splunk, LogStash, Fluentd, or other options.  But that will have to wait for a future post.

A final note, after writing my rules I ran them through, just to make sure I don't get any json parser related errors.  I would recommend it as a practice.   Yes, these are pretty static indicators, stick around for part three, where I will discuss more "flexible" queries.   Again, the full query pack can be found on my github repository.

Part Three: Triage With Osquery and Obtaining Indicators