篇幅有限

完整内容及源码关注公众号:ReverseCode,发送

当我们拿到一个网站时,首先就是抓包定位加密参数的实现,本文将通过常用的定位方案结合实际案例完成对加密参数的分析。

搜索关键参数

这是最常见也是最简单的定位方案,F12打开网站控制台后,Ctrl+Shift+F打开搜索面板,比如搜索password参数或者submit函数

password:`,`password=`,`password =`请求url,搜索方法`var submit`或者`function submit`或者`submit:

to8to

搜索password位置太多,由于抓包请求是new_login.php

在Element面板中搜索new_login.php,ctrl+shift+f 搜索loginCheck

该方法中jq('#rsa_userNum').val(rsaString(password));,调用rsaString方法加密password

function rsaString(str) {return encodeURIComponent(RSAUtilszb.encryptfun(str));
}

进入encryptfun定义的js中,rsa加密最少2000行,该方法不过163行,拷贝该js通过编程猫专用工具中的JS调试工具,加载代码,报错引用错误: window 未定义,添加var window = this;,报错引用错误: JSEncrypt 未定义,添加原js中var JSEncrypt = JSEncryptExports.JSEncrypt;,报错引用错误: JSEncryptExports 未定义,搜索var JSEncryptExports,将var JSEncryptExports = {};添加到JS调试工具,报错类型错误: JSEncrypt is not a constructor

尝试打上断点,但是每次都不能进入断点,说明肯定是动态加载的js,且每次刷新js后缀会有时间戳。勾选Disable cache,打开fiddler抓包,将js拷贝到本地实现http欺骗,选中该请求点击AutoResponder-Add Rule下拉选择Find a File,找到本地保存的js并开启规则

由于每次js请求地址不一样,使用正则匹配regex:https://static\.to8to\.com/gb_js/to8torsaszb\.js\?_=\d+并保存规则重新发起请求https://static.to8to.com/gb_js/to8torsaszb.js?_=1628128571412,使用本地js欺骗网络请求js

将整个js格式化找到之前报错JSEncrypt is not a constructor是从上面的压缩的js中export出来的

将上面压缩的代码添加到编程猫的JS调试工具中加载代码,报错引用错误: navigator 未定义,添加var navigator = {},报错引用错误: window 未定义,添加var window =this,因为如果用window ={}报错ASN1 未定义,而用this则可以拿到当前js中所有的变量函数。

dom元素事件监听

通过控制台的Elements中的Event Listeners逐个排除按钮的Remove节点,直到最后一个Event Listeners使按钮无效,拿到该按钮真正生效的js位置。

中烟新商盟

以下通过dom元素事件监听实现对该j_mcmm加密参数逻辑定位分析。

以上通过尽可能多的地方打上断点,监听元素事件定位到jsmain-9826b285f8fad5a5.js,左下角格式化js后添加断点,在js页面ctrl查看所有变量值

鼠标悬停,或者控制台打印出来,点击进入方法声明时打上断点,为同一行中的函数打上断点,F8单步调试,完成加密参数的定位

xhr断点

通过定位发包函数跟栈,复制网址请求路径到Sources下的XHR/fetch Breakpoints,支持正则。

七麦数据

通过关键加密参数analysis搜索无果,尝试在Sources中加入XHR断点,以请求路径作为断点内容

XHR断点后追溯调用栈,查看每个调用栈的出入参是否包含加密后的analysis,直到进入Promise异步l.request,单步调试到n.then(t.shift(), t.shift()),then作为Promise的异步函数,promise.then(onCompleted, onRejected);,而shift()通过逐条调用t中的方法,参数是上一个方法的返回值,同时删除该方法,相当于队列先进先出。控制台打印t,逐个方法进入打上断点

l.prototype.request中暂时还没生成analysis加密参数,逐个进入t方法中

执行完r().interceptors.request.use该方法后生成的a就是analysis,观察该代码中的逻辑完成加密分析。a=(0,n.cv)((0,n.oZ)(r, l))作为逗号表达式,由上图分析n.cv和n.oZ是函数,r和l是变量,可以还原为n.cv(n.oz(r,l))

