js逆向系列——入门篇

214 阅读4分钟

js逆向系列——入门篇

对于偏好研究数据请求过程中协议破解的朋友而言,js逆向是必不可少的环节。本文简单介绍了逆向过程使用到的工具、逆向流程以及一些简单案例。

一、常用工具

名称作用用法
chrome dev tools调试web程序查看数据请求流程、调试js等
postman接口测试复制curl请求,自定义请求头、请求参数,模拟发包
hashlib计算散列值python包,可计算MD5/SHA1/SHA256/SHA512/shake_128/...
Crypto加解密pip install cryptodome,AES/DES/3DES/RSA/...
curlconvertercurl转脚本curlconverter.com/
jsnicejs反混淆www.jsnice.org
spidertools爬虫工具库spidertools.cn/
decode_obfuscator解ob混淆tool.yuanrenxue.cn/decode_obfu…
JStilleryjs反混淆mindedsecurity.github.io/jstillery/
JSbeautifierjs反混淆beautifier.io/

二、逆向流程

1. 数据获取流程

一个直观的数据获取流程如下:

graph TD
创建socket --> 建立tcp连接 --> 构造请求头/payload --> 发送请求数据 --> 接收响应数据 --> 解析响应数据

2. 逆向流程

常规逆向流程包含如下步骤:

graph TD
发现加密参数or加密响应内容 --> 检索加密函数位置 --> 分析加密函数 --> 复现加解密逻辑 --> 模拟实际请求

(1)发现加密参数or加密响应内容

在构造请求头时,有时需要携带需要验证的参数或者payload,部分参数在客户端生成。

解析响应数据时,有时会发现原始的响应数据为密文。

(2)检索加密函数位置

包含关键词检索法和跟栈分析方法。

常用的关键词包含

  • 加密参数key
  • JSON.parse(
  • decrypt(
  • btoa(
  • base64
  • hmac

(3)分析加密函数

包含静态分析法和动态分析法。

(4)复现加解密逻辑

可以直接把相关的js代码扣下来,也可以根据加解密逻辑复现。

复现加解密逻辑后,可以直接构造加密参数,模拟请求;也可以解密密文形式的响应内容,得到原始数据。

(5)模拟实际请求

python运行js的方法包含:

  • 使用pyexecjs库运行js
  • 调用系统命令运行node

3. 数据获取流程与逆向流程对应关系

逆向与数据获取流程的关系,可以简单对应成如下形式

timeline
title 逆向流程与数据获取流程对应关系
      创建socket
      建立tcp连接
      构造请求头/payload : 构造加密参数
      发送请求数据 : 模拟实际请求
      接收响应数据 : 检索加密函数位置
      : 分析加密函数
      : 扣包含加密逻辑的js代码
      解析响应数据 : 解析加密响应内容

三、案例

1. aHR0cHM6Ly9sb2dpbjEuc2NyYXBlLmNlbnRlci8=

网页如下,是一个登陆页面

image.png

填写用户名密码,提交可以发现请求的数据包

image.png

通过POST方法,发送了一个token参数,但是token加密了。通过关键词token检索,可以定位到XHR发包位置。也可以跟栈,下断查看token生成位置。

image.png

token为e,e是this.form转字符串后传入c.encode生成。在此处下断

image.png

先查看传入参数,是我们填充的明文,再查看c.encode

image.png

image.png

分析之,encode函数包含e,r两个参数,此时只赋值了e,那么接下来的三目表达式跟到_encode(String(e)),e为之前传入的字符串形式的账密,此处再次做了字符串转换后,调用_encode函数处理字符串。

分析作用域,知buffer为undefined,此时_encode函数为btoa(utob(e))

image.png

utob是unicode转utf-8的函数,btoa是base64编码函数,由此确定该加密逻辑实际是将序列化的用户名和密码用base64编码,进而通过接口发送请求。

2. aHR0cHM6Ly93d3cuc3BpZGVyZGVtby5jbi9hdXRoZW50aWNhdGlvbi9wcm90b2J1Zl9jaGFsbGVuZ2UvP2NoYWxsZW5nZV90eXBlPXByb3RvYnVmX2NoYWxsZW5nZQ==

这是来自靶场的一道题目,网页如下

image.png

可以看到POST请求的payload以及响应内容均为密文

image.png

image.png

此处关注响应内容的解密。题目已经提示protobuf,且每次翻页前,都会请求challenge.proto文件,该文件定义了protobuf明文的数据结构

image.png

参考protobuf编码的文档【zhuanlan.zhihu.com/p/192089514…】,可以直接把响应内容复制到在线的protobuf解密工具【protobuf-decoder.netlify.app/】中,再自己编写proto文件解码。

image.png

下面看密文的payload,可以通过下xhr断点先找发包位置,再找加密位置

image.png

发包函数在一个严重混淆的js文件中,同时也可以在当前作用域中看到请求数据的明文内容。xhr发包函数传入的值finalBuffer是一个uint8array,这个就是编码的payload

image.png

由于在.proto数据结构文件中已经看到了ChallengeRequest的定义,那么此处直接构造ChallengeRequest,并测试生成的payload

image.png

image.png

接下来就是请求数据的构造,多次测试发现challengetype是定值,另外timestamp是时间戳,page为请求页码,实际只需要构造signature即可

image.png

格式化js,查看加密逻辑,但是由于js中的常量存在零宽、换行等字符,此处简单分析即可,不做反混淆,检索signature

image.png

image.png

可以清楚看到,先使用md_sign['OooO'](timestampStr)计算得到signature,然后赋值给requestData的signature字段。

下面复现md_sign['OooO']

image.png

代码量不是很多,可以直接在控制台打印函数,然后在本地node环境中测试。本题并没有针对node环境检测的部分,复现之后,测试生成的signature。

image.png

四、总结

主要介绍了js逆向的一般流程,从数据获取的过程中,针对加密的请求参数、响应内容,通过关键词检索、跟栈等手法能够跟进到加密逻辑的位置,进而手动构造出加密参数、响应解析函数。