请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,作者不为此承担任何责任。如有侵权烦请告知,我们会立即删除并致歉。谢谢!
https://store.steampowered.com/login/?redir=&redir_ssl=1
1)输入用户名和密码后,点击登录按钮,通过抓包工具捕获点击登录按钮后发起请求对应的相关数据包。
2)打开全局搜索框:点击右上角的三个点,打开search表示的全局搜索框即可,在其内部搜索password。在这些数据包中重点关注js文件对应的代码,在其内部找寻加密解密的相关操作。
3)定位一个js数据包,点击左下角的大括号进行js文件代码的格式化显示。在该数据包内部代码中点击一下,按下Ctrl+F进行局部搜索,搜索password即可,在可疑加密的位置打下断点即可。
4)在可以之处打上断点后,需要基于抓包工具进行请求的重新发送,查看是否会停留在断点的位置。看到是调用了RSA的encryt进行数据加密,该函数有两个参数,参数1是明文密码(已知),参数2是pubkey公钥,公钥具体的数值(未知)。
5)断点生效,下一步对加密函数进行js改写
# 改写之前varpubKey=RSA.getPublicKey(results.publickey_mod, results.publickey_exp); //results.publickey_mod和results.publickey_exp经过光标显示为字符串,这里是暂时定义为定值varencryptedPassword=RSA.encrypt(password, pubKey); //需要pubKey# 改写之后functiongetPwd(password) {varmod="bed9ed2e78163c171c8055d7fda27f3d160d483489e15fae222f94c6d918e1ccc2754d9111de471983ac8bf78dc999151db9c07525f62486d2d71b875ec6c511821bcb632704ef6ae1751bdc0a0193fedc7d6b6e2f948710bb88b0f9a5f3deea4f4ea5eccf421c83c4118e5e8af348aefe8da35f19dee632c239392d9e4563e364bfad8472333a2babcc051730d340a8bfb3d3e7b40c806e33405ae75bc430bfd2e00c74bff202a4e311c34a0b67177723536dd95cdba8b4e7344a21e7307e14b66b4a60ac96de37c76c769e0c81cfc4a893f14f13c9ba61de641d456054201f1332827e7e599d35e6a7ce58f58365099f5c8d04ae9df7b4f52f194da6bf281b"varexp="010001"varpubKey=RSA.getPublicKey(mod, exp);varencryptedPassword=RSA.encrypt(password, pubKey); //需要pubKeyreturnencryptedPassword; //返回加密后的密文}
6)构建函数需要的上下文(需要找到getPublicKey和encrypt这两个函数的实现)
重要的经验分享:
这里是分析的难点,遇到未定义的对象直接抄走所有代码(比如遇到this)
js的内置对象有:window,document,navigator,在js改写的过程中,如果出现了上述内置对象未定义的情况,直接给该内置对象赋值this即可!window = this; navigator = this;
改写成功后的js代码,这里具体分析就不写了,多练练就会了
functiongetPwd(password) {varmod="bed9ed2e78163c171c8055d7fda27f3d160d483489e15fae222f94c6d918e1ccc2754d9111de471983ac8bf78dc999151db9c07525f62486d2d71b875ec6c511821bcb632704ef6ae1751bdc0a0193fedc7d6b6e2f948710bb88b0f9a5f3deea4f4ea5eccf421c83c4118e5e8af348aefe8da35f19dee632c239392d9e4563e364bfad8472333a2babcc051730d340a8bfb3d3e7b40c806e33405ae75bc430bfd2e00c74bff202a4e311c34a0b67177723536dd95cdba8b4e7344a21e7307e14b66b4a60ac96de37c76c769e0c81cfc4a893f14f13c9ba61de641d456054201f1332827e7e599d35e6a7ce58f58365099f5c8d04ae9df7b4f52f194da6bf281b"varexp="010001"varpubKey=RSA.getPublicKey(mod, exp);varencryptedPassword=RSA.encrypt(password, pubKey); //需要pubKeyreturnencryptedPassword; //返回加密后的密文}
7)小问题:上述改写的js代码中,getPublicKey函数需要的公钥是写死在程序中,如何实现动态获取公钥的数据呢?公钥和私钥都不会明文的写在程序中,网站中加密算法的公钥/私钥一般都是隐藏在前台的html页面中或者是通过单独的请求获取的!
用python实现动态获取publickey
importrequests#动态获取rsa的公钥数据headers= {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36',}url='https://store.steampowered.com/login/getrsakey/'data= {"donotcache": "1647951542258","username": "[email protected]"}json_data=requests.post(url,headers=headers,data=data).json()mod=json_data['publickey_mod']exp=json_data['publickey_exp']
8)最终的js改写的代码为
//这里省略了函数实现的代码,太长了functiongetPwd(password,mod,exp) {varpubKey=RSA.getPublicKey(mod, exp);varencryptedPassword=RSA.encrypt(password, pubKey); //需要pubKeyreturnencryptedPassword; //返回加密后的密文}
9)完整的python代码:
importrequests#动态获取rsa的公钥数据headers= {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36',}url='https://store.steampowered.com/login/getrsakey/'data= {"donotcache": "1647951542258", # 时间戳,这个在这里不受影响"username": "admin"}json_data=requests.post(url,headers=headers,data=data).json()mod=json_data['publickey_mod']exp=json_data['publickey_exp']importexecjsnode=execjs.get()fp=open('steam.js','r',encoding='utf-8')ctx=node.compile(fp.read())pwd="123456"jsFunc='getPwd("%s","%s","%s")'%(pwd,mod,exp)result=ctx.eval(jsFunc)print(result)
原文始发于微信公众号(Sec探索者):【实战案例】STEAM登陆算法JS逆向分析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论