通过控制台获取n中的函数

window = global;
window.document = {cookie: ''  // 这边带上自己的cookie
}
function i(e) {var t, a = (t = "",["66", "72", "6f", "6d", "43", "68", "61", "72", "43", "6f", "64", "65"].forEach((function (e) {t += unescape("%u00" + e)})),t);return String[a](e)
}
function s() {return unescape("861831832863830866861836861862839831831839862863839830865834861863837837830830837839836861835833".replace(/8/g, "%u00"))
}
var n = {oZ: function g(e, t) {t || (t = s());for (var a = (e = e.split("")).length, n = t.length, o = "charCodeAt", r = 0; r < a; r++)e[r] = i(e[r][o](0) ^ t[(r + 10) % n][o](0));return e.join("")},cv: function h(e) {return function (e) {try {return btoa(e)} catch (t) {return Buffer.from(e).toString("base64")}}(encodeURIComponent(e).replace(/%([0-9A-F]{2})/g, (function (e, t) {return i("0x" + t)})))},ej: function u(e) {var t, a = new RegExp("(^| )" + e + "=([^;]*)(;|$)");return (t = document.cookie.match(a)) ? unescape(t[2]) : null}
}

由于btoa本质就是base64加密,通过引入CryptoJS.pad.js后

function base64(data) {var wordArray = CryptoJS.enc.Utf8.parse(data);var base64_data = CryptoJS.enc.Base64.stringify(wordArray);return base64_data
}
var n = {oZ: function g(e, t) {t || (t = s());for (var a = (e = e.split("")).length, n = t.length, o = "charCodeAt", r = 0; r < a; r++)e[r] = i(e[r][o](0) ^ t[(r + 10) % n][o](0));return e.join("")},cv: function h(e) {return function (e) {try {return base64(e)} catch (t) {return Buffer.from(e).toString("base64")}}(encodeURIComponent(e).replace(/%([0-9A-F]{2})/g, (function (e, t) {return i("0x" + t)})))},ej: function u(e) {var t, a = new RegExp("(^| )" + e + "=([^;]*)(;|$)");return (t = document.cookie.match(a)) ? unescape(t[2]) : null}
}

将try/catch中逻辑还原

var l = "00000008d78d46a"
var d = "@#"
var e = {// url: "/rank/indexPlus/brand_id/1",url: "/rank/indexPlus/brand_id/" + pg,    // 1.免费榜 0.付费 2.畅销榜baseURL: "https://api.qimai.cn",
}
var c = {default: function On(e) {this._init(e)}
}
var u = "synct"
var t = (0, n.ej)(u);
var m = "syncd"
var f = f = c.default.prototype.difftime = -(0, n.ej)(m) || +new Date - 1e3 * t
var o = +new Date - (f || 0) - 1515125653845
var r = []
r = r.sort().join(""), r = (0, n.cv)(r), r += d + e.url.replace(e.baseURL, ""), r += d + o, r += d + 1,
a_ = (0, n.cv)((0, n.oZ)(r, l))
return a_

Initiator栈追踪

Network下的发包请求的Initiator,如jquery堆栈的顶层断点(可能会请求多次,找到发包请求时进入的断点),重新请求找到堆栈中属于目标网站的js格式化断点。

升学e网通

登录抓包,打开Initiator,进入堆栈顶层定位的代码行

打上断点,查看右侧调用栈,逐个方法往底层去调用,直到react库js找到了preLogin,找到出现password的位置,打上断点

再次登录时,进入断点,找到password

进入加密方法中,aes加密

打开WT-JS中的Crypto类复制key和iv,输出以HEX的十六进制格式,对比结果是标准的AES加密。

基于base64或十六进制的AES加解密实现见aes.js

长房集团

搜索j_password后打断点,重新登录

进入desEncrypt中,大致加密完成逻辑就在该函数中

加密逻辑中首先根据SECURITYKEY.get()获取到key,首先通过请求后端拿到str,判断加密类型是否为aes后截取字符串通过toHexString转成十六进制拿到key和iv和security

整理完逻辑扣出js报错CryptoJS is not defined,点击进入CryptoJS.AES.encrypt扣出来aes.js源码

