声明
本文章中所有内容仅供学习交流,敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!
逆向目标目标:某加速商城登录接口
主页:aHR0cDovL3d3dy4xNXl1bm1hbGwuY29tL3BjL2xvZ2luL2luZGV4
接口:aHR0cDovL3d3dy4xNXl1bm1hbGwuY29tL3BjL2xvZ2luL2NoZWNr
逆向参数:Cookie:
PHPSESSID=g9jp7sfpukg99v03gj69nr9r56
FormData:
u[password]:7aad70aba07f2e20bee7beaaafdfb......_csrfToken:4beac5ccdddf4cb0逆向过程抓包分析
在首页点击登陆,来到登录页面,随便输入一个账号密码登陆,抓包定位到登录接口为aHR0cDovL3d3dy4xNXl1bm1hbGwuY29tL3BjL2xvZ2luL2NoZWNr,POST请求,FormData里,密码u[password]被加密处理了,此外还有一个_csrfToken也是需要我们解决的,cookie里面有一个PHPSESSID,经过测试,如果不带此参数,最终的请求也是失败的。
参数逆向首先看看_csrfToken,先尝试直接搜索一下它的值,可以发现其实在首页的源码里面就有,直接匹配拿过来即可:
再看一下cookie里面的PHPSESSID,首先想到的,可能是第一次访问页面,ResponseHeaders返回的Set-Cookie得到的,查看第一次请求,确实是的,如果没有的话,需要清除缓存再访问(开发者工具——Application——Storage——Clearsitedata)。
最后一个密码参数u[password],肯定是通过JS加密得到的,直接Ctrl+Shift+F全局搜索,可以直接在index首页找到RSA加密的地方,埋下断点进行调试,最后的res正是加密后的密码:
我们将这段关键代码进行改写,封装成一个函数:
functiongetEncryptedPassword(password){varpublic_key="00bdf3dbb9c4dddceaccf89fa08f28bbedcbf81baec2b52e2b02be7aa8b25a8ea0b";varpublic_length="";varrsa=newRSAKey();rsa.setPublic(public_key,public_length);returnrsa.encrypt(password);}
这里主要用到的三个函数RSAKey()、setPublic()、encrypt(),在开发者工具中,鼠标放到函数上,可以看到这里都是调用的rsa.js里面的方法,我们直接将整个文件剥离下来进行本地调试:
本地调试会发现提示BigInteger未定义,鼠标移到这个函数上面,可以发现是调用了jsbn.js里面的方法,同样的,直接将整个jsbn.js文件剥离下来进行本地调试。
这里其实在rsa.js文件的第一行有一句注释://Dependsonjsbn.jsandrng.js,我们可以猜测rsa.js是可能依赖jsbn.js和rng.js这两个文件的。
有了jsbn.js的代码,再次进行调试,会发现又提示navigator和SecureRandom未定义,navigator我们已经非常熟悉了,是浏览器的相关信息,一般情况下直接定义为空即可(navigator={};);将鼠标移到SecureRandom函数上面,可以发现是调用了rng.js里面的方法,同样的,直接将整个rng.js文件剥离下来进行本地调试。这里就证实了前面我们的猜想,rsa.js确实是依赖jsbn.js和rng.js的。
我们注意到,这里在rng.js文件的第一行,同样有一句注释://Randomnumbergenerator-requiresaPRNGbackend,e.g.prng4.js,表明rng.js是随机数生成器,需要PRNG后端,例如prng4.js,在密码学中,PRNG全称是pseudorandomnumbergenerator,即伪随机数生成器,是指通过特定算法生成一系列的数字,使得这一系列的数字看起来是随机的,但是实际是确定的,所以叫伪随机数,感兴趣的朋友可以深入研究一下,在这里我们知道rng.js可能还依赖于prng4.js,需要进一步调试才清楚。
rsa.js、jsbn.js、rng.js都齐全了,再次本地调试,会发现rng.js里面的rng_psize未定义,鼠标放上去看到rng_psize就是一个定值,在右边的Global全局变量里也可以看到值为,尝试搜索一下rng_psize,可以发现在prng4.js里面有定义varrng_psize=;,果然和注释说得一样,rng.js是依赖prng4.js的,但是这里似乎直接定义一下rng_psize就行了。
直接在本地代码定义一下varrng_psize=;,再次进行调试,此时又会提示rng.js里缺少prng_newstate()对象,再次回到开发者工具,可以看到prng_newstate()是prng4.js里面的方法,果然rng.js和prng4.js的关系并不简单,同样的,我们也直接将整个prng4.js文件剥离下来进行本地调试。
再次调试,运行无误,可以成功拿到加密后的密码了:
逻辑总结加密入口可以在index首页找到,用到了rsa.js里面的三个加密函数RSAKey()、setPublic()、encrypt();
rsa.js里的BigInteger()函数依赖jsbn.js,SecureRandom()函数依赖rng.js;
rng.js里的变量rng_psize在prng4.js中定义,prng_newstate()函数也依赖prng4.js;
要将rsa.js、jsbn.js、rng.js、prng4.js这四个JS加密文件完整的剥离下来才能还原整个加密过程。
完整代码GitHub