carbonblackliveresponse
Collect information and take action on remote endpoints in real time with VMware Carbon Black EDR (Live Response API) (formerly known as Carbon Black Enterprise Live Response).
Endpoint · Carbon Black Enterprise Live Response
Details
| ID | carbonblackliveresponse |
|---|---|
| Provider | Broadcom |
| Category | Endpoint |
| From Version | 5.0.0 |
| Supported Modules | Agentix XSIAM EDR Cortex Cloud Cloud Runtime Security |
README
Overview
Use the VMware Carbon Black EDR (Live Response API) integration (formerly known as Carbon Black Enterprise Live Response) to enable security operators to collect information and take action on remote endpoints in real time.
VMware Carbon Black EDR (Live Response API) Integration is configurable with both VMware Carbon Black EDR (formerly known as Carbon Black Response) and VMware Carbon Black Endpoint Standard (formerly known as Carbon Black Defense).
Use Cases
- Upload, download, and remove files.
- Retrieve and remove registry entries.
- Dump contents of physical memory.
- Execute and terminate processes.
Playbooks
- Carbonblackliveresponse playbook
- Carbon Black Live Response - Wait until command complete
- Carbon Black Live Response - Create active session
- Carbon Black Live Response - Download file
Prerequisites
This integration can be used on either VMware Carbon Black EDR (formerly known as Carbon Black Response) or VMware Carbon Black Endpoint Standard (formerly known as Carbon Black Defense).
Carbon Black Live Response
Enable the Live Response API and get an API key. Live Response is disabled by default. If you attempt to use the Live Response integration before enabling it you receive a code 412 error message.
- In the
/etc/cb/cb.conffile, set CbLREnabled=True, to enable Live Response in your Carbon Black Response server. - Restart the Carbon Black Enterprise services to activate the changes.
Get an API key
Each user in VMware Carbon Black EDR has a personal API key. The API key confers all rights and capabilities assigned to that user to anyone with access to that API key. Therefore, treat your API key as you would your password.
If the API Token is missing or compromised, you can reset the API key to generate a new token and revoke any previous API keys issued to a user.
- Log in to the Carbon Black console.
- Click the username in the upper right and select Profile info.
- Click API Token on the left hand side to reveal your API token. If there is no API token displayed, click Reset to create a new one.
VMware Carbon Black Endpoint Standard
Retrieve an apiKey and connectorId from the Carbon Black environment.
- Navigate to Settings > Connector.
- Set up a VMware API Connector. This gives you access to the apiKey and connectorId.
Configure VMware Carbon Black EDR (Live Response API) on Cortex XSOAR
You can set up the integration to work with either VMware Carbon Black EDR or VMware Carbon Black Endpoint Standard.
Set the required fields to suit your instance ONLY.
To set up the integration to work with VMware Carbon Black EDR:
- Navigate to Settings > Integrations > Servers & Services.
- Search for carbonblackliveresponse.
- Click _Add instance to create and configure a new integration instance.
- Name: a textual name for the integration instance.
- Server URL: The hostname or IP address and port of the VMware Carbon Black EDR server used.
- API Token (CB Response): The VMware Carbon Black EDR API token.
- Click Test to validate the URLs, token, and connection.
To set up the integration to work with VMware Carbon Black Endpoint Standard:
- Navigate to Settings > Integrations > Servers & Services.
- Search for carbonblackliveresponse.
- Click _Add instance to create and configure a new integration instance.
- Name: a textual name for the integration instance.
- Server URL: The hostname or IP address and port of the VMware Carbon Black Endpoint Standard server used.
- API Token (CB Defense): The VMware Carbon Black Endpoint Standard API token.
- Connector ID (CB Defense): The VMware Carbon Black Endpoint Standard connector ID.
- Click Test to validate the URLs, token, and connection.
Using Live Response Integration
Establish a session with the sensor, to enable commands to be sent to an endpoint.
A sensor with an active session will keep an open connection to the Carbon Black server for as long as the session is active. Sessions are kept for a timeout period, and then recycled.
When executing Live response commands, you can either establish a new session with the sensor or execute commands without session management.
Establish a new session with the sensor and execute commands
- Enables you to execute multiple commands on the endpoint with one continues session.
- Faster execution time per command.
- Requires session management.
Establish a new session with a specified sensor
Create a new session using cb-session-create or cb-session-create-and-wait (for the session data to be returned only once active).
In the data returned you can find the session ID. This ID will be used to execute Live Response commands on the sensor and retrieve session information when needed.
Only one active session per sensor is allowed at a given time.
Execute Live Response commands providing the session ID
For example, !cb-directory-listing path="c:\" session=1234 wait-timeout=120
Command information will be returned once the command status is active or the wait-timeout has expired (in this case, the command status remains as pending).
In the case of timeout, you may inquire command status and retrieve the command data using cb-command-info.
You may run multiple Live Response commands on one running session, but note that each session has a timeout. This is the timeout that a sensor should wait between commands. If no command is issued over this timeout the sensor will quit.
To avoid session timeout:
- Set a longer timeout when creating a new session.
- Run the cb-keepalive command to reset session timeout.
Close the session using the cb-session-close command.
Execute commands without session management
- Session management is automated.
- Longer execution time per command.
-
Execute Live Response commands providing the sensor ID, e.g. !cb-directory-listing path="c:\" sensor=1 wait-timeout=120
This will automatically establish a new session with the endpoint, execute the command on the sensor and finally close the session.
Command information will be returned once the command status is active or thewait-timeouthas expired (in this case, the command status remains pending).
In the case of timeout, you may inquire command status and retrieve the command data usingcb-command-info.
Known Limitations
Session Limitations
Only one session per sensor is allowed at a given time. An error will occur when trying to open a new session for a sensor with existing active session.
Commands
You can execute these commands from the Cortex XSOAR CLI, as part of an automation, or in a playbook. After you successfully execute a command, a DBot message appears in the War Room with the command details.
- Archive a session: cb-archive
- Cancel a pending command: cb-command-cancel
- Display information for a command: cb-command-info
- Delete a file: cb-file-delete
- Download a file: cb-file-get
- Get a file's metadata: cb-file-info
- Upload a file to the Carbon Black server: cb-file-upload
- Keep a session alive: cb-keepalive
- List existing command instances for a session: cb-list-commands
- List files: cb-list-files
- List all sessions: cb-list-sessions
- Close a session: cb-session-close
- Create a new session: cb-session-create
- Create a new session and wait: cb-session-create-and-wait
- Get information about a session: cb-session-info
- Terminate a process: cb-process-kill
- List directories on the endpoint: cb-directory-listing
- Run an executable on an endpoint: cb-process-execute
- Endpoint memory dump: cb-memdump
- Create a command: cb-command-create
- Create a command and wait: cb-command-create-and-wait
- Terminate a process: cb-terminate-process
- Delete a file from an endpoint: cb-file-delete-from-endpoint
- Enumerate registry values: cb-registry-get-values
- Query for a registry value: cb-registry-query-value
- Create a new registry key: cb-registry-create-key
- Delete a registry key: cb-registry-delete-key
- Delete a registry value: cb-registry-delete-value
- Set a registry value: cb-registry-set-value
- Get a list of processes running on an endpoint: cb-process-list
- Get a file from an endpoint: cb-get-file-from-endpoint
- Save a file to an endpoint: cb-push-file-to-endpoint
1. Archive a session
Archives the specified session. If the session has no content the command fails.
Base Command
cb-archive
Input
| Parameter | Description | Required |
| session | Session ID to archive | Required |
Context Output
There is no context output for this command.
Command Example
cb-archive session=3997
Context Example
{
"EntryID": "56@a8449d77-4188-4270-846a-396c5a20d1ef",
"Extension": "zip",
"Info": "zip",
"MD5": "81e67ceddfa1dd2fa668840ffab869c0",
"Name": "session-3951-archive.zip",
"SHA1": "212ee624e5312d6e589018c23b708682499074f3",
"SHA256": "64ef1bd46694f9da1ddc1820d3e5f32e147945f024ab8808b6daba4c6b9b1d86",
"SSDeep": "96:+DAlcOC5Ee//Jbv6CAOYfyYbzz10xldoqbcdqcLE:+DucOa5bv6CdYXbzJ0x7oLLE",
"Size": 3751,
"Type": "gzip compressed data, was "/tmp/tmpvpb7Nt", last modified: Mon Aug 6 07:41:02 2018, max compression\n"
}
Human Readable Output
2. Cancel a pending command
Cancels the specified command. Only pending commands can be canceled.
Base Command
cb-command-cancel
Input
| Parameter | Description | Required |
| session | Session ID of command to cancel | Required |
| command | Command ID to cancel | Required |
Context Output
| Path | Description |
| CbLiveResponse.Commands.Status | The command status. |
| CbLiveResponse.Commands.Hostname | The hostname of the host running the command. |
| CbLiveResponse.Commands.CbSensorID | The sensor ID. |
| CbLiveResponse.Commands.CommandName | The command name. |
| CbLiveResponse.Commands.CbSessionID | The session ID. |
| CbLiveResponse.Commands.CbCommandID | The command ID. |
| CbLiveResponse.Commands.OperandObject | Object argument for the CbLive command.For example, for directory list this is the dir path.Click here for more information about the command objects. |
| CbLiveResponse.Commands.CreateTime | The command's time of creation. |
| CbLiveResponse.Commands.CommandCompletionTime |
When the command was completed. (0 means the command is still in progress.) |
| CbLiveResponse.Commands.Result.Desc | Result description. |
| CbLiveResponse.Commands.esult.Type | Result type. |
| CbLiveResponse.Commands.Result.Code | Result code. |
Command Example
!cb-command-cancel command=1 session=348
Context Example
Human Readable Output
3. Display information for a command
Displays the information of the specified command.
Base Command
cb-command-info
Input
| Parameter | Description | Required |
| session | Session ID of the command | Required |
| command | Command ID | Required |
Context Output
There is no context output for this command.
Command Example
!cb-command-info command=1 session=348
Context Example
{
"CbLiveResponse": {
"Commands": {
"CbCommandID": 1,
"CbSensorID": 17,
"CbSessionID": 348,
"CommandCompletionTime": 1540228071.195328,
"CommandName": "process list",
"CreateTime": 1540228071.098885,
"OperandObject": null,
"Process": [
{
"CommandLine": "",
"CreateTime": 1535357799,
"Parent": 0,
"ParentGuid": "00000011-0000-0000-0000-000000000000",
"Path": "c:\\windows\\system32\\ntoskrnl.exe",
"ProcessGuid": "00000011-0000-0004-01d4-3dde478174d0",
"ProcessID": 4,
"SecurityIdentifier": "s-1-5-18",
"Username": "NT AUTHORITY\\SYSTEM"
}
],
"Result.Code": 0,
"Result.Desc": "",
"Result.Type": "WinHresult",
"Status": "complete"
}
}
}
Human Readable Output
CB Response - List Processes: Command Status
| Cb Sensor ID | Cb Session ID | Cb Command ID | Command Name | Status | Create Time | Command Completion Time | Operand Object | Result Desc | Result Type | Result Code |
|---|---|---|---|---|---|---|---|---|---|---|
| 17 | 348 | 1 | process list | complete | 1540228071.098885 | 1540228071.195328 | WinHresult | 0 |
CB Response - Processes
| Process ID | Create Time | Process Guid | Path | Command Line | Security Identifier | Username | Parent | Parent Guid |
|---|---|---|---|---|---|---|---|---|
| 4 | 1535357799 | 00000011-0000-0004-01d4-3dde478174d0 | c:\windows\system32\ntoskrnl.exe | s-1-5-18 | NT AUTHORITY\SYSTEM | 0 | 00000011-0000-0000-0000-000000000000 |
4. Delete a file
Deletes the specified file from the Carbon Black server.
Base Command
cb-file-delete
Input
| Parameter | Description | Required |
| session | Session ID | Required |
| file-id | File ID | Required |
Context Output
| Path | Description |
| CbLiveResponse.Files.Filename | The file name. |
| CbLiveResponse.Files.Size | The file size. |
| CbLiveResponse.Files.CbFileID |
The ID of the file within the Cb Session Storage. - use with |
| CbLiveResponse.Files.Status | File status (0 means there is no error). |
| CbLiveResponse.Files.Delete | Whether the file was deleted (Boolean). |
Command Example
Context Example
Human Readable Output
5. Download a file
Downloads the specified file from the specified session from the Carbon Black server.
Before executing this command, push the file to the Carbon Black endpoint. use command 7-hyperlink, and the name=get-file argument to do this.
Use cb-command-create with name=get-file to push the file from a path on the endpoint to the Carbon Black server before executing cb-file-get.
Base Command
cb-file-get
Input
| Parameter | Description | Required |
| session | Session ID | Required |
| file-id | File ID | Required |
Context Output
There is no context output for this command.
Command Example
Context Example
Human Readable Output
6. Get a file's metadata
Returns information about the specified file in a specified session.
Base Command
cb-file-info
Input
| Parameter | Description | Required |
| session | Session ID | Required |
| file-id | File ID | Optional |
Context Output
| Path | Description |
| CbLiveResponse.Files.Filename | The file name. |
| CbLiveResponse.Files.Size | The file size. |
| CbLiveResponse.Files.CbFileID |
The ID of the file within the Carbon Black Session Storage use with cb-file-get. |
| CbLiveResponse.Files.Status | File status (0 means there is no error). |
| CbLiveResponse.Files.Delete | Whether the file was deleted (Boolean). |
Command Example
Context Example
Human Readable Output
7. Upload a file to the Carbon Black server
Uploads the specified file to the Carbon Black server.
Use cb-command-create with name=put-file to push the file from Cb server to a path on the endpoint.
Base Command
cb-file-upload
Input
| Parameter | Description | Required |
| session | The ID of the session to upload the attachment file through | Required |
| file-id | The entry ID of the attachment file to upload. | Required |
Context Output
| Path | Description |
| CbLiveResponse.Files.Filename | The File name |
| CbLiveResponse.Files.Size | The file size |
| CbLiveResponse.Files.CbFileID |
The ID of the file within the Carbon Defence Session Storage - use with cb-file-get. |
| CbLiveResponse.Files.Status | File status (0 means there is no error). |
| CbLiveResponse.Files.Delete | Whether the file was deleted (Boolean). |
Command Example
Context Example
Human Readable Output
8. Keep a session alive
Keeps the specified session alive so that it does not close due to timeout.
Base Command
cb-keepalive
Input
| Parameter | Description | Required |
| session | The ID of the session to keep alive | Required |
Context Output
There is no context output for this command.
Command Example
Context Example
Human Readable Output
9. List existing command instances in a specified session
Returns a list of the existing command instances and their details for the specified session.
Base Command
cb-list-commands
Input
| Parameter | Description | Required |
| session | The session ID | Required |
Context Output
There is no context output for this command.
Command Example
!cb-list-commands session="3951"
Context Example
{
"Commands": [
{
"CbCommandID": 1,
"CbSensorID": 13,
"CbSessionID": 3951,
"CommandCompletionTime": 1533449964.328933,
"CommandName": "process list",
"CreateTime": 1533449963.906452,
"OperandObject": null,
"Result": {
"Code": 0,
"Desc": "",
"Type": "WinHresult"
},
"Status": "complete"
},
{
"CbCommandID": 2,
"CbSensorID": 13,
"CbSessionID": 3951,
"CommandCompletionTime": 1533450217.730081,
"CommandName": "process list",
"CreateTime": 1533450217.214258,
"OperandObject": null,
"Result": {
"Code": 0,
"Desc": "",
"Type": "WinHresult"
},
"Status": "complete"
},
{
"CbCommandID": 3,
"CbSensorID": 13,
"CbSessionID": 3951,
"CommandCompletionTime": 1533450219.874692,
"CommandName": "directory list",
"CreateTime": 1533450219.635134,
"OperandObject": "C:\\Windows\\CarbonBlack",
"Result": {
"Code": 0,
"Desc": "",
"Type": "WinHresult"
},
"Status": "complete"
},
{
"CbCommandID": 4,
"CbSensorID": 13,
"CbSessionID": 3951,
"CommandCompletionTime": 1533450220.312491,
"CommandName": "directory list",
"CreateTime": 1533450220.067548,
"OperandObject": "C:\\Windows\\CarbonBlack\\*",
"Result": {
"Code": 0,
"Desc": "",
"Type": "WinHresult"
},
"Status": "complete"
},
{
"CbCommandID": 5,
"CbSensorID": 13,
"CbSessionID": 3951,
"CommandCompletionTime": 1533450225.146843,
"CommandName": "directory list",
"CreateTime": 1533450224.903408,
"OperandObject": "C:\\Windows",
"Result": {
"Code": 0,
"Desc": "",
"Type": "WinHresult"
},
"Status": "complete"
}
]
}
Human Readable Output
10. List files
Lists files in the given session
Base Command
cb-list-files
Input
| Parameter | Description | Required |
| session | The session ID | Required |
Context Output
| Path | Description |
| CbLiveResponse.Files.Filename | The file name |
| CbLiveResponse.Files.Size | The file size |
| CbLiveResponse.Files.CbFileID |
The ID of the file within the Carbon Black Session Storage - use with cb-file-get. |
| CbLiveResponse.Files.Status | File status (0 means there is no error) |
| CbLiveResponse.Files.Delete | Whether the file was deleted (Boolean) |
Command Example
!cb-list-files session=3951
Context Example
Human Readable Output
11. List Carbon Black sessions
Returns a list of the Carbon Black sessions.
Base Command
cb-list-sessions
Input
| Parameter | Description | Required |
| sensor | Sensor ID to filter sessions by. | Optional |
| status |
Status to filter by. Valid values are:
|
Optional |
Context Output
| Path | Description |
| CbLiveResponse.Sessions.CbSensorID | Sensor ID |
| CbLiveResponse.Sessions.CbSessionID | Session ID |
| CbLiveResponse.Sessions.Hostname | Hostname |
| CbLiveResponse.Sessions.Status | Session status |
| CbLiveResponse.Sessions.WaitTimeout | Sensor wait timeout |
| CbLiveResponse.Sessions.SessionTimeout | Session Timeout |
Command Example
!cb-list-sessions status=timeout
Context Example
{
"Sessions": {
"CbSensorID": 13,
"CbSessionID": 3951,
"Hostname": "WIN1",
"SessionTimeout": 300,
"Status": "timeout",
"SupportedCommands": [
"delete file",
"put file",
"reg delete key",
"directory list",
"reg create key",
"get file",
"reg enum key",
"reg query value",
"kill",
"create process",
"process list",
"reg delete value",
"reg set value",
"create directory",
"memdump"
],
"WaitTimeout": 120
}
}
Human Readable Output
12. Close a session
Closes the specified session.
Base Command
cb-session-close
Input
| Parameter | Description | Required |
| session | The ID of the session to close | Required |
Context Output
| Path | Description |
| CbLiveResponse.Sessions.Status | Session status |
| CbLiveResponse.Sessions.Hostname | Hostname |
| CbLiveResponse.Sessions.CbSensorID | Sensor ID |
| CbLiveResponse.Sessions.CbSessionID | Session ID |
| CbLiveResponse.Sessions.SessionTimeout | Session Timeout |
| CbLiveResponse.Sessions.WaitTimeout | Sensor wait timeout |
Command Example
!cb-session-close session=3951
Context Example
{
"CbSensorID": 13,
"CbSessionID": 3951,
"Hostname": "WIN1",
"SessionTimeout": 300,
"Status": "close",
"SupportedCommands": [
"delete file",
"put file",
"reg delete key",
"directory list",
"reg create key",
"get file",
"reg enum key",
"reg query value",
"kill",
"create process",
"process list",
"reg delete value",
"reg set value",
"create directory",
"memdump"
],
"WaitTimeout": 120
}
Human Readable Output
13. Create a new session
Creates a new Carbon Black session for the specified sensor.
Base Command
cb-session-create
Input
| Parameter | Description | Required |
| sensor | The ID of the sensor to create a session for | Required |
| command-timeout | If a command is not be issued before this time, the session closes | Optional |
| keepalive-timeout |
If a command is not issued after this specified number of seconds, the device quits. |
Optional |
Context Output
| Path | Description |
| CbLiveResponse.Sessions.Status | Session Status |
| CbLiveResponse.Sessions.Hostname | Hostname |
| CbLiveResponse.Sessions.CbSensorID | Sensor ID |
| CbLiveResponse.Sessions.CbSessionID | Session ID |
| CbLiveResponse.Sessions.SessionTimeout | Session Timeout |
| CbLiveResponse.Sessions.WaitTimeout | Sensor wait timeout |
Command Example
!cb-session-create sensor=13
Context Example
{
"CbSensorID": 13,
"CbSessionID": 3996,
"Hostname": "WIN1",
"SessionTimeout": 300,
"Status": "pending",
"SupportedCommands": [],
"WaitTimeout": 120
}
Human Readable Output
14. Create a new session and wait
Creates a new Carbon Black session for the specified sensor and waits for it to be active.
Base Command
cb-session-create-and-wait
Input
| Parameter | Description | Required |
| sensor | The ID of the sensor to create a session for | Required |
| command-timeout | If a command is not be issued before this time, the session closes | Optional |
| keepalive-timeout |
If the 8 command (keepalive) -hyperlink, is not issued before this time, the session closes. |
Optional |
| wait-timeout | The number of seconds to wait for session to be active | Optional |
Context Output
| Path | Description |
| CbLiveResponse.Sessions.Status | Session status |
| CbLiveResponse.Sessions.Hostname | Hostname |
| CbLiveResponse.Sessions.CbSensorID | Sensor ID |
| CbLiveResponse.Sessions.CbSessionID | Session ID |
| CbLiveResponse.Sessions.SessionTimeout | Session Timeout |
| CbLiveResponse.Sessions.WaitTimeout | Sensor wait timeout |
Command Example
!cb-session-create-and-wait sensor=17
Context Example
{
"CbLiveResponse": {
"Sessions": {
"CbSensorID": 17,
"CbSessionID": 334,
"Hostname": "WIN-B73RGE9AAIF",
"SessionTimeout": 300,
"Status": "active",
"SupportedCommands": [
"delete file",
"put file",
"reg delete key",
"directory list",
"reg create key",
"get file",
"reg enum key",
"reg query value",
"kill",
"create process",
"process list",
"reg delete value",
"reg set value",
"create directory",
"memdump"
],
"WaitTimeout": 120
}
}
}
Human Readable Output
CB Response - Create Session And Wait
| Cb Sensor ID | Cb Session ID | Hostname | Status | Wait Timeout | Session Timeout | Supported Commands |
|---|---|---|---|---|---|---|
| 17 | 334 | WIN-B73RGE9AAIF | active | 120 | 300 | delete file,put file,reg delete key,directory list,reg create key,get file,reg enum key,reg query value,kill,create process,process list,reg delete value,reg set value,create directory,memdump |
15. Get information about a session
Displays information about the specified session.
Base Command
cb-session-info
Input
| Parameter | Description | Required |
| session | The ID of the session ID to get information about | Required |
Context Output
| Path | Description |
| CbLiveResponse.Sessions.Status | Session status |
| CbLiveResponse.Sessions.Hostname | Hostname |
| CbLiveResponse.Sessions.CbSensorID | Sensor ID |
| CbLiveResponse.Sessions.CbSessionID | Session ID |
| CbLiveResponse.Sessions.SessionTimeout | Session Timeout |
| CbLiveResponse.Sessions.WaitTimeout | Sensor wait timeout |
Command Example
!cb-session-info session=3997
Context Example
{
"CbSensorID": 13,
"CbSessionID": 3997,
"Hostname": "WIN1",
"SessionTimeout": 300,
"Status": "active",
"SupportedCommands": [
"delete file",
"put file",
"reg delete key",
"directory list",
"reg create key",
"get file",
"reg enum key",
"reg query value",
"kill",
"create process",
"process list",
"reg delete value",
"reg set value",
"create directory",
"memdump"
],
"WaitTimeout": 120
}
Human Readable Output
16. Terminate a process
Terminates the specified process on the sensor or endpoint.
Base Command
cb-process-kill
Input
| Parameter | Description | Required |
| session | The session ID | Optional |
| pid | The PID of the process to terminate | Required |
| wait-timeout | Time to wait (in seconds) for Cb command to be executed (change status from pending to in progress</em/complete) | Optional |
| cancel-on-timeout | If the command is still pending after this time, the command is cancelled | Optional |
| sensor | The sensor ID. Provided the sensor ID to run the command with a new session. The session will be created and closed automatically | Optional |
Context Output
| Path | Description |
| CbLiveResponse.Commands.CbCommandID | Unique command ID |
| CbLiveResponse.Commands.CommandName | The command name |
| CbLiveResponse.Commands.Status |
The command status
|
| CbLiveResponse.Commands.CommandCompletionTime | The time the command was completed (0 if not completed) |
| CbLiveResponse.Commands.OperandObject | The process ID |
Command Example
!cb-process-kill pid=972 sensor=17
Context Example
{
"CbLiveResponse": {
"Commands": {
"CbCommandID": 1,
"CbSensorID": 17,
"CbSessionID": 328,
"CommandCompletionTime": 1540219865.188614,
"CommandName": "kill",
"CreateTime": 1540219865.160948,
"OperandObject": "972",
"Result": {
"Code": 0,
"Desc": "",
"Type": "WinHresult"
},
"Status": "complete"
}
}
}
Human Readable Output
CB Response - Kill Process 972: Command Status
| Cb Sensor ID | Cb Session ID | Cb Command ID | Command Name | Status | Create Time | Command Completion Time | Operand Object | Result Desc | Result Type | Result Code |
|---|---|---|---|---|---|---|---|---|---|---|
| 17 | 328 | 1 | kill | complete | 1540219865.160948 | 1540219865.188614 | 972 | WinHresult | 0 |
17. List directories
Returns a list of directories on the endpoint.
Base Command
cb-directory-listing
Input
| Parameter | Description | Required |
| session | The session ID. | Optional |
| path | Path for the directory (e.g. "c:\Users\"). Note to end with double backslash. | Required |
| wait-timeout | Time to wait (in seconds) for Cb command to be executed (change status from 'pending' to 'in-progress'/'complete'). | Optional |
| cancel-on-timeout | Cancel the command if still 'pending' after timeout. | Optional |
| sensor | The sensor ID. Provided the sensor ID to run the command with a new session. The session will be created and closed automatically. | Optional |
Context Output
| Path | Description |
| CbLiveResponse.Commands.CbCommandID | Unique command ID |
| CbLiveResponse.Commands.CommandName | The command name |
| CbLiveResponse.Commands.DirectoryList.Status |
The command status
|
| CbLiveResponse.Commands.CommandCompletionTime | The time the command was completed (0 if not complete) |
| CbLiveResponse.Commands.OperandObject | the directory listing filter (or path) |
| CbLiveResponse.Commands.Files.FileAttributes | A list of file attributes |
| CbLiveResponse.Commands.Files.CreateTime | Create time in Unix time format |
| CbLiveResponse.Commands.Files.LastAccessTime | Last access time in Unix time format. |
| CbLiveResponse.Commands.Files.LastWriteTime | Last write time in Unix time format. |
| CbLiveResponse.Commands.Files.FileSize | The file size. |
| CbLiveResponse.Commands.Files.FileName | The file name. |
Command Example
!cb-directory-listing path="c:\Users\All Users\Desktop\" sensor=17
Context Example
{
"CbLiveResponse": {
"Commands": {
"CbCommandID": 1,
"CbSensorID": 17,
"CbSessionID": 332,
"CommandCompletionTime": 1540220585.720132,
"CommandName": "directory list",
"CreateTime": 1540220585.692945,
"Files": [
{
"AlternativeName": null,
"CreateTime": 1377185970,
"FileAttributes": [
"READONLY",
"HIDDEN",
"DIRECTORY"
],
"FileName": ".",
"FileSize": 0,
"LastAccessTime": 1534297982,
"LastWriteTime": 1534297982
},
{
"AlternativeName": null,
"CreateTime": 1377185970,
"FileAttributes": [
"READONLY",
"HIDDEN",
"DIRECTORY"
],
"FileName": "..",
"FileSize": 0,
"LastAccessTime": 1534297982,
"LastWriteTime": 1534297982
},
{
"AlternativeName": null,
"CreateTime": 1377185972,
"FileAttributes": [
"HIDDEN",
"SYSTEM",
"ARCHIVE"
],
"FileName": "desktop.ini",
"FileSize": 174,
"LastAccessTime": 1377185877,
"LastWriteTime": 1377185877
},
{
"AlternativeName": "GOOGLE~1.LNK",
"CreateTime": 1509481395,
"FileAttributes": [
"ARCHIVE"
],
"FileName": "Google Chrome.lnk",
"FileSize": 2163,
"LastAccessTime": 1509481395,
"LastWriteTime": 1533760799
}
],
"OperandObject": "c:\\Users\\All Users\\Desktop\\",
"Result": {
"Code": 0,
"Desc": "",
"Type": "WinHresult"
},
"Status": "complete"
}
}
}
Human Readable Output
CB Response - Directory Listing: Command Status
| Cb Sensor ID | Cb Session ID | Cb Command ID | Command Name | Status | Create Time | Command Completion Time | Operand Object | Result Desc | Result Type | Result Code |
|---|---|---|---|---|---|---|---|---|---|---|
| 17 | 332 | 1 | directory list | complete | 1540220585.692945 | 1540220585.720132 | c:\Users\All Users\Desktop| | WinHresult | 0 |
CB Response - Directory Listing
| File Attributes | Create Time | Last Access Time | Last Write Time | File Size | File Name | Alternative Name |
|---|---|---|---|---|---|---|
| READONLY,HIDDEN,DIRECTORY | 1377185970 | 1534297982 | 1534297982 | 0 | . | |
| READONLY,HIDDEN,DIRECTORY | 1377185970 | 1534297982 | 1534297982 | 0 | .. | |
| HIDDEN,SYSTEM,ARCHIVE | 1377185972 | 1377185877 | 1377185877 | 174 | desktop.ini | |
| ARCHIVE | 1509481395 | 1509481395 | 1533760799 | 2163 | Google Chrome.lnk | GOOGLE~1.LNK |
18. Run an executable on an endpoint
Runs the executable on an endpoint.
Base Command
cb-process-execute
Input
| Parameter | Description | Required |
| session | The session ID. | Optional |
| sensor | The sensor ID. Provided the sensor ID to run the command with a new session. The session will be created and closed automatically. | Optional |
| path | the path and command line of the executable | Required |
| wait | An optional parameter to specify whether to wait for the process to complete execution before reporting the result. | Optional |
| working-directory | An optional parameter to specify the working directory of the executable. | Optional |
| output-file | An option file that STDERR and STDOUT will be redirected to. | Optional |
| wait-timeout | Time to wait (in seconds) for Cb command to be executed (change status from 'pending' to 'in-progress'/'complete'). | Optional |
| cancel-on-timeout | Cancel the command if still 'pending' after timeout. | Optional |
Context Output
| Path | Description |
| CbLiveResponse.Commands.CbCommandID | Unique command ID |
| CbLiveResponse.Commands.CommandName | The command name |
| CbLiveResponse.Commands.Status |
The command Status
|
| CbLiveResponse.Commands.CommandCompletionTime | The command completion time (0 if not complete). |
| CbLiveResponse.Commands.OperandObject | The path and command line of the executable |
| CbLiveResponse.Commands.ReturnCode | The return code of the process (if wait was set to true) |
| CbLiveResponse.Commands.ProcessID | The PID of the executed process |
Command Example
Context Example
Human Readable Output
19. Endpoint memory dump
Endpoint memory dump.
Base Command
cb-memdump
Input
| Parameter | Description | Required |
| session | The session ID. | Optional |
| sensor | The sensor ID. Provided the sensor ID to run the command with a new session. The session will be created and closed automatically. | Optional |
| path | the path to save the resulting memory dump (on the endpoint). | Required |
| compress | An optional parameter to specify whether to compress resulting memory dump. | Optional |
| wait-timeout | Time to wait (in seconds) for Cb command to be executed (change status from 'pending' to 'in-progress'/'complete'). | Optional |
| cancel-on-timeout | Cancel the command if still 'pending' after timeout. | Optional |
Context Output
| Path | Description |
| CbLiveResponse.Commands.CbCommandID | Unique command ID |
| CbLiveResponse.Commands.CommandName | The command name |
| CbLiveResponse.Commands.Status |
The command Status
|
| CbLiveResponse.Commands.CommandCompletionTime | The command completion time (0 if not complete) |
| CbLiveResponse.Commands.OperandObject | The path to save the resulting memory dump (on the endpoint) |
| CbLiveResponse.Commands.ReturnCode | Return code of the memory dump process |
| CbLiveResponse.Commands.CompressingEnabled | Boolean flag indicating if compression is enabled. |
| CbLiveResponse.Commands.Complete | Boolean flag indicating if memory dump is completed. |
| CbLiveResponse.Commands.PercentDone | Percent of the process completed |
| CbLiveResponse.Commands.DumpingInProgress | Boolean flag indicating if memory dump is in progress. |
Command Example
!cb-memdump path="c:\Users\All Users\Desktop" sensor=17
Context Example
Human Readable Output
20. Create a live response command
Creates a Carbon Black Live Response command.
Base Command
cb-command-create
Input
| Parameter | Description | Required |
| name | Command name | Required |
| timeout | Command timeout | Optional |
| object | the object the command operates on. This is specific to the command but has meaning in a generic way for logging, and display purposes | Optional |
| compress | "true" or "false" - an optional parameter to specify whether to compress resulting memory dump | Optional |
| working-dir | An optional parameter to specify the working directory of the executable | Optional |
| output-file | An option file that STDERR and STDOUT will be redirected to. | Optional |
| value-data | the data associated with the registry value | Optional |
| value-type | the string representation of the registry value type (ie REG_DWORD, REG_QWORD, ….) | Optional |
| overwrite | “true” or “false”. An optional parameter to specify whether to overwrite the value if it already exists (default value is “false”) | Optional |
| offset | a byte offset to start getting the file. Supports a partial get. | Optional |
| get-count | the number of bytes to grab | Optional |
| session | Session ID to create command for | Required |
Context Output
| Path | Description |
| CbLiveResponse.Commands.Status | The Command Status |
| CbLiveResponse.Commands.Hostname | The hostname running the command |
| CbLiveResponse.Commands.CbLiveResponse.Commands.CbSensorID | The Sensor ID |
| CbLiveResponse.Commands.CommandName | The Command name |
| CbLiveResponse.Commands.CbSessionID | The Session ID |
| CbLiveResponse.Commands.CbCommandID | The Command ID |
| CbLiveResponse.Commands.OperandObject | Object argument for the CbLive command - e.g. for 'directory list' this is the path of the dir to list. For more information, see the Carbon Black documentation. |
| CbLiveResponse.Commands.CreateTime | Command create time |
| CbLiveResponse.Commands.CommandCompletionTime | The time the command completed or 0 if still in progres. |
| CbLiveResponse.Commands.Result.Desc | Result description |
| CbLiveResponse.Commands.Result.Type | Result type |
| CbLiveResponse.Commands.Result.Code | Result code |
Command Example
!cb-command-create session=337 name="process-list"
!cb-command-create session=337 name="directory-list" object="c:\Users\" (path)
!cb-command-create session=337 name=kill object=1 (pid)
Context Example
Human Readable Output
21. Create a Live Response command and wait
Creates a Live Response command and waits for it to finish executing.
Base Command
cb-command-create-and-wait
Input
| Parameter | Description | Required |
| name | Command name | Required |
| timeout | Command timeout | Optional |
| object | the object the command operates on. This is specific to the command but has meaning in a generic way for logging, and display purposes | Optional |
| compress | "true" or "false" - an optional parameter to specify whether to compress resulting memory dump | Optional |
| working-dir | An optional parameter to specify the working directory of the executable | Optional |
| output-file | An option file that STDERR and STDOUT will be redirected to. | Optional |
| value-data | the data associated with the registry value | Optional |
| value-type | the string representation of the registry value type (ie REG_DWORD, REG_QWORD, ….) | Optional |
| overwrite | “true” or “false”. An optional parameter to specify whether to overwrite the value if it already exists (default value is “false”) | Optional |
| offset | a byte offset to start getting the file. Supports a partial get. | Optional |
| get-count | the number of bytes to grab | Optional |
| session | Session ID to create command for | Required |
| wait-timeout | Time to wait in seconds to wait for command to finish executing | Optional |
Context Output
There is no context output for this command.
Command Example
!cb-command-create-and-wait session=337 name="process-list"
!cb-command-create-and-wait session=337 name="directory-list" object="c:\Users\" (path)
!cb-command-create-and-wait session=337 name=kill object=1 (pid)
Context Example
Human Readable Output
22. Terminate a process
Terminates the specified process at the sensor endpoint.
Base Command
cb-terminate-process
Input
| Parameter | Description | Required |
| session | Session ID | Required |
| pid | The PID of the process to terminate | Required |
| wait-timeout | Time to wait in seconds for process to complete termination | Optional |
Context Output
There is no context output for this command.
Command Example
Context Example
Human Readable Output
23. Delete a file from an endpoint
Deletes the specified file from an endpoint.
Base Command
cb-file-delete-from-endpoint
Input
| Parameter | Description | Required |
| session | The session ID. | Optional |
| sensor | The sensor ID. Provided the sensor ID to run the command with a new session. The session will be created and closed automatically. | Optional |
| path | The source path of the object to delete. | Required |
| wait-timeout | Time to wait (in seconds) for Cb command to be executed (change status from 'pending' to 'in-progress'/'complete'). | Optional |
| cancel-on-timeout | Cancel the command if still 'pending' after timeout. | Optional |
Context Output
| Path | Description |
| CbLiveResponse.Commands.CbCommandID | Unique command ID |
| CbLiveResponse.Commands.CommandName | The command name |
| CbLiveResponse.Commands.Status |
The command status
|
| CbLiveResponse.Commands.CommandCompletionTime | The command completion time (0 if not complete). |
| CbLiveResponse.Commands.OperandObject | The source path of the object to delete |
Command Example
!cb-file-delete-from-endpoint sensor="17" path="c:\Users\All Users\Desktop\mooncake.jpg" wait-timeout="20"
Context Example
{
"CbLiveResponse": {
"Commands": {
"CbCommandID": 1,
"CbSensorID": 17,
"CbSessionID": 339,
"CommandCompletionTime": 1540224791.225669,
"CommandName": "delete file",
"CreateTime": 1540224791.197925,
"OperandObject": "c:\\Users\\All Users\\Desktop\\mooncake.jpg",
"Result": {
"Code": 2147942402,
"Desc": "",
"Type": "WinHresult"
},
"Status": "error"
}
}
}
Human Readable Output
CB Response - Delete File From Endpoint: Command Status
| Cb Sensor ID | Cb Session ID | Cb Command ID | Command Name | Status | Create Time | Command Completion Time | Operand Object | Result Desc | Result Type | Result Code |
|---|---|---|---|---|---|---|---|---|---|---|
| 17 | 339 | 1 | delete file | error | 1540224791.197925 | 1540224791.225669 | c:\Users\All Users\Desktop\mooncake.jpg | WinHresult | 2147942402 |
24. Enumerate registry values
Enumerates the registry values.
Base Command
cb-registry-get-values
Input
| Parameter | Description | Required |
| session | The session ID. | Optional |
| sensor | The sensor ID. Provided the sensor ID to run the command with a new session. The session will be created and closed automatically. | Optional |
| path | The path of the key to query | Required |
| wait-timeout | Time to wait (in seconds) for Cb command to be executed (change status from 'pending' to 'in-progress'/'complete'). | Optional |
| cancel-on-timeout | Cancel the command if still 'pending' after timeout. | Optional |
Context Output
| Path | Description |
| CbLiveResponse.Commands.CbCommandID | Unique command ID |
| CbLiveResponse.Commands.CommandName | The command name |
| CbLiveResponse.Commands.Status |
The command status
|
| CbLiveResponse.Commands.CommandCompletionTime | The command completion time (0 if not complete). |
| CbLiveResponse.Commands.OperandObject | The path of the key to queried |
| CbLiveResponse.Commands.Values.RegKeyType | Registry value type |
| CbLiveResponse.Commands.Values.RegKeyName | The name of the registry value |
| CbLiveResponse.Commands.Values.RegKeyData | The data associated with the registry value |
| CbLiveResponse.Commands.SubKeys | List of subkey names |
Command Example
Context Example
Human Readable Output
25. Query for a registry value
Query for registry value.
Base Command
cb-registry-query-value
Input
| Parameter | Description | Required |
| session | The session ID. | Optional |
| sensor | The sensor ID. Provided the sensor ID to run the command with a new session. The session will be created and closed automatically. | Optional |
| path | The path of the key + the path of the value (e.g. HKEY_LOCAL_MACHINE\blah\key\value). | Required |
| wait-timeout | Time to wait (in seconds) for Cb command to be executed (change status from 'pending' to 'in-progress'/'complete'). | Optional |
| cancel-on-timeout | Cancel the command if still 'pending' after timeout. | Optional |
Context Output
| Path | Description |
| CbLiveResponse.Commands.CbCommandID | Unique command identifier. |
| CbLiveResponse.Commands.CommandName | The command name. |
| CbLiveResponse.Commands.Status | The command Status ('pending', 'in progress', 'complete', 'error', 'canceled'). |
| CbLiveResponse.Commands.CommandCompletionTime | The command completion time (0 if not complete). |
| CbLiveResponse.Commands.OperandObject | the path of the key + the path of the value (ie HKEY_LOCAL_MACHINE\blah\key\value). |
| CbLiveResponse.Commands.Registry.QueryValue.Values.RegKeyType | Registry value type. |
| CbLiveResponse.Commands.RegKeyName | the name of the registry value. |
| CbLiveResponse.Commands.RegKeyData | The data associated with the registry value. |
| CbLiveResponse.Commands.SubKeys | List of subkey names. |
Command Example
Context Example
Human Readable Output
26. Create a new registry key
Creates a new registry key.
Base Command
cb-registry-create-key
Input
| Parameter | Description | Required |
| session | The session ID. | Optional |
| sensor | The sensor ID. Provided the sensor ID to run the command with a new session. The session will be created and closed automatically. | Optional |
| path | The key path to create. | Required |
| wait-timeout | Time to wait (in seconds) for Cb command to be executed (change status from 'pending' to 'in-progress'/'complete'). | Optional |
| cancel-on-timeout | Cancel the command if still 'pending' after timeout. | Optional |
Context Output
| Path | Description |
| CbLiveResponse.Commands.CbCommandID | Unique command ID |
| CbLiveResponse.Commands.CommandName | The command name |
| CbLiveResponse.Commands.Status |
The command status
|
| CbLiveResponse.Commands.CommandCompletionTime | The command completion time (0 if not complete) |
| CbLiveResponse.Commands.OperandObject | The key path |
Command Example
Context Example
Human Readable Output
27. Delete a registry key
Deletes the specified registry key.
Base Command
cb-registry-delete-key
Input
| Parameter | Description | Required |
| session | The session ID. | Optional |
| sensor | The sensor ID. Provided the sensor ID to run the command with a new session. The session will be created and closed automatically. | Optional |
| path | The key path to delete. | Required |
| wait-timeout | Time to wait (in seconds) for Cb command to be executed (change status from 'pending' to 'in-progress'/'complete'). | Optional |
| cancel-on-timeout | Cancel the command if still 'pending' after timeout. | Optional |
Context Output
| Path | Description |
| CbLiveResponse.Commands.CbCommandID | Unique command ID |
| CbLiveResponse.Commands.CommandName | The command name |
| CbLiveResponse.Commands.Status |
The command status
|
| CbLiveResponse.Commands.CommandCompletionTime | The command completion time (0 if not complete) |
| CbLiveResponse.Commands.OperandObject | the key path |
Command Example
Context Example
Human Readable Output
28. Delete a registry value
Delete registry value.
Base Command
cb-registry-delete-value
Input
| Parameter | Description | Required |
| session | The session ID. | Optional |
| sensor | The sensor ID. Provided the sensor ID to run the command with a new session. The session will be created and closed automatically. | Optional |
| path | The path of the key + the path of the value. | Required |
| wait-timeout | Time to wait (in seconds) for Cb command to be executed (change status from 'pending' to 'in-progress'/'complete'). | Optional |
| cancel-on-timeout | Cancel the command if still 'pending' after timeout. | Optional |
Context Output
| Path | Description |
| CbLiveResponse.Commands.CbCommandID | Unique command ID |
| CbLiveResponse.Commands.CommandName | The command name |
| CbLiveResponse.Commands.Status |
The command status
|
| CbLiveResponse.Commands.CommandCompletionTime | The command completion time (0 if not complete). |
| CbLiveResponse.Commands.OperandObject | The key path |
Command Example
Context Example
Human Readable Output
29. Set a registry value
Sets a registry value.
Base Command
cb-registry-set-value
Input
| Parameter | Description | Required |
| session | The session ID. | Optional |
| sensor | The sensor ID. Provided the sensor ID to run the command with a new session. The session will be created and closed automatically. | Optional |
| path | The path of the key + the path of the value. | Required |
| data | The data to set for the value. Note if the value type ‘REG_MULTI_SZ’ then multiple values should be separated by a comma (e.g. value1, value2, value3). | Required |
| type | One of common registry value types (REG_DWORD, REG_QWORD, REG_SZ etc). | Required |
| overwrite | An optional parameter to specify whether to overwrite the value if it already exists (default value is ’no’). | Optional |
| wait-timeout | Time to wait (in seconds) for Cb command to be executed (change status from 'pending' to 'in-progress'/'complete'). | Optional |
| cancel-on-timeout | Cancel the command if still 'pending' after timeout. | Optional |
Context Output
| Path | Description |
| CbLiveResponse.Commands.CbCommandID | Unique command ID |
| CbLiveResponse.Commands.CommandName | The command name |
| CbLiveResponse.Commands.Status |
The command status
|
| CbLiveResponse.Commands.CommandCompletionTime | The command completion time (0 if not complete) |
| CbLiveResponse.Commands.OperandObject | The key path |
Command Example
Context Example
Human Readable Output
30. Get a list processes running on an endpoint
Returns a list of processes running on the endpoint.
Base Command
cb-process-list
Input
| Parameter | Description | Required |
| session | The session ID. | Optional |
| sensor | The sensor ID. Provided the sensor ID to run the command with a new session. The session will be created and closed automatically. | Optional |
| wait-timeout | Time to wait (in seconds) for Cb command to be executed (change status from 'pending' to 'in-progress'/'complete'). | Optional |
| cancel-on-timeout | Cancel the command if still 'pending' after timeout. | Optional |
Context Output
| Path | Description |
| CbLiveResponse.Commands.CbCommandID | Unique command identifier. |
| CbLiveResponse.Commands.CommandName | The command name. |
| CbLiveResponse.Commands.Status | The command Status ('pending', 'in progress', 'complete', 'error', 'canceled'). |
| CbLiveResponse.Commands.CommandCompletionTime | The command completion time (0 if not complete). |
| CbLiveResponse.Commands.Processes.ProcessID | Process ID. |
| CbLiveResponse.Commands.Processes.CreateTime | The creation time of the process in Unix time. |
| CbLiveResponse.Commands.Processes.ProcessGuid | The process guid of the process. |
| CbLiveResponse.Commands.Processes.Path | The execution path of the process. |
| CbLiveResponse.Commands.Processes.SecurityIdentifier | The Security Identifier (SID) of the default process token. |
| CbLiveResponse.Commands.Processes.Username | The username of the default process token. |
| CbLiveResponse.Commands.Processes.Parent | The pid (process id ) of the parent. |
| CbLiveResponse.Commands.Processes.ParentGuid | The process guid of the parent process. |
Command Example
!cb-process-list sensor=1
Context Example
{
"CbLiveResponse": {
"Commands": {
"CbCommandID": 1,
"CbSensorID": 17,
"CbSessionID": 327,
"CommandCompletionTime": 1540219086.030599,
"CommandName": "process list",
"CreateTime": 1540219085.939409,
"OperandObject": null,
"Process": [
{
"CommandLine": "",
"CreateTime": 1535357799,
"Parent": 0,
"ParentGuid": "00000011-0000-0000-0000-000000000000",
"Path": "c:\\windows\\system32\\ntoskrnl.exe",
"ProcessGuid": "00000011-0000-0004-01d4-3dde478174d0",
"ProcessID": 4,
"SecurityIdentifier": "s-1-5-18",
"Username": "NT AUTHORITY\\SYSTEM"
},
{
"CommandLine": "\\SystemRoot\\System32\\smss.exe",
"CreateTime": 1535357799,
"Parent": 4,
"ParentGuid": "00000011-0000-0004-01d4-3dde478174d0",
"Path": "c:\\windows\\system32\\smss.exe",
"ProcessGuid": "00000011-0000-0188-01d4-3dde4783d56b",
"ProcessID": 392,
"SecurityIdentifier": "s-1-5-18",
"Username": "NT AUTHORITY\\SYSTEM"
}
]
}
Human Readable Output
CB Response - List Processes: Command Status
| Cb Sensor ID | Cb Session ID | Cb Command ID | Command Name | Status | Create Time | Command Completion Time | Operand Object | Result Desc | Result Type | Result Code |
|---|---|---|---|---|---|---|---|---|---|---|
| 17 | 327 | 1 | process list | complete | 1540219085.939409 | 1540219086.030599 | WinHresult | 0 |
CB Response - Processes
| Process ID | Create Time | Process Guid | Path | Command Line | Security Identifier | Username | Parent | Parent Guid |
|---|---|---|---|---|---|---|---|---|
| 4 | 1535357799 | 00000011-0000-0004-01d4-3dde478174d0 | c:\windows\system32\ntoskrnl.exe | s-1-5-18 | NT AUTHORITY\SYSTEM | 0 | 00000011-0000-0000-0000-000000000000 |
31. Get a file from an endpoint
Retrieves a file from a path on the endpoint.
Base Command
cb-get-file-from-endpoint
Input
| Parameter | Description | Required |
| session | The session ID. | Optional |
| sensor | The sensor ID. Provided the sensor ID to run the command with a new session. The session will be created and closed automatically. | Optional |
| path | The source path of the file. | Required |
| wait-timeout | Time to wait (in seconds) for Cb command to be executed (change status from 'pending' to 'in-progress'/'complete'). | Optional |
Context Output
| Path | Description |
| CbLiveResponse.Commands.CbCommandID | Unique command identifier. |
| CbLiveResponse.Commands.CommandName | The command name. |
| CbLiveResponse.Commands.Status | The command Status ('pending', 'in progress', 'complete', 'error', 'canceled'). |
| CbLiveResponse.Commands.CommandCompletionTime | The command completion time (0 if not complete). |
| CbLiveResponse.Commands.OperandObject | The source path of the file. |
| CbLiveResponse.Commands.FileID | Unique file ID. |
| CbLiveResponse.File.Size | File size. |
| CbLiveResponse.File.SHA1 | File SHA1. |
| CbLiveResponse.File.SHA256 | File SHA256. |
| CbLiveResponse.File.Name | File name. |
| CbLiveResponse.File.SSDeep | File SSDeep. |
| CbLiveResponse.File.EntryID | File EntryID. |
| CbLiveResponse.File.Info | File info. |
| CbLiveResponse.File.Type | File type. |
| CbLiveResponse.File.MD5 | File MD5 hash |
| CbLiveResponse.File.Extension | File extension. |
Command Example
!cb-get-file-from-endpoint path="c:\Users\All Users\Desktop\mooncake.jpg" sensor=17
Context Example
{
"CbLiveResponse": {
"Commands": {
"CbCommandID": 2,
"CbSensorID": 17,
"CbSessionID": 356,
"CommandCompletionTime": 1540229207.655335,
"CommandName": "get file",
"CreateTime": 1540229207.608662,
"FileID": 1,
"OperandObject": "c:\\Users\\All Users\\Desktop\\mooncake.jpg",
"Result": {
"Code": 0,
"Desc": "",
"Type": "WinHresult"
},
"Status": "complete"
}
},
"File": {
"EntryID": "168@583490",
"Extension": "jpg",
"Info": "image/jpeg",
"MD5": "1fe52b291d16c7f9a6eaf43074024011",
"Name": "mooncake.jpg",
"SHA1": "30bd2461d6cee80227bcf557a6fd47922b96263c",
"SHA256": "a87b0fa1006b301b7ef2259cfa9aed2ff12c15217796b5dd08b36e006a137cd2",
"SSDeep": "192:pAzQbZ/ujghzcZHcsWw6o6E7ODeADcBwjZ4P:pAzG/ujgh6xCo60ODe3wj8",
"Size": 11293,
"Type": "data\n"
}
}
Human Readable Output
32. Save a file to an endpoint
Saves a file to a specific path on an endpoint.
Base Command
cb-push-file-to-endpoint
Input
| Parameter | Description | Required |
| session | The session ID. | Optional |
| sensor | The sensor ID. Provided the sensor ID to run the command with a new session. The session will be created and closed automatically. | Optional |
| entry-id | The file entry ID. | Required |
| wait-timeout | Time to wait (in seconds) for Cb command to be executed (change status from 'pending' to 'in-progress'/'complete'). | Optional |
| path | The destination path of the file. Include file name and type (e.g. "c:\Users\USER\Desktop\log.txt"). | Required |
Context Output
| Path | Description |
| CbLiveResponse.Commands.CbCommandID | Unique command identifier. |
| CbLiveResponse.Commands.CommandName | The command name. |
| CbLiveResponse.Commands.Status | The command Status ('pending', 'in progress', 'complete', 'error', 'canceled'). |
| CbLiveResponse.Commands.CommandCompletionTime | The command completion time (0 if not complete). |
| CbLiveResponse.Commands.OperandObject | The destination path of the file. |
Command Example
!cb-push-file-to-endpoint entry-id=84@583490 path="c:\Users\All Users\Desktop" sensor=17
Context Example
{
"CbLiveResponse": {
"Commands": {
"CbCommandID": 1,
"CbSensorID": 17,
"CbSessionID": 338,
"CommandCompletionTime": 1540224253.942851,
"CommandName": "put file",
"CreateTime": 1540224253.915233,
"OperandObject": "c:\\Users\\All Users\\Desktop",
"Result": {
"Code": 2147942405,
"Desc": "",
"Type": "WinHresult"
},
"Status": "error"
},
"Files": {
"CbFileID": 1,
"Delete": false,
"Filename": "mooncake.jpg",
"Size": 6167,
"SizeUploaded": 6167,
"Status": 0
}
},
"File": {
"EntryID": "84@583490",
"Extension": "jpg",
"Info": "image/jpeg",
"MD5": "e42a08714529d9c78cce07a04d2e5e7c",
"Name": "mooncake.jpg",
"SHA1": "d5b5f31018a1d6d51ff1857d3d79cda60ae525ac",
"SHA256": "769509b39aad9992435bf900dd9c96ac409be154eaae5c52f40393e9a9c2ffb4",
"SSDeep": "96:dkwEkdwRnxWUfLO//UTDEuDQ/qBIG9ywAPIloeAIVvx7TM01LT9C:9z2JQLGDQkRzoeAIvlRT9C",
"Size": 6167,
"Type": "JPEG image data, JFIF standard 1.01\n"
}
}
Human Readable Output
CB Response - Push File: Command Status
| Cb Sensor ID | Cb Session ID | Cb Command ID | Command Name | Status | Create Time | Command Completion Time | Operand Object | Result Desc | Result Type | Result Code |
|---|---|---|---|---|---|---|---|---|---|---|
| 17 | 338 | 1 | put file | error | 1540224253.915233 | 1540224253.942851 | c:\Users\All Users\Desktop | WinHresult | 2147942405 |
CB Response - File Info
| Cb File ID | Filename | Size | Size Uploaded | Status | Delete |
|---|---|---|---|---|---|
| 1 | mooncake.jpg | 6167 | 6167 | 0 | false |
Configuration parameters
serverurl— Server URL (required)apitoken— API Token (CB Response)credentials_api_token—apikey— API Key (CB Defense)credentials_api_key—connector— Connector ID (CB Defense)insecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (33)
-
cb-archiveArchive the given session (If the session has no content it will fail)
-
cb-command-cancelDeprecatedCancel the given command. Only pending commands can be canceled.
-
cb-command-createDeprecatedCreate a live response command. Use cb-session-create instead.
-
cb-command-create-and-waitDeprecatedCreate a live response command and wait for it to finish executing
-
cb-command-infoDisplay information on command
-
cb-directory-listingList directories on the endpoint.
-
cb-file-deleteDelete a given file in the session from Cb server.
-
cb-file-delete-from-endpointDelete a file from the endpoint.
-
cb-file-getDownload a file from Cb server in a given session.
-
cb-file-infoGet file info for a given file in a session
-
cb-file-uploadDeprecatedUploads the file to the Cb server. Use cb-push-file-to-endpoint instead.
-
cb-get-file-from-endpointRetrieves a file from a path on the endpoint. For large files, set the "download" argument to "false". Verify that the command completed by using the !cb-command-info command. After the command completes, download the file using the !cb-file-get command.
-
cb-keepaliveKeep the session alive to avoid closing due to timeout
-
cb-list-commandsList the CarbonBlack existing commands for a given session
-
cb-list-filesList files in a given session
-
cb-list-sessionsList the CarbonBlack sessions
-
cb-memdeumpDeprecatedDeprecated - use cb-memdump instead.
-
cb-memdumpExecutes an endpoint memory dump.
-
cb-process-executeRun executable on the endpoint.
-
cb-process-killTerminates a process at the sensor/endpoint
-
cb-process-listList processes running on the endpoint.
-
cb-push-file-to-endpointSave a file to a specific path on the endpoint.
-
cb-registry-create-keyCreate a new registry key.
-
cb-registry-delete-keyDelete registry key.
-
cb-registry-delete-valueDelete registry value.
-
cb-registry-get-valuesEnumerate registry values
-
cb-registry-query-valueQuery for registry value.
-
cb-registry-set-valueSet registry value.
-
cb-session-closeClose the given session
-
cb-session-createCreate a new CarbonBlack session for a given sensor
-
cb-session-create-and-waitCreate a new CarbonBlack session for a given sensor and wait for it to be active
-
cb-session-infoDisplay session info
-
cb-terminate-processDeprecatedTerminates a process at the sensor/endpoint
"use strict"; /// Global Vars let CB_PRODUCT; let BASE_URL; let AUTH; let COMMAND_DATA; let SLEEP_BETWEEN_RETRIES = 1000 * 5; let DEFAULT_WAIT_TIMEOUT = 1000 * 60 * 2; let ERROR_MESSAGE = 'Use Live Response for Cb Defense or Cb Response.\nFor Cb Defense: Provide \'Live Response\' API key and connector.\nFor Cb Response: Provide API Token.'; //validate the credentials are provided to match only one of the products let API_TOKEN = (params.credentials_api_token)? params.credentials_api_token.password : params.apitoken; let API_KEY = (params.credentials_api_key)? params.credentials_api_key.password : params.apikey; if (API_TOKEN && (API_KEY || params.connector) ) { throw ERROR_MESSAGE; } //determain Cb product if (API_TOKEN) { CB_PRODUCT = 'Response'; BASE_URL = `${params.serverurl}/api/v1/cblr`; AUTH = API_TOKEN; COMMAND_DATA = [ {to: 'CbSensorID', from: 'sensor_id'}, {to: 'CbSessionID', from: 'session_id'}, {to: 'CbCommandID', from: 'id'}, {to: 'CommandName', from: 'name'}, {to: 'Status', from: 'status'}, {to: 'CreateTime', from: 'create_time'}, {to: 'CommandCompletionTime', from: 'completion'}, {to: 'OperandObject', from: 'object'}, {to: 'Result.Desc', from: 'result_desc'}, {to: 'Result.Type', from: 'result_type'}, {to: 'Result.Code', from: 'result_code'} ]; } else if (API_KEY && params.connector){ CB_PRODUCT = 'Defense'; BASE_URL = `${params.serverurl}/integrationServices/v3/cblr` AUTH = API_KEY + '/' + params.connector; COMMAND_DATA = [ {to: 'CbSensorID', from: 'sensor_id'}, {to: 'CbSessionID', from: 'session_id'}, {to: 'CbCommandID', from: 'id'}, {to: 'CommandName', from: 'name'}, {to: 'Status', from: 'status'}, {to: 'CreateTime', from: 'create_time'}, {to: 'CommandCompletionTime', from: 'completion_time'}, {to: 'OperandObject', from: 'obj.object'}, {to: 'Result.Desc', from: 'result_desc'}, {to: 'Result.Type', from: 'result_type'}, {to: 'Result.Code', from: 'result_code'} ]; } else { throw ERROR_MESSAGE; } /// Base Functions function splitCamelCase(str) { return str .replace(/([a-z])([A-Z])/g, '$1 $2') .replace('.', ' '); } function sendRequest(path, method, requestParams, headers, ignoredStatusCodes) { if (!headers) { headers = {}; } if (!headers['X-Auth-Token']) { headers['X-Auth-Token'] = [AUTH]; } if (!headers['Accept']) { headers['Accept'] = ['application/json']; } if (!headers['Content-Type']) { headers['Content-Type'] = ['application/json']; } let request = { Method: method, Headers: headers }; let querystring = ''; if (requestParams) { if (typeof requestParams === 'string') { querystring = requestParams; } else { request.Body = JSON.stringify(requestParams); } } let result = http(BASE_URL + path + querystring, request, params.insecure, params.proxy); if (!ignoredStatusCodes || ignoredStatusCodes.indexOf(result.StatusCode) === -1) { if (result.StatusCode < 200 || result.StatusCode >= 300) { if (result.StatusCode === 404) { throw `Cannot find the requested resource\nError message: ${result.Body}\nStatus Code: 404`; } throw `Request Failed.\nStatus code: ${result.StatusCode}.\nMessage: ${result.Body}.`; } } return result; } function sendFileRequest(path, fileId, requestParams, headers, ignoredStatusCodes) { if (!headers) { headers = {}; } if (!headers['X-Auth-Token']) { headers['X-Auth-Token'] = [AUTH]; } if (!headers['Accept']) { headers['Accept'] = ['application/json']; } if (!headers['Content-Type']) { headers['Content-Type'] = ['application/json']; } let request = { Method: 'POST', Headers: headers }; let result = httpMultipart(BASE_URL + path, fileId, request, requestParams, params.insecure, params.proxy); if (result.StatusCode < 200 || result.StatusCode >= 300) { if (result.StatusCode === 404) { throw `${result.Body} (Status Code: 404)`; } throw `Request Failed.\nStatus code: ${result.StatusCode}.\nMessage: ${JSON.stringify(result.Body)}`; } return result; } function createEntry(title, data, dataMap, contextKeys, headerTransformer) { let headers = dataMap.map(cn => cn.to); let translatedData = mapObjFunction(dataMap)(data); let humanReadable = tableToMarkdown(title, translatedData, headers, undefined, headerTransformer); let contextData = createContext(translatedData); let context = {}; for (let i = 0 ; i < contextKeys.length; i++) { let key = contextKeys[i]; context[key] = contextData; } return { Type: entryTypes.note, Contents: data, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: humanReadable, EntryContext: context, }; } /// Cb Live Response Session function testModule() { let res = sendRequest('/session', 'GET'); if (res.StatusCode === 200) { return 'ok'; } // 405 - Method Not Allowed. // This error can raise when using CB Defence; This URL (which is used to list sessions) is theoretically not available for CB Defence. In practice it works for some cases. // 401 is the status code used for 'UNAUTHORIZED' error if (CB_PRODUCT === 'Defense' && res.StatusCode === 405) { return 'ok'; } return `Test failed. Status Code: ${res.StatusCode}` } const sessionData = [ {to: 'CbSensorID', from: 'sensor_id'}, {to: 'CbSessionID', from: 'id'}, {to: 'Hostname', from: 'hostname'}, {to: 'Status', from: 'status'}, {to: 'WaitTimeout', from: 'sensor_wait_timeout'}, {to: 'SessionTimeout', from: 'session_timeout'}, {to: 'SupportedCommands', from: 'supported_commands'} ]; function getSessionsRequest(sessionId, sensorId, status) { let path = `/session`; if (sessionId) { path += '/' + sessionId; } let response = sendRequest(path, 'GET').Body; let result; try { result = JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } // If optional sensor argument is given, filter the results by it. if (!sessionId && sensorId) { sensorId = parseInt(sensorId); result = result.filter(session => (parseInt(session.sensor_id) === sensorId)); } if (!sessionId && status) { result = result.filter(session => (status.indexOf(session.status) > -1)); } return result; } function getSessions() { let result = getSessionsRequest(args.session, args.sensor, args.status); let title = `Cb ${CB_PRODUCT} - Get Sessions`; let dataMap = sessionData; //keep CbResponse context for backward competability let contextKeys = [ 'CbResponse.Sessions(val.CbSessionID==obj.CbSessionID)', 'CbLiveResponse.Sessions(val.CbSessionID==obj.CbSessionID)' ]; return createEntry(title, result, dataMap, contextKeys, splitCamelCase); } function createSessionRequest(sensorId, commandTimeout, keepaliveTimeout) { let queryParams = { sensor_id: parseInt(sensorId) }; if (commandTimeout) { queryParams.session_timeout = keepaliveTimeout; } if (keepaliveTimeout) { queryParams.sensor_wait_timeout = commandTimeout; } let path = CB_PRODUCT === 'Response' ? '/session' : `/session/${sensorId}`; let response = sendRequest(path, 'POST', queryParams).Body; try { return JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } function createSession() { let result = createSessionRequest(args.sensor, args['command-timeout'], args['keepalive-timeout']); let title = `CB ${CB_PRODUCT} - Create Session`; let dataMap = sessionData; //keep CbResponse context for backward competability let contextKeys = [ 'CbResponse.Sessions(val.CbSessionID==obj.CbSessionID)', 'CbLiveResponse.Sessions(val.CbSessionID==obj.CbSessionID)' ]; return createEntry(title, result, dataMap, contextKeys, splitCamelCase); } function createSessionAndWait() { let result = createSessionRequest(args.sensor, args['command-timeout'], args['keepalive-timeout']); sleep(1000); let sessionId = result.id; let timeout = (args['wait-timeout']) ? parseInt(args['wait-timeout']) * 1000 : DEFAULT_WAIT_TIMEOUT ; let retries = Math.ceil(timeout / SLEEP_BETWEEN_RETRIES); let curTry = 0; while (curTry < retries) { let result = getSessionsRequest(sessionId, args.sensor); let status = result.status.toLowerCase() if (status === 'active' ) { let title = `CB ${CB_PRODUCT} - Create Session And Wait`; let dataMap = sessionData; //keep CbResponse context for backward competability let contextKeys = [ 'CbResponse.Sessions(val.CbSessionID==obj.CbSessionID)', 'CbLiveResponse.Sessions(val.CbSessionID==obj.CbSessionID)' ]; return createEntry(title, result, dataMap, contextKeys, splitCamelCase); } else if (status !== 'pending') { throw `Executing session ${sessionId} failed, status: ${result.status}`; } sleep(SLEEP_BETWEEN_RETRIES); curTry++; } throw `Exceeded timeout.\nNew session for sensor ${args.sensor} was created with ID: ${sessionId}.\nSession status remains '${result.status}'. Wait for session to become active (you may query for session staus with 'cb-session-info').\nIt is recomended to increase wait-timeout for this command.`; } function closeSessionRequest(sessionId) { let queryParams = { session_id: sessionId }; queryParams.status = CB_PRODUCT === 'Response' ? 'close' : 'CLOSE'; let path = CB_PRODUCT === 'Response' ? `/session/${sessionId}` : '/session'; let response = sendRequest(path, 'PUT', queryParams).Body; try { return JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } function closeSession() { let result = closeSessionRequest(args.session); let title = `CB ${CB_PRODUCT} - Session Closed`; let dataMap = sessionData; //keep CbResponse context for backward competability let contextKeys = [ 'CbResponse.Sessions(val.CbSessionID==obj.CbSessionID)', 'CbLiveResponse.Sessions(val.CbSessionID==obj.CbSessionID)' ]; // cb response - session will have 'active' value for 'status' field although status is 'closed' if (CB_PRODUCT === 'Response') { // retrieving closed session info returns inconsistent results (expected to return the updated info with correct status, but in practice this may return an error) // do not try to retrieve updated session info, simply change the session status in the result to avoid confusion // see https://developer.carbonblack.com/reference/enterprise-response/6.1/live-response-api/#close-sessions result.status = 'close' } return createEntry(title, result, dataMap, contextKeys, splitCamelCase); } function sessionKeepaliveRequest(sessionId) { let response = sendRequest(`/session/${sessionId}/keepalive`, 'GET', undefined, undefined, [404]); if (response.StatusCode === 404) { throw `Session ${sessionId} has expired and is now closed. Create a new session to continue working.`; } try { return JSON.parse(response.Body); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response.Body}`; } } function sessionKeepAlive() { let result = sessionKeepaliveRequest(args.session); let translatedData = mapObjFunction(sessionData)(result); let contextData = createContext(translatedData); //keep CbResponse context for backward competability let context = { 'CbResponse.Sessions(val.CbSessionID==obj.CbSessionID)': contextData, 'CbLiveResponse.Sessions(val.CbSessionID==obj.CbSessionID)': contextData }; return { Type: entryTypes.note, Contents: result, ContentsType: formats.json, ReadableContentsFormat: formats.text, HumanReadable: `Keepalive successful for session ${args.session}`, EntryContext: context, }; } function archiveSessionRequest(sessionId) { let response = sendRequest(`/session/${sessionId}/archive`, 'GET', undefined, undefined, [500]); if (response.StatusCode === 500) { // Current bug in CBResponse returns 500 for empty sessions throw `Session ${sessionId} is empty and so it has no archive.`; } return response; } function archiveSession() { let response = archiveSessionRequest(args.session); let fileEntryId = saveFile(response.Bytes); let fileName = `session-${args.session}-archive.zip`; return { Type: entryTypes.file, FileID: fileEntryId, File: fileName, Contents: fileName }; } /// Cb Live Response file operations const fileData = [ {to: 'CbFileID', from: 'id'}, {to: 'Filename', from: 'file_name'}, {to: 'Size', from: 'size'}, {to: 'SizeUploaded', from: 'size_uploaded'}, {to: 'Status', from: 'status'}, {to: 'Delete', from: 'delete'} ]; function listFilesRequest(sessionId, fileId) { if (!sessionId) { throw 'Session ID is required'; } let path = `/session/${sessionId}/file`; if (fileId) { path += '/' + fileId; } let response = sendRequest(path, 'GET').Body; try { return JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } function listFiles() { let result = listFilesRequest(args.session, args['file-id']); let title = `CB ${CB_PRODUCT} - List Files`; let dataMap = fileData; //keep CbResponse context for backward competability let contextKeys = [ 'CbResponse.Files(val.CbFileID==obj.CbFileID)', 'CbLiveResponse.Files(val.CbFileID==obj.CbFileID)' ]; return createEntry(title, result, dataMap, contextKeys, splitCamelCase); } function downloadFileRequest(sessionId, fileId) { var headers = {Accept: ['*/*']}; if (!sessionId) { throw 'Session ID is required'; } if (!fileId) { throw 'File ID is required'; } let path = `/session/${sessionId}/file/${fileId}/content`; return sendRequest(path, 'GET', null, headers); } function downloadFileEntry(sessionId, fileId) { let fileInfo = listFilesRequest(sessionId, fileId); let fileContentResponse = downloadFileRequest(sessionId, fileId); let fileEntryId = saveFile(fileContentResponse.Bytes); let fileName = fileInfo.file_name.split('\\').pop(); return { Type: entryTypes.file, FileID: fileEntryId, File: fileName, Contents: fileInfo.file_name }; } function downloadFile() { return downloadFileEntry(args['session'], args['file-id']); } function uploadFileRequest(sessionId, fileId) { if (!sessionId) { throw 'Session ID is required'; } if (!fileId) { throw 'File ID is required'; } let response = sendFileRequest(`/session/${sessionId}/file`, fileId); try { return JSON.parse(response.Body); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } function uploadFile() { let result = uploadFileRequest(args.session, args['file-id']); let title = `CB ${CB_PRODUCT} - Upload File`; let dataMap = fileData; //keep CbResponse context for backward competability let contextKeys = [ 'CbResponse.Files(val.CbFileID==obj.CbFileID)', 'CbLiveResponse.Files(val.CbFileID==obj.CbFileID)' ]; return createEntry(title, result, dataMap, contextKeys, splitCamelCase); } function deleteFileRequest(sessionId, fileId) { if (!sessionId) { throw 'Session ID is required'; } if (!fileId) { throw 'File ID is required'; } let path = `/session/${sessionId}/file/${fileId}`; let response = sendRequest(path, 'DELETE').Body; } function deleteFile() { deleteFileRequest(args.session, args['file-id']); return { Type: entryTypes.note, Contents: `File ${args['file-id']} deleted successfully`, ContentsType: formats.text }; } /// Cb Live Response Commands //generic function to create a new command function createCommandRequest(sessionId, name, timeout, object, compress, wait, workingDir, outputFile, valueData, valueType, overwrite, offset, getCount) { let queryParams = { name: name.split('-').join(' ') }; if (timeout) { queryParams.timeout = timeout; } if (object) { queryParams.object = object; } if (compress) { queryParams.compress = compress; } queryParams.wait = true; if (wait !== undefined && wait === false) { queryParams = wait; } if (workingDir) { queryParams.working_directory = workingDir; } if (outputFile) { queryParams.output_file = outputFile; } if (valueData) { queryParams.value_data = valueData; } if (valueType) { queryParams.value_type = valueType; } if (overwrite) { queryParams.overwrite = overwrite; } if (offset) { queryParams.offset = offset; } if (getCount) { queryParams.get_count = getCount; } let response = sendRequest(`/session/${sessionId}/command`, 'POST', queryParams).Body; try { return JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } //TODO: Spec for commands interface function createCommand() { let result = createCommandRequest(args.session, args.name, args.timeout, args.object, args.compress, args.wait, args['working-dir'], args['output-file'], args['value-data'], args['value-type'], args.overwrite, args.offset, args['get-count']); let title = `CB Response - Run Command ${args.name}`; let dataMap = COMMAND_DATA; let contextKeys = [ 'CbResponse.Commands(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID)', 'CbLiveResponse.Commands(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID)' ]; return createEntry(title, command, dataMap, contextKeys, splitCamelCase); } function getCommandRequest(sessionId, commandId) { let path = `/session/${sessionId}/command/${commandId}`; let response = sendRequest(path, 'GET').Body; try { return JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } function getCommandsRequest(sessionId) { let path = `/session/${sessionId}/command`; let response = sendRequest(path, 'GET').Body; try { return JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } function getCommands() { let result = getCommandsRequest(args.session); let title = `CB ${CB_PRODUCT} - Get Commands`; let dataMap = COMMAND_DATA; //keep CbResponse context for backward competability let contextKeys = [ 'CbResponse.Commands(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID)', 'CbLiveResponse.Commands(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID)' ]; return createEntry(title, result, dataMap, contextKeys, splitCamelCase); } function createCommandAndWait() { let result = createCommandRequest(args.session, args.name, args.timeout, args.object, args.compress, args.wait, args['working-dir'], args['output-file'], args['value-data'], args['value-type'], args.overwrite, args.offset, args['get-count']); sleep(1000); let commandId = result.id; let timeout = (args['wait-timeout']) ? parseInt(args['wait-timeout']) * 1000 : DEFAULT_WAIT_TIMEOUT; let retries = Math.ceil(timeout / SLEEP_BETWEEN_RETRIES); let curTry = 0; while (curTry < retries) { let result = getCommandRequest(args.session, commandId); if (result.status === 'complete') { let entries = []; let title = 'CB Response - Execute Command And Wait'; let dataMap = COMMAND_DATA; let headers = dataMap.map(cn => cn.to); let translatedData = mapObjFunction(dataMap)(result); let humanReadable = tableToMarkdown(title, translatedData, headers, undefined, dotToSpace); let context = { 'CbResponse.Commands(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID)': createContext(translatedData) }; entries.push({ Type: entryTypes.note, Contents: result, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: humanReadable, EntryContext: context }); // If we have the command in args then we get info for the command, // in this case we want to parse the result: let contents = result; switch (result.name) { case "directory list": contents = result.files; break; case "process list": contents = result.processes; break; } logInfo("Here2"); entries.push({ Type: entryTypes.note, Contents: contents, ContentsType: formats.json, // TODO: Add human readable and context for specific commands }); return entries; } else if (result.status !== 'pending') { throw `Executing command ${commandId} failed, status: ${result.status}`; } sleep(SLEEP_BETWEEN_RETRIES); curTry++; } throw `Executing command ${commandId} timedout (${timeout / 1000} seconds), increase wait-timeout and try again`; } function cancelCommandRequest(sessionId, commandId) { let queryParams = {cmdid: commandId}; let response = sendRequest(`/session/${sessionId}/command/${commandId}`, 'PUT', queryParams).Body; try { return JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } function cancelCommand() { let result = cancelCommandRequest(args.session, args.command); let title = `CB ${CB_PRODUCT} - Cancel Command`; let dataMap = COMMAND_DATA; //keep CbResponse context for backward competability let contextKeys = [ 'CbResponse.Commands(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID)', 'CbLiveResponse.Commands(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID)' ]; return createEntry(title, result, dataMap, contextKeys, splitCamelCase); } /// Explicit Commands const directoryData = [ {to: 'FileAttributes', from: 'attributes'}, {to: 'CreateTime', from: 'create_time'}, {to: 'LastAccessTime', from: 'last_access_time'}, {to: 'LastWriteTime', from: 'last_write_time'}, {to: 'FileSize', from: 'size'}, {to: 'FileName', from: 'filename'}, {to: 'AlternativeName', from:'alt_name'} ]; const processesData = [ {to: 'ProcessID', from: 'pid'}, {to: 'CreateTime', from: 'create_time'}, {to: 'ProcessGuid', from: 'proc_guid'}, {to: 'Path', from: 'path'}, {to: 'CommandLine', from: 'command_line'}, {to: 'SecurityIdentifier', from: 'sid'}, {to: 'Username', from: 'username'}, {to: 'Parent', from: 'parent'}, {to: 'ParentGuid', from: 'parent_guid'} ]; const processData = [ {to: 'ProcessID', from: 'pid'}, {to: 'ReturnCode', from: 'return_code'} ]; const memdumpData = [ {to: 'ReturnCode', from: 'return_code'}, {to: 'CompressingEnabled', from: 'compressing'}, {to: 'Complete', from: 'complete'}, {to: 'PercentDone', from: 'percentdone'}, {to: 'DumpingInProgress', from: 'dumping'} ]; const regKeysData = [ {to: 'RegKeyType', from: 'value_type'}, {to: 'RegKeyName', from: 'value_name'}, {to: 'RegKeyData', from: 'value_data'} ]; const regKeyData = [ {to: 'RegKeyType', from: 'value.value_type'}, {to: 'RegKeyName', from: 'value.value_name'}, {to: 'RegKeyData', from: 'value.value_data'} ]; function collectRegistryDataToGeneralContext(data) { let regKey = CB_PRODUCT === 'Response' ? data.object : data.obj.object; let RegistryKeys = []; for (let value of data.values) { let entry = { Path: regKey, Name: value.value_name, Value: value.value_data }; RegistryKeys.push(entry); } return RegistryKeys; }; const commandEntries = { 'directory list' : function(data) { let dataMap = COMMAND_DATA; let title = `CB ${CB_PRODUCT} - Directory Listing: Command Status`; let contextKeys = ['CbLiveResponse.Commands(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID)']; let commandInfoEntry = createEntry( title, data, dataMap, contextKeys, splitCamelCase ); if (data.status !== 'complete') { return commandInfoEntry; } //create entry to hold directory data dataMap = directoryData; title = `CB ${CB_PRODUCT} - Directory Listing`; contextKeys = ['CbLiveResponse.Commands(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID).Files']; let directoryListEntry = createEntry( title, data.files, dataMap, contextKeys, splitCamelCase ); return [commandInfoEntry, directoryListEntry]; }, 'put file': function(data) { let dataMap = COMMAND_DATA; let title = `CB ${CB_PRODUCT} - Push File: Command Status`; let contextKeys = ['CbLiveResponse.Commands(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID)']; let commandInfoEntry = createEntry( title, data, dataMap, contextKeys, splitCamelCase ); return commandInfoEntry; }, 'get file': function(data) { let dataMap = COMMAND_DATA; let title = `CB ${CB_PRODUCT} - Get File From Path ${args.path}: Command Status`; let contextKeys = ['CbLiveResponse.Commands(val.CbCommandID==obj.CbCommandID&&val.CbSessionID==obj.CbSessionID)']; if (data.status === 'complete') { dataMap.push({to: 'FileID', from: 'file_id'}); } let commandInfoEntry = createEntry( title, data, dataMap, contextKeys, splitCamelCase ); return commandInfoEntry; }, 'kill': function(data) { let dataMap = COMMAND_DATA; let title = `CB ${CB_PRODUCT} - Kill Process ${args.pid}: Command Status`; let contextKeys = ['CbLiveResponse.Commands(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID)']; let commandInfoEntry = createEntry( title, data, dataMap, contextKeys, splitCamelCase ); return commandInfoEntry; }, 'create process' : function(data) { let dataMap = COMMAND_DATA; if (data.status === 'complete') { dataMap = dataMap.concat(processData); } let title = `CB ${CB_PRODUCT} - Execute Process: Command Status`; let contextKeys = ['CbLiveResponse.Commands(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID)']; let commandInfoEntry = createEntry( title, data, dataMap, contextKeys, splitCamelCase ); return commandInfoEntry; }, 'memdump': function(data) { let dataMap = COMMAND_DATA; if (data.status === 'complete') { dataMap = dataMap.concat(memdumpData); } let title = `CB ${CB_PRODUCT} - Memdump: Command Status`; let contextKeys = ['CbLiveResponse.Commands(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID)']; let commandInfoEntry = createEntry( title, data, dataMap, contextKeys, splitCamelCase ); return commandInfoEntry; }, 'delete file': function(data) { let dataMap = COMMAND_DATA; let title = `CB ${CB_PRODUCT} - Delete File From Endpoint: Command Status`; let contextKeys = ['CbLiveResponse.Commands(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID)']; let commandInfoEntry = createEntry( title, data, dataMap, contextKeys, splitCamelCase ); return commandInfoEntry; }, 'reg enum key': function(data) { let dataMap = COMMAND_DATA; if (data.status === 'complete'){ dataMap.push({to: 'SubKeys', from: 'sub_keys'}); } let commandData = mapObjFunction(dataMap)(data); let commandMD = tableToMarkdown( `CB ${CB_PRODUCT} - Registry Keys: Command Status`, commandData, dataMap.map(cn => cn.to), undefined, splitCamelCase ); if (data.status !== 'complete' || !data.values) { return { Type: entryTypes.note, Contents: data, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: commandMD, EntryContext: { 'CbLiveResponse.Commands(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID)': commandData } }; } let registryEntry = mapObjFunction(regKeysData)(data.values); let registryMD = tableToMarkdown( `Registry Values`, registryEntry, regKeysData.map(cn => cn.to), undefined, splitCamelCase ); //collect registry data for general context let generalConetxt = collectRegistryDataToGeneralContext(data); return { Type: entryTypes.note, Contents: data, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: commandMD + '\n\n' + registryMD, EntryContext: { 'CbLiveResponse.Commands(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID)': commandEntry, 'CbLiveResponse.Commands(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID).Values': registryEntry, 'RegistryKey': generalConetxt } }; }, 'reg query value': function(data) { let dataMap = COMMAND_DATA; if (data.status === 'complete') { dataMap = dataMap.concat(regKeyData); } let commandData = mapObjFunction(dataMap)(data); let commandMD = tableToMarkdown( `CB ${CB_PRODUCT} - Query Registry Value: Command Status`, commandData, dataMap.map(cn => cn.to), undefined, splitCamelCase ); let context = { 'CbLiveResponse.Commands(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID)': commandData }; if (data.status !== 'complete') { context.RegistryKey = collectRegistryDataToGeneralContext(data); } return { Type: entryTypes.note, Contents: data, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: commandMD, EntryContext: context }; }, 'reg create key': function(data) { let dataMap = COMMAND_DATA; let title = `CB ${CB_PRODUCT} - Create Registry Key: Command Status`;; let contextKeys = ['CbLiveResponse(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID)']; let commandInfoEntry = createEntry( title, data, dataMap, contextKeys, splitCamelCase ); return commandInfoEntry; }, 'reg delete key': function(data) { let dataMap = COMMAND_DATA; let title = `CB ${CB_PRODUCT} - Create Registry Key: Command Status`;; let contextKeys = ['CbLiveResponse.Commands(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID)']; let commandInfoEntry = createEntry( title, data, dataMap, contextKeys, splitCamelCase ); return commandInfoEntry; }, 'reg delete values': function(data) { let dataMap = COMMAND_DATA; let title = `CB ${CB_PRODUCT} - Delete Registry Value: Command Status`;; let contextKeys = ['CbLiveResponse.Commands(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID)']; let commandInfoEntry = createEntry( title, data, dataMap, contextKeys, splitCamelCase ); return commandInfoEntry; }, 'reg set values': function(data) { let dataMap = COMMAND_DATA; let title = `CB ${CB_PRODUCT} - Delete Registry Value: Command Status`;; let contextKeys = ['CbLiveResponse.Commands(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID)']; let commandInfoEntry = createEntry( title, data, dataMap, contextKeys, splitCamelCase ); return commandInfoEntry; }, 'process list' : function(data) { let commandData = mapObjFunction(COMMAND_DATA)(data); let commandMD = tableToMarkdown( `CB ${CB_PRODUCT} - List Processes: Command Status`, commandData, COMMAND_DATA.map(cn => cn.to), undefined, splitCamelCase ); if (data.status !== 'complete') { return { Type: entryTypes.note, Contents: data, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: commandMD, EntryContext: { 'CbLiveResponse.Commands(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID)': commandData } }; } let processes = mapObjFunction(processesData)(data.processes); let processesMD = tableToMarkdown( `CB ${CB_PRODUCT} - Processes`, processes, processesData.map(cn => cn.to), undefined, splitCamelCase ); // collect processes data for general context let processesCollection = []; for (let process of data.processes) { processesCollection.push({ 'PID': process.pid, 'CommandLine': process.command_line, 'Path': process.path, 'Start Time': process.create_time, 'Parent': process.parent }); } return { Type: entryTypes.note, Contents: data, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: commandMD + '\n\n' + processesMD, EntryContext: { 'CbLiveResponse.Commands(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID)': commandData, 'CbLiveResponse.Commands(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID).Process': processes, 'Process': processesCollection } }; } }; function getCommand() { let command = getCommandRequest(args.session, args.command); if (commandEntries[command.name]){ return commandEntries[command.name](command); } //create generic entry let title = `CB ${CB_PRODUCT} - Get Command`; let dataMap = COMMAND_DATA; //keep CbResponse context for backward competability let contextKeys = [ 'CbResponse.Commands(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID)', 'CbLiveResponse.Commands(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID)' ]; return createEntry( title, result, dataMap, contextKeys, splitCamelCase ); } function getCommandInfo(sessionId, commandId, timeout, timeInterval, cancelOnPending) { let retries = timeout ? Math.ceil(timeout / timeInterval) : 1; //loop to get command info. Stop when command status is no longer 'pending' or when exeeded wait-time. let result; let curTry = 0; while (curTry < retries) { result = getCommandRequest(sessionId, commandId); if (result.status !== 'pending') { return result; } curTry++; sleep(timeInterval); } if (cancelOnPending && cancelOnPending === 'yes') { cancelCommandRequest(sessionId, commandId); throw 'Wait-time expired. Canceled command'; } return result; } function terminateProcess() { let result = createCommandRequest(args.session, 'kill', undefined, args.pid, undefined, args.wait); sleep(1000); let commandId = result.id; let timeout = (args['wait-timeout']) ? parseInt(args['wait-timeout']) * 1000 : DEFAULT_WAIT_TIMEOUT; let retries = Math.ceil(timeout / SLEEP_BETWEEN_RETRIES); let curTry = 0; while (curTry < retries) { let result = getCommandRequest(args.session, commandId); if (result.status === 'complete') { let title = `CB Response - Terminate Process ${args.pid}`; let dataMap = COMMAND_DATA; let headers = dataMap.map(cn => cn.to); let translatedData = mapObjFunction(dataMap)(result); let humanReadable = tableToMarkdown(title, translatedData, headers, undefined, dotToSpace); let context = { 'CbResponse.Commands(val.CbCommandID == obj.CbCommandID && val.CbSessionID == obj.CbSessionID)': createContext(translatedData) }; return { Type: entryTypes.note, Contents: result, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: humanReadable, EntryContext: context, }; } else if (result.status !== 'pending') { throw `Terminating process failed, status: ${result.status}`; } sleep(SLEEP_BETWEEN_RETRIES); curTry++; } throw `Terminating process timedout (${timeout / 1000} seconds), increase wait-timeout and try again`; } function putFileRequest(sessionId, fileId, path) { let queryParams = { name: 'put file', object: path, file_id: fileId }; let response = sendRequest(`/session/${sessionId}/command`, 'POST', queryParams).Body; try { return JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } function putFile() { let fileInfo = uploadFileRequest(args['session'], args['entry-id']); let result = putFileRequest(args['session'], fileInfo.id, args.path); //wait for 1 second before trying to get command information sleep(1000); let timeout = (args['wait-timeout']) ? parseInt(args['wait-timeout']) * 1000 : DEFAULT_WAIT_TIMEOUT; let command = getCommandInfo(args['session'], result.id, timeout, SLEEP_BETWEEN_RETRIES); let commandEntry = commandEntries['put file'](command); //add entry to hold gile information let title = `CB ${CB_PRODUCT} - File Info`; let dataMap = fileData; let contextKeys = ['CbLiveResponse.Files(val.CbFileID==obj.CbFileID)']; let fileInfoEntry = createEntry( title, fileInfo, dataMap, contextKeys, splitCamelCase ); return [commandEntry, fileInfoEntry]; } function getFileRequest(sessionId, path, offset, bytes) { let queryParams = { name: 'get file', object: path, offset: offset }; if (bytes) { queryParams['get_count'] = bytes; } let response = sendRequest(`/session/${sessionId}/command`, 'POST', queryParams).Body; try { return JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } function getFile() { let command = getFileRequest(args.session, args.path, 0); //wait for 1 second before trying to get command information sleep(1000); let timeout = (args['wait-timeout']) ? parseInt(args['wait-timeout']) * 1000 : DEFAULT_WAIT_TIMEOUT; try{ command = getCommandInfo(args['session'], command.id, timeout, SLEEP_BETWEEN_RETRIES, args['cancel-on-timeout']); } catch(err) { throw `Failed to get the file.\nError: ${err}.`; } let commandEntry = commandEntries['get file'](command); let fileEntry = {} if (args.download == 'true') { if (command.status !== 'complete') { return commandEntry; } //download the file from Cb server and add file entry to the war room fileEntry = downloadFileEntry(args['session'], command['file_id']); return [commandEntry, fileEntry]; } return commandEntry; } function directoryListRequest(sessionId, path) { let queryParams = { name: 'directory list', object: path }; let response = sendRequest(`/session/${sessionId}/command`, 'POST', queryParams).Body; try { return JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } function directoryList() { let result = directoryListRequest(args['session'], args.path); //wait for 1 second before trying to get command information sleep(1000); let timeout = args['wait-timeout'] ? parseInt(args['wait-timeout']) * 1000 : DEFAULT_WAIT_TIMEOUT; let command = getCommandInfo(args['session'], result.id, timeout, SLEEP_BETWEEN_RETRIES, args['cancel-on-timeout']); return commandEntries['directory list'](command); } function processKillRequest(sessionId, pid) { let queryParams = { name: 'kill', object: pid }; let response = sendRequest(`/session/${sessionId}/command`, 'POST', queryParams).Body; try { return JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } //equivalent to 'terminateProcess' function function processKill() { let result = processKillRequest(args['session'], args.pid); //wait for 1 second before trying to get command information sleep(1000); let timeout = (args['wait-timeout']) ? parseInt(args['wait-timeout']) * 1000 : DEFAULT_WAIT_TIMEOUT; let command = getCommandInfo(args['session'], result.id, timeout, SLEEP_BETWEEN_RETRIES, args['cancel-on-timeout']); return commandEntries['kill'](command); } function processExecRequest(sessionId, path, wait, workingDirectory, outputFile) { let queryParams = { name: 'create process', object: path }; if (wait !== undefined) { queryParams.wait = wait; } if (workingDirectory) { queryParams.working_directory = workingDirectory; } if (outputFile) { queryParams.output_file = outputFile; } let response = sendRequest(`/session/${sessionId}/command`, 'POST', queryParams).Body; try { return JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } function processExec() { if (args.wait) { args.wait = args.wait === 'yes'; } let result = processExecRequest(args['session'], args.path, args.wait, args['working-directory'], args['output-file']); //wait for 1 second before trying to get command information sleep(1000); let timeout = (args['wait-timeout']) ? parseInt(args['wait-timeout']) * 1000 : DEFAULT_WAIT_TIMEOUT; let command = getCommandInfo(args['session'], result.id, timeout, SLEEP_BETWEEN_RETRIES, args['cancel-on-timeout']); return commandEntries['create process'](command); } function memdumpRequest(sessionId, path, compress) { let queryParams = { name: 'memdump', object: path, compress: false //in the API there is a typo that says this field is spelled 'commpress' }; if (compress === 'true') { queryParams.compress = true; } let response = sendRequest(`/session/${sessionId}/command`, 'POST', queryParams).Body; try { return JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } function memdump() { let result = memdumpRequest(args['session'], args.path, args.compress); //wait for 1 second before trying to get command information sleep(1000); let timeout = (args['wait-timeout']) ? parseInt(args['wait-timeout']) * 1000 : DEFAULT_WAIT_TIMEOUT; let command = getCommandInfo(args['session'], result.id, timeout, SLEEP_BETWEEN_RETRIES, args['cancel-on-timeout']); return commandEntries['memdump'](command); } function deleteFileFromEndpointRequest(sessionId, path){ let queryParams = { name: 'delete file', object: path }; let response = sendRequest(`/session/${sessionId}/command`, 'POST', queryParams).Body; try { return JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } function deleteFileFromEndpoint() { let result = deleteFileFromEndpointRequest(args['session'], args.path); //wait for 1 second before trying to get command information sleep(1000); let timeout = (args['wait-timeout']) ? parseInt(args['wait-timeout']) * 1000 : DEFAULT_WAIT_TIMEOUT; let command = getCommandInfo(args['session'], result.id, timeout, SLEEP_BETWEEN_RETRIES, args['cancel-on-timeout']); return commandEntries['delete file'](command); } function regEnumKeyRequest(sessionId, path){ let queryParams = { name: 'reg enum key', object: path }; let response = sendRequest(`/session/${sessionId}/command`, 'POST', queryParams).Body; try { return JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } function regEnumKey() { let result = regEnumKeyRequest(args.session, args.path); //wait for 1 second before trying to get command information sleep(1000); let timeout = (args['wait-timeout']) ? parseInt(args['wait-timeout']) * 1000 : DEFAULT_WAIT_TIMEOUT; let command = getCommandInfo(args['session'], result.id, timeout, SLEEP_BETWEEN_RETRIES, args['cancel-on-timeout']); return commandEntries['reg enum key'](command); } function regQueryValueRequest(sessionId, path){ let queryParams = { name: 'reg query value', object: path }; let response = sendRequest(`/session/${sessionId}/command`, 'POST', queryParams).Body; try { return JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } function regQueryValue() { let result = regQueryValueRequest(args.session, args.path); //wait for 1 second before trying to get command information sleep(1000); let timeout = (args['wait-timeout']) ? parseInt(args['wait-timeout']) * 1000 : DEFAULT_WAIT_TIMEOUT; let command = getCommandInfo(args['session'], result.id, timeout, SLEEP_BETWEEN_RETRIES, args['cancel-on-timeout']); return commandEntries['reg query value'](command); } function regCreateRequest(sessionId, path){ let queryParams = { name: 'reg create key', object: path }; let response = sendRequest(`/session/${sessionId}/command`, 'POST', queryParams).Body; try { return JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } function regCreate() { let result = regCreateRequest(args.session, args.path, args.timeout); //wait for 1 second before trying to get command information sleep(1000); let timeout = (args['wait-timeout']) ? parseInt(args['wait-timeout']) * 1000 : DEFAULT_WAIT_TIMEOUT; let command = getCommandInfo(args['session'], result.id, timeout, SLEEP_BETWEEN_RETRIES, args['cancel-on-timeout']); return commandEntries['reg create key'](command); } function regDeleteKeyRequest(sessionId, path){ let queryParams = { name: 'reg delete key', object: path }; let response = sendRequest(`/session/${sessionId}/command`, 'POST', queryParams).Body; try { return JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } function regDeleteKey() { let result = regDeleteKeyRequest(args.session, args.path); //wait for 1 second before trying to get command information sleep(1000); let timeout = (args['wait-timeout']) ? parseInt(args['wait-timeout']) * 1000 : DEFAULT_WAIT_TIMEOUT; let command = getCommandInfo(args['session'], result.id, timeout, SLEEP_BETWEEN_RETRIES, args['cancel-on-timeout']); return commandEntries['reg delete key'](command); } function regDeleteValueRequest(sessionId, path){ let queryParams = { name: 'reg delete value', object: path }; let response = sendRequest(`/session/${sessionId}/command`, 'POST', queryParams).Body; try { return JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } function regDeleteValue() { let result = regDeleteValueRequest(args.session, args.path); //wait for 1 second before trying to get command information sleep(1000); let timeout = (args['wait-timeout']) ? parseInt(args['wait-timeout']) * 1000 : DEFAULT_WAIT_TIMEOUT; let command = getCommandInfo(args['session'], result.id, timeout, SLEEP_BETWEEN_RETRIES, args['cancel-on-timeout']); return commandEntries['reg delete value'](command); } function regSetValueRequest(sessionId, path, data, type, overwrite){ let queryParams = { name: 'reg set value', object: path, value_data: data, value_type: type } if (overwrite) { queryParams.overwrite = true; } let response = sendRequest(`/session/${sessionId}/command`, 'POST', queryParams).Body; try { return JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } function regSetValue() { if (args.type = 'REG_MULTI_SZ') { args.data = args.data.split(','); } if (args.overwrite) { args.overwrite = args.overwrite === 'yes'; } let result = regSetValueRequest(args.session, args.path, args.data, args.type, args.overwrite); //wait for 1 second before trying to get command information sleep(1000); let timeout = (args['wait-timeout']) ? parseInt(args['wait-timeout']) * 1000 : DEFAULT_WAIT_TIMEOUT; let command = getCommandInfo(args['session'], result.id, timeout, SLEEP_BETWEEN_RETRIES, args['cancel-on-timeout']); return commandEntries['reg set value'](command); } function listProcessesRequest(sessionId, path){ let queryParams = { name: 'process list' } let response = sendRequest(`/session/${sessionId}/command`, 'POST', queryParams).Body; try { return JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } function listProcesses() { let result = listProcessesRequest(args['session'], args.path); //wait for 1 second before trying to get command information sleep(1000); let timeout = (args['wait-timeout']) ? parseInt(args['wait-timeout']) * 1000 : DEFAULT_WAIT_TIMEOUT; let command = getCommandInfo(args['session'], result.id, timeout, SLEEP_BETWEEN_RETRIES, args['cancel-on-timeout']); return commandEntries['process list'](command); } /// Execution try { switch (command) { case 'test-module': return testModule(); case 'cb-list-sessions': if (CB_PRODUCT == 'Defense') { throw '\'cb-list-sessions\' is not available for Cb Defense.'; } return getSessions(); case 'cb-session-info': return getSessions(); case 'cb-session-create': return createSession(); case 'cb-session-create-and-wait': return createSessionAndWait(); case 'cb-session-close': return closeSession(); case 'cb-keepalive': return sessionKeepAlive(); case 'cb-archive': if (CB_PRODUCT == 'Defense') { throw '\'cb-archive\' is not available for Cb Defense.'; } return archiveSession(); case 'cb-list-commands': return getCommands(); case 'cb-command-info': return getCommand(); case 'cb-terminate-process': return terminateProcess(); case 'cb-command-create': return createCommand(); case 'cb-command-create-and-wait': return createCommandAndWait(); case 'cb-command-cancel': return cancelCommand(); case 'cb-file-get': return downloadFile(); case 'cb-list-files': case 'cb-file-info': return listFiles(); case 'cb-file-upload': return uploadFile(); case 'cb-file-delete': return deleteFile(); } } catch (err) { return { Type: entryTypes.error, Contents: err, ContentsType: formats.json, ReadableContentsFormat: formats.text, HumanReadable: err.message }; } // execute Cb commands let closeSessionAfterExecution = false; try { //validate either sensor or session was passed if ((!args.session && !args.sensor) || (args.session && args.sensor)) { throw 'Provide either the session ID or the sensor ID'; } if (args.sensor) { let session = createSessionRequest(args.sensor); let wait = 3 * 1000; while (session.status === 'pending' || session.status === 'PENDING') { sleep(wait); session = getSessionsRequest(session.id); } if (session.status !== 'active' && session.status !== 'ACTIVE') { throw 'Failed to start a new session'; } closeSessionAfterExecution = true; args.session = session.id; } switch (command) { case 'cb-process-kill': return processKill(); case 'cb-directory-listing': return directoryList(); case 'cb-process-execute': return processExec(); case 'cb-memdeump': return memdump(); case 'cb-memdump': return memdump(); case 'cb-file-delete-from-endpoint': return deleteFileFromEndpoint(); case 'cb-registry-get-values': return regEnumKey(); case 'cb-registry-query-value': return regQueryValue(); case 'cb-registry-create-key': return regCreate(); case 'cb-registry-delete-key': return regDeleteKey(); case 'cb-registry-delete-value': return regDeleteValue(); case 'cb-registry-set-value': return regSetValue(); case 'cb-process-list': return listProcesses(); case 'cb-get-file-from-endpoint': return getFile(); case 'cb-push-file-to-endpoint': return putFile(); } } catch (err) { return { Type: entryTypes.error, Contents: err, ContentsType: formats.json, ReadableContentsFormat: formats.text, HumanReadable: err.message }; } finally { if (closeSessionAfterExecution) { closeSessionRequest(args.session); } } /// Util methods function sleep(ms) { var start = new Date().getTime(); var expire = start + ms; while (new Date().getTime() < expire) { /*Do nothing*/ } return; }






