一、浏览器调试
1、elements
2、Network
用于抓包
Preserve log:保留日志,所有日志都会被保留,而不是被覆盖,刷新前刷新后的日志都会被保留
Disable cache:禁止缓存,保证每次变化都是从服务器请求的数据,而不是本地缓存的数据
△:这两个可以勾选上
此处的筛选只能筛选name的元素(文件名)
Request URL:请求地址
Request Method:请求协议post/get
Remote Address:如果端口是443的话,则说明是HTTPS协议
Status Code:状态码
Referrer Policy:来源页面政策,可以不用管
HTTP/1.1:协议版本,1.1
set-cookie:cookie
Request Headers
Accept:本地可接受的格式
Accept-Encoding:gzip会不会使用gzip压缩
Cookie:本地发给服务器的Cookie
Cookie:Request Cookies是当前已经存在的包,Response Cookies是服务器返回的包
initiator:可以看到什么JS请求,也可以看出这个请求的发起人
一条http请求,发起人有以下几种:
①浏览器发起
②自己发起:自己构造http,send js
可以点击waterfall,跟随时间轴来分析
对包右键可以呼出菜单
open in Sources panel:可以直接打开对应的资源面板
copy:可以copy对应的字符,包括request
sources
overrides:可以对现有js资源进行重写覆盖
对js的包,右键选中open in source panel或者save as
snippets可以编写一个临时的JS脚本,点击右下方的Ctrl+enter执行一次
可以影响整个页面
打断点
按钮用法
暂停
逐方法运行
进入方法运行(逐语句运行)
返回调用的位置
逐语句运行(和第三个按钮一样)
禁用/启用用户断点
pause on caught exceptions:异常捕获,如果有异常,进入断点
右键可以设置断点属性,或者过滤断点
watch
监听变量,可以实时刷新
作用域
console
可以输出日志
开隐身可以避免一些反爬
application
浏览器的一些存储功能
本地运行JS,得到和浏览器一样的加密数据,目标是拿到JS整个加密过程
1、能对网站JS进行调试,
1.1、能修改js运行当中的一些变量的值,能输出,
1.2、能下断点
1.3、智能侦听值
断点
DOM断点
DOM事件断点
xhr断点:发包断点
代码行断点
代码断点:源码中的debugger
全局事件断点:浏览器事件断点
异常捕获断点
DOM断点
DOM断点:在source中→审查元素→右键break on→选中其中一个modification
渲染(样子有变化)才进入断点
网站代码运行时间轴
加载html 加载js - 运行js初始化 - 用户触发某个事件 - 调用了某段js - 执行js加密(加密函数) - 请求服务器(send)[XHR-SEND] - 接收服务器返回数据 - 执行js解密(解密函数) - 刷新网页渲染
DOM断点:距离加密函数比较远(属于"用户触发某个事件"),无法根据栈去快速定位,但是会定位得比较准(不太推荐)
DOM事件断点:Element→Event Listeners
如果DOM断点不能下断,就可以用DOM事件 和 DOM断点一致
去掉ancestors可以看到当前的元素事件(所选的审查元素)
XHR断点:Sources→XHR/fetch Breakpoints
执行的比较靠后,距离加密函数相对比较近,可以根据栈快速定位
非xhr发送的不能断
全局事件断点:sources→event listener breakpoints→create canvas context(画布捕获[验证码/滑块])
异常捕获断点:srouces→breakpoints→勾选pause on caught exceptions→在代码行的左边三小点,可以设置为false,不再捕获
XHR断点
把url其中的一段复制到XHR/fetch breakpoints里,如果出现发送改url的事件,就会进入断点
方法栈
方法的调用流程
在上面进入XHR/fetch breakpoints断点后,就能够进入call stack方法栈
加载html,加载js→运行js初始化→加密函数→给服务器发信息
找到send的变量,比如f.send→再找f的proto→open→查找open
更新时间轴
加载html,加载js→运行js初始化→用户触发事件→调用了某段js→明文数据→加密数据→加密后数据→给服务器发信息(XHR-SEND)→接收到服务器数据→解密函数→刷新网页渲染
在进入断点后,可以点击栈来观看哪一步从明文变成了密文
JS逆向思路:
抓包→调试→扣取JS→改写→本地运行出值→请求服务器拿值
加密方式
取盐校验,不可逆,crc
md5 md2 md4 带密码的md5(hmac)
默认key 0123456789abcdef
md5:16位,32位,40位
测试加密方式可以用123456来测试,md5的话,16位就是49开头,32位就是e开头
123456 49ba59abbe56e057 e10adc3949ba59abbe56e057f20f883e
sha1 sha256 sha512
40 64 128位
123456
7c4a8d09ca3762af61e59520943dc26494f8941b 记住7c
对称加密,私钥
AES DES 3DES
非对称加密,公钥,私钥
RSA,同一个明文可以生成不同的密文
1.16进制
2.base64是编码,可以还原,包含A-Z a-z 0-9 + _ =
会包含abcdefg
逆向流程
1.抓包
2.调试
先全局搜,再文件搜,格式化后需要留意加空格
关键字:url,password
XHR
3.扣取JS
需要包含this对象
再snippets中编写,并输出测试,可能需要修改
4.改写
5.本地运行出值
请求服务器拿值
找到明文值,例如12345后加了一些自定义字符,这个过程称为加盐
插桩
获取变量值的方法:
在对象声明下面直接加上,window.test = 对象,然后后面给别的对象补一个 var
- window是全局,可以直接在console中使用
- 后面补个var是为了语法完整
混淆
全局声明
var test
test是全局
可以通过
window.test
window[‘test’]
var xxx = ["test1","test2"]
var test1 = "1"
var test2 = "2"
console.log(window[xxx[1]])
// 2
//btoa:base64加密
//atob:base64解密
//btoa("test1") = 'dGVzdDE',btoa("test2") = 'dGVzdDI=',
var xxx = ["dGVzdDE=","dGVzdDI="]
function x1(id){
return atob(xxx[id])
}
console.log(window[xxx[1]])
eval
混淆代码
//btoa("function xx(){return '12'} xx()")='ZnVuY3Rpb24geHgoKXtyZXR1cm4gJzEyJ30geHgoKQ=='
eval("function xx(){return '12'} xx()")
eval(atob('ZnVuY3Rpb24geHgoKXtyZXR1cm4gJzEyJ30geHgoKQ=='))
"eval(\"function xx(){return \"MTI=\"} xx()\")"