Skip to content
KitploitKITPLOIT
StrumentiBlog
Log in
Invia
StrumentiBlog
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
HallWatch — Rilevatore in modalità utente che intercetta syscall indirette. Intrappola Hell's Hall, Tartarus' Gate, RecycledGate e syscall VEH e molte altre. | Kitploit
Strumenti/GitHubGitHub/zypherion-technologies/hallwatch
Strumenti DifensiviAnalisi MalwareAnalisi di BinariThreat IntelligenceRisposta agli Incidenti
GitHubzypherion-technologies/hallwatch

HallWatch

Rilevatore in modalità utente che intercetta syscall indirette. Intrappola Hell's Hall, Tartarus' Gate, RecycledGate e syscall VEH e molte altre.

Vedi Repository

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 →
8710103 mesi faRevisionato da Kitploit
Condividi

HallWatch

License: GPL v3 Website Discord Telegram X

Copyright (C) 2026 Adam Zypherion <[email protected]> — con licenza GPL-3.0.


Le syscall indirette sono semplici una volta che ne hai vista una. Il loader attraversa ntdll, legge l'SSN dal prologo di Nt*, trova i due byte 0F 05 poco dopo, imposta di persona r10/rax/rdx/r8/r9 e fa jmp direttamente a quei due byte. La syscall avviene dall'interno di ntdll. La tua hook sull'export di kernel32 non viene mai toccata. La tua hook sull'export di ntdll non viene mai toccata. [RSP] al momento della SYSCALL punta alla pagina RWX del loader, ma nulla nella chiamata appare insolito dall'esterno.

HellHall proc
    mov  r10, rcx
    mov  eax, dwSSN
    jmp  qword ptr [qAddr]
    ret
HellHall endp

Le varianti hanno nomi. Tartarus' Gate e RecycledGate usano l'istruzione syscall appartenente a uno stub ma l'SSN di un altro, quindi anche se registri il nome dello stub che la tua hook riporta, è una menzogna. VEH syscall innesca intenzionalmente una violazione di accesso e usa la propria VEH per riscrivere il contesto in modo che RIP cada sull'istruzione syscall di ntdll con i registri già pronti. Hell's Gate non usa affatto ntdll. Il loader scrive 0F 05 nella propria pagina RWX e viene eseguito da lì.

La risposta in modalità kernel (KM) è un driver; potrei effettivamente occuparmene col tempo e rilasciare un progetto, ma non accadrà presto :D


PAGE_GUARD sembrava dovesse funzionare. Marchi la pagina che contiene i byte della syscall con PAGE_GUARD, intercetti la STATUS_GUARD_PAGE_VIOLATION in una VEH, ispezioni, reindirizzi a un trampolino privato, imposti il flag trap, esci a passo singolo, riarmi la pagina. Un trap per chiamata Nt, indipendentemente da come il loader ci è arrivato. Funziona contro tutto tranne Hell's Gate.

Il problema è che il sistema operativo non collabora. PAGE_GUARD è monouso – cosa significa? Ogni volta che scatta il bit viene cancellato e devi rimetterlo. Il tuo handler esegue syscall (NtProtect per rimettere la guardia, NtContinue per riprendere) e quelle syscall hanno stub e quegli stub sono sulla pagina che hai appena protetto. Ho aggirato gran parte di questo problema con stub di syscall privati costruiti su una pagina separata di nostra proprietà (allocare RWX, scrivere mov r10,rcx; mov eax,SSN; syscall; ret, bloccare RX, non toccare mai ntdll), ma era fragile. Ogni versione minore di Windows cambiava i tempi. Ogni thread generato dal campione era un'altra corsa contro il worker di integrità che ricostruiva la guardia. Il successo demo era circa dal 30 al 50 percento su dieci esecuzioni sulla stessa macchina.

Alla fine ho smesso di cercare di convincere Windows che PAGE_GUARD dovesse comportarsi come volevo io e ho provato invece a sovrascrivere il byte.


Se hai problemi a capire, guarda questo video :)

https://github.com/user-attachments/assets/0cb670fd-e51b-413e-bf00-08f9297888ed


