Skip to content
KitploitKITPLOIT
StrumentiExploitsBlog
Log in
Invia
StrumentiExploitsBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

FeedContattoPrivacy© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
Unwinder — Spoofing dello stack di chiamate per Rust | Kitploit
Strumenti/GitHubGitHub/kudaes/unwinder
Evasione IDS/IPSPost-ExploitRed TeamingSviluppo PayloadAttacco Avversario
GitHubkudaes/unwinder

Unwinder

Spoofing dello stack di chiamate per Rust

Vedi Repository
38436161 anno faRevisionato da Kitploit

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

Contenuto

  • SilentMoonWalk
    • Descrizione
    • Crediti
    • Utilizzo
      • Macro call_function!()
      • Macro indirect_syscall!()
      • Passaggio dei parametri
    • Esempi
      • Chiamare kernel32.dll!Sleep()
      • Chiamare kernel32.dll!OpenProcess()
      • Chiamare NtDelayExecution() come syscall indiretta
      • Concatenare chiamate di macro
    • Considerazioni
      • Frame iniziale
      • PoC
  • Stack replacement
    • Descrizione
    • Utilizzo
    • Esempio pratico
    • Osservazioni

SilentMoonWalk

Descrizione

Unwinder fornisce una piena weaponizzazione della tecnica SilentMoonWalk, consentendo di ottenere uno spoofing completo e stabile della call stack in Rust.

