JS逆向进阶篇【去哪儿旅行登录】【下篇-逆向Bella参数JS加密逻辑Python生成】

目录:

  • 每篇前言:
  • 引子——本篇目的
  • 1、 代码混淆和还原
    • (1)单独替换:
    • (2)整个js文件替换:
  • 2、算法入口分析
  • 3、 深入分析
      • (0)整体分析:
      • (1)_0x4dd553:
      • (2)_0x15c356:
      • (3)_0x4fb8ac:
      • (4)_0x34877a:
      • (5)_0x5ad2bb:
      • (6)_0xc21476:
      • (7)_0x34c54c:
      • (8)至此,结束:
  • 4、Python还原算法
  • 5、整体测试

每篇前言:

  • 🏆🏆作者介绍:【孤寒者】—CSDN全栈领域优质创作者、HDZ核心组成员、华为云享专家Python全栈领域博主、CSDN原力计划作者

  • 🔥🔥本文已收录于爬虫进阶+实战系列教程专栏:《爬虫进阶+实战系列教程》
  • 🔥🔥热门专栏推荐:《Python全栈系列教程》、《爬虫从入门到精通系列教程》、《爬虫进阶+实战系列教程》、《Scrapy框架从入门到实战》、《Flask框架从入门到实战》、《Django框架从入门到实战》、《Tornado框架从入门到实战》、《前端系列教程》。
  • 📝​📝本专栏面向广大程序猿,为的是大家都做到Python全栈技术从入门到精通,穿插有很多实战优化点。
  • 🎉🎉订阅专栏后可私聊进一千多人Python全栈交流群(手把手教学,问题解答); 进群可领取Python全栈教程视频 + 多得数不过来的计算机书籍:基础、Web、爬虫、数据分析、可视化、机器学习、深度学习、人工智能、算法、面试题等。
  • 🚀🚀加入我一起学习进步,一个人可以走的很快,一群人才能走的更远!

在这里插入图片描述

引子——本篇目的

在中篇其实已经通过补浏览器环境的方式破解出了bella参数,但是如果补浏览器环境不行的时候该怎么办呢?
这就得一点点扣js了!
所以,本篇文章来扣一波!
逆向分析出bella参数的加密算法,全部基于Python来实现!!!

1、 代码混淆和还原

分析这个js文件,有很多形如_0x5a69('0x0')_0x5a69('0x1')这样的代码,其实这些最终得到的就是一个个对应的字符串。

很入门级的代码混淆,这时候要做的就是尝试解混淆,将这个js文件中这样的代码替换为对应的字符串,这样看着就会直观了!
在这里插入图片描述

上述红框部分就是代码混淆的实现逻辑;而下述整个try部分就是整个加密逻辑。

【很明显,这些最终的字符串,即上图红框中那个大数组中的值,都经过base64加密~】

(1)单独替换:

解这种混淆也非常简单,我们直接执行对应的函数,如_0x5a69('0x0')就可以得到其对应的字符串:
在这里插入图片描述

在这里插入图片描述
pyexecjs执行:
在这里插入图片描述

(2)整个js文件替换:

只需要处理整个try部分代码(放到js3.js文件中)即可~

import reimport execjswith open('js2.js', 'r') as f:JS = execjs.compile(f.read())res = JS.call("_0x5a69", "0x0")print(res)with open("js3.js", 'r', encoding='utf-8') as f1, open("js4.js", 'w', encoding='utf-8') as f2:for line in f1:match_list = re.findall(r"_0x5a69\(.*?\)", line)if not match_list:f2.write(line)continuefor mt_str in match_list:try:# arg = str(re.findall(r"\('(.*?)'\)", mt_str)[0])arg = mt_str[9: -2]line = line.replace(mt_str, f'"{JS.call("_0x5a69", arg)}"')except Exception as e:passf2.write(line)print(line.strip())

