Finish verion 0.1.0

This commit is contained in:
DaZuo0122
2026-01-16 13:27:07 +08:00
parent 240107e00f
commit b63bcd405b
17 changed files with 4788 additions and 26 deletions

View File

@@ -1,6 +1,7 @@
use async_trait::async_trait;
use network_interface::{Addr, NetworkInterface, NetworkInterfaceConfig};
use regex::Regex;
use std::collections::HashMap;
use sha2::Digest;
use x509_parser::oid_registry::{
OID_KEY_TYPE_DSA, OID_KEY_TYPE_EC_PUBLIC_KEY, OID_KEY_TYPE_GOST_R3410_2012_256,
@@ -302,6 +303,7 @@ fn parse_ipconfig_dns(text: &str) -> DnsConfigSnapshot {
}
fn parse_windows_listeners() -> Result<Vec<ListenSocket>, PlatformError> {
let proc_map = load_windows_process_map();
let output = std::process::Command::new("netstat")
.arg("-ano")
.output()
@@ -316,11 +318,13 @@ fn parse_windows_listeners() -> Result<Vec<ListenSocket>, PlatformError> {
for line in text.lines() {
let trimmed = line.trim();
if trimmed.starts_with("TCP") {
if let Some(socket) = parse_netstat_tcp_line(trimmed) {
if let Some(mut socket) = parse_netstat_tcp_line(trimmed) {
enrich_socket(&mut socket, &proc_map);
sockets.push(socket);
}
} else if trimmed.starts_with("UDP") {
if let Some(socket) = parse_netstat_udp_line(trimmed) {
if let Some(mut socket) = parse_netstat_udp_line(trimmed) {
enrich_socket(&mut socket, &proc_map);
sockets.push(socket);
}
}
@@ -414,6 +418,103 @@ fn extract_port(value: &str) -> Option<u16> {
None
}
fn enrich_socket(socket: &mut ListenSocket, map: &HashMap<u32, ProcInfo>) {
let pid = match socket.pid {
Some(pid) => pid,
None => return,
};
if let Some(info) = map.get(&pid) {
socket.process_name = info.name.clone();
socket.process_path = info.path.clone();
}
}
#[derive(Clone)]
struct ProcInfo {
name: Option<String>,
path: Option<String>,
}
fn load_windows_process_map() -> HashMap<u32, ProcInfo> {
let mut map = HashMap::new();
let mut name_map = HashMap::new();
let tasklist = std::process::Command::new("tasklist")
.args(["/fo", "csv", "/nh"])
.output();
if let Ok(output) = tasklist {
if output.status.success() {
let text = String::from_utf8_lossy(&output.stdout);
for line in text.lines() {
let parts = parse_csv_line(line);
if parts.len() < 2 {
continue;
}
if let Ok(pid) = parts[1].parse::<u32>() {
name_map.insert(pid, parts[0].to_string());
}
}
}
}
let wmic = std::process::Command::new("wmic")
.args(["process", "get", "ProcessId,ExecutablePath", "/FORMAT:CSV"])
.output();
if let Ok(output) = wmic {
if output.status.success() {
let text = String::from_utf8_lossy(&output.stdout);
for line in text.lines() {
let parts = parse_csv_line(line);
if parts.len() < 3 {
continue;
}
let path = parts[1].trim();
let pid = parts[2].trim().parse::<u32>().ok();
if let Some(pid) = pid {
let name = name_map.get(&pid).cloned();
let path = if path.is_empty() {
None
} else {
Some(path.to_string())
};
map.insert(pid, ProcInfo { name, path });
}
}
}
}
for (pid, name) in name_map {
map.entry(pid)
.or_insert_with(|| ProcInfo {
name: Some(name),
path: None,
});
}
map
}
fn parse_csv_line(line: &str) -> Vec<String> {
let mut out = Vec::new();
let mut current = String::new();
let mut in_quotes = false;
for ch in line.chars() {
match ch {
'"' => {
in_quotes = !in_quotes;
}
',' if !in_quotes => {
out.push(current.trim_matches('"').to_string());
current.clear();
}
_ => current.push(ch),
}
}
if !current.is_empty() {
out.push(current.trim_matches('"').to_string());
}
out
}
fn load_native_roots(store: &str) -> Result<Vec<RootCert>, PlatformError> {
let certs = rustls_native_certs::load_native_certs()
.map_err(|err| PlatformError::new(ErrorCode::IoError, err.to_string()))?;