node模拟登录并管理小米路由器

小孩长大之后沉迷看动画片和玩手机,为了更好的限制他看电视、用手机,准备动用技术手段实现一个方便管理路由器web应用,不直接使用路由器的手机客户端,是因为我家里有2台路由器,厅里的的小米路由器,卧室的TP-LINK,我想将2个路由器整合在一起展示在web应用中,快速管理2个路由器,先给大家看一个最终的效果图(这里主要实现的是快速踢设备和接入设备)。

本系列将会写2篇文章,本文是第1篇文章,主要讲如何利用node模拟登录小米路由器,并实现简单的管理。下一节我们将会讲如何利用node模拟登录TP-LINK路由器并实现简单的管理,敬请期待,好了,我们继续本文。

既然我们要模拟登录,我们首先需要分析一下登录协议,打开小米路由器的登录页,地址一般是http://192.168.31.1/

接着我们按F12打开Chrome控制台,切换到network选项卡准备抓包,记得要提前勾选Preserve log

输入一个密码(不要输入正确密码,便于抓包),并点击登录,发现发送了以下请求:

请求地址是:http://192.168.31.1/cgi-bin/luci/api/xqsystem/login,并通过POST请求的方式发送了一些参数,通过对于参数的分析,我们发现,username默认是admin,这个估计是硬编码的,password是一个加密的字符串,logtype应该是一个常量,nounce应该是配合password解密和校验的,通过分析,我们知道重点就是找到password和nounce的生成方式,如何找呢?看过我之前文章的朋友应该知道我们可以通过initiator追踪发起登录请求的js代码,

没有显示initiator这一列的可以右击Name Status Type这一列在弹出框中勾选initiator就可以了,这里不好截图,大家自行尝试。

鼠标移动到登录请求后的Initiator上,我们可以看到js的调用链,

排除掉jQuery类库的调用,我们直接点击loginHandle这个调用,

直接找到了我们的登录函数,并发现password和password分别是通过Encrypt这个类的init方法和oldPwd方法生成的,通过进一步的代码搜索,我们很容易就可以找到Encrypt这个类的实现:

var Encrypt = {
    key: 'a2ffa5c9be07488bbb04a3a47d3c5f6a',
    iv: '64175472480004614961023454661220',
    nonce: null,
    init: function(){
        var nonce = this.nonceCreat();
        this.nonce = nonce;
        return this.nonce;
    },
    nonceCreat: function(){
        var type = 0;
        var deviceId = 'ac:d5:64:a5:0b:33';
        var time = Math.floor(new Date().getTime() / 1000);
        var random = Math.floor(Math.random() * 10000);
        return [type, deviceId, time, random].join('_');
    },
    oldPwd : function(pwd){
        return CryptoJS.SHA1(this.nonce + CryptoJS.SHA1(pwd + this.key).toString()).toString();
    },
    newPwd: function(pwd, newpwd){
        var key = CryptoJS.SHA1(pwd + this.key).toString();
        key = CryptoJS.enc.Hex.parse(key).toString();
        key = key.substr(0, 32);
        key = CryptoJS.enc.Hex.parse(key);
        var password = CryptoJS.SHA1(newpwd + this.key).toString();
        var iv = CryptoJS.enc.Hex.parse(this.iv);
        var aes = CryptoJS.AES.encrypt(
                password,
                key,
                {iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }
            ).toString();
        return aes;
    }
};

而Encrypt这个类使用了CryptoJS来对密码进行加密,到这里登录就分析完了,接下来我们登录进去继续分析后面的设备列表,踢设备,接入设备的请求。

1、获取设备列表

登录进去之后我们发现页面地址变成了http://192.168.31.1/cgi-bin/luci/;stok=2fe259e2c78462ac1f00db82f8d9f765/web/home#router,后面附带了stok参数,猜测这应该是是一个类似token的东西,应该很重要,需要提取出来。

而且我们很容易就可以找到获取设备列表的接口,http://192.168.31.1/cgi-bin/luci/;stok=2fe259e2c78462ac1f00db82f8d9f765/api/misystem/devicelist,是以GET形式发起的,而中间就是我们刚才说的那个很重要的stok参数,

2、踢设备、接入设备

根据上面的思路我们很容易找到踢设备和接入设备的接口都是http://192.168.31.1/cgi-bin/luci/;stok=2fe259e2c78462ac1f00db82f8d9f765/api/xqsystem/set_mac_filter,以GET形式传递了2个参数,一个mac是接入设备的mac地址,还有wan是表示禁用还是允许,进一步分析我们可以知道wan=0表示禁止设备接入,wan=1表示允许设备接入。

当然要做的很完善,这个里面需要分析的东西还有很多,这里就不一一分析了,大家可以根据本文提供的方法分析其他的接口,也可以找找本站其他的抓包分析的文章,里面还有一些别的很实用的抓包分析方法。

好了,本文到这里就结束了,如果大家有任何疑问,欢迎在评论区留言,我都会第一时间一一回复,文末附上node实现的小米路由器登录类,有需要的朋友请自行下载。

猛戳这里下载本文案例源码包
  • 支付宝二维码 支付宝
  • 微信二维码 微信
相关文章