Il byte all'istruzione syscall è 0F 05. Solo il primo byte (0F) è il prefisso per una famiglia di opcode a due byte che include SYSCALL, CPUID e RDTSC. Da solo non è eseguibile; la CPU ha bisogno del secondo byte per decodificare. Se sostituisci il primo byte con 0xCC (INT3), la coppia diventa CC 05, che la CPU decodifica come INT3 seguito da un byte randagio che non raggiunge mai. Qualsiasi percorso di codice che atterra su quell'indirizzo solleva EXCEPTION_BREAKPOINT.

Questo è l'intero meccanismo. La nostra VEH intercetta il breakpoint, cerca a quale stub appartiene l'indirizzo (costruiamo la mappa all'inizializzazione enumerando gli export di ntdll), esegue tre controlli su chi si è presentato e imposta Context->Rip su un trampolino privato che esegue la vera syscall e ritorna. Il byte rimane CC. Il chiamante successivo lo colpisce allo stesso modo, quindi nessun capovolgimento di protezione di pagina avanti e indietro.

Per essere chiari: sì, questo è un hook tramite sovrascrittura di byte. Non è però il byte che di solito si intende con "hook ntdll". Il classico hook EDR sovrascrive i primi byte dello stub con un JMP <my_func>:

ntdll!NtAllocateVirtualMemory:
  E9 ?? ?? ?? ??       jmp my_hook     ; sovrascrive "mov r10, rcx"
  ...
  0F 05                syscall
  C3                   ret

Questo è esattamente ciò che le syscall indirette aggirano. Il loader legge l'SSN da solo e salta direttamente al 0F 05; il prologo (e il tuo jmp) non vengono mai eseguiti, l'hook non scatta mai. Quello che facciamo noi è sovrascrivere il byte della syscall stesso:

ntdll!NtAllocateVirtualMemory:
  4C 8B D1             mov r10, rcx     ; non toccato
  B8 18 00 00 00       mov eax, 18h     ; non toccato
  CC 05                int3 / 05        ; era 0F 05, abbiamo scritto CC sopra 0F
  C3                   ret

Ora non importa come sei arrivato a quell'indirizzo. Attraverso il prologo, attraverso un salto indiretto che salta il prologo, attraverso una riscrittura del contesto VEH-syscall che ci fa cadere RIP, qualsiasi cosa. Se la CPU esegue quel byte, si blocca. Stessa famiglia di tecnica dell'hook classico, posizione diversa, copertura completamente diversa.

Il trampolino si presenta così:

F3 0F 1E FA              endbr64
49 89 CA                 mov r10, rcx
B8 <stub SSN>            mov eax, ssn
0F 05                    syscall
C3                       ret

I tre controlli sono invariati rispetto alla versione PAGE_GUARD perché erano i tre controlli giusti; avevano solo bisogno di un posto affidabile dove vivere.

Indirizzo di ritorno. [RSP] è dove la syscall sarebbe tornata. Per una chiamata reale è all'interno di ntdll, kernel32, kernelbase o una delle DLL runtime correlate. Per Hell's Hall è all'interno della pagina RWX da cui il loader sta eseguendo. Abbiamo una lista breve di target di ritorno affidabili costruita all'inizializzazione chiamando GetModuleHandle per quei nomi e leggendo gli intervalli .text dai loro header PE.

SSN. Il prologo dello stub è già stato eseguito prima che raggiunga il byte di syscall, quindi eax contiene il valore che vi è stato caricato. Se il loader ha fatto uno scambio Tartarus, quel valore non corrisponderà all'SSN che abbiamo letto da questo stesso stub durante l'enumerazione. Registriamo la discrepanza e il trampolino scrive l'SSN corretto prima della propria syscall, quindi la funzione kernel che viene eseguita è quella che appartiene al byte invece di quella voluta dal loader. La tecnica viene registrata e neutralizzata nello stesso passaggio.

Stack walk. RtlVirtualUnwind dal contesto corrente, cinque frame su. Ogni frame dovrebbe avere RIP all'interno di un modulo noto e dovrebbe avere una voce RUNTIME_FUNCTION. Lo shellcode e i gadget ROP falliscono questo controllo anche quando [RSP] stesso sembra affidabile, cosa che un loader può falsificare (può prevedere approssimativamente dove sarà il suo chiamante in memoria e forgiare un indirizzo di ritorno credibile lì).

Se un controllo fallisce, inseriamo una piccola struct in un ring lock free e il thread di drenaggio la stampa la prossima volta che si sveglia:

Scarica lo strumento