上述代码try的作用:

  • 这个js代码这么多,上述简单的替换逻辑肯定会有报错的时候,但是报错又没事,何必一个个扣报错,然后完善逻辑呢?
    等下面具体分析这部分js代码的时候,如果分析到了未替换成功的代码块,手动单独替换下不更方便吗?

2、算法入口分析

直接分析处理后的js文件即可~
在这里插入图片描述
在这里插入图片描述

分析,形参_0x29235d接收的是slideToken:
在这里插入图片描述
但是上一个调用栈其实是传过来了两个参数:
在这里插入图片描述
这就是JavaScript的一个神奇之出,当传给js函数的参数多于js函数的形参时并不会报错,而且在函数内部可以通过arguments加索引的方式取得对应的参数:

var _0x5d0961 = arguments["length"] > 0x1 && arguments[0x1] !== undefined ? arguments[0x1] : '';

所以上述这个三元运算就会赋值{v: 2}_0x5d0961

继续分析:
在这里插入图片描述
执行try的时候,第一句delete删除参数_0x29235d中的Bella,第二句_0x398212(_0x29235d, _0x5d0961)就是生成Bella的函数;
如果捕获到异常,就直接返回_0x2e61cb,而这是个固定值,我直接将Bella写死为这个值,也是没问题的!
【为啥会有这种奇怪的代码,直接写死就可以,这不就是个漏洞吗?
这是因为核心加密逻辑可能需要读取各种浏览器参数,而浏览器千千万,有些浏览器也许不适配,那么就会报错,但是不能影响到用户使用,所以就有了这个try】
下面深入剖析Bella的加密逻辑:

3、 深入分析

(0)整体分析:

在这里插入图片描述
分析都在注释:
在这里插入图片描述

在这里插入图片描述

(1)_0x4dd553:

var _0x4dd553 = _0x318499(_0x481ca8);

入参是:{slideToken: "80ed997a295a75f57e6d8cbe88d77a8b"}
结果是:

{"bParam": "80ed997a295a75f57e6d8cbe88d77a8b","keyArray": ["slideToken"]
}

(2)_0x15c356:

var _0x15c356 = (0x0, _0x5b06ff["default"])();解读:
var _0x15c356 = _0x5b06ff["default"]();

对应js函数:

