Overview
Eldritch is a Pythonic red team Domain Specific Language (DSL) based on starlark. It uses and supports most python syntax and basic functionality such as list comprehension, string operations (lower()
, join()
, replace()
, etc.), and built-in methods (any()
, dir()
, sorted()
, etc.). For more details on the supported functionality not listed here, please consult the Starlark Spec Reference, but for the most part you can treat this like basic Python with extra red team functionality.
Eldritch is a small interpreter that can be embedded into a c2 agent as it is with Golem and Imix. By embedding the interpreter into the agent conditional logic can be quickly evaluated without requiring multiple callbacks.
Eldritch is currently under active development to help delineate methods in development the description contains the phrase X method will
.
Trying to create a tome? Check out the guide in Golem.
Examples
Kill a specific process name
for p in process.list():
if p['name'] == "golem":
process.kill(p['pid'])
Copy your current executable somewhere else
cur_bin_path = process.info()['exe']
dest_path = '/tmp/win'
file.copy(cur_bin_path, dest_path)
file.remove(cur_bin_path)
Parse a JSON file
json_str = file.read("/tmp/config.json")
config_data = crypto.from_json(json_str)
print(config_data['key1'])
Data types
Eldritch currently only supports the default starlark data types.
Error handling
Eldritch doesn’t implement any form of error handling. If a function fails it will stop the tome from completing execution. There is no way to recover after a function has errored.
If you’re using a function that has a chance to error (functions that do file / network IO) test preemptively with function like is_file
, is_dir
, is_windows
, etc.
For example:
def read_passwd():
if is_linux():
if is_file("/etc/passwd"):
file.read("/etc/passwd")
read_passwd()
def write_systemd_service():
if is_linux():
if is_dir("/lib/systemd/system/"):
service_args = {
"name":"my-service",
"desc":"A test",
"binary_path":"/bin/false",
}
assets.copy("systemd-template.j2", "/tmp/systemd-template.j2")
file.template("/tmp/systemd-template.j2","/lib/systemd/system/myservice.service",args,False)
file.remove("/tmp/systemd-template.j2")
write_systemd_service()
Standard Library
The standard library is the default functionality that eldritch provides. It contains the following libraries:
assets
- Used to interact with files stored natively in the agent.crypto
- Used to encrypt/decrypt or hash data.file
- Used to interact with files on the system.http
- Used to make http(s) requests from the agent.pivot
- Used to identify and move between systems.process
- Used to interact with processes on the system.random
- Used to generate cryptographically secure random values.regex
- Regular expression capabilities for operating on strings.report
- Structured data reporting capabilities.sys
- General system capabilities can include loading libraries, or information about the current context.time
- General functions for obtaining and formatting time, also add delays into code.
🚨 DANGER 🚨: Name shadowing
Do not use the standard library names as local variables as it will prevent you from accessing library functions. For example, if you do:
for file in file.list("/home/"):
print(file["file_name"])
The file library will become inaccessible.
It may even raise an error: error: Local variable 'file' referenced before assignment
Instead we recommend using more descriptive names like:
for user_home_dir in file.list("/home/"):
print(user_home_dir["file_name"])
Assets
assets.copy
assets.copy(src: str, dst: str) -> None
The assets.copy method copies an embedded file from the agent to disk.
The src
variable will be the path from the embed_files_golem_prod
as the root dir.
For example embed_files_golem_prod/sliver/agent-x64
can be referenced as sliver/agent-x64
.
If dst
exists it will be overwritten. If it doesn’t exist the function will fail.
def deploy_agent():
if file.is_dir("/usr/bin"):
assets.copy("sliver/agent-x64","/usr/bin/notsu")
sys.exec("/usr/bin/notsu",[],true)
deploy_agent()
assets.list
assets.list() -> List<str>
The assets.list method returns a list of asset names that the agent is aware of.
assets.read_binary
assets.read_binary(src: str) -> List<int>
The assets.read_binary method returns a list of u32 numbers representing the asset files bytes.
assets.read
assets.read(src: str) -> str
The assets.read method returns a UTF-8 string representation of the asset file.
Crypto
crypto.aes_decrypt_file
crypto.aes_decrypt_file(src: str, dst: str, key: str) -> None
The crypto.aes_decrypt_file method decrypts the given src file using the given key and writes it to disk at the dst location.
Key must be 16 Bytes (Characters)
crypto.aes_encrypt_file
crypto.aes_encrypt_file(src: str, dst: str, key: str) -> None
The crypto.aes_encrypt_file method encrypts the given src file, encrypts it using the given key and writes it to disk at the dst location.
Key must be 16 Bytes (Characters)
crypto.encode_b64
crypto.encode_b64(content: str, encode_type: Optional<str>) -> str
The crypto.encode_b64 method encodes the given text using the given base64 encoding method. Valid methods include:
- STANDARD (default)
- STANDARD_NO_PAD
- URL_SAFE
- URL_SAFE_NO_PAD
crypto.decode_b64
crypto.decode_b64(content: str, decode_type: Optional<str>) -> str
The crypto.decode_b64 method encodes the given text using the given base64 decoding method. Valid methods include:
- STANDARD (default)
- STANDARD_NO_PAD
- URL_SAFE
- URL_SAFE_NO_PAD
crypto.from_json
crypto.from_json(content: str) -> Value
The crypto.from_json method converts JSON text to an object of correct type.
crypto.from_json("{\"foo\":\"bar\"}")
{
"foo": "bar"
}
crypto.hash_file
crypto.hash_file(file: str, algo: str) -> str
The crypto.hash_file method will produce the hash of the given file’s contents. Valid algorithms include:
- MD5
- SHA1
- SHA256
- SHA512
crypto.to_json
crypto.to_json(content: Value) -> str
The crypto.to_json method converts given type to JSON text.
crypto.to_json({"foo": "bar"})
"{\"foo\":\"bar\"}"
File
file.append
file.append(path: str, content: str) -> None
The file.append method appends the content
to file at path
. If no file exists at path create the file with the content.
file.compress
file.compress(src: str, dst: str) -> None
The file.compress method compresses a file using the gzip algorithm. If the destination file doesn’t exist it will be created. If the source file doesn’t exist an error will be thrown. If the source path is a directory the contents will be placed in a tar archive and then compressed.
file.copy
file.copy(src: str, dst: str) -> None
The file.copy method copies a file from src
path to dst
path. If dst
file doesn’t exist it will be created.
file.exists
file.exists(path: str) -> bool
The file.exists method checks if a file or directory exists at the path specified.
file.follow
file.follow(path: str, fn: function(str)) -> None
The file.follow method will call fn(line)
for any new line
that is added to the file (such as from bash_history
and other logs).
# Print every line added to bob's bash history
file.follow('/home/bob/.bash_history', print)
file.is_dir
file.is_dir(path: str) -> bool
The file.is_dir method checks if a path exists and is a directory. If it doesn’t exist or is not a directory it will return False
.
file.is_file
file.is_file(path: str) -> bool
The file.is_file method checks if a path exists and is a file. If it doesn’t exist or is not a file it will return False
.
file.list
file.list(path: str) -> List<Dict>
The file.list method returns a list of files at the specified path. The path is relative to your current working directory and can be traversed with ../
.
This function also supports globbing with *
for example:
file.list("/home/*/.bash_history") # List all files called .bash_history in sub dirs of `/home/`
file.list("/etc/*ssh*") # List the contents of all dirs that have `ssh` in the name and all files in etc with `ssh` in the name
Each file is represented by a Dict type. Here is an example of the Dict layout:
[
{
"file_name": "implants",
"absolute_path": "/workspace/realm/implants",
"size": 4096,
"owner": "root",
"group": "0",
"permissions": "40755",
"modified": "2023-07-09 01:35:40 UTC",
"type": "Directory"
},
{
"file_name": "README.md",
"absolute_path": "/workspace/realm/README.md",
"size": 750,
"owner": "root",
"group": "0",
"permissions": "100644",
"modified": "2023-07-08 02:49:47 UTC",
"type": "File"
},
{
"file_name": ".git",
"absolute_path": "/workspace/realm/.git",
"size": 4096,
"owner": "root",
"group": "0",
"permissions": "40755",
"modified": "2023-07-10 21:14:06 UTC",
"type": "Directory"
}
]
file.mkdir
file.mkdir(path: str, parent: Option<bool>) -> None
The file.mkdir method will make a new directory at path
. If the parent directory does not exist or the directory cannot be created, it will error; unless the parent
parameter is passed as True
.
file.moveto
file.moveto(src: str, dst: str) -> None
The file.moveto method moves a file or directory from src
to dst
. If the dst
directory or file exists it will be deleted before being replaced to ensure consistency across systems.
file.parent_dir
file.parent_dir(path: str) -> str
The file.parent_dir method returns the parent directory of a give path. Eg /etc/ssh/sshd_config
-> /etc/ssh
file.read
file.read(path: str) -> str
The file.read method will read the contents of a file. If the file or directory doesn’t exist the method will error to avoid this ensure the file exists, and you have permission to read it.
This function supports globbing with *
for example:
file.read("/home/*/.bash_history") # Read all files called .bash_history in sub dirs of `/home/`
file.read("/etc/*ssh*") # Read the contents of all files that have `ssh` in the name. Will error if a dir is found.
file.remove
file.remove(path: str) -> None
The file.remove method deletes a file or directory (and it’s contents) specified by path.
file.replace
file.replace(path: str, pattern: str, value: str) -> None
The file.replace method finds the first string matching a regex pattern in the specified file and replaces them with the value. Please consult the Rust Regex Docs for more information on pattern matching.
file.replace_all
file.replace_all(path: str, pattern: str, value: str) -> None
The file.replace_all method finds all strings matching a regex pattern in the specified file and replaces them with the value. Please consult the Rust Regex Docs for more information on pattern matching.
file.tmp_file
file.tmp_file(name: Option<str>) -> str
The file.temp method returns the path of a new temporary file with a random filename or the optional filename provided as an argument.
file.template
file.template(template_path: str, dst: str, args: Dict<String, Value>, autoescape: bool) -> None
The file.template method reads a Jinja2 template file from disk, fill in the variables using args
and then write it to the destination specified.
If the destination file doesn’t exist it will be created (if the parent directory exists). If the destination file does exist it will be overwritten.
The args
dictionary currently supports values of: int
, str
, and List
.
autoescape
when True
will perform HTML character escapes according to the OWASP XSS guidelines
file.timestomp
file.timestomp(src: str, dst: str) -> None
Unimplemented.
file.write
file.write(path: str, content: str) -> None
The file.write method writes to a given file path with the given content. If a file or directory already exists at this path, the method will fail.
file.find
file.find(path: str, name: Option<str>, file_type: Option<str>, permissions: Option<int>, modified_time: Option<int>, create_time: Option<int>) -> List<str>
The file.find method finds all files matching the used parameters. Returns file path for all matching items.
- name: Checks if file name contains provided input
- file_type: Checks for ‘file’ or ‘dir’ for files or directories, respectively.
- permissions: On UNIX systems, takes numerical input of standard unix permissions (rwxrwxrwx == 777). On Windows, takes 1 or 0, 1 if file is read only.
- modified_time: Checks if last modified time matches input specified in time since EPOCH
- create_time: Checks if last modified time matches input specified in time since EPOCH
HTTP
The HTTP library also allows the user to allow the http client to ignore TLS validation via the allow_insecure
optional parameter (defaults to false
).
http.download
http.download(uri: str, dst: str, allow_insecure: Option<bool>) -> None
The http.download method downloads a file at the URI specified in uri
to the path specified in dst
. If a file already exists at that location, it will be overwritten.
http.get
http.get(uri: str, query_params: Option<Dict<str, str>>, headers: Option<Dict<str, str>>, allow_insecure: Option<bool>) -> str
The http.get method sends an HTTP GET request to the URI specified in uri
with the optional query paramters specified in query_params
and headers specified in headers
, then return the response body as a string. Note: in order to conform with HTTP2+ all header names are transmuted to lowercase.
http.post
http.post(uri: str, body: Option<str>, form: Option<Dict<str, str>>, headers: Option<Dict<str, str>>, allow_insecure: Option<bool>) -> str
The http.post method sends an HTTP POST request to the URI specified in uri
with the optional request body specified by body
, form paramters specified in form
, and headers specified in headers
, then return the response body as a string. Note: in order to conform with HTTP2+ all header names are transmuted to lowercase. Other Note: if a body
and a form
are supplied the value of body
will be used.
Pivot
pivot.arp_scan
pivot.arp_scan(target_cidrs: List<str>) -> List<str>
The pivot.arp_scan method is for enumerating hosts on the agent network without using TCP connect or ping.
target_cidrs
must be in a CIDR format eg.127.0.0.1/32
. Domains and single IPsexample.com
/127.0.0.1
cannot be passed.- Must be running as
root
to use. - Not supported on Windows
Results will be in the format:
$> pivot.arp_scan(["192.168.1.1/32"])
Success
[
{ "ip": "192.168.1.1", "mac": "ab:cd:ef:01:23:45", "interface": "eno0" }
]
Failure
[]
pivot.bind_proxy
pivot.bind_proxy(listen_address: str, listen_port: int, username: str, password: str ) -> None
The pivot.bind_proxy method is being proposed to provide users another option when trying to connect and pivot within an environment. This function will start a SOCKS5 proxy on the specified port and interface, with the specified username and password (if provided).
pivot.ncat
pivot.ncat(address: str, port: int, data: str, protocol: str ) -> str
The pivot.ncat method allows a user to send arbitrary data over TCP/UDP to a host. If the server responds that response will be returned.
protocol
must be tcp
, or udp
anything else will return an error Protocol not supported please use: udp or tcp.
.
pivot.port_forward
pivot.port_forward(listen_address: str, listen_port: int, forward_address: str, forward_port: int, str: protocol ) -> None
The pivot.port_forward method is being proposed to provide socat like functionality by forwarding traffic from a port on a local machine to a port on a different machine allowing traffic to be relayed.
pivot.port_scan
pivot.port_scan(target_cidrs: List<str>, ports: List<int>, protocol: str, timeout: int) -> List<str>
The pivot.port_scan method allows users to scan TCP/UDP ports within the eldritch language. Inputs:
target_cidrs
must be in a CIDR format eg.127.0.0.1/32
. Domains and single IPsexample.com
/127.0.0.1
cannot be passed.ports
can be a list of any number of integers between 1 and 65535.protocol
must be:tcp
orudp
. These are the only supported options.timeout
is the number of seconds a scan will wait without a response before it’s marked astimeout
Results will be in the format:
[
{ "ip": "127.0.0.1", "port": 22, "protocol": "tcp", "status": "open"},
{ "ip": "127.0.0.1", "port": 21, "protocol": "tcp", "status": "closed"},
{ "ip": "127.0.0.1", "port": 80, "protocol": "tcp", "status": "timeout"},
]
A ports status can be open, closed, or timeout:
State | Protocol | Meaning |
---|---|---|
open | tcp | Connection successful. |
close | tcp | Connection refused. |
timeout | tcp | Connection dropped or didn’t respond. |
open | udp | Connection returned some data. |
timeout | udp | Connection was refused, dropped, or didn’t respond. |
Each IP in the specified CIDR will be returned regardless of if it returns any open ports. Be mindful of this when scanning large CIDRs as it may create large return objects.
NOTE: Windows scans against localhost
/127.0.0.1
can behave unexpectedly or even treat the action as malicious. Eg. scanning ports 1-65535 against windows localhost may cause the stack to overflow or process to hang indefinitely.
pivot.reverse_shell_pty
pivot.reverse_shell_pty(cmd: Optional<str>) -> None
The pivot.reverse_shell_pty method spawns the provided command in a cross-platform PTY and opens a reverse shell over the agent’s current transport (e.g. gRPC). If no command is provided, Windows will use cmd.exe
. On other platforms, /bin/bash
is used as a default, but if it does not exist then /bin/sh
is used.
pivot.smb_exec
pivot.smb_exec(target: str, port: int, username: str, password: str, hash: str, command: str) -> str
The pivot.smb_exec method is being proposed to allow users a way to move between hosts running smb.
pivot.ssh_copy
pivot.ssh_copy(target: str, port: int, src: str, dst: str, username: str, password: Optional<str>, key: Optional<str>, key_password: Optional<str>, timeout: Optional<int>) -> None
The pivot.ssh_copy method copies a local file to a remote system. If no password or key is specified the function will error out with:
Failed to run handle_ssh_exec: Failed to authenticate to host
If the connection is successful but the copy writes a file error will be returned.
ssh_copy will first delete the remote file and then write to its location.
The file directory the dst
file exists in must exist in order for ssh_copy to work.
pivot.ssh_exec
pivot.ssh_exec(target: str, port: int, command: str, username: str, password: Optional<str>, key: Optional<str>, key_password: Optional<str>, timeout: Optional<int>) -> List<Dict>
The pivot.ssh_exec method executes a command string on the remote host using the default shell. If no password or key is specified the function will error out with:
Failed to run handle_ssh_exec: Failed to authenticate to host
If the connection is successful but the command fails no output will be returned but the status code will be set.
Not returning stderr is a limitation of the way we’re performing execution. Since it’s not using the SSH shell directive we’re limited on the return output we can capture.
{
"stdout": "uid=1000(kali) gid=1000(kali) groups=1000(kali),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),109(netdev),118(bluetooth),128(lpadmin),132(scanner),143(docker)\n",
"status": 0
}
pivot.ssh_password_spray
pivot.ssh_password_spray(targets: List<str>, port: int, credentials: List<str>, keys: List<str>, command: str, shell_path: str) -> List<str>
The pivot.ssh_password_spray method is being proposed to allow users a way to test found credentials against neighboring targets. It will iterate over the targets list and try each credential set. Credentials will be a formatted list of usernames and passwords Eg. “username:password”. The function will return a formatted list of “target:username:password”. command and shell_path is intended to give more flexibility but may be adding complexity.
Process
process.info
process.info(pid: Optional<int>) -> Dict
The process.info method returns all information on a given process ID. Default is the current process.
{
"pid": 1286574,
"name": "golem",
"cmd": [
"./target/debug/golem",
"-i"
],
"exe": "/home/user/realm/implants/target/debug/golem",
"environ": [
"USER=user",
"HOME=/home/user",
"PATH=/home/user/.cargo/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/snap/bin:/home/user/.dotnet/tools",
"SHELL=/bin/zsh",
"TERM=xterm-256color",
"SSH_TTY=/dev/pts/0",
"SHLVL=1",
"PWD=/home/user",
"OLDPWD=/home/user",
"XDG_DATA_DIRS=/usr/local/share:/usr/share:/var/lib/snapd/desktop",
"P9K_TTY=old",
"_P9K_TTY=/dev/pts/0",
"ZSH=/home/user/.oh-my-zsh",
],
"cwd": "/home/user/realm/implants",
"root": "/",
"memory_usage": 32317440,
"virtual_memory_usage": 1712074752,
"ppid": 1180405,
"status": "Sleeping",
"start_time": 1698106833,
"run_time": 2,
"uid": 1000,
"euid": 1000,
"gid": 1000,
"egid": 1000,
"sid": 1180405
}
process.kill
process.kill(pid: int) -> None
The process.kill method will kill a process using the KILL signal given its process id.
process.list
process.list() -> List<Dict>
The process.list method returns a list of dictionaries that describe each process. The dictionaries follow the schema:
{
"pid": "9812",
"ppid": "1",
"status": "Sleeping",
"name": "golem",
"path": "/usr/bin/golem",
"username": "root",
"command": "/usr/bin/golem -i",
"cwd": "/root/",
"environ": "CARGO_PKG_REPOSITORY= CARGO_PKG_RUST_VERSION= CARGO_PKG_VERSION=0.1.0 CARGO_PKG_VERSION_MAJOR=0",
}
process.name
process.name(pid: int) -> str
The process.name method returns the name of the process from it’s given process id.
process.netstat
process.netstat() -> List<Dict>
The process.netstat method returns all information on TCP, UDP, and Unix sockets on the system. Will also return PID and Process Name of attached process, if one exists.
Currently only shows LISTENING TCP connections
[
{
"socket_type": "TCP",
"local_address": "127.0.0.1",
"local_port": 46341,
"pid": 2359037
},
...
]
Random
The random library is designed to enable generation of cryptogrphically secure random vaules. None of these functions will be blocking.
random.bool
random.bool() -> bool
The random.bool method returns a randomly sourced boolean value.
random.string
random.string(length: uint, charset: Optional<str>) -> str
The random.string method returns a randomly generated string of the specified length. If charset
is not provided defaults to Alphanumeric. Warning, the string is stored entirely in memory so exceptionally large files (multiple megabytes) can lead to performance issues.
Regex
The regex library is designed to enable basic regex operations on strings. Be aware as the underlying implementation is written in Rust we rely on the Rust Regex Syntax as talked about here. Further, we only support a single capture group currently, defining more/less than one will cause the tome to error.
regex.match_all
regex.match_all(haystack: str, pattern: str) -> List<str>
The regex.match_all method returns a list of capture group strings that matched the given pattern within the given haystack. Please consult the Rust Regex Docs for more information on pattern matching.
regex.match
regex.match(haystack: str, pattern: str) -> str
The regex.match method returns the first capture group string that matched the given pattern within the given haystack. Please consult the Rust Regex Docs for more information on pattern matching.
regex.replace_all
regex.replace_all(haystack: str, pattern: str, value: string) -> str
The regex.replace_all method returns the given haystack with all the capture group strings that matched the given pattern replaced with the given value. Please consult the Rust Regex Docs for more information on pattern matching.
regex.replace
regex.replace(haystack: str, pattern: str, value: string) -> str
The regex.replace method returns the given haystack with the first capture group string that matched the given pattern replaced with the given value. Please consult the Rust Regex Docs for more information on pattern matching.
Report
The report library is designed to enable reporting structured data to Tavern. It’s API is still in the active development phase, so future versions of Eldritch may break tomes that rely on this API.
report.file
report.file(path: str) -> None
Reports a file from the host that an Eldritch Tome is being evaluated on (e.g. a compromised system) to Tavern. It has a 1GB size limit, and will report the file in 1MB chunks. This process happens asynchronously, so after report.file()
returns there are no guarantees about when this file will be reported. This means that if you delete the file immediately after reporting it, it may not be reported at all (race condition).
report.process_list
report.process_list(list: List<Dict>) -> None
Reports a snapshot of the currently running processes on the host system. This should only be called with the entire process list (e.g. from calling process.list()
), as it will replace Tavern’s current list of processes for the host with this new snapshot.
report.ssh_key
report.ssh_key(username: str, key: str) -> None
Reports a captured SSH Key credential to Tavern. It will automatically be associated with the host that the Eldritch Tome was being evaluated on.
report.user_password
report.user_password(username: str, password: str) -> None
Reports a captured username & password combination to Tavern. It will automatically be associated with the host that the Eldritch Tome was being evaluated on.
Sys
sys.dll_inject
sys.dll_inject(dll_path: str, pid: int) -> None
The sys.dll_inject method will attempt to inject a dll on disk into a remote process by using the CreateRemoteThread
function call.
sys.dll_reflect
sys.dll_reflect(dll_bytes: List<int>, pid: int, function_name: str) -> None
The sys.dll_reflect method will attempt to inject a dll from memory into a remote process by using the loader defined in realm/bin/reflective_loader
.
The ints in dll_bytes will be cast down from int u32 —> u8 in rust. If your dll_bytes array contains a value greater than u8::MAX it will cause the function to fail. If you’re doing any decryption in starlark make sure to be careful of the u8::MAX bound for each byte.
sys.exec
sys.exec(path: str, args: List<str>, disown: Optional<bool>) -> Dict
The sys.exec method executes a program specified with path
and passes the args
list.
Disown will run the process in the background disowned from the agent. This is done through double forking and only works on *nix systems.
sys.exec("/bin/bash",["-c", "whoami"])
{
"stdout":"root\n",
"stderr":"",
"status":0,
}
sys.exec("/bin/bash",["-c", "ls /nofile"])
{
"stdout":"",
"stderr":"ls: cannot access '/nofile': No such file or directory\n",
"status":2,
}
sys.get_env
sys.get_env() -> Dict
The sys.get_env method returns a dictionary that describes the current process’s environment variables. An example is below:
{
"FOO": "BAR",
"CWD": "/"
}
sys.get_ip
sys.get_ip() -> List<Dict>
The sys.get_ip method returns a list of network interfaces as a dictionary. An example is available below:
[
{
"name": "eth0",
"ips": [
"172.17.0.2/24"
],
"mac": "02:42:ac:11:00:02"
},
{
"name": "lo",
"ips": [
"127.0.0.1/8"
],
"mac": "00:00:00:00:00:00"
}
]
sys.get_os
sys.get_os() -> Dict
The sys.get_os method returns a dictionary that describes the current systems OS. An example is below:
{
"arch": "x86_64",
"desktop_env": "Unknown: Unknown",
"distro": "Debian GNU/Linux 10 (buster)",
"platform": "PLATFORM_LINUX"
}
sys.get_pid
sys.get_pid() -> int
The sys.get_pid method returns the process ID of the current process. An example is below:
$> sys.get_pid()
123456
sys.get_reg
sys.get_reg(reghive: str, regpath: str) -> Dict
The sys.get_reg method returns the registry values at the requested registry path. An example is below:
$> sys.get_reg("HKEY_LOCAL_MACHINE","SOFTWARE\\Microsoft\\Windows\\CurrentVersion")
{
"ProgramFilesDir": "C:\\Program Files",
"CommonFilesDir": "C:\\Program Files\\Common Files",
"ProgramFilesDir (x86)": "C:\\Program Files (x86)",
"CommonFilesDir (x86)": "C:\\Program Files (x86)\\Common Files",
"CommonW6432Dir": "C:\\Program Files\\Common Files",
"DevicePath": "%SystemRoot%\\inf",
"MediaPathUnexpanded": "%SystemRoot%\\Media",
"ProgramFilesPath": "%ProgramFiles%",
"ProgramW6432Dir": "C:\\Program Files",
"SM_ConfigureProgramsName": "Set Program Access and Defaults",
"SM_GamesName": "Games"
}
sys.get_user
sys.get_user() -> Dict
The sys.get_user method returns a dictionary that describes the current process’s running user. On *Nix, will return UID, EUID, GID, EGID, and detailed user info for the UID and EUID mappings. For users, will return name and groups of user.
{
"uid": {
"uid": 0,
"name": "root",
"gid": 0,
"groups": ["root"]
},
"euid": {
"uid": 0,
"name": "root",
"gid": 0,
"groups": ["root"]
},
"gid": 0,
"egid": 0
}
sys.hostname
sys.hostname() -> String
The sys.hostname method returns a String containing the host’s hostname.
sys.is_bsd
sys.is_bsd() -> bool
The sys.is_bsd method returns True
if on a freebsd
, netbsd
, or openbsd
system and False
on everything else.
sys.is_linux
sys.is_linux() -> bool
The sys.is_linux method returns True
if on a linux system and False
on everything else.
sys.is_macos
sys.is_macos() -> bool
The sys.is_macos method returns True
if on a mac os system and False
on everything else.
sys.is_windows
sys.is_windows() -> bool
The sys.is_windows method returns True
if on a windows system and False
on everything else.
sys.shell
sys.shell(cmd: str) -> Dict
The sys.shell Given a string run it in a native interpreter. On MacOS, Linux, and *nix/bsd systems this is /bin/bash -c <your command>
. On Windows this is cmd /C <your command>
. Stdout, stderr, and the status code will be returned to you as a dictionary with keys: stdout
, stderr
, status
. For example:
sys.shell("whoami")
{
"stdout":"root\n",
"stderr":"",
"status":0,
}
sys.shell("ls /nofile")
{
"stdout":"",
"stderr":"ls: cannot access '/nofile': No such file or directory\n",
"status":2,
}
sys.write_reg_hex
sys.write_reg_hex(reghive: str, regpath: str, regname: str, regtype: str, regvalue: str) -> Bool
The sys.write_reg_hex method returns True
if registry values are written to the requested registry path and accepts a hexstring as the value argument.
An example is below:
$> sys.write_reg_hex("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_SZ","deadbeef")
True
$> sys.write_reg_hex("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_BINARY","deadbeef")
True
$> sys.write_reg_hex("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_NONE","deadbeef")
True
$> sys.write_reg_hex("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_EXPAND_SZ","deadbeef")
True
$> sys.write_reg_hex("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_DWORD","deadbeef")
True
$> sys.write_reg_hex("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_DWORD_BIG_ENDIAN","deadbeef")
True
$> sys.write_reg_hex("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_LINK","deadbeef")
True
$> sys.write_reg_hex("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_MULTI_SZ","dead,beef")
True
$> sys.write_reg_hex("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_RESOURCE_LIST","deadbeef")
True
$> sys.write_reg_hex("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_FULL_RESOURCE_DESCRIPTOR","deadbeef")
True
$> sys.write_reg_hex("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_RESOURCE_REQUIREMENTS_LIST","deadbeef")
True
$> sys.write_reg_hex("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_QWORD","deadbeefdeadbeef")
True
sys.write_reg_int
sys.write_reg_int(reghive: str, regpath: str, regname: str, regtype: str, regvalue: int) -> Bool
The sys.write_reg_int method returns True
if registry values are written to the requested registry path and accepts an integer as the value argument.
An example is below:
$> sys.write_reg_int("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_SZ",12345678)
True
$> sys.write_reg_int("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_BINARY",12345678)
True
$> sys.write_reg_int("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_NONE",12345678)
True
$> sys.write_reg_int("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_EXPAND_SZ",12345678)
True
$> sys.write_reg_int("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_DWORD",12345678)
True
$> sys.write_reg_int("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_DWORD_BIG_ENDIAN",12345678)
True
$> sys.write_reg_int("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_LINK",12345678)
True
$> sys.write_reg_int("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_MULTI_SZ",12345678)
True
$> sys.write_reg_int("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_RESOURCE_LIST",12345678)
True
$> sys.write_reg_int("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_FULL_RESOURCE_DESCRIPTOR",12345678)
True
$> sys.write_reg_int("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_RESOURCE_REQUIREMENTS_LIST",12345678)
True
$> sys.write_reg_int("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_QWORD",12345678)
True
sys.write_reg_str
sys.write_reg_str(reghive: str, regpath: str, regname: str, regtype: str, regvalue: str) -> Bool
The sys.write_reg_str method returns True
if registry values are written to the requested registry path and accepts a string as the value argument.
An example is below:
$> sys.write_reg_str("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_SZ","BAR1")
True
$> sys.write_reg_str("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_BINARY","DEADBEEF")
True
$> sys.write_reg_str("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_NONE","DEADBEEF")
True
$> sys.write_reg_str("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_EXPAND_SZ","BAR2")
True
$> sys.write_reg_str("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_DWORD","12345678")
True
$> sys.write_reg_str("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_DWORD_BIG_ENDIAN","12345678")
True
$> sys.write_reg_str("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_LINK","A PLAIN STRING")
True
$> sys.write_reg_str("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_MULTI_SZ","BAR1,BAR2,BAR3")
True
$> sys.write_reg_str("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_RESOURCE_LIST","DEADBEEF")
True
$> sys.write_reg_str("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_FULL_RESOURCE_DESCRIPTOR","DEADBEEF")
True
$> sys.write_reg_str("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_RESOURCE_REQUIREMENTS_LIST","DEADBEEF")
True
$> sys.write_reg_str("HKEY_CURRENT_USER","SOFTWARE\\TEST1","FOO1","REG_QWORD","1234567812345678")
True
Time
time.format_to_epoch
time.format_to_epoch(input: str, format: str) -> int
The time.format_to_epoch method returns the seconds since epoch for the given UTC timestamp of the provided format. Input must include date and time components.
Some common formatting methods are:
- “%Y-%m-%d %H:%M:%S” (24 Hour Time)
- “%Y-%m-%d %I:%M:%S %P” (AM/PM)
For reference on all available format specifiers, see https://docs.rs/chrono/latest/chrono/format/strftime/index.html
time.format_to_readable
time.format_to_readable(input: int, format: str) -> str
The time.format_to_readable method returns the timestamp in the provided format of the provided UTC timestamp.
Some common formatting methods are:
- “%Y-%m-%d %H:%M:%S” (24 Hour Time)
- “%Y-%m-%d %I:%M:%S %P” (AM/PM)
For reference on all available format specifiers, see https://docs.rs/chrono/latest/chrono/format/strftime/index.html
time.now
time.now() -> int
The time.now method returns the time since UNIX EPOCH (Jan 01 1970). This uses the local system time.
time.sleep
time.sleep(secs: float)
The time.sleep method sleeps the task for the given number of seconds.
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.