|
Non so cosa fare e mi sto annoiando, così invece di andare a dormire ho deciso
di programmare un pò. Mi oriento verso le reti Wireless e più in particolare
verso il WZCSVC (Wireless Zero Configuration Service) di Windows che fornisce la
configurazione automatica per le schede 802.11. Si tratta di un servizio di
Windows (il nome è proprio WZCSVC) che consente la gestione di schede Wireless.
Se si dispone di una scheda Wireless allora nelle Risorse di Rete sarà presente
anche l'oggetto corrispondente (come del resto per tutti i dispositivi di rete
rilevati dal sistema operativo). Pulsante destro del mouse -> Proprietà ed ecco
apparire la scheda delle proprietà. Nel tab "Reti senza fili" nella sezione
"Reti preferite" vi è l'elenco degli HotSpot a cui ci si è collegati
precedentemente. Selezionandone uno qualsiasi e clickando sul pulsante Proprietà
si apre la scheda con le caratteristiche della connessione alla rete Wireless in
questione. Come si può vedere, possono essere salvate tutte le informazioni
necessarie per la connessione incluse le Chiavi di connessione. Focalizziamoci
sul tab "Associazione", nella sezione "Chiave rete senza fili": prenderemo in
esame la situazione corrispondente alle seguenti impostazioni
Autenticazione di rete: Aperta
Crittografia dati: WEP
E' possibile inserire e salvare la Chiave di Rete. Bene, ci sono alcuni
programmi che riescono a restituire la Chiave di Rete salvata. L'obiettivo sarà
quello di realizzare appunto un programma che faccia la stessa cosa.
1. Analizziamo
La prima cosa da fare è cercare coi motori di ricerca se esiste qualcuno che
ha già realizzato qualcosa di open source. Uhmmm.... non si trova nulla usando
le parole chiave WEP, WZCSVC, etc... occorre sapere qualcosa in più per ampliare
le ricerche. La prima cosa che viene naturale chiedersi è la seguente: dove
vengono salvate le Chiavi di Rete? Behhh ovviamente o nel registro di Windows o
su un file (che poi è la stessa cosa visto che il registro è un insieme di
file). Quasi sicuramente il risultato sarà criptato, vabè ok però intanto
cominciamo a trovare la locazione di salvataggio, una cosa alla volta ecchecca***.
Cominciamo a cercare nel registro? Ok, aggiudicato, vada per il registro.
Useremo il programmino downloadabile all'indirizzo
RegEnum.exe.7z
che consente di enumerare le chiavi di registro modificate in un determinato
intervallo di tempo. Basterà ad esempio andare a modificare la Chiave di Rete,
salvare il tutto e poi aprire il programma e settare un range temporale ridotto
(ad esempio 1 minuto) che include l'istante in cui sono state salvate le nuove
impostazioni. Se tali impostazioni vengono salvate nel registro, allora avremo
elencate le chiavi di registro coinvolte. Bene, eseguiamo il tutto e taaacccc
ecco spuntare la seguente chiave di registro
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WZCSVC\Parameters\Interfaces\{AE46022F-9FB5-42B4-8A67-7325A23D69B8}
Uhmm, non male come inizio:
{AE46022F-9FB5-42B4-8A67-7325A23D69B8} è
il GUID della mia interfaccia di rete wireless. Tutte le interfacce di rete
(ossia le classiche schede di rete LAN, le schede wireless, etc...) rilevate dal
sistema operativo vengono identificate dal sistema operativo stesso con un
codice espresso sotto forma di GUID. Per un esempio che enumera le interfacce di
rete rilevate e per ognuna di esse le caratteristiche base (quindi anche il GUID)
si può far riferimento al seguente programmino
usingtheiphelperapi.7z
Ok, tornando alla chiave di registro trovata, è facile intuire che la chiave
di registro
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WZCSVC
contiene le informazioni che ci interessano (almeno alcune). La chiave di
registro
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WZCSVC\Parameters\Interfaces
contiene tante sottochiavi quante sono le interfacce di rete Wireless
rilevate, ognuna con un nome pari al GUID dell'interfaccia di rete Wireless in
questione.
Torniamo ora alla prima chiave (quella che include anche il GUID). Salviamoci
il contenuto, cambiamo il valore della chiave WEP di rete e poi risalviamoci
nuovamente il contenuto della medesima chiave di registro. Confrontando i 2 file
si vede come cambi il dato associato ad uno dei valori di registro di nome
Static#...Uhmm, interessante. Facciamo doppio click uno alla volta su ognuno dei
valori Static# e potremo vedere dall'editor esadecimale che a partire dal byte
in posizione $15 (valore in esadecimale quindi posizione decimale 21) vi è il
nome di uno degli HotSpot salvati . La conclusione è che l'elenco degli HotSpot
viene salvato nel registro nei valori Static#: ognuno di questi valori
corrisponde ad un HotSpot ed il dato associato raccoglie le proprietà del
medesimo (ivi inclusa l'eventuale chiave WEP di rete o almeno qualche
informazione associata dato che il dato cambia al variare del valore assegnato
alla chiave WEP medesima). Se ad esempio una interfaccia di rete Wireless ha
memorizzato 3 HotSpot, allora nella sua chiave di registro corrispondente avremo
i valori
Static#0001
Static#0002
Static#0003
Bene, ora si tratta di capire bene come la chiave WEP viene salvata.
Ricercando sul web con questi numerosi indizzi che si sono aggiunti, giungo ad
alcuni siti web che fanno rifermento al celebre software Aircrack-ng. In mezzo a
tutto il pagliaio riesco a trovare, comprensivo di file di progetto in Visual C++,
uno degli elementi del programma Aircrack-ng: si tratta di "wzcook"
wzcook.7z
Questo programma, comprensivo dei sorgenti in Visual C++, fa esattamente
quello che stavo cercando ossia restituire in chiaro le chiavi WEP degli HotSpot
memorizzati dalle varie interfacce di rete Wireless rilevate dal sistema
operativo. Possiamo quindi affermare che la fase di ricerca del materiale
necessario allo sviluppo del nostro programma, termina ufficialmente qui avendo
infatti trovato tutto l'occorrente.
2. Studiamoci wzcook
Analizzando i sorgenti si può vedere come wzcook utilizzi i concetti già
esposti precedentemente per enumerare gli HotSpot memorizzati per ogni
interfaccia di rete Wireless rilevata. Una cosa importante che si evince è la
locazione della chiave WEP: essa si trova nel registro di windows e più
precisamente nel dato associato al valore Static# corrispondente all'HotSpot
preso in esame. La posizione è definita dai primi 2 byte del dato in questione:
ad esempio nel mio caso, visualizzando il dato associato a Static#0000, i primi
2 byte sono i valori $C8 e $02; ecco, la password si trova a partire dalla
posizione $02C8 in poi. O meglio, il risultato della sua criptazione. Nello
specifico si ha che la chiave WEP può essere ottenuta coi seguenti passaggi:
consideriamo l'HotSpot corrispondente al valore di registro Static#0000 (per
gli altri basta fare la stessa cosa andando su Static#0001, Static#0002, etc...
quindi il discorso è analogo)
prendiamo i primi 2 byte del dato: il loro valore esprime l'offset a cui si
trova la sequenza di byte che ci interessa;
chiamiamo EncKey la sequenza di byte che va dall'offset così definito fino
alla fine del dato
1) Decriptiamo EncKey tramite l'api win32 CryptUnprotectData ed
otteniamo una sequenza di byte che chiameremo ClearKey
2) Otteniamo la chiave WEP eseguendo un semplice XOR tra la ClearKey e la
seguente sequenza di byte:
$56, $66, $09, $42, $08, $03, $98, $01, $4D, $67, $08, $66,
$11, $56, $66, $09, $42, $08, $03, $98, $01, $4D, $67, $08, $66, $11, $56, $66,
$09, $42, $08, $03
Ok, abbiamo ottenuto la chiave WEP associata ad uno degli HotSpot memorizzati
da una delle interfacce di rete Wireless rilevate dal sistema. Per gli altri il
discorso è analogo.
Rimane un solo, piccolissimo dettaglio: l'api win32 CryptUnprotectData
decripta il risultato restituito dall'api win32 CryptProtectData. Il fatto
importante è che le credenziali con cui deve essere chiamata la
CryptUnprotectData devono essere le medesime con cui fu chiamata a suo tempo la
CryptProtectData. In questo caso la criptazione della chiave WEP viene
effettuata con credenziali System e quindi la chiamata a CryptUnprotectData dovrà
essere effettuata all'interno di un thread eseguito come SYSTEM. Wzcook si crea
il suo bel servizio e lo manda in esecuzione (i servizi di Windows di default
vengono eseguiti con l'utenza SYSTEM) mentre io mantengo fede al mio
attaccamento per il Code Injection e decido di realizzare il tutto appunto
tramite Code Injection: creazione di un thread nello spazio di memoria di
winlogon (processo eseguito come SYSTEM).
Non mi sembra il caso di andare a riempire questa pagina html con la montagna
di codice associato. Mi limito però ad esporre l'utilizzo del codice
implementativo che si riduce alla chiamata ad una funzione alla quale viene
passato come parametro un puntatore ad una funzione di callback adeguatamente
definita (un meccanismo già visto più volte nell'ambito delle api win32 ad
esempio nell'enumerazione delle finestre)
function GetDataCallBack(
DataType: Cardinal;
Data: Pointer;
DataSize: Cardinal
): Boolean;
begin
case DataType of
1: //GUID della WiFi Network Interface
begin
FrmMain.mmoLog.Lines.Add(PAnsiChar(Data));
end;
2: //nome dell'HOT-SPOT
begin
FrmMain.mmoLog.Lines.Add(PAnsiChar(Data));
end;
3: //Wep Key dell'HOT-SPOT
begin
FrmMain.mmoLog.Lines.Add(DumpData(Data, DataSize));
end;
end;
end;
procedure TFrmMain.btnDumpClick(Sender: TObject);
begin
//
mmoLog.Lines.Clear;
GetWZCSVCData(@GetDataCallBack);
end;
Sorgenti (VCL e KOL) EXE (relativo alla versione KOL) 3. Appendice
In appendice vado ad esporre del codice in C che utilizza le api esportate dalla dll wzcsapi.dll che viene usata dal WZCSVC. E' possibile vedere come enumerare le interfacce di rete Wireless e per ognuna di esse andare a leggerne le caratteristiche. Queste api non sono documentate ed il codice è utile come riferimento base. Il tutto per avere nuovo materiale da cercare su Google (o Yahoo, etc...). P.S. per chi non lo avesse capito, non ha nulla a che vedere con questo articolo (se non per il fatto che viene trattato WZCSVC a livello di programmazione).
//Indirizzo originale:
http://forums.chasenet.org/index.php?showtopic=13998
//The code is not perfect, but demonstrates the given problem. If the API
//is changed the code can be easily broken.
//The code is released under GPL (http://www.gnu.org/licenses/gpl.html), by Laszlo Toth.
//Use the code at your own responsibility.
//http://www.soonerorlater.hu/index.khtml?article_id=62
#include "stdafx.h"
#include
#include
#include
#include
#include
#include
struct GUID_STRUCT{
//How many wireless cards are in the PC?
int count;
wchar_t** guids_ar;
}guids;
struct PSK_STRUCT{
char ssid[92];
int psk_length;
unsigned char psk[32];
char other[584];
};
struct SSIDS_STRUCT{
//How many profile are configured?
int count;
char other[24];
PSK_STRUCT psk;
};
struct INTF_ENTRY_STRUCT{
wchar_t* guid;
char other[72];
SSIDS_STRUCT* ssidlist;
char other2[10000];
}iestr;
typedef int (WINAPI* PQUERYI)(void*, int, void*, void*);
typedef int (WINAPI* PENUMI)(void*, GUID_STRUCT*);
int _tmain(int argc, _TCHAR* argv[])
{
//Load wzcsapi to use the implemented RPC interface of Wireless Zero
//Configuration Service
HMODULE hMod = LoadLibrary ("wzcsapi.dll");
if (NULL == hMod)
{
printf ("LoadLibrary failed\n");
return 1;
}
//Get the address of the WZCEnumInterfaces. We need the guid of the
//wireless devices.
PENUMI pEnumI = (PENUMI) GetProcAddress (hMod, "WZCEnumInterfaces");
if (NULL == pEnumI)
{
printf ("GetProcAddress pEnumI failed\n");
return 1;
}
//The call of WZCEnumInterfaces
int ret=pEnumI(NULL, &guids);
if (ret!=0){
printf("WZCEnumInterfaces failed!\n");
return 1;
}
//Get the address of the WZCQueryInterface
PQUERYI pQueryI = (PQUERYI) GetProcAddress (hMod, "WZCQueryInterface");
if (NULL == pQueryI)
{
printf ("GetProcAddress pQueryI failed\n");
return 1;
}
int j;
for(j=0;jpsk);
int i=0;
for(i=0;icount;i++){
if(32==temp->psk_length){
printf("%s:",temp->ssid);
for(int j=0; j<32; j++){
printf("%02x",temp->psk[j]);
}
printf("\n");
}else{
printf("%s:%s\n",temp->ssid, temp->psk);
}
temp++;
}
}
}
return 0;
}
Data ultimo aggiornamento: 03/09/07 (riorganizzato il codice e prodotte 2 versioni, una con VCL e l'altra con la KOL Library)
|