目录
🎄免责声明
技术仅用于交流!交流!交流!请勿做违法以及影响他人的事情!特此声明!
🎄开篇前言
事情的发生源于好奇,我在家中登录路由器的时候发现请求的密码不是明文密码,而是一个从未见过的一种加密,在我输入了admin之后,向路由器请求的并非是admin,示例请看图!上百度上谷歌也没找到对应的文章解析,因此才自己动手去找对应的加密位置,才有了本文作为记录!
🎄思路分析
当我们点击登录按钮之后肯定是会调用js脚本的,那么在调用js之后可能会有其他一些处理,其中也包含了对明文密码加密的一个处理,接着才会向路由器发送请求,整理下来大概过程如下:
点击登录 -> 调用js -> 调用加密函数 -> 可能会其他处理 -> 发送请求
通过上面的分析,我们可以对请求的变量进行一个全局的搜索,为什么要这么做呢?因为在我们发送请求那部分肯定是会对请求的变量进行赋值操作的,那么就可以通过对值的追踪确定其加密函数得位置!该思路得缺点就是全局搜索可能会搜出很多值,如下:
一个一个找很麻烦,所以我不打算使用该方式,我后面教程使用的是XHR断点值追踪的方式,XHR断点是在发送请求前不让它进行发送请求,在即将send的位置开始向上进行值的追踪!
🎄教程开始
🍎1. 添加XHR断点
首先将我们的请求链接复制下来(复制这个需要复制一直固定不变的值,因为这个路由器的请求比较特殊,具体情况需要自己具体分析)
按下键盘上的F12可显示该面板!!!
找到源代码面板中的XHR断点进行添加,如图:
🍎2. 调式
XHR断点添加完成之后我们再次点击登录,它就会在发送请求前断住,如图:
一堆密密麻麻的代码,别急,我们可以美化它!!!
效果:
🍎3. 值追踪
我们可以借助栈进行值追踪,需要针对password的值去进行追踪,我们输入的是admin这个明文密码,那么我们就需要追踪到有显示明文密码的位置,在明文密码和加密密码之间就是加密函数,这个时候我们就能定位到需要的加密函数;
在这里大概介绍栈,栈里存放的是执行过程中调用的方法,一种先进后出的数据结构,感兴趣的可以私下自行了解下
图片中标绿框那部分的jquery可以忽略(只要是看到jquery的都可以先暂时忽略),通过这个技巧,我们可以知道明文密码大概就是在最后一个方法里面了,让我们论证一下:
如果没有智能提示,可以按下CTRL键就会有智能提示了!!!
这个时候我们已经找到铭文密码了,但是我们还没看到加密的密码,这个时候我们可以点倒数第二个方法,看下传进去的值是不是明文密码,如果不是明文密码,那么说明是加密了之后才传进去的,有了假设,我们来论证下:
和我们的假设没有误差,但是这里有个点需要注意一下,虽然显示的是加密密码,但是不能通过该方法保证传进来的就是加密密码,因为可能存在一个值污染的可能性,什么意思呢?就是这个方法传进来的可能就是明文密码,但是后面可能会对这个变量进行了处理,处理之后这个变量的值也会改变,所以为了确定传进来的是不是真的是明文密码,我们需要在这个方法里面打个断点,然后再重新点登录,让它在这个位置断住!!!
断点打好了,我们需要将XHR断点停掉才能重新点登录!!!如图:
恢复正常之后再点登录,如下图已经重新登录后在我们希望的位置断住了!!!
断住之后发现已经没有智能提示了,这个时候就需要我们把鼠标移动到对应的变量名查看数据了
由上图得知,密码是在加密之前传进来的,所以我们通过点击栈来返回上一个方法,看下是不是调用了什么函数进行了加密
我们在auth这个方法里看到第一个参数是加密密码,所以我们只需要看第一个位置就行,如下图:
如上图,我们可以进去查看一下调用的orgAuthPwd方法,应该就在里面进行了加密,让我们往下验证一下:
里我们的目标又近了一步,让我们进入securityEncode方法查看下
看不懂是吧?我也没看懂,哈哈 ~ ,那就让我们在方法末尾加个断点查下处理完之后是不是就是加密密码!!!往下看:
加了断点之后我们需要先一直点那个箭头结束之前的断点,然后我们再点击登录,让它再securityEncode方法里断住,再接着往后看:
上图显示的结果是已经重新点击登录后断住的结果,发现a变量已经变成加密密码了,说明这里就是加密函数了!!!恭喜哇!!!
抠出来的加密函数,已添加注释
var TpLinkPasswordEncoder = {
// 'presetString' 是一个预设的字符串,用于与输入密码进行异或操作的一部分
presetString: "RDpbLfCPsJZ7fiv",
// 'dictionary' 字典字符串,用于生成加密后的字符
dictionary: "yLwVl0zKqws7LgKPRQ84Mdt708T1qQ3Ha7xv3H7NyU84p21BriUWBU43odz3iP4rBL3cD02KZciX" +
"TysVXiV8ngg6vL48rPJyAUw0HurW20xqxv9aYb4M9wK1Ae0wlro510qXeU07kV57fQMc8L6aLgML" +
"wygtc0F10a0Dg70TOoouyFhdysuRMO51yY5ZlOZZLEal1h0t9YQW0Ko7oBwmCAHoic4HYbUyVeU3" +
"sfQ1xtXcPcf1aT303wAQhv66qzW",
// 'encodePassword' 方法用于加密传入的密码
encodePassword: function (password) {
var dictionary = this.dictionary;
var output = ""; // 加密后的字符串将存储在这里
var len, lenPassword, lenPreset, lenDict;
var charLeft = 0xBB, charRight = 0xBB;
lenPassword = password.length; // 输入密码的长度
lenPreset = this.presetString.length; // 预设字符串的长度
lenDict = dictionary.length; // 字典字符串的长度
len = lenPassword > lenPreset ? lenPassword : lenPreset; // 取最长的长度作为循环的次数
// 遍历每个字符进行加密处理
for (var index = 0; index < len; index++) {
charLeft = 0xBB;
charRight = 0xBB;
// 根据索引位置,决定如何与预设字符串的字符进行异或操作
if (index >= lenPassword) {
// 如果索引超出了密码长度,只使用预设字符串的字符
charRight = this.presetString.charCodeAt(index);
} else if (index >= lenPreset) {
// 如果索引超出了预设字符串长度,只使用密码的字符
charLeft = password.charCodeAt(index);
} else {
// 如果索引在两个字符串的长度内,使用两者的字符进行异或操作
charLeft = password.charCodeAt(index);
charRight = this.presetString.charCodeAt(index);
}
// 根据异或操作的结果,从字典中选取字符,添加到输出字符串中
output += dictionary.charAt((charLeft ^ charRight) % lenDict);
}
return output; // 返回加密后的字符串
}
};
// 测试加密功能,输出加密后的'admin'密码
console.log(TpLinkPasswordEncoder.encodePassword("admin"));
🎄结束语
相信大部分童鞋看下来都是懵逼状态的,的确这种文章不太好写,很多东西通过文字表达很僵硬,有不懂得问题可以评论,我会逐一回复解惑!!!
再次声明:技术仅用于交流,请勿做违法的事!!!