> For the complete documentation index, see [llms.txt](https://rasta-mouse.gitbook.io/crystalc2/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://rasta-mouse.gitbook.io/crystalc2/documentation/lua/functions.md).

# Functions

CrystalC2 uses [MoonSharp](https://www.moonsharp.org/) (a Lua 5.2 interpreter) to let operators extend the client with custom commands and automation.  Scripts run in a hardened sandbox so the standard `io`, `os`, and `package` libraries are not available.

All custom functions are accessed through the global `crystal` table.

<details>

<summary>barch</summary>

Returns the architecture of a beacon as a string: "x86", "x64", or "unknown".

#### Example

```lua
local arch = crystal.barch( id )
crystal.log( "Beacon is " .. arch )
```

</details>

<details>

<summary>bof_pack</summary>

Pack arguments in a way that's suitable for the Beacon APIs to unpack.

#### Arguments

* `$1` - Beacon ID
* `$2` - Format template
* `...` - Arguments

<table><thead><tr><th width="139">Format string</th><th>Description</th><th>Unpack with</th></tr></thead><tbody><tr><td>b</td><td>Length-prefixed raw bytes</td><td>BeaconDataExtract</td></tr><tr><td>i</td><td>Signed 32-bit integer</td><td>BeaconDataInt</td></tr><tr><td>s</td><td>Signed 16-bit integer</td><td>BeaconDataShort</td></tr><tr><td>z</td><td>Length-prefixed ANSI string, null-terminated.</td><td>BeaconDataExtract</td></tr><tr><td>Z</td><td>Length-prefixed UTF-16LE string, double-null-terminated</td><td>(wchar_t *) BeaconDataExtract</td></tr></tbody></table>

#### Example

```lua
-- pack a string followed by an integer
local args = crystal.bof_pack( id, "zi", "hello", 42 )
crystal.inline( id, "/path/to/bof.o", args )
```

</details>

<details>

<summary>exit</summary>

Task a beacon to terminate.

#### Arguments

* `$1` - Beacon ID

#### Example

```lua
crystal.exit( id )
```

</details>

<details>

<summary>get_payload</summary>

Look up a payload from the payload store by name (case-insensitive).  Returns `nil` if not found, otherwise a table:

| Field   | Type          | Description             |
| ------- | ------------- | ----------------------- |
| `name`  | string        | Payload name            |
| `user`  | string        | User who added it       |
| `note`  | string or nil | Optional note           |
| `bytes` | binary string | Raw payload bytes       |
| `yara`  | string or nil | YARA rules if generated |

#### Example

```lua
local pl = crystal.get_payload( "http.x64.xprocess" )
if pl then
  crystal.log( "Payload size: " .. #pl.bytes )
end
```

</details>

<details>

<summary>inline</summary>

Execute a BOF in-process.

#### Arguments

* `$1` - Beacon ID
* `$2` - Path to COFF
* `$3` - Optional packed arguments
* `$4` - Optional spec file

#### Example

```lua
crystal.inline( id, "/path/to/coff.o" )
```

</details>

<details>

<summary>log</summary>

Write a string to the script console output.

#### Arguments

* `$1` - Text to print

#### Example

```lua
crystal.log( "Hello World" )
```

</details>

<details>

<summary>print</summary>

Send a text message to a specific Beacon's interaction window.

#### Arguments

* `$1` - Beacon ID
* `$2` - Text to print

#### Example

```lua
crystal.print( id, "Task queued successfully" )
```

</details>

<details>

<summary>railgun</summary>

Compile a Railgun script from a source string and dispatch it to a Beacon.

#### Example

```lua
local src = [[
import kernel32
$r = kernel32!GetCurrentProcessId()
]]
crystal.railgun( id, src )
```

</details>

<details>

<summary>register_command</summary>

Register a new command that appears in Beacon interaction sessions.

#### Arguments

* `$1` - Command alias
* `$2` - Command description
* `$3` - Handler
* `$4` - Callback

#### Example

```lua
function demo_handler( id, args )
  -- id: the target beacon
  -- args: 1-indexed array of string arguments the user typed
end

function demo_callback( info )
  -- info.beacon_id : the beacon id
  -- info.status    : string  ("Pending", "Tasked", "Complete", "Error")
  -- info.output    : string or nil (UTF-8 text from the beacon)
end

crystal.register_command( "demo", "Demo command", demo_handler, demo_callback )
```

</details>

<details>

<summary>sessions</summary>

Returns a table (array) of all active sessions.  Each entry has the following fields:

| Field      | Type    | Description                           |
| ---------- | ------- | ------------------------------------- |
| `id`       | integer | Beacon ID                             |
| `computer` | string  | Hostname                              |
| `user`     | string  | Username (with \* prefix if elevated) |
| `listener` | string  | Listener name                         |
| `ip`       | string  | Internal IP address                   |
| `pid`      | integer | Process ID                            |
| `process`  | string  | Process name                          |
| `arch`     | string  | "x86" or "x64"                        |
| `os`       | string  | OS version string                     |

#### Example

```lua
for _, s in ipairs( crystal.sessions() ) do
  crystal.log( s.computer .. " / " .. s.user )
end
```

</details>

<details>

<summary>script_resource</summary>

Resolve a path relative to the directory containing the current script.  Use this to load companion files that ship alongside a script.

#### Example

```lua
local path = crystal.script_resource( "bin/demo.x64.o" )
```

</details>

<details>

<summary>sleep</summary>

Task a beacon to update its sleep interval.  Jitter is a percentage (defaults to 0).

#### Example

```lua
crystal.sleep( id, 60, 25 )  -- 60s ± 25%
```

</details>
