前言
前段时间笔者在测试嵌入式设备的时候遇到了nmap扫不出端口的问题,当时非常迷惑这个设备的通信方式。后面研究发现不同于传统的像http或者mqtt这种能通过常用的工具与设备进行通讯的协议,此设备所用的通训方式更为底层,也涉及了笔者第一次接触的通信方式——组播通信。
组播通信介绍
直白的讲,组播就是为同一个网段下两个或多个设备提供信息交换的渠道。这个渠道被称作组播组,本质上是一个IP。如果以同一网段下的两个设备A,B举例,要实现他们直接的组播通信,首先需要A,B同时加入这个组播组,并且往这个IP的同一端口收发信息。我们发现这其中涉及了两个协议——设备加入组播组所使用的协议,以及设备往组播端口发送信息的协议。笔者测试的设备所用的组播协议为IGMPV3,而设备和端口通信用的是UDP协议。具体的端口号的问题,后面会进行分析。
设备实战
本次实战中的设备ip为192.168.1.12
nmap扫描
发现什么也没扫出来(试过了nmap -sS -sU -T4 -A -v也不太行)
wireshark抓包
通过wireshark抓包可以发现这个设备向230.1.1.1发了32字节的消息:
具体的消息能够从下面的详情里获取:
发现是32个”x00″,很疑惑,先不管它
从关键点入手分析
这个“230.1.1.1”很值得我们思考,我们通过”grep”大法可以发现有一个二进制文件包含它,并通过ida逆向找到它的位置:
然后我们看查这一行所在的一整个函数能看见几个重要的信息
重要信息一
从这里我们能够找到设备往230.1.1.1发的32个0:
那么50001端口是怎么来的呢?这里就要先细说一下sendto函数了:
sendto(int s, const void * msg, int len, unsigned int flags, const struct sockaddr * to, int tolen);
它有一个关键的结构体”sockaadr”,而这个结构体有个成员为“sin_port”一般的写法为:
addr.sin_port = htons(PORT);
这里的htons其实是把机器上的整数转换为网络字节序,用人话说就是把小端自序转大端回到这个函数中,我们通过逆向分析能够确定addr这个结构体的十进制表示为1371734018:
通过计算器,我们能算出端口:
正好就是50001
重要信息二
这个设备如何接受信息可以从recvfrom看出:
recvfrom和sendto是配套函数,也能通过刚才的方法分析出具体的端口:
于是下一步我们就可以尝试往50002端口发送信息了
重要信息三
发现我们发送的消息的低二字节必须是“xAFxE0”以及整体长度必须为0x220,然后就会进入switch
尝试攻击
switch中有很多能够利用的地方,这里就挑两个地方来谈谈
第一个
这里能够将这个设备打reboot,不过前面会有检查,这个检查是能绕过的,具体是在第一个case:
通过wireshark抓包就能找到
第二个
这里是直接一个命令执行,但是,这里的v7和case选项是一个值而且不是0x2009,也就是说会卡在前面的v7!=0x2009而不能执行成功,笔者猜测这里可能是厂商临时进行的一个修复,而导致不能直接执行。但是,在这个case分支中是存在一个注入点的,绕过以及执行的exp非常巧妙,但是因为厂商的要求等种种原因不能公布,于是无法与大家分享。但是笔者已经构思好了一道能够把这个手法运用的CTF iotpwn题,或许在未来的某天能够以题目的形式出现(狗头)
招新小广告
ChaMd5 Venom 招收大佬入圈
新成立组IOT+工控+样本分析 长期招新
原文始发于微信公众号(ChaMd5安全团队):组播路由介绍以及攻击实战