function getdes(encodeType) {// 请求"/resource/js/session.jsp?_=1628210376229"返回var str = "E55A433905551AC39DB3165591D9CD74";if (encodeType == null || encodeType == 'aes') {if (str.length < 32) {str += "abcdefghijklmnopqrstuvwxyz1234567890"}str = str.toUpperCase();var key = {};key.key = str.substring(0, 16);key.iv = str.substring(16, 32);key.security = "\u4435\u5320\u4d35"} else {if (str.length < 16) {str += "abcdefghijklmnopqrstuvwxyz"}str = str.toUpperCase();var key = {};key.key = toHexString(str.substring(0, 8));key.iv = toHexString(str.substring(8, 16));key.security = "\u4445\u5320\u4d45"}return key
}
function getPwd(value, type) {var keyObj = {};if (type == null || "aes" == type.toLowerCase()) {keyObj = getdes()value = CryptoJS.AES.encrypt(value, CryptoJS.enc.Utf8.parse(keyObj.key), {iv: CryptoJS.enc.Utf8.parse(keyObj.iv)}).toString()} else {keyObj = getdes()('des');value = CryptoJS.DES.encrypt(value, CryptoJS.enc.Hex.parse(keyObj.key), {iv: CryptoJS.enc.Hex.parse(keyObj.iv)})}return keyObj.security + value
}

安装编程猫插件

  • fiddler 版本必须 >= v4.6.3,复制Fiddler 编程猫专用插件到fiddler程序目录下的Scripts目录中示例: C:\Program Files (x86)\Fiddler2\Scripts

爱奇艺

  1. 覆盖原函数
  function xxx(){console.log("1111")}var xxx_ = xxx;xxx = function(){console.log("2222")}window.alert = function(){console.log("?")}console.clear = function(){console.log("?")}setInterval = function(){}
  1. Object.defineProperty替换对象属性(getter.setter)
  (function () {var a = "";Object.defineProperty(document, 'cookie', {set: function (val) {console.log('Hook捕获到cookie设置->', val);a = val;return val;},get: function(){return a;}});})();document.cookie = "1"  // 设置document.cookie  // 获取
  1. hook的时机在控制台注入的hook,刷新网页就失效了,过滤Network的js找到第一个加载的js,右键Open in Sources panel格式化,第一行断点,不过有些cookie可能异步可能在html中js生成,在控制台中注入以上hook,清除cookie,手动注入hook,控制台中找到VM虚拟机找到我们的hook的js打上断点,,每次hook都会经过set,右侧就可以查看调用栈,追溯cookie的来源与加密方式。(有可能注入hook的时机会晚于部分异步请求或者html中的js)

  1. 利用fiddler代理所有请求替换响应,编程猫专用工具注入hook

(function () {'use strict';Object.defineProperty(document, 'cookie', {set: function (val) {if (val.indexOf("__dfp") != -1) {debugger;}console.log('Hook捕获到cookie设置->', val);return val;}});
})();

接下来查看调用栈,最终保存到window.name中。

(function () {'use strict';var a = "";Object.defineProperty(window, 'name', {set: function (val) {debugger;a = val;console.log('Hook捕获到cookie设置->', val);return val;}, get: function(){return a;}});
})();

重新进入iqiyi,断点完成hook定位从而可以根据调用栈分析cookie的生成逻辑。

本文由博客群发一文多发等运营工具平台 OpenWrite 发布

