floss-cli 0.1.1

在 Rust 中以子进程方式调用 FLARE FLOSS CLI,并可选解析 -j JSON 输出
Documentation
# floss-cli ????


??????**???? API/??**?????? Rust ??? FLOSS CLI ????

## 1. ??


```toml
[dependencies]
floss-cli = "0.1.1"
```

> ???? tokio ???????????????? tokio runtime ??

## 2. ????


- ?????????? FLOSS CLI?`floss`/`floss.exe`????? `python -m floss`?
- ????? **CLI**???? FLOSS ? Python API?

## 3. ?? FlossCli????


### 3.1 ????????


```rust
use floss_cli::{FlossCli, Result};

#[tokio::main]

async fn main() -> Result<()> {
    let cli = FlossCli::detect().await?;
    Ok(())
}
```

### 3.2 ????


```rust
use floss_cli::{FlossCli, Result};

#[tokio::main]

async fn main() -> Result<()> {
    let cli = FlossCli::new("floss");
    let cli = FlossCli::python_module("python"); // python -m floss
    Ok(())
}
```

### 3.3 ???????????????


1. `FLOSS_EXE`????????????
2. `FLOSS_PYTHON` + `FLOSS_PYTHON_ARGS`??? Python ????????
3. `PATH` ?? `floss`/`floss.exe`
4. ?? Python ???Windows?`python/python3/py -3`????`python3/python`?

`FLOSS_PYTHON_ARGS` ???
- ?????
- ?? `'` ? `"` ?????????
- ??? `"` ????????????????

## 4. ???????FlossCommand?


```rust
use floss_cli::{FlossCli, Result};

#[tokio::main]

async fn main() -> Result<()> {
    let cli = FlossCli::detect().await?;

    let cmd = cli
        .command()
        .arg("--only")
        .args(["static", "decoded"])
        .sample("malware.exe");

    let line = cmd.command_line();
    println!("{}", line); // program + args
    Ok(())
}
```

- `.arg(...)` / `.args(...)`???????
- `.sample(...)`????? `--`????????????
- `.command_line()`??? `program + args`?????/??

## 5. ??????????


### 5.1 ????


- `run().await`??? stdout/stderr???????? 0 ?????
- `run_allow_exit_codes([1, 2]).await`????????????
- `run_raw().await`??? stdout/stderr???????
- `run_raw_limited(max_bytes).await`??? stdout/stderr ?????

### 5.2 JSON ??


- `run_json::<T>().await`???? `-j/--json`???????????? `T`
- `run_results().await`?????? `ResultDocument`

### 5.3 ?????????????


- `run_inherit().await`?stdout/stderr ???????????
- `run_inherit_checked().await`??????? 0 ?????

### 5.4 ?????


- `spawn()`?stdout/stderr ??????? `tokio::process::Child`
- `spawn_piped()`?stdout/stderr ? piped??? `Child`

> `spawn/spawn_piped` ?????????? Job Object?????????????

## 6. ???????


### 6.1 FlossOutput


`run/run_raw/run_allow_exit_codes` ?? `FlossOutput`?
- `program` / `args` / `status`
- `stdout: Vec<u8>` / `stderr: Vec<u8>`

????????
- `stdout_lossy()` / `stderr_lossy()`??? UTF-8
- `stdout_string()` / `stderr_string()`??? UTF-8

### 6.2 FlossOutputLimited


`run_raw_limited` ?? `FlossOutputLimited`????
- `stdout_truncated` / `stderr_truncated` ????

### 6.3 JSON ????


?????`ResultDocument`??? `floss_cli::results`??
- `decoding_function_scores` ? key ?????? `0x` ?????????

## 7. ????????


- `FlossCli::with_timeout(...)` ? `FlossCommand::with_timeout(...)` ????
- ????????????Best-effort??
  - Windows??? Job Object?`KILL_ON_JOB_CLOSE`?????? `taskkill`/`kill`
  - Unix?? `SIGTERM`??? 100ms????? `SIGKILL`
- ??????? `FlossError::TimedOutKillFailed`

## 8. ??????


### 8.1 ?? JSON ??


```rust
use floss_cli::{FlossCli, Result, ResultDocument};

#[tokio::main]

async fn main() -> Result<()> {
    let cli = FlossCli::detect().await?;
    let doc: ResultDocument = cli
        .command()
        .sample("malware.exe")
        .run_results()
        .await?;

    println!("decoded strings: {}", doc.strings.decoded_strings.len());
    Ok(())
}
```

### 8.2 ??? 0 ???


```rust
use floss_cli::{FlossCli, Result};

#[tokio::main]

async fn main() -> Result<()> {
    let cli = FlossCli::detect().await?;
    let out = cli.command().sample("malware.exe").run_allow_exit_codes([1]).await?;
    println!("status: {}", out.status);
    Ok(())
}
```

### 8.3 ???????????


```rust
use floss_cli::{FlossCli, Result};

#[tokio::main]

async fn main() -> Result<()> {
    let cli = FlossCli::detect().await?;
    cli.command().arg("-H").run_inherit().await?;
    Ok(())
}
```

### 8.4 ??????????


```rust
use floss_cli::{FlossCli, Result};

#[tokio::main]

async fn main() -> Result<()> {
    let cli = FlossCli::detect().await?;
    let out = cli.command().sample("malware.exe").run_raw_limited(1024 * 1024).await?;
    println!("stdout truncated: {}", out.stdout_truncated);
    Ok(())
}
```

### 8.5 spawn_piped + ????


```rust
use floss_cli::{FlossCli, Result};
use tokio::io::AsyncReadExt;

#[tokio::main]

async fn main() -> Result<()> {
    let cli = FlossCli::detect().await?;
    let mut child = cli.command().sample("malware.exe").spawn_piped()?;

    let mut stdout = Vec::new();
    if let Some(mut reader) = child.stdout.take() {
        reader.read_to_end(&mut stdout).await?;
    }

    let status = child.wait().await?;
    println!("status: {}", status);
    Ok(())
}
```

## 9. ?????????


`FlossError` ?????
- `AutoDetectFailed`???????
- `Io`?????/IO ??
- `Json`?JSON ??????
- `NonZeroExit`?? 0 ?????? stdout/stderr?
- `TimedOut` / `TimedOutKillFailed`????????
- `Utf8`??? UTF-8 ????

`NonZeroExit`/`TimedOut` ??? `command`?program + args?????????????

## 10. ?????


- Windows??? Job Object ?????????? `taskkill`/`kill`
- Unix??? `SIGTERM` ? `SIGKILL`
- `spawn/spawn_piped` ???????????