use anyhow::{Context, Result};
use clap::Parser;
use crate::winrm;
#[derive(Parser)]
pub(crate) struct WinrmArgs {
#[command(flatten)]
pub auth: crate::shared_args::SmbAuth,
#[arg(long, default_value_t = 5985)]
pub port: u16,
#[arg(long)]
pub nt_hash: Option<String>,
#[arg(long)]
pub command: String,
}
pub(crate) async fn winrm_exec(mut a: WinrmArgs) -> Result<()> {
a.auth.password = crate::resolve_secret(&a.auth.password, "ADHAMMER_PASSWORD")?;
let secret = match &a.nt_hash {
Some(h) => {
let raw = hex::decode(h.trim()).context("NT hash must be 32 hex chars")?;
let arr: [u8; 16] = raw
.as_slice()
.try_into()
.context("NT hash must be exactly 16 bytes (32 hex)")?;
winrm::Secret::NtHash(arr)
}
None => winrm::Secret::Password(a.auth.password.clone()),
};
let (mut client, shell_id) =
winrm::WinRm::connect(&a.auth.host, a.port, &a.auth.domain, &a.auth.user, &secret).await?;
eprintln!(
"[+] WinRM shell opened on {} (ShellId {})",
a.auth.host, shell_id
);
let (stdout, stderr, exit) = client.run(&shell_id, &a.command).await?;
print!("{stdout}");
if !stderr.is_empty() {
eprint!("{stderr}");
}
eprintln!("[+] WinRM command exited {exit}");
Ok(())
}