使用Python来操作你的路由器(TP_LINK WR885N)

开始之前咱们先了解一下TPLINK WR885N这款设备,官方地址为 http://www.tp-link.com.cn/product_368.html 针对官方介绍,这里博主做个简短的讲解

首先看到的是官方的路由器图片

ex.jpg - 大小: 196.22 KB - 尺寸:  x  - 点击打开新窗口浏览全图
外观还是不错的,博主手上拿到的设备就是那款黑色的,接着来看下官方介绍的管理界面
p7.jpg - 大小: 253.21 KB - 尺寸:  x  - 点击打开新窗口浏览全图
嗯,看起来似乎非常不错的样子,但是实际测试发现,其实不是这样的,还是很久以前那种传统的管理界面,这个先按住不说。关于其他的各种参数以及优点之类的博主就不多说了,不是本文的重点。

好的,现在开始实战。

登录界面是这样的

login.png - 大小: 24.84 KB - 尺寸:  x  - 点击打开新窗口浏览全图
相信有很多同学对这个登录界面已经是非常熟悉了,只需要一个密码即可登录,这跟之前博主写的那篇登录小米路由器登录的那个登录界面一样,所以理论上来说应该是默认使用的admin账户登录。

当然,推测终究是推测,咱们肯定是要先得证明一下推测的正确性。好的,这里咱们直接查看页面源代码。

右键查看页面源代码(火狐浏览器)......额,竟然禁用了鼠标右键,好吧,这么鸡肋的功能我也是醉了,博主推荐安装一个火狐浏览器的小工具Web Deverloper Toolbar 这个工具很实用,后面会用到。

deverloop.png - 大小: 27.94 KB - 尺寸: 745 x 412 - 点击打开新窗口浏览全图
安装完之后会在浏览器上面看到一条工具栏,这里查看源代码就直接点击 Web Deverloper Toolbar 的View Source选择View Source选项即可
bar.png - 大小: 11.39 KB - 尺寸:  x  - 点击打开新窗口浏览全图
当然也可以按快捷键Alt + Shift + U查看源代码,总之是非常好使的工具。

查看源代码就很容易看到页面里面做了什么动作了,下面这段代码就是禁用鼠标右键的

function Click(){return false;}
document.oncontextmenu=Click;
function doPrev(){history.go(-1);}
这段代码博主也不知道为何要写上去,禁用右键的目的是什么呢?是怕别人看出代码写的太渣?

来接着看代码,javascript部分写了一些登录的操作,下面方法是生成base64编码,推测登录的时候是有用到base64编码

function Base64Encoding(input) 
{
	var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
	var output = "";
	var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
	var i = 0;

	input = utf8_encode(input);

	while (i < input.length) 
	{

		chr1 = input.charCodeAt(i++);
		chr2 = input.charCodeAt(i++);
		chr3 = input.charCodeAt(i++);

		enc1 = chr1 >> 2;
		enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
		enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
		enc4 = chr3 & 63;

		if (isNaN(chr2)) {
			enc3 = enc4 = 64;
		} else if (isNaN(chr3)) {
			enc4 = 64;
		}

		output = output +
		keyStr.charAt(enc1) + keyStr.charAt(enc2) +
		keyStr.charAt(enc3) + keyStr.charAt(enc4);

	}
 
	return output;
}
略过一些鸡肋方法之后找到登录的方法
function PCSubWin()
{
	if(CheckPswLength() == true )
	{
		var password = $("pcPassword").value;	
		var auth = "Basic "+Base64Encoding("admin:"+password); 
                document.cookie = "Authorization="+escape(auth)+";path=/";
		location.reload();
	}
}

嗯,根据方法的逻辑是先检查密码的长度,咱们在脚本中就没必要检查了,所以剩下的就简单了,先制造一个字符串作为Cookie的值

"Basic "+Base64Encoding("admin:"+password);
注意看这里,默认的用户是admin,证明了之前的推测是没错的,登录用户是admin写死的,将用户和密码组合一下进行一次base64加密,然后接着看
document.cookie = "Authorization="+escape(auth)+";path=/";

这里往Cookie里面写入值,注意上面生成的那个base64编码需要调用escape方法进行一个url编码,然后刷新页面就好了,登录过程如此简单,比小米的登录简单多了

那么看到这有的同学就说了,这样的设计是很不科学的,很容易造成爆破,因为用户名都不用猜,只需要爆破密码就可以了,真的是这样吗?

博主就用错误的密码登录了数次之后出现了这个提示

10.png - 大小: 11.87 KB - 尺寸: 510 x 368 - 点击打开新窗口浏览全图
密码错误已达10次,请两小时后再尝试看来还是有做一些防御的,防止爆破嘛,博主决定研究下这个防御有没有起到实际作用于是继续看代码

