Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Einreichen
ToolsExploitsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
Unwinder — Call-Stack-Spoofing für Rust | Kitploit
Tools/GitHubGitHub/kudaes/unwinder
IDS/IPS-UmgehungPost-ExploitationRed TeamingPayload-EntwicklungAdversarial-Angriff
GitHubkudaes/unwinder

Unwinder

Call-Stack-Spoofing für Rust

Repository anzeigen
3843616vor 1 JahrVon Kitploit geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

Inhalt

  • SilentMoonWalk
    • Beschreibung
    • Credits
    • Verwendung
      • Makro call_function!()
      • Makro indirect_syscall!()
      • Parameterübergabe
    • Beispiele
      • Aufruf von kernel32.dll!Sleep()
      • Aufruf von kernel32.dll!OpenProcess()
      • Aufruf von NtDelayExecution() als indirekter Syscall
      • Verkettung von Makroaufrufen
    • Hinweise
      • Initialer Frame
      • PoC
  • Stack-Ersetzung
    • Beschreibung
    • Verwendung
    • Praktisches Beispiel
    • Anmerkungen

SilentMoonWalk

Beschreibung

Unwinder bietet eine vollständige Weaponization der SilentMoonWalk-Technik und ermöglicht vollständiges und stabiles Call-Stack-Spoofing in Rust.

Diese Technik weist die folgenden Eigenschaften auf:

  • Unterstützung für die Ausführung beliebiger Funktionen mit bis zu 11 Parametern.
  • Unterstützung für die Ausführung indirekter Syscalls (ohne zusätzliche Heap-Allokationen) mit bis zu 11 Parametern.
  • Die Crate ermöglicht den Abruf des Rückgabewerts der darüber aufgerufenen Funktionen.
  • Der Spoofing-Prozess kann beliebig oft verkettet werden, ohne dass die Größe des Aufrufstapels zunimmt.
  • TLS wird verwendet, um die Effizienz während des Spoofing-Prozesses zu erhöhen.
  • dinvoke_rs wird verwendet, um alle von der Crate benötigten Windows-API-Aufrufe durchzuführen.

Credits

Dank an die Ersteller der SilentMoonWalk-Technik:

  • KlezVirus
  • Waldo-IRC
  • Trickster0

Und natürlich ein großes Lob an namazso für den Twitter-Thread, der dieses gesamte Projekt inspiriert hat.

Verwendung

Importieren Sie diese Crate in Ihr Projekt, indem Sie die folgende Zeile zu Ihrer cargo.toml hinzufügen und im release-Modus kompilieren:

[dependencies]
unwinder = "=0.1.4"

Die Hauptfunktionalität dieser Crate ist in zwei Makros gekapselt:

  • Das Makro call_function!() ermöglicht die Ausführung einer beliebigen Funktion mit einem sauberen Aufrufstapel.
  • Das Makro indirect_syscall!() führt den angegebenen (indirekten) Syscall mit einem sauberen Aufrufstapel aus.

Um eines dieser Makros verwenden zu können, muss der Datentyp std::ffi::c_void importiert werden.

Beide Makros geben einen *mut c_void zurück, der verwendet werden kann, um den von der ausgeführten Funktion zurückgegebenen Wert abzurufen. Detailliertere Informationen finden Sie im Abschnitt Beispiele.

Makro call_function

Dieses Makro wird verwendet, um eine beliebige gewünschte Funktion mit einem sauberen Aufrufstapel aufzurufen. Das Makro erwartet die folgenden Parameter:

  • Der erste Parameter ist die Speicheradresse, die nach dem Spoofing des Aufrufstapels aufgerufen werden soll. Dieser Parameter sollte als usize, isize oder als Zeiger übergeben werden.
  • Der zweite Parameter ist ein bool, der angibt, ob der Frame der Startfunktion erhalten bleiben soll oder nicht. Wenn Sie sich nicht sicher sind, setzen Sie ihn auf false, was immer einen guten Aufrufstapel garantiert.
  • Die folgenden Parameter sind die Argumente, die an die Funktion gesendet werden, sobald der Aufrufstapel gespooft wurde.

Makro indirect_syscall

Dieses Makro wird verwendet, um einen beliebigen gewünschten indirekten Syscall mit einem sauberen Aufrufstapel auszuführen. Das Makro erwartet die folgenden Parameter:

  • Der erste Parameter ist ein String, der den Namen der NT-Funktion enthält, deren Syscall Sie ausführen möchten.
  • Der zweite Parameter ist ein bool, der angibt, ob der Frame der Startfunktion erhalten bleiben soll oder nicht. Wenn Sie sich nicht sicher sind, setzen Sie ihn auf false, was immer einen guten Aufrufstapel garantiert.
  • Die folgenden Parameter sind die Argumente, die an die NT-Funktion gesendet werden.

Parameterübergabe

Um Argumente verschiedener Typen an diese beiden Makros zu übergeben, müssen die folgenden Überlegungen berücksichtigt werden:

  • Jeder einfache Datentyp, der in usize konvertiert werden kann (u8-u64, i8-i64, bool usw.), kann direkt an die Makros übergeben werden.
  • Structs und Unions mit einer Größe von 8, 16, 32 oder 64 Bit werden so übergeben, als wären sie ganze Zahlen derselben Größe.
  • Strukturen und Unions mit einer Größe von mehr als 64 Bit müssen als Zeiger übergeben werden.
  • Strings (&str und String) müssen als Zeiger übergeben werden.
  • Nullzeiger (ptr::null(), ptr::null_mut() usw.) werden als 0 übergeben (egal ob u8, u16, i32 oder irgendein anderer Typ).
  • Gleitkomma- und Doppelpräzisionsparameter werden derzeit nicht unterstützt.
  • Jeder andere Datentyp muss als Zeiger übergeben werden.

Beispiele

Aufruf von 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);

Aufruf von 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);

Beachten Sie, dass das Makro einen *mut c_void zurückgibt, der direkt in einen HANDLE konvertiert werden kann, da beide Datentypen dieselbe Größe haben. Dadurch kann auf den von OpenProcess zurückgegebenen Wert zugegriffen werden, also auf das neue Handle zum Zielprozess.

Aufruf von NtDelayExecution als indirekter Syscall

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);

Beachten Sie, dass das Makro einen *mut c_void zurückgibt, mit dem der von NtDelayExecution zurückgegebene NTSTATUS abgerufen werden kann.

Verkettung von Makroaufrufen

Der Spoofing-Prozess kann beliebig oft verkettet werden, ohne dass die Größe des Aufrufstapels abnormal zunimmt. Auch der Ausführungsfluss bleibt erhalten. Der folgende Code ist ein Beispiel dafür:

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.
	}
}

Hinweise

Initialer Frame

Tool herunterladen