Questa tecnica presenta le seguenti caratteristiche:

  • Supporto per eseguire qualsiasi funzione arbitraria con un massimo di 11 parametri.
  • Supporto per eseguire syscall indirette (senza allocazioni aggiuntive nell'heap) con un massimo di 11 parametri.
  • La crate consente di recuperare il valore restituito dalle funzioni chiamate tramite essa.
  • Il processo di spoofing può essere concatenato un numero qualsiasi di volte senza aumentare la dimensione della call stack.
  • Viene utilizzata la TLS per aumentare l'efficienza durante il processo di spoofing.
  • dinvoke_rs viene utilizzata per effettuare qualsiasi chiamata API Windows richiesta dalla crate.

Crediti

un ringraziamento ai creatori della tecnica SilentMoonWalk:

  • KlezVirus
  • Waldo-IRC
  • Trickster0

E naturalmente un enorme ringraziamento a namazso per il thread su Twitter che ha ispirato l'intero progetto.

Utilizzo

Importa questa crate nel tuo progetto aggiungendo la seguente riga al tuo cargo.toml e compila in modalità release:

[dependencies]
unwinder = "=0.1.4"

La funzionalità principale di questa crate è stata racchiusa in due macro:

  • La macro call_function!() consente di eseguire qualsiasi funzione arbitraria con una call stack pulita.
  • La macro indirect_syscall!() esegue la syscall indiretta specificata con una call stack pulita.

Per utilizzare una qualsiasi di queste macro è necessario importare il tipo di dato std::ffi::c_void.

Entrambe le macro restituiscono un *mut c_void che può essere utilizzato per recuperare il valore restituito dalla funzione eseguita. Maggiori dettagli nella sezione esempi.

Macro call_function

Questa macro viene utilizzata per chiamare qualsiasi funzione desiderata con una call stack pulita. La macro richiede i seguenti parametri:

  • Il primo parametro è l'indirizzo di memoria da chiamare dopo lo spoofing della call stack. Questo parametro deve essere passato come usize, isize o puntatore.
  • Il secondo parametro è un bool che indica se mantenere o meno il frame della funzione iniziale. Se non sei sicuro, impostalo a false, cosa che garantisce sempre una buona call stack.
  • I parametri successivi sono gli argomenti da inviare alla funzione una volta che la call stack è stata spoofata.

Macro indirect_syscall

Questa macro viene utilizzata per eseguire qualsiasi syscall indiretta desiderata con una call stack pulita. La macro richiede i seguenti parametri:

  • Il primo parametro è una stringa che contiene il nome della funzione NT di cui si desidera eseguire la syscall.
  • Il secondo parametro è un bool che indica se mantenere o meno il frame della funzione iniziale. Se non sei sicuro, impostalo a false, cosa che garantisce sempre una buona call stack.
  • I parametri successivi sono gli argomenti da inviare alla funzione NT.

Passaggio dei parametri

Per passare argomenti di tipi diversi a queste due macro, è necessario tenere in considerazione le seguenti indicazioni:

  • Qualsiasi tipo di dato base convertibile in usize (u8-u64, i8-i64, bool, ecc.) può essere passato direttamente alle macro.
  • Le struct e le union di dimensione 8, 16, 32 o 64 bit vengono passate come se fossero interi della stessa dimensione.
  • Le struct e le union con dimensione superiore a 64 bit devono essere passate come puntatore.
  • Le stringhe (&str e String) devono essere passate come puntatore.
  • I puntatori nulli (ptr::null(), ptr::null_mut(), ecc.) vengono passati come 0 (indipendentemente dal fatto che siano u8, u16, i32 o qualsiasi altro).
  • I parametri a virgola mobile e a doppia precisione non sono attualmente supportati.
  • Qualsiasi altro tipo di dato deve essere passato come puntatore.

Esempi

Chiamare Sleep

let k32 = dinvoke_rs::dinvoke::get_module_base_address("kernel32.dll");
let sleep = dinvoke_rs::dinvoke::get_function_address(k32, "Sleep"); // Memory address of kernel32.dll!Sleep() 
let miliseconds = 1000i32;
unwinder::call_function!(sleep, false, miliseconds);

Chiamare OpenProcess

let k32 = dinvoke_rs::dinvoke::get_module_base_address("kernel32.dll"); 
let open_process: isize = dinvoke_rs::dinvoke::get_function_address(k32, "Openprocess");
let desired_access: u32 = 0x1000;
let inherit = 0i32;
let pid = 20628i32;
let handle = unwinder::call_function!(open_process, false, desired_access, inherit, pid); // returns *mut c_void
let handle: HANDLE = std::mem::transmute(handle);
println!("Handle id: {:x}", handle.0);

Nota che la macro restituisce un *mut c_void che può essere convertito direttamente in un HANDLE poiché entrambi i tipi di dato hanno la stessa dimensione. Questo consente di accedere al valore restituito da OpenProcess, ovvero il nuovo handle al processo target.

Chiamare NtDelayExecution come syscall indiretta

let large = 0x8000000000000000 as u64; // Sleep indefinitely
let large: *mut i64 = std::mem::transmute(&large);
let alertable = false;
let ntstatus = unwinder::indirect_syscall!("NtDelayExecution", false, alertable, large); // returns *mut c_void
println!("ntstatus: {:x}", ntstatus as i32);

Nota che la macro restituisce un *mut c_void che può essere utilizzato per recuperare l'NTSTATUS restituito da NtDelayExecution.

Concatenare chiamate di macro

Il processo di spoofing può essere concatenato un numero qualsiasi di volte senza un incremento anomalo della dimensione della call stack. Anche il flusso di esecuzione verrà preservato. Il codice seguente è un esempio:

fn main()
{
	function_a();
}

fn function_a()
{
	unsafe
	{
		let func_b = function_b as usize;
		call_function!(func_b, false);
		println!("function_a done.");
	}
}

fn function_b()
{
	unsafe
	{
		let func_c = function_c as usize;
		call_function!(func_c, false);
		println!("function_b done.")
	}
}

fn function_c()
{
	unsafe
	{
		let large = 0x0000000000000000 as u64; // Don't sleep so we return to function_b, allowing to check the execution flow preservation.
		let large: *mut i64 = std::mem::transmute(&large);
		let alertable = false;
		let ntstatus = unwinder::indirect_syscall!("NtDelayExecution", false, alertable, large);
		println!("ntstatus: {:x}", (ntstatus as usize) as i32); //NTSTATUS is a i32, although that second casting is not really required in this case.
	}
}

Considerazioni

Frame iniziale

Se imposti il secondo parametro a true (in entrambe le macro), il processo di spoofing proverà a mantenere nella call stack il frame dell'indirizzo di inizio del thread per aumentare la legittimità.

Scarica lo strumento