function pageLoad()
{
	document.cookie = "Authorization=;path=/";
	var ErrNum = httpAutErrorArray[0];
	switch(ErrNum)
	{
		case 1:
			isShowReset = true;
			$("errMsg").innerHTML = "密码错误,请重新输入。";
			$("errMsg").style.visibility = "visible";
			$("resetMsg").style.visibility = "visible";
			setPswDisable(false);
		break;
		case 2:
			isShowReset = true;
			$("errMsg").innerHTML = "密码错误已达10次,请两小时后再尝试。";
			$("errMsg").style.visibility = "visible";
			$("resetMsg").style.visibility = "visible";
			setPswDisable(true);	
		break;
		case 0:
		default:
			isShowReset = false;
			$("errMsg").style.visibility = "hidden";
			$("resetMsg").style.visibility= "hidden";
			setPswDisable(false);	
		break;
	}
	
	var loginBtn = $("loginBtn");
	loginBtn.onmouseover = function(){
		loginBtn.style.background = "url(../login/loginBtnH.png)";
	};
	loginBtn.onmouseout = function(){
		loginBtn.style.background = "url(../login/loginBtn.png)";
	};
	
	$("officialLink").onclick = function(){
		window.open(httpAutErrorArray[1]);
	};
}
这段代码里面有提到关键字,所以就研究这段吧,这个pageLoad方法是页面加载完成后立刻执行的方法,看关键部分
var ErrNum = httpAutErrorArray[0];
switch(ErrNum)
{
	....
	case 2:
		isShowReset = true;
		$("errMsg").innerHTML = "密码错误已达10次,请两小时后再尝试。";
		$("errMsg").style.visibility = "visible";
		$("resetMsg").style.visibility = "visible";
		setPswDisable(true);	
	break;
	...
}
那个密码次数达到10次的提示就是这里生成的,看上去跟 httpAutErrorArray 这个数组里面的值有关系,找到这个数组所在的方法
var httpAutErrorArray=new Array(2,"http:\/\/www.tp-link.com.cn",0,0 );

这段js代码是页面加载的时候自动生成的,很显然是服务端直接生成的,而需要的值就是httpAutErrorArray数组的第一个值,这里很显然是2,根据上面方法,状态时密码次数10次,正常登录的时候第一个值为0,这样才不会出现那个提示。这里咱们尝试修改第一个值试下,那么问题来了,怎么改?这个是服务端传过来的,拦截response?这么做是可以的,使用神器burp就能做到,但是这里使用burp未免显得大材小用,博主使用常用的小工具Firebug即可,首先调出firebug,调出console控制台,如图

console.png - 大小: 44.11 KB - 尺寸: 824 x 496 - 点击打开新窗口浏览全图
博主用荧光笔写This的区域就是控制台区域,可以在这里写js代码并运行。

好了,开始,这里需要执行的操作就是修改httpAutErrorArray的第一个值,然后执行pageLoad方法即可,在控制台这么写就好了

httpAutErrorArray[0] = 0;
pageLoad();
点击执行之后再看页面就变成了这个样子
losin1.png - 大小: 9.35 KB - 尺寸: 546 x 385 - 点击打开新窗口浏览全图
是不是一下子就兴奋了起来呢?试下登录吧,输入正确的密码后点击登录,出现这个界面
10.png - 大小: 11.87 KB - 尺寸: 510 x 368 - 点击打开新窗口浏览全图
OH ,Fuck!看来是服务端也有限制了

不过没关系,不妨碍咱们的研究,上面提到了登录是直接向Cookie里面写入拼接好的字符串即可,那咱们就直接往cookie里面写不就好了,这里有两种方法

第一种就是使用firebug直接执行登录的方法

另外一种就是使用开始提到的那个Web Deverloper Toolbar工具

点击工具栏的Cookies

cookie.png - 大小: 4.23 KB - 尺寸: 266 x 52 - 点击打开新窗口浏览全图
选择View cookies Infomation进入Cookies的编辑界面
viewcookie.png - 大小: 24.21 KB - 尺寸: 718 x 493 - 点击打开新窗口浏览全图
点击下面的Edit按钮就可以开始编辑了

这里咱们需要编辑的是Value字段,根据js代码中的登录方法得到值应该是Base加空格加base64(admin:密码)的形式,博主这里使用的密码是666888,所以得到的值为Base YWRtaW46NjY2ODg4 然后进行url编码,得到的结果是Base%20YWRtaW46NjY2ODg4

URL编码和解码的网站 http://tool.chinaz.com/tools/urlencode.aspx

Base64加密解密的网站 http://www1.tc711.com/tool/BASE64.htm

写入Cookie值之后保存刷新登录界面,不出意外的话就登录成功了,当然博主这里还是处于密码输入错误的状态,需要两个小时后再试

好了,趁着这段等待的时间咱们直接来写Python脚本吧,这个利用Cookie就能登录的脚本写起来应该是非常容易了。

需要的模块:requests,base64,re

base64模块用来生成base64编码的字符串,re模块是用来匹配服务端返回的一些字段。

登录成功之后页面会进行跳转,跳转是使用了前端的js跳转,代码如下

if(window != window.parent)
{
    window.parent.location.href = "/userRpm/Index.htm";
}

