diff --git a/docs/_docs/user-guide/eldritch.md b/docs/_docs/user-guide/eldritch.md
index 08b348c96..82990ccb8 100644
--- a/docs/_docs/user-guide/eldritch.md
+++ b/docs/_docs/user-guide/eldritch.md
@@ -552,37 +552,32 @@ The pivot.smb_exec method is being proposed to allow users a way to move
### pivot.ssh_copy
-`pivot.ssh_copy(target: str, port: int, src: str, dst: str, username: str, password: Optional, key: Optional, key_password: Optional, timeout: Optional) -> None`
+`pivot.ssh_copy(target: str, port: int, src: str, dst: str, username: str, password: Optional, key: Optional, key_password: Optional, timeout: Optional) -> str`
-The pivot.ssh_copy method copies a local file to a remote system. If no password or key is specified the function will error out with:
-`Failed to run handle_ssh_exec: Failed to authenticate to host`
+The pivot.ssh_copy method copies a local file to a remote system.
+ssh_copy will return `"Sucess"` if successful and `"Failed to run handle_ssh_copy: ..."` on failure.
If the connection is successful but the copy writes a file error will be returned.
-
-ssh_copy will first delete the remote file and then write to its location.
+ssh_copy will overwrite the remote file if it exists.
The file directory the `dst` file exists in must exist in order for ssh_copy to work.
+
### pivot.ssh_exec
`pivot.ssh_exec(target: str, port: int, command: str, username: str, password: Optional, key: Optional, key_password: Optional, timeout: Optional) -> List`
-The pivot.ssh_exec method executes a command string on the remote host using the default shell. If no password or key is specified the function will error out with:
-`Failed to run handle_ssh_exec: Failed to authenticate to host`
-If the connection is successful but the command fails no output will be returned but the status code will be set.
-Not returning stderr is a limitation of the way we're performing execution. Since it's not using the SSH shell directive we're limited on the return output we can capture.
+The pivot.ssh_exec method executes a command string on the remote host using the default shell.
+Stdout returns the string result from the command output.
+Stderr will return any errors from the SSH connection but not the command being executed.
+Status will be equal to the code returned by the command being run and -1 in the event that the ssh connection raises an error.
```json
{
"stdout": "uid=1000(kali) gid=1000(kali) groups=1000(kali),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),109(netdev),118(bluetooth),128(lpadmin),132(scanner),143(docker)\n",
+ "stderr":"",
"status": 0
}
```
-### pivot.ssh_password_spray
-
-`pivot.ssh_password_spray(targets: List, port: int, credentials: List, keys: List, command: str, shell_path: str) -> List`
-
-The pivot.ssh_password_spray method is being proposed to allow users a way to test found credentials against neighboring targets. It will iterate over the targets list and try each credential set. Credentials will be a formatted list of usernames and passwords Eg. "username:password". The function will return a formatted list of "target:username:password". command and shell_path is intended to give more flexibility but may be adding complexity.
-
---
## Process
diff --git a/implants/lib/eldritch/src/pivot/mod.rs b/implants/lib/eldritch/src/pivot/mod.rs
index 6cf790ff5..eb8457bcc 100644
--- a/implants/lib/eldritch/src/pivot/mod.rs
+++ b/implants/lib/eldritch/src/pivot/mod.rs
@@ -7,7 +7,6 @@ mod reverse_shell_pty_impl;
mod smb_exec_impl;
mod ssh_copy_impl;
mod ssh_exec_impl;
-mod ssh_password_spray_impl;
use anyhow::Result;
use async_trait::async_trait;
@@ -48,14 +47,8 @@ fn methods(builder: &mut MethodsBuilder) {
}
#[allow(unused_variables)]
- fn ssh_copy<'v>(this: &PivotLibrary, target: String, port: i32, src: String, dst: String, username: String, password: Option, key: Option, key_password: Option, timeout: Option) -> anyhow::Result {
- ssh_copy_impl::ssh_copy(target, port, src, dst, username, password, key, key_password, timeout)?;
- Ok(NoneType{})
- }
-
- #[allow(unused_variables)]
- fn ssh_password_spray(this: &PivotLibrary, targets: UnpackList, port: i32, credentials: UnpackList, keys: UnpackList, command: String, shell_path: String) -> anyhow::Result {
- ssh_password_spray_impl::ssh_password_spray(targets.items, port, credentials.items, keys.items, command, shell_path)
+ fn ssh_copy<'v>(this: &PivotLibrary, target: String, port: i32, src: String, dst: String, username: String, password: Option, key: Option, key_password: Option, timeout: Option) -> anyhow::Result {
+ ssh_copy_impl::ssh_copy(target, port, src, dst, username, password, key, key_password, timeout)
}
#[allow(unused_variables)]
diff --git a/implants/lib/eldritch/src/pivot/ssh_copy_impl.rs b/implants/lib/eldritch/src/pivot/ssh_copy_impl.rs
index e426295dd..3d0250212 100644
--- a/implants/lib/eldritch/src/pivot/ssh_copy_impl.rs
+++ b/implants/lib/eldritch/src/pivot/ssh_copy_impl.rs
@@ -42,7 +42,7 @@ pub fn ssh_copy(
key: Option,
key_password: Option,
timeout: Option,
-) -> Result<()> {
+) -> Result {
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()?;
@@ -63,14 +63,11 @@ pub fn ssh_copy(
)) {
Ok(local_res) => local_res,
Err(local_err) => {
- return Err(anyhow::anyhow!(
- "Failed to run handle_ssh_exec: {}",
- local_err.to_string()
- ))
+ return Ok(format!("Failed to run handle_ssh_copy: {}", local_err));
}
};
- Ok(())
+ Ok("Sucess".to_string())
}
#[cfg(test)]
diff --git a/implants/lib/eldritch/src/pivot/ssh_exec_impl.rs b/implants/lib/eldritch/src/pivot/ssh_exec_impl.rs
index b00d6549c..3ac3f4ad7 100644
--- a/implants/lib/eldritch/src/pivot/ssh_exec_impl.rs
+++ b/implants/lib/eldritch/src/pivot/ssh_exec_impl.rs
@@ -63,7 +63,7 @@ pub fn ssh_exec(
let key_password_ref = key_password.as_deref();
let local_port: u16 = port.try_into()?;
- let cmd_res = match runtime.block_on(handle_ssh_exec(
+ let (out, status, err) = match runtime.block_on(handle_ssh_exec(
target,
local_port,
command,
@@ -73,19 +73,15 @@ pub fn ssh_exec(
key_password_ref,
timeout,
)) {
- Ok(local_res) => local_res,
- Err(local_err) => {
- return Err(anyhow::anyhow!(
- "Failed to run handle_ssh_exec: {}",
- local_err.to_string()
- ))
- }
+ Ok(local_res) => (local_res.stdout, local_res.status, String::from("")),
+ Err(local_err) => (String::from(""), -1, local_err.to_string()),
};
let res = SmallMap::new();
let mut dict_res = Dict::new(res);
- insert_dict_kv!(dict_res, starlark_heap, "stdout", &cmd_res.stdout, String);
- insert_dict_kv!(dict_res, starlark_heap, "status", cmd_res.status, i32);
+ insert_dict_kv!(dict_res, starlark_heap, "stdout", &out, String);
+ insert_dict_kv!(dict_res, starlark_heap, "stderr", &err, String);
+ insert_dict_kv!(dict_res, starlark_heap, "status", status, i32);
Ok(dict_res)
}
diff --git a/implants/lib/eldritch/src/pivot/ssh_password_spray_impl.rs b/implants/lib/eldritch/src/pivot/ssh_password_spray_impl.rs
deleted file mode 100644
index c0ad7a2dc..000000000
--- a/implants/lib/eldritch/src/pivot/ssh_password_spray_impl.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-use anyhow::Result;
-
-pub fn ssh_password_spray(
- _targets: Vec,
- _port: i32,
- _credentials: Vec,
- _keys: Vec,
- _command: String,
- _shell_path: String,
-) -> Result {
- unimplemented!("Method unimplemented")
-}
diff --git a/implants/lib/eldritch/src/runtime/mod.rs b/implants/lib/eldritch/src/runtime/mod.rs
index 99792a2be..483024cf7 100644
--- a/implants/lib/eldritch/src/runtime/mod.rs
+++ b/implants/lib/eldritch/src/runtime/mod.rs
@@ -119,7 +119,7 @@ mod tests {
parameters: HashMap::new(),
file_names: Vec::new(),
},
- want_text: format!("{}\n", r#"["arp_scan", "bind_proxy", "ncat", "port_forward", "port_scan", "reverse_shell_pty", "smb_exec", "ssh_copy", "ssh_exec", "ssh_password_spray"]"#),
+ want_text: format!("{}\n", r#"["arp_scan", "bind_proxy", "ncat", "port_forward", "port_scan", "reverse_shell_pty", "smb_exec", "ssh_copy", "ssh_exec"]"#),
want_error: None,
},
assets_bindings: TestCase {