JS逆向之基础定位技巧相关推荐

  1. js逆向-逆向部分技巧总结

    js逆向-逆向部分技巧总结 前面我们已经学习了不少JavaScript逆向相关的知识,包括浏览器调试.Hook.AST.无限debugger的绕过以及JavaScript的模拟调用等,这些知识点都比较 ...

  2. Js逆向教程20-Hook基础

    Js逆向教程19-Hook基础 一.jshook Hook就是在这些流程任意环节插入自己的代码,让浏览器先执行自己的代码 然后再执行原本网站的 hook在以下流程中可以做的事情: 1.1 html流程 ...

  3. JS逆向必会基础案例 | 百度翻译参数破解

    前情回顾:有道翻译参数破解 在上一篇博客中,我们系统地分析了有道翻译的JS逆向过程.不难看出,JS逆向其实就是用Python重新来复写Javascript的代码.但当JS代码很长时,弄懂里面的逻辑关系 ...

  4. JS逆向--PyExecJS基本用法--网易云音乐逆向思路,node.js安装教程,逆向思路,逆向分析,加密机制,RSA,AES加密算法,加密算法啊破解,js引擎,定位数据包,分析栈结构,无痕窗口

    文章目录 前言 一.JS逆向以及PyExecJS模块介绍 1.JS逆向 2.PyEecJS 二.使用步骤 1.环境安装 安装PyExecJS模块 安装node.js开发环境(官网链接 https:// ...

  5. 不会JS逆向还说自己是爬虫人?从负(负基础)开是逆向JS有道翻译

    引言-啥是JS逆向?: 这个问题我在网上搜过,答案大多都似是而非

  6. Python爬虫之Js逆向案例(2)-某乎搜索

    Python爬虫之Js逆向案例(2)-知乎搜索 声明:某乎加密逆向分析仅用于研究和学习 大家好,今天继续分享关于某乎关键词搜索接口为案例的Js逆向实战.如果你是一名新手,而且还没有来得及看上一篇< ...

  7. js rsa解密中文乱码_建议收藏 | 最全的 JS 逆向入门教程合集

    点击上方"咸鱼学Python",选择"加为星标" 第一时间关注Python技术干货! 嘿,大家好,截止今天咸鱼零零散散分享爬虫.数据分析基础和 Web 的内容已 ...

  8. 【JS 逆向百例】webpack 改写实战,G 某游戏 RSA 加密

    关注微信公众号:K哥爬虫,QQ交流群:808574309,持续分享爬虫进阶.JS/安卓逆向等技术干货! 声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途 ...

  9. 如何快速定位BUG?BUG定位技巧及测试人员定位的N板斧

    很多测试人员可能会说,我的职责就是找到bug,至于找原因并修复,那是开发的事情,关我什么事? 好,我的回答是,如果您只想做一个测试人员最基本最本分的事情,那么可以这么想.但是,如果您想要在测试甚至开发 ...

最新文章

  1. (循环练习题) 五只猴子分桃子
  2. Activiti 笔记
  3. 重返学术界!​微软全球执行副总载沈向洋加盟清华大学!招收计算机视觉图形学博士生...
  4. LeetCode 4 两个排序数组的中位数
  5. python学习框架图-Python学习—框架篇之初识Django
  6. split、replace、indexof、substr 用法 (获取后台富文本框内容,截取图片)
  7. hive 分区_代码 | Spark读取mongoDB数据写入Hive普通表和分区表
  8. Ubuntu 12.04LTS 找不到eth0网卡
  9. 算法之美--2.2数组
  10. 多语言 获取当前语言
  11. 《SQL Server 2000 完全实战:数据转换服务(DTS)》
  12. C语言中可变参数的宏 __VA_ARGS__
  13. 台达DVP-PLC编程资料
  14. 基于Maya 2018安装OpenVDB插件
  15. 互联网赚钱:一个抖音小项目,分析下,人人都能做
  16. AI遇上农业会怎样?最新UNT《智慧农业》2022全面综述农业4.0发展的架构、技术、应用等
  17. 前端知识学习——html
  18. Harmonious Graph (并查集 —父亲为最大值)
  19. 图像类的分类模型假阳性(FP)高的解决思路
  20. node+express实现文件上传功能

热门文章

  1. 软件测试用例设计方法-场景法
  2. 第一次拿CNVD证书
  3. 2021 新标准大学英语综合教程3 第二版 答案 Unit7 西电研究生B类综合英语
  4. python青少儿编程教程-青少年PYTHON编程入门
  5. 金山云排名第十五,2019年云综合收入 39.56亿元
  6. VSCode调试单片机
  7. C++ constexpr 常量表达式
  8. 技术篇丨音频监控应用现状分析
  9. Linux Debian11安装Wireshark教程
  10. linux系统c 如何使用教程,基于Linux操作系统的C语言编译和调试方法解析