scripts:
<script_name>: <base64_encoded_script>
Scripts are distinct atomic functionalities of an ATLAS rule, like functions of the functional programming languages.
Note
Currently Python and Powershell are supported. Javascript support is in the backlog.
A key can be an arbitrary keyword or the function name of the entry point in the script. First, it tries to call the key. Then, if it fails, it calls the run.
Note
The value must be base64 encoded.
scripts:
# def printer(*args) -> bool:
# print(" ".join(args))
# return True
s1: "ZGVmIHByaW50ZXIoKmFyZ3MpIC0+IGJvb2w6CgogICAgcHJpbnQoIiAiLmpvaW4oYXJncykpCiAgICByZXR1cm4gVHJ1ZQ=="
import base64
with open('script.py', 'rb') as file:
data = file.read()
encoded_script = base64.b64encode(data)
# It is important to give -Encoding as UTF8 instead of directly getting Byte.
# The byte option appends byte order marker at the beginning thus ruins everthing
$content = Get-Content .\script.ps1 -Raw -Encoding UTF8
[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($content))
python_executor function inside the core library is used. The function gets the script as base64 encoded, the script's name and arguments to pass to its entry point.
- It does in-memory import for the script.
- Calls the entry point.
- Gets the return data.
If the script contains null bytes, they must be encoded in the script:
def run(data: bytes) -> bool:
try:
keyIL = re.search(b'(?<=((\x72)[\x00-\xff]{4}(\x80)[\x00-\xff]{4}(\x72)))[\x00-\xff]{4}', data).group()
su = re.search(b'[\x00-\xff]{4}(?=([\x00-\xff]{4}(\x23\x55\x53\x00)))', data).group()
except:
return False
return True
When ATLAS tries to execute a rule that contains the above function as a script, the base64 module will raise an exception due to null bytes.
def run(data: bytes) -> bool:
try:
keyIL_encoded = b'KD88PSgocilbAC3/XXs0fSiAKVsALf9dezR9KHIpKSlbAC3/XXs0fQ=='
su_encoded = b'WwAt/117NH0oPz0oWwAt/117NH0oI1VTACkpKQ=='
keyIL = re.search(b64decode(keyIL_encoded), data).group()
su = re.search(b64decode(su_encoded), data).group()
except:
return False
powershell_executor function inside the core library is used. The function gets the script as base64 encoded, the script's name and arguments to pass to its entry point.
- Creates a Powershell process.
- Inside this process;
- Decodes the script and creates a ScriptBlock.
- Prepares the arguments.
- Calls the entry point.
- Base64 encodes the return data.
- Creates TemporaryFile, prints the path, and writes encoded data to the file.
- Stores the encoded data to the file.
- In Python, it reads the file and decodes it.
Note
Right now str and bytes type arguments are supported for powershell execution.