# T1059.002 - Applescript

### Sample output
`python -m posixath macos -t T1059_002 -k NSAppleScript`
```json
{
  "activity_at_ts": "2022-10-05T15:13:59.913Z",
  "attack_id": "T1059.002",
  "command_line": "[PosixPath('.../posix/src/posixath/tests/macos/library/T1059_002/nsapplescript_example')]",
  "cwd": ".../posix/src",
  "executable_name": "nsapplescript_example",
  "executed_applescript": "return short user name of (system info)\n delay 1",
  "gid": 20,
  "md5": "e12d158a2812e868c725c1344c15b805",
  "pid": 3584,
  "ppid": 3579,
  "process_path": ".../posix/src/posixath/tests/macos/library/T1059_002/nsapplescript_example",
  "result": "success",
  "return_code": 0,
  "stderr": null,
  "stdin": ".../posix/src/posixath/tests/macos/library/T1059_002/whoami.scpt",
  "stdout": "darkarts\n",
  "uid": 502
}
```

## Supported technique variations
- `NSAppleScript`: Utilizing the `NSAppleScript` API (part of the Foundation library) read AppleScript source from a 
  plain text script file, compile, and execute it. To do this, first we compile the Swift source file then execute
  the binary.
- `osascript`: Leveraging the `/usr/bin/osascript` platform binary execute AppleScript from a script load and
  line-by-line. 
- Shell scripts: The Unix shebang (`#!`) also allows us to call the `/usr/bin/osascript` binary.
- Applets: Simply application bundles constructed from OSA (Open Scripting Architecture) source code. This variation
  compiles a plain text AppleScript file into an applet and executes it.
- Stay-Open-Scripts: Very similar to applets, but with the exception that they generally contain an idle handler and
  also must contain the `OSAAppletStayOpen` key in their `Info.plist`. This enables them to stay open even after the
  script has returned from execution.

## Running tests
After installing the POSIX AtomicTestHarness executer module `posixath` you can begin to run the following tests:
- **Execute all T1059 macOS tests**
  - `python -m posixath macos -t T1059`
- **Execute all AtomicTestHarness tests for T1059.002 AppleScript**
  - `python -m posixath macos -t T1059_002`
- **Execute a specific AppleScript technique variation**
  - `python -m posixath macos -t T1059_002 -k "NSAppleScript""`
- **Execute tests with a custom script(s)**
  - `python -m posixath macos -t T1059_002 --osascript-path <PATH TO OSA SCRIPT> --osa-shell-path <PATH TO SHELL SCRIPT>`
- **Execute a test with a custom script**
  - `python -m posixath macos -t T1059_002 -k "NSAppleScript" --osascript-path <PATH TO OSA SCRIPT>`

## Command line arguments
- `--osascript-path`: The path to an uncompiled OSA (Open Scripting Architecture) script. E.g. AppleScript or JXA.
- `--osa-shell-path`: The path to an OSA (Open Scripting Architecture) shell script. E.g. `#!/usr/bin/osascript`

## Detection guidance
### NSAppleScript
- Direct EDR detection is difficult here. At the most atomic level you're trying to detect a process reading arbitrary 
  AppleScript and passing it to the NSAppleScript API via `executeAndReturnError` or `compileAndReturnError`. 
- The Apple Event Manager then takes over handling sending / receiving messages in the form of Apple Events.
- This behavior is not directly logged by any macOS EDR sensor to date.
- Instead, detection opportunities will focus around suspicious process behaviors (e.g. network connections and memory
  mapping events).
- We can infer a binary is executing OSA code by observing the process mapping (`ES_EVENT_TYPE_NOTIFY_MMAP`)
  either the JXA (`/System/Library/Components/JavaScript.component`) or AppleScript  
  (`/System/Library/Components/AppleScript.component`) components into memory along with Standard Additions 
  (`/System/Library/ScriptingAdditions/StandardAdditions.osax`). These Endpoint Security Framework events will look
  like the following:

```json
{
  "initating_process_name": "nsapplescript_example",
  "initating_process_signing_id": "nsapplescript_example",
  "ppid": 14140,
  "initating_pid": 14146,
  "path_is_truncated": false,
  "initiating_process_path": "/Users/housecup/.local/share/virtualenvs/posix-Y-QvriGh/lib/python3.10/site-packages/posixath/tests/macos/library/T1059_002/nsapplescript_example",
  "rpid": 1170,
  "es_event_type": "ES_EVENT_TYPE_NOTIFY_MMAP",
  "mmap_event": {
    "path": "/System/Library/ScriptingAdditions/StandardAdditions.osax/Contents/MacOS/StandardAdditions"
  },
  "should_drop": false
},
{
  "initating_process_name": "nsapplescript_example",
  "initating_process_signing_id": "nsapplescript_example",
  "ppid": 14140,
  "initating_pid": 14146,
  "path_is_truncated": false,
  "initiating_process_path": "/Users/housecup/.local/share/virtualenvs/posix-Y-QvriGh/lib/python3.10/site-packages/posixath/tests/macos/library/T1059_002/nsapplescript_example",
  "rpid": 1170,
  "es_event_type": "ES_EVENT_TYPE_NOTIFY_MMAP",
  "mmap_event": {
    "path": "/System/Library/Components/AppleScript.component/Contents/MacOS/AppleScript"
  },
  "should_drop": false
}
```

### OSAScript binary
- Execution of the `osascript` binary will take place and any command line arguments will also be visible.
- This is the most trivial case to detect. Any execution of osascript taking in input from a remote source 
  (most commonly through `curl` and `eval(ObjC.unwrap(...))`) should be looked at this an extra degree of suspicion.
- Executing AppleScript using the -e statement flags, while not as common, creates very long command-lines and is an
  inefficient way to execute most OSA scripts. However, it has been seen in the wild and since this execution variation 
  executes via the command-line there is ample detection opportunity.
- While not directly associated, compiling AppleScript as run-only is suspicious and has been seen in the wild
  (e.g. XCSSET).

### Applet
- By default, and if constructed with `Automator.app`, the Mach-O binary in the `../MacOS` directory will be named 
  `Automator Application Stub`
- By disassembling the binary we can see that the `ScriptMonitor.app` is being called as a way to provide a visual 
  indicator that a script is running to the user. In other words, when an applet is launched so is `ScriptMonitor.app`. 
  From a defender's perspective this enables another avenue for detection.
- If built using Automator, the contents of the OSA script will be placed in the `document.wflow` file (XML based) 
  under the: `<key>Action Parameters</key>` tag. Otherwise, there will be a `../Resources/Scripts` directory which will 
  contain all the scripts for the applet.
- During execution an osascript CMDL will generally not be seen in this case, unless the osascript binary is explicitly 
  invoked.
- Looking for the execution of the `Automator Application Stub` or `applet` binary is always a good indication of 
  applet execution as is `ScriptMonitor.app`, albeit to a lesser degree. However, the name of the binary is able to 
  be modified and thus detection on the binary name alone would not provide sufficient coverage.
- Applets contain the property list key value pair: `"CFBundleSignature": "aplt"` and contain references to scripts in
  their TCC usage descriptions.

### Stay-Open-Script
- Detection opportunities are the same as those for applets. However, Stay-Open-Scripts can be uniquely identified by
  the `OSAAppletStayOpen` key in their `Info.plist`