function _0x9beb5a() {var _0x2bb251 = document[_0x5a69('0xf9')](_0x5a69('0xfa'));var _0x4ba4c2 = _0x2bb251 && _0x2bb251[0x0] && _0x2bb251[0x0][_0x5a69('0xfb')];var _0x5a5787 = document['getElementsByName'](_0x5a69('0xfc'));var _0x4030ec = _0x5a5787 && _0x5a5787[0x0] && _0x5a5787[0x0][_0x5a69('0xfb')];var _0x5a2ba8 = document[_0x5a69('0xfd')];return [{'key': _0x5a69('0xfe'),'value': document['referrer'][_0x5a69('0xb7')]('?')[0x0][_0x5a69('0xd4')](/^http(s)?:\/\//, '')[_0x5a69('0xff')](0x0, 0x14) || ''}, {'key': _0x5a69('0x100'),'value': _0x89ccfe()}, {'key': _0x5a69('0x101'),'value': window['shirley'] || _0xd6c5e7[_0x5a69('0x8a')]['string']}, {'key': _0x5a69('0xfd'),'value': _0x5a2ba8 && _0x5a2ba8['slice'](-0xa) || _0xd6c5e7[_0x5a69('0x8a')][_0x5a69('0xcb')]}, {'key': _0x5a69('0xfa'),'value': _0x4ba4c2 && _0x4ba4c2[_0x5a69('0x1f')](-0xa) || _0xd6c5e7[_0x5a69('0x8a')]['string']}, {'key': _0x5a69('0xfc'),'value': _0x4030ec && _0x4030ec[_0x5a69('0xff')](0x0, 0x14) || _0xd6c5e7['default'][_0x5a69('0xcb')]}, {'key': _0x5a69('0x102'),'value': window[_0x5a69('0xd0')][_0x5a69('0x102')][_0x5a69('0xd4')](/^http(s)?:\/\//, '')[_0x5a69('0xff')](0x0, 0x14) || _0xd6c5e7[_0x5a69('0x8a')][_0x5a69('0xcb')]}, {'key': _0x5a69('0x103'),'value': _0x1916ab() || _0xd6c5e7[_0x5a69('0x8a')][_0x5a69('0xcb')]}];}

在这里插入图片描述

在这里插入图片描述
分析piccolo:

在这里插入图片描述

在这里插入图片描述
生成_0x113a55中随机16个字符拼接而成的字符串~

此参数结果:

[{"key": "referer","value": ""},{"key": "piccolo","value": "5879##420347A09BF3F723##1708962151096"},{"key": "shirley","value": "unknown"},{"key": "title","value": "unknown"},{"key": "keywords","value": "unknown"},{"key": "description","value": "unknown"},{"key": "host","value": "user.qunar.com"},{"key": "scriptSrc","value": ["qimgs.qunarzz.co","q.qunarzz.com/ho"]}
]

(3)_0x4fb8ac:

此参数结果:

{"referer": "","piccolo": "5879##420347A09BF3F723##1708962151096","shirley": "unknown","title": "unknown","keywords": "unknown","description": "unknown","host": "user.qunar.com","scriptSrc": ["qimgs.qunarzz.co","q.qunarzz.com/ho"]
}

(4)_0x34877a:

var _0x34877a = (0x0, _0xd98ca5["default"])();

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

生成_0x24b4d9中随机21个字符拼接而成的字符串~
此参数结果:

dWre6Dts7TLT1O2GkSeTZ

(5)_0x5ad2bb:

var _0x5ad2bb = _0x4dd553["bParam"] + _0x34877a + JSON["stringify"](_0x4dd553['keyArray']);

唯一注意的就是JSON["stringify"](_0x4dd553['keyArray'])的值是["slideToken"]

此参数结果:

3d8b8860db2bf9a6aef7f872979113dedWre6Dts7TLT1O2GkSeTZ["slideToken"]

(6)_0xc21476:

var _0xc21476 = _0x5625ac['default']["signature"](_0x5ad2bb);

在这里插入图片描述

很明显是将入参_0x5ad2bb使用sha1加密,最终将结果转换为十六进制字符串。
加密秘钥16进制表示为:
在这里插入图片描述
Python实现:

import binascii
import hmac
from hashlib import sha1key_str = '68386673614b337771652b696f4d7673'
key = binascii.a2b_hex(key_str)
data = 'b363b3f511bf0e3e556c29cb56dcf4c9hLHNl1SVxE8UR2ONt1-N9["slideToken"]'hmac_code = hmac.new(key, data.encode('utf-8'), sha1)
res = hmac_code.hexdigest()
print(res)

此参数结果:

df95bd703794a4cc96e611da8a53b87f2aadcb40

(7)_0x34c54c:

var _0x34c54c = (0x0, _0x38cd63["default"])(JSON["stringify"](_0x4fb8ac), _0x3d0fe0["default"]);等价于:var _0x34c54c = _0x38cd63["default"](JSON["stringify"](_0x4fb8ac), _0x3d0fe0["default"])
  • 函数第一个参数:
    将上述得到的_0x4fb8ac序列化;
  • 函数第二个参数:
    多次测试为固定值:
["B6F1YrNm+OA=sw","n8xbeLlzQ","p5M02SUHt/dog","cyfj-9kPKu","EX7VWaqJi","3CIGDRhTv4"
]

分析此函数:
在这里插入图片描述
看看_0x21da9c函数:
在这里插入图片描述
内部又调用_0x2d06ba函数,先来看看第一个参数:

_0x1414cd["charCodeAt"]()['toString'](0x2)

获得传进来的参数的unicode编码,toString后得到对应二进制字符串。

在这里插入图片描述
多次调试可发现_0x2d06ba函数的作用就是对传进来的第一个参数左边补0达到八位。

继续看_0x26cf34函数:
在这里插入图片描述
在这里插入图片描述
上述使用js列表的some方法,会对列表中的每个值执行给定函数,但凡有一个返回True则整体为True。

window["location"]["href"]
获取浏览器当前url。再.include("x")就是判断浏览器当前url中是否含有x。

在这里插入图片描述

(8)至此,结束:

拓展:js字符串和数组拼接知识点~
在这里插入图片描述

在JavaScript中,当你使用 + 运算符连接一个字符串和一个数组时,数组会被转换为字符串,并与原始字符串连接。这个过程被称为字符串拼接。

在上图中,"GuHanZhe" 是一个字符串,["Cool"] 是包含一个字符串元素的数组。当它们相加时,JavaScript会将数组转换为字符串,然后进行字符串拼接。这导致了结果 'GuHanZheCool'

4、Python还原算法

import binascii
import hmac
import json
import random
import string
import time
from hashlib import sha1
from urllib.parse import quote_plusdef hmac_sha1(data_string):key_str = "68386673614b337771652b696f4d7673"key = binascii.a2b_hex(key_str)# data_string = 'b363b3f511bf0e3e556c29cb56dcf4c9hLHNl1SVxE8UR2ONt1-N9["slideToken"]'hmac_code = hmac.new(key, data_string.encode('utf-8'), sha1)return hmac_code.hexdigest()def _0x26cf34(_0x4800e6, _0x572efb):_0x5ee954 = ['qunar', 'tujia']_0x403118 = "B6F1YrNm+OA=sw"_0x501116 = "n8xbeLlzQ"_0x3b5454 = "p5M02SUHt/dog"_0x251b31 = "cyfj-9kPKu"_0x222d7d = "EX7VWaqJi"_0x47c310 = "3CIGDRhTv4"_0x3af887 = "".join(_0x572efb) + (_0x403118 + _0x501116 + _0x3b5454 + _0x251b31 + _0x222d7d + _0x47c310);_0x3af887 = list(_0x403118 + _0x501116 + _0x3b5454 + _0x251b31 + _0x222d7d + _0x47c310)_0x4800e6 = quote_plus(_0x4800e6)while len(_0x4800e6) % 0x3 != 0x0:_0x4800e6 += '\x20'_0x933810 = [format(ord(i), "0>8b") for i in _0x4800e6]_0x2e4d85 = []for i in range(0, len(_0x933810), 3):end_index = min(i + 3, len(_0x933810))group = _0x933810[i: end_index]_0x2e4d85.append(group)_0x2a779b = ''for _0x28ee6c in _0x2e4d85:_0x572061 = "".join(_0x28ee6c)_0x351bb8 = []for j in range(0, len(_0x572061), 6):end_idx = min(j + 6, len(_0x572061))_0x351bb8.append(_0x572061[j: end_idx])new_0x351bb8 = []for _0x2a9721 in _0x351bb8:_0x2a9721 = "".join(["0" if char == "1" else "1" for char in _0x2a9721])idx = int(_0x2a9721, base=2)part = _0x3af887[idx]new_0x351bb8.append(part)_0x2a779b += "".join(new_0x351bb8)return _0x2a779bdef run():slide_token = "d8cc3d473f4d895b3af483e122f1ddc061ccb250"_0x4dd553 = {"KeyArray": ["slideToken"], "bParam": slide_token}total_string = string.digits + string.ascii_lettersrandom_string = "".join([random.choice(total_string) for _ in range(16)])_0x4fb8ac = {"referer": "","piccolo": f"{random.randint(1000, 9999)}##{random_string}##{int(time.time() * 1000)}","shirley": "unknown","title": "unknown","keywords": "unknown","description": "unknown","host": "user.qunar.com","scriptSrc": ["qimgs.qunarzz.co", "q.qunarzz.com/ho"]}total_string = '-_zyxwvutsrqponmlkjihgfedcba9876543210ZYXWVUTSRQPONMLKJIHGFEDCBA'_0x34877a = "".join([random.choice(total_string) for _ in range(21)])_0x5ad2bb = slide_token + _0x34877a + json.dumps(_0x4dd553['KeyArray'])_0xc21476 = hmac_sha1(_0x5ad2bb)_0x4fb8ac["sign"] = _0xc21476_0x4fb8ac["randomNum"] = _0x34877a_0x4fb8ac["t"] = int(time.time() * 1000)_0x572efb = ["B6F1YrNm+OA=sw","n8xbeLlzQ","p5M02SUHt/dog","cyfj-9kPKu","EX7VWaqJi","3CIGDRhTv4"]_0x34c54c = _0x26cf34(json.dumps(_0x4fb8ac, separators=(',', ':')), _0x572efb)june_v = "1683616182042"_0x112026 = june_v + '##' + _0xc21476 + '##' + _0x34c54c + '##' + _0x34877a + '##' + 'slideToken'print(_0x112026)if __name__ == '__main__':run()

在这里插入图片描述

5、整体测试

很简单~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/269217.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32启动过程及反汇编

STM32从Flash启动的过程,主要是从上电复位到main函数的过程,主要有以下步骤: 1.初始化堆栈指针 SP_initial_sp,初始化 PC 指针Reset_Handler 2.初始化中断向量表 3.配置系统时钟 4.调用 C 库函数_main 初始化用户堆栈&#xf…

华为配置WLAN高密业务示例

配置WLAN高密业务示例 组网图形 图1 配置高密WLAN环境网络部署组网图 业务需求组网需求数据规划配置思路配置注意事项操作步骤配置文件 业务需求 体育场由于需要接入用户数量很大,AP间部署距离较小,因此AP间的干扰较大,可能导致用户上网网…

Qt 中Qwidget相关属性

文章目录 1. QWidget 核心属性1.1 enabled1.2 geometry1.2.1 window frame 的影响 1.3 windowTitle1.4 windowIcon1.4.1 qrc的使用 1.5 windowOpacity1.6 cursor1.7 focusPolicy1.8 styleSheet 1. QWidget 核心属性 在 Qt 中, 使⽤ QWidget 类表⽰ “控件”. 像按钮, 视图, 输…

Shell管道和过滤器

一、Shell管道 Shell 还有一种功能,就是可以将两个或者多个命令(程序或者进程)连接到一起,把一个命令的输出作为下一个命令的输入,以这种方式连接的两个或者多个命令就形成了管道(pipe)。 重定…

应用方案 | D722 9MHz,轨对轨I/O CMOS运放,低噪声、低电压、低功耗运放,应用广泛

D722是低噪声、低电压、低功耗运放,应用广泛。D722具有9MHz的高增益带宽积,转换速率为8.5V/μs,静态电流为1.7mA(5V电源电压)。 D722具有低电压、低噪声的特点,并提供轨到轨输出能力,D722的最大…

Shell编程——条件测试(五)

在shell编程中,if语句本身不执行任何判断,它实际上接受一个程序作为参数,然后执行这个程序,并依据这个程序的返回值来判断是否执行相应的语句。 程序的返回值是0,则为真,反之则为假。 目录 test命令&…

SpringCloud搭建微服务之Consul服务注册与发现

1. Consul介绍 Consul是由HashiCorp公司使用Go语言开发的一款开源工具,主要用于实现分布式系统的服务发现和服务配置,其内置了服务注册与发现框架、分布式一致性协议实现、健康检查、Key-Value存储、多数据中心方案。Consul具有高可移植性,支…

《Redis 设计与实现》读书概要

注: 《Redis 设计与实现》一书基于 Redis 2.9 版本编写,部分内容已过时,过时之处本文会有所说明。本文为读书笔记,部分简单和日常使用较少的知识点未记录。原书网页版地址 https://redisbook.com/ 一、底层数据结构 SDS(Simple Dy…

654.最大二叉树

这段Java代码实现了一个名为Solution的类,其中包含两个方法:constructMaximumBinaryTree()和constructMaximumBinaryTree1(),目的是从给定的整数数组nums中构建出一个最大二叉树。以下是详细的注释说明: class Solution {// 主方…

某品零食交易平台设计与实现|基于springboot+ Mysql+Java的某品交易平台设计与实现(源码+数据库+文档+PPT)

目录 基于springboot MysqlJava的某品交易平台设计与实现 摘 要 系统详细设计 数据库设计 论文参考 源码获取 文末获取源码联系 基于springboot MysqlJava的某品交易平台设计与实现 摘 要 随着科学技术的飞速发展,社会的方方面面、各行各业都在努力与现代的…

利用excel文件增量同步一个库的数据并自动校正两端数据库条数不一致

利用excel文件增量同步一个库的数据并自动校正两端数据库条数不一致 现在有sqlserver和mysql两个库上的表在进行同步,sqlserver上的是源表,mysql上是目标表。 我们就把sqlserver上的数据同步到mysql上 mysql 是没有数据的。 sqlserver的三个表只是创建了…

240多道!Go开发岗位面试题合集(含答案)

随着今年大环境的影响,找工作的人在今年达到顶峰,马上金九银十面试黄金季,很多人都想在这次面试中拿到心仪Offer。 数以百计的面试,为何迟迟无法顺利入职?能力无疑是至关重要的,可却有不少能力不比已入职的…

未来已来!AI大模型引领科技革命

未来已来!AI大模型正以惊人的速度引领着科技革命。随着科技的发展,人工智能在各个领域展现出了非凡的能力和潜力,大模型更是成为了科技领域的明星。从自然语言处理到图像识别,从智能推荐到语音识别,大模型的应用正在改…

Linux-信号3_sigaction、volatile与SIGCHLD

文章目录 前言一、sigaction__sighandler_t sa_handler;__sigset_t sa_mask; 二、volatile关键字三、SIGCHLD方法一方法二 前言 本章内容主要对之前的内容做一些补充。 一、sigaction #include <signal.h> int sigaction(int signum, const struct sigaction *act,struc…

阿里云2核4G服务器支持多少人在线?多少钱?

阿里云2核4G服务器多少钱一年&#xff1f;2核4G5M带宽优惠价格199元一年&#xff0c;轻量应用服务器2核4G4M带宽165元一年&#xff0c;2核4G服务器30元3个月&#xff0c;可以在阿里云官方活动查看2核4G配置详细报价 https://t.aliyun.com/U/bLynLC 阿里云2核4G服务器价格 2核4G…

07. Nginx进阶-Nginx负载均衡

简介 负载均衡 什么是负载均衡&#xff1f; 负载均衡&#xff0c;英文名称为Load Balance&#xff0c;其含义就是指将负载&#xff08;工作任务&#xff09;进行平衡、分摊到多个操作单元上进行运行。 Nginx负载均衡 什么是Nginx负载均衡&#xff1f; Nginx负载均衡可以大…

深度学习算法的基本原理

深度学习是一种机器学习方法&#xff0c;其核心是通过构建深层神经网络来学习数据的表示和特征&#xff0c;以解决各种复杂的任务。以下是深度学习算法的基本原理&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎…

Vue.js中的diff算法:让虚拟DOM更高效

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

【Docker】Windows11操作系统下安装、使用Docker保姆级教程

【Docker】Windows11操作系统下安装、使用Docker保姆级教程 大家好 我是寸铁&#x1f44a; 总结了一篇【Docker】Windows11操作系统下安装、使用Docker保姆级教程的文章✨ 喜欢的小伙伴可以点点关注 &#x1f49d; 前言 什么是 Docker&#xff1f; Docker 是一个开源平台&…

「MySQL」基本操作类型

&#x1f387;个人主页&#xff1a;Ice_Sugar_7 &#x1f387;所属专栏&#xff1a;数据库 &#x1f387;欢迎点赞收藏加关注哦&#xff01; 数据库的操作 创建、显示数据库 使用 create 创建一个数据库 create database goods;然后可以用 show databases 来查看已经创建的数…