所以这里只需要判断页面中是否有    userRpm 这个字符串即可,有则登录成功,没有则失败,失败的情况有两种,第一种是密码错误,第二种是密码输错了10次禁止登录,这里需要判断下

路由器功能相对简单,就不写什么class类了,直接定义几个方法,首先做登录方法,代码如下,很简单,不做过多解释
def doLogin():

    host = sys.argv[1]
    password = base64.b64encode("admin:"+sys.argv[2])

    url_login = 'http://' + host
    cookie = {"Authorization":"Basic " + password}

    try:
        response = requests.get(url = url_login,cookies = cookie)
        serverResult = ''.join(response.text.split())
        
        ifSuccess = serverResult.split('userRpm')

        if len(ifSuccess) < 2:
            loginStatus = re.findall(r'varhttpAutErrorArray=newArray\((.+?),"http',serverResult)
            print 'Login Failed. Status is ' + loginStatus[0]
        else:
            print 'Login Success.'
            
    except Exception,e:
        print e
        return

运行效果是这样的

选区_001.png - 大小: 10.16 KB - 尺寸: 582 x 118 - 点击打开新窗口浏览全图

[2个小时后~~~]

好了,现在可以正常登录路由器了,来看下实际管理界面是怎么样的

450m.png - 大小: 159.29 KB - 尺寸:  x  - 点击打开新窗口浏览全图
为了搞明白为何界面跟官方宣传的不一致,博主仔细查阅了官方相关的文档,发现,官方所宣传的那个高端大气的管理后台是针对硬件版本4.0以后的机型,当前硬件版本为WR885N 1.0 00000000 软件版本为 1.0.2 Build 140504 Rel.33139n 官方提供的最新固件版本为 TL-WR885N V1.0_140728标准版 修复和优化说明如下

1、适用于TL-WR885N V1.0版本的标准版升级软件,不同型号或硬件版本不能使用该软件,升级前请确认版本。
2、优化无线信道自动选择的功能。
3、解决因第三方软件频繁探测路由器导致路由器登录界面被锁定2小时的问题。
第三条似乎对我们进行密码爆破有帮助,这里暂时不讨论。

接着咱们来写个修改登录密码的方法作为例子,其他的功能写起来类似,根据firebug咱们得知修改密码的连接为

http://192.168.1.1/userRpm/ChangeLoginPwdRpm.htm?oldpassword=666888&newpassword=admin123&newpassword2=admin123&Save=%B1%A3+%B4%E6
没错直接一个get请求就OK了,python写起来就简单了,注意这里请求时候必须带上Cookie,因为各种操作都是基于Cookie来认证
根据Firebug得知修改成功之后会返回如下内容
<html>
	<head></head>
	<body onload="goUrl()">
	<script type="text/javascript">
		function goUrl(){
			window.parent.document.cookie="Authorization=BasicYWRtaW46NjY2ODg4;path=/";
			window.parent.location.href="http://192.168.1.1";
		}
	</script>
	</body>
</html>

修改失败的话就直接返回修改密码的原始页面,所以这里判断修改是否成功则只需要判断返回的内容中是否存在goUrl这个字符串即可
这里如果单独请求修改密码的页面会提示验证失败,所以必须带上Header,referer指向 http://192.168.1.1/userRpm/ChangeLoginPwdRpm.htm ,代码写出来就是这样的

def changePwd():

    host = sys.argv[1]
    oldPwd = sys.argv[2]
    newPwd = sys.argv[3]

    url_password = "http://"+ host +"/userRpm/ChangeLoginPwdRpm.htm?oldpassword="+ oldPwd +"&newpassword="+ newPwd +"&newpassword2="+ newPwd +"&Save=%B1%A3+%B4%E6"
    cookie = {"Authorization":"Basic " + base64.b64encode("admin:" + oldPwd)}

    headers = { 
        'Host': host,
        'User-Agent' : 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; BOIE9;ZHCN)',  
        'Referer' : 'http://'+ host +'/userRpm/ChangeLoginPwdRpm.htm',
        }

    try:
        response = requests.get(url = url_password,headers = headers,cookies = cookie)
        serverResult = ''.join(response.text.split())

        changeResult = serverResult.split('goUrl')

        if len(changeResult) > 1:
            print 'Change password success.'
        else:
            print 'Change password failed.'
            
    except Exception,e:
        print e
        return

这样就可以快速修改密码了,当然其他的功能也是同样的原理。

如果您觉得文章有帮助到您,请到 https://www.92ez.com/index.php?action=show&id=23403 进行打赏/捐赠,谢谢!
如果您觉得文章有帮助到您,请 使劲戳这里 进行打赏/捐赠,谢谢!
本文链接:https://www.92ez.com/?action=show&id=23380
提示:技术文章有一定的时效性,请先确认是否适用你当前的系统环境。

上一篇: 博客被运营商屏蔽(目前已可以正常访问)
下一篇: 三极管的妙用之C118自动刷机

访客评论
目前还没有人评论,您发表点看法?
发表评论

评论内容 (必填):