JS逆向:【硬干货】手把手实战某条_signature参数破解(下)——WebSocket与JS函数
本文仅供学习交流使用,请勿用于商业用途或不正当行为
如果侵犯到贵公司的隐私或权益,请联系我立即删除
前两篇文章:
js逆向:【硬干货】手把手实战某条_signature参数破解(上)
js逆向:【硬干货】手把手实战某条_signature参数破解(中)
我们介绍了如何分析定位关键加密函数的位置,以及如何抠出需要的js代码
之前我提到需要将Index页面源代码里的init代码扣下来,现在又发现,其实没有init生成的值也能用,而且调试起来更简单,需要补的环境代码更少。
我们先将之前扣的代码里的init这部分代码删掉
然后运行代码,这时报错:window未定义
window是浏览器的全局对象,而Node环境下的全局对象是global,所以我们可以这样定义
window = global;
继续运行,报错:href未定义
一般报错href未定义,是缺少Location对象下面的href属性
我们先看一下浏览器环境下href的值是什么
所以我们这样定义
window.location = {"href": "https://www.toutiao.com/ch/news_hot/","protocol": "https:",
};
继续运行,报错:userAgent未定义
我们将浏览器的userAgent复制下来然后定义
window.navigator = {userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36",
};
继续运行…
提示 please call init first!,但已经能看到加密结果了
先不用管这个提示,我们直接去测试下这个值是否能拿到数据
顺利拿到数据,虽然不完美但是目的达到了,大家如果想要完美就自行去调试吧。
到这里,我想说,使用Node环境运行代码其实也挺麻烦的,我们都知道,只要能调用真实浏览器运行JS就能拿到加密结果了,但是web自动化工具被检测不能用,那还有什么办法能够控制浏览器运行JS呢?
有!WebSocket ,通过websocket可以实现浏览器与服务器进行双向通信,也就是说浏览器客户端可以给服务端发送数据,服务端能给浏览器客户端发送数据。
那么我们可以利用这一点让服务端将要加密的参数发送给浏览器客户端,浏览器将接收到的参数传入目标加密函数并运行,就能得到加密结果,最后将结果返回给服务器,实现不使用web自动化工具"操控"浏览器。
关于websocket我就不科普了,大神讲得很好了:
http://www.ruanyifeng.com/blog/2017/05/websocket.html
说下实现思路:
- 同时开启一个http服务端和一个websocket服务端;
- http客户端请求http服务端,服务端收到请求后触发websocket服务端给websocket客户端发送消息;
- 利用中间人代理给浏览器注入js,让浏览器成为webcoket客户端,它收到websocket服务端发来的消息时,调用相关目标加密函数生成值,然后将值发送给websocket服务端
- websocket服务端收到值后将值转交给Http服务端,然后返回给http客户端
mitmproxy很多小伙伴都熟悉吧,这是一个python下的中间人代理库,可以很方便地使用Python代码拦截、篡改请求和响应,本文使用mitmproxy进行js注入,不熟悉的小伙伴参考这篇文章:
https://www.cnblogs.com/20175211lyz/p/12255610.html
直接上代码:
http和websocket服务端:
from tornado import websocket, web, ioloop, gencl = []
msg = []
msg_flag = Falseclass IndexHandler(web.RequestHandler):def get(self):self.write("hello...")class SocketHandler(websocket.WebSocketHandler):def check_origin(self, origin):return Truedef open(self):"""新的websocket连接后被调动"""if self not in cl:cl.append(self)print('有新客户端连接!')def on_close(self):"""websocket连接关闭后被调用"""if self in cl:cl.remove(self)def on_message(self, message):"""接收到客户端消息时被调用"""global msg_flagprint('收到客户端发送回来的加密值:%s' % message)msg.append(message)if not 'started' in message:msg_flag = Trueclass ApiHandler(web.RequestHandler):@gen.coroutinedef post(self):global msg_flag,msg"""接收参数,发送给ws客户端"""url = self.get_body_argument('url')print('http server收到参数:%s' % url)# 将URL推送给客户端for c in cl:c.write_message(url)while not msg_flag:yield gen.sleep(0.1)msg_flag = Falseself.write(msg[-1])app = web.Application([(r'/', IndexHandler),(r'/ws', SocketHandler), # http://127.0.0.1:8000/ws(r'/api', ApiHandler), # http://127.0.0.1:8000/api
])if __name__ == '__main__':app.listen(8000)ioloop.IOLoop.instance().start()
Tornado框架的websocket服务参考:
https://www.xiaoqc.cn/detail/python-tornado-websocket/
代理端
import mitmproxy.http
from mitmproxy import options
from mitmproxy import proxy
from mitmproxy.tools.dump import DumpMaster# 要注入到页面的js代码
inject = """
//连接websocket服务端
var ws = new WebSocket('ws://localhost:8000/ws');//连接成功时执行
ws.onopen= function() {ws.send('browser started')
};// 收到服务端消息时执行
ws.onmessage= function(evt) {// evt.data 是websocket服务端发送过来的值console.log(evt.data);//调用目标加密函数signature = window.byted_acrawler.sign({url: evt.data});//将生成的值发送给websocket服务端ws.send(signature);console.log(signature);
};
"""class Myaddon():def response(self, flow: mitmproxy.http.HTTPFlow):if 'acrawler.js' in flow.request.url: # 注入到acrawler.js文件里flow.response.text = inject + flow.response.textaddons = [Myaddon()
]def run():myaddon = Myaddon()port = 8080opts = options.Options(listen_port=port)pconf = proxy.config.ProxyConfig(opts)m = DumpMaster(opts)m.server = proxy.server.ProxyServer(pconf)m.addons.add(myaddon)print(f'启动监听 {port} 端口')try:m.run()except KeyboardInterrupt:m.shutdown()if __name__ == "__main__":run()
以代理方式启动浏览器,访问目标URL:
./Chrome.exe http://www.xxxxxxxx.com --proxy-server=127.0.0.1:8080 --ignore-certificate-errors
浏览器启动后,成功注入js代码到acrawler.js文件
请求http服务,将要加密的参数传过去,可以成功拿到加密结果了
测试加密结果是否可用
可以看到成功拿到数据了
今天的分享先到这里,大家如果有更好的思路,欢迎大佬指点呀,拜~
公众号:一生向风
JS逆向:【硬干货】手把手实战某条_signature参数破解(下)——WebSocket与JS函数相关推荐
- 【JS逆向】无限debugger实战之八仙过海,各显神通。
这里来说debugger这个东西,其实debugger只是算反调试的一部分,首先我们先理解一下这个debugger这个东西 声明:本文只作学习研究,禁止用于非法用途. 1.debugger 语句用于停 ...
- 21.网络爬虫—js逆向详讲与实战
网络爬虫-js逆向 js逆向 JavaScript逆向的详细讲解 实战演示 有道翻译 设置密钥和初始向量 对密钥和初始向量进行哈希处理 创建AES对象并解密消息 移除padding并返回结果 前言:
- 【JS 逆向百例】有道翻译接口参数逆向
文章目录 逆向目标 逆向过程 抓包分析 参数逆向 完整代码 youdao_encrypt.js youdaofanyi.py 逆向目标 目标:有道翻译接口参数 主页:https://fanyi.you ...
- 【JS 逆向百例】房天下登录接口参数逆向
文章目录 声明 逆向目标 逆向过程 抓包分析 参数逆向 完整代码 fang_encrypt.js fang_login.py 声明 本文章中所有内容仅供学习交流,严禁用于商业用途和非法用途,否则由此产 ...
- JS逆向 2021-8-16 网易云音乐 params、encSecKey参数
声明:文章仅供学习,禁止非法用途,侵权请告知删除 文章目录 前言 一.网页分析 二.参数获取 1.参数定位 2.参数解密 三.部分代码 结尾 前言 地址:aHR0cHM6Ly9tdXNpYy4xNjM ...
- 手机淘宝宝贝详情页《问大家》数据爬虫手把手实战,包含动态参数如何生成...
开年后,一直在弄爬虫相关方面的工作,今天就以淘宝问大家为例,将爬虫的整套过程记录下来.总结经验,查漏补缺 如何找到问大家的网页链接 打开手机淘宝,随意浏览个宝贝 进入宝贝详情页,进入问大家主页 点击分 ...
- JS逆向:猿人学爬虫比赛第五题详细题解(下)
上篇文章,我们已经找到了加密的地方,关键代码是这样的: _$Ww = _$Tk["enc"]["Utf8"]["parse"](window ...
- C语言实战篇-----调试关键参数+printf输出_文件名_函数名_执行数!!!
背景说明 这边先来个案例 案例中实现了函数名的文件,调试执行的行数,以及函数名 我们在代码中会经常看到以下定义 #define SAK_PRINT_LOG(module,level,fmt, ...) ...
- js rsa解密中文乱码_建议收藏 | 最全的 JS 逆向入门教程合集
点击上方"咸鱼学Python",选择"加为星标" 第一时间关注Python技术干货! 嘿,大家好,截止今天咸鱼零零散散分享爬虫.数据分析基础和 Web 的内容已 ...
最新文章
- 10篇顶会paper,入选微软学者,上海交大吴齐天的科研思考!
- 北大教授杨超、清华教授唐杰获首届“王选杰出青年学者奖”
- (转载)星期几问题——蔡勒公式
- 手动修改Outlook 2007 邮件签名
- 卡式水分滴定仪预测模型分析
- Python Module_openpyxl_处理Excel表格
- 在visualstudio中使用Qt
- 地球椭球体(Ellipsoid)、大地基准面(Datum)及地图投影(Projection)三者的基本概念
- python 如何查看模块所有方法-Python查看模块(变量、函数、类)方法
- 【CodeForces - 215A】Bicycle Chain (水题)
- c语言实现ftp网络应用程序,使用C语言socket实现windows pc与ftp服务器通信---socket实现ftp客户端...
- c 语言 json序列化,C#中json字符串的序列化和反序列化 – 万能的聪哥 – 博客园...
- 不同程序语言的注释和变量要求
- 业务复杂就用 if-else?刚来的技术大佬用这招彻底干掉了!
- Spring的注入方式中,官方推荐哪种方式
- jquery ztree 设置勾选_zTree 勾选checkbox
- 吉林大学超星学习通02(2)
- 【递推】wikioi 2825 危险的组合
- 柯西过程(Cauchy process)
- mac 取消 “Ctrl+空格“切换输入法