35_某东登录参数与流程分析(包含滑块)

Date
Mar 6, 2024
Created
Mar 8, 2024 02:01 PM
Tags
JS逆向实战

声明

本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!

目标网站

aHR0cHM6Ly9wYXNzcG9ydC5qZC5jb20vbmV3L2xvZ2luLmFzcHg/UmV0dXJuVXJsPWh0dHBzJTNBJTJGJTJGd3d3LmpkLmNvbSUyRg==

前言

上次介绍了H5st的加密。这次来研究一下模拟登陆。即登录+滑块 这里先贴一张图 下图所示 是登录要的所有参数。至于所得所有参数 怎么来的? 如何来的?请往下看。
notion image
有能力的同学可以加下本人星球哦
https://t.zsxq.com/17OvVkJha
本文详细原文
https://mp.weixin.qq.com/s/D2MTec5F92GoSho0af26ww

接口分析

参数过多。这里直接步入正题。 首先打开一个无痕浏览器(这很重要)
notion image
关注一下这个
slide/g.html
请求。 发现这里只有一个 e 请求是会改变的。但是好像写死也没问题。如下图然后往后看有很多个请求。但请求都大同小异啊。这里不卖关子了。请求是绑定的鼠标事件。每次移动鼠标都有请求发过来。
notion image
notion image
进栈点看看。
notion image
这里发现d的结果已经出来 往上走。
notion image
这里发现
C(a)
的值就是生成
d
的参数。 这里 传参
a
notion image
c函数如下
notion image
这里我扣下来了。
C = function (a) { if (void 0 == a || null == a) return null; var b = "{", e; for (e in a) b += "'" + e + "':", b = "string" == typeof a[e] ? b + ("'" + a[e] + "'") : b + a[e], b += ","; b = b.substring(0, b.length - 1); return E(b + "}") } E = function (a) { this.tdmovebit = function () { var a = 10 , b = 20 , c = 30; ++a; a++; a = ++a + ++b + c++ + a++; return d + a - 76 } ; var b = "23IL"; a = encodeURIComponent(a); var e = "" , c = ""; b += "<N01c7KvwZO56RSTAfghiFyzWJqVabGH4PQdopUrsCuX*xeBjkltDEmn89.-"; var d = 0; var g = ""; do { var h = a.charCodeAt(d); d = this.tdmovebit(d); var f = a.charCodeAt(d); d = this.tdmovebit(d); e = a.charCodeAt(d); d = this.tdmovebit(d); var k = h >> Math.round(((19 << 43) / 90 ^ 34) / 214); h = (h & 3) << 4 | f >> 4; var l = (f & 15) << 2 | e >> 6; c = e & Math.round(((19 << 43) / 90 ^ 34) / 6) - 4; isNaN(f) ? l = c = Math.round(((19 << 43) / 90 ^ 34) / 6) - 3 : isNaN(e) && (c = Math.round(((19 << 43) / 90 ^ 34) / 6) - 3); g = g + b.charAt(k) + b.charAt(h) + b.charAt(l) + b.charAt(c); k = h = l = c = h = f = e = "" } while (d <= a.length); return g + "/" } let a = { "bizId": "passport_jd_com_login_pc", "elementId": "loginname", "seq": "sniffV", "sessionId": "294576929414652485", "special": "0", "sp": 1, "version": "1.0", "val": "", "ctime": 1709542681074 } console.log(C(a));
拿到这个d
值了。 这里继续往下 下断点。
notion image
然后我们移动鼠标就会有请求发过来。 发现这个地方 就是监听鼠标的事件。这里不扯这个了。继续回头来走这个流程 然后我们输完密码 发现又有个
slide/s.html
请求
notion image
然后它的返回值是
fail
意思是滑动失败
notion image
然后随后又发了个
slide/g.html
请求。
notion image
那这样的话。我们是不是可以简单梳理一下。
  • g请求拿验证码
  • s请求返回结果
那这个g请求中的e
是什么? 我们找一下 第二个堆栈
notion image
notion image
那这个方法中如何获取eid
呢 我们继续追栈进去
notion image
继续进这个
a = getJdEid()['eid']
好了 进去一个虚拟机了
notion image
notion image
然后发现 这个eid
居然在这个fcf.html 请求中
notion image
然后要访问这个请求 需要三个加密方法。 分别为a
,g
,d
.
notion image
嫌麻烦可以把 e 参数写死 能不能成功我就不知道了。

fcf接口加密分析

这里不废话了。打断点 开干。 这里不知道怎么找。直接追栈吧。就直接从最上面的栈追。然后一步一步往上看。 如下图所示 就是加密的地方。
notion image
这里我们一个一个看把

z(a)参数分析

notion image
notion image
如上图 传递了很多参数。其中要注意的是fc fp jtb
notion image
这里其实可以全拉下来补环境。但是我感觉有点麻烦了。 可以一个一个去扣下。 这里tdencrypt
函数很好扣。 如下图所示
notion image
这里抠出来了。但是传参我们还没扣。
fc
fc是eid 测试下来可以为空; **fp ** fp 如下图
notion image
继续往上追
notion image
然后我们全局搜索 _JdJrTdRiskFpInfo
notion image
然后我们进去get这个方法
notion image
把这个方法全扣下来 然后补一下环境。
notion image
ok 这样就出结果了
jtb
jtb就是jd_shadow__
notion image
这里往上找 终于找到加密的地方是个自执行函数。用了什么加密就不说了 一目了然
notion image
这里给他扣下来。发现扣下来执行结果是undefined 这里有两种结果。第一种是异常了。第二种是加密的值就是undefined
notion image
这里发现 加密了r值 而r一开始是个数组,添加了一些数组然后拼接成字符串。
notion image
然后修修补补 最后修改一下 运行就行。
notion image

n(g,d)参数分析

notion image
如上图 g 和 d 参数都被赋值给了 n。
g
n.g = td_collect.tdencrypt(u); 这里就直接伪造u就可以了 tdencrypt上文 搞z的时候已经写好了。
d
n.d = _JdJrRiskClientCollectData;
notion image
但是 td_collect.collect()
这个 应该是很多环境检测。我们进去看看。 至于我为什么笃定是环境检测。因为上一篇h5st中collect函数也是。 如下图 是collect() 函数。这里我们直接滑到最低。
notion image
直接把g全弄下来构造环境即可。
notion image
至此a
,g
,d
全部搞定。全部搞定就可以获得eid了。
这里扣不扣代码和补环境差不多 都是两千多行。 这部分的代码 我放到星球里了。

滑块分析

s请求。
这里我们先看s请求。
notion image
这里我们需要逆向的参数是
d
其他的值 有的是通过
g
有的是可以写死。 这里
o
是用户账号 但是密码不在这个请求里。这里我们直接进 下图这个栈 通过这个栈跟。
notion image
notion image
然后到达 submit 函数
notion image
继续追 到
a['getCoordinate'](b)
这个地方就是生成d的地方。其他值 生成的逻辑大家也可以看看。 这里我们发现 还是没有发现密码的参数是哪个?
notion image
这里可以把 这个函数抠出来。 这个抠出来的逻辑 巨!!!简单。不说了 如下图所示
notion image
notion image
g请求
搞完了s 我们来继续请求
g
这里之所以倒退 主要是其他值生成的逻辑 我们可以提前看看。就可以找到要拿哪些需要的参数了 先访问这个请求。
notion image
这里值得注意的是这个
challenge
是验证码ID 也需要提出来。
notion image
其他的参数更简单了 提取出s需要的参数就行了。

密码加密

但是这里有另一个问题。
s
请求和
g
请求都搞了。但是我们一直没找到密码的加密参数啊 这里重新走一遍流程。 这里发现,我们鼠标即使不动。在输入密码的时候 依然有很多请求发过去。那这个是怎么回事?
notion image
这里继续在这个C(a)这个地方打断点。并且埋点,看看整体的逻辑。
notion image
notion image
console.log(a,">>>>>",C(a));false
这里为什么这么写就不用多说了 。之前xhs写过了。
这里 elementId: "nloginpwd" 暴露了这是密码加密的地方。并且传递密码还是通过每次的键盘事件。
notion image
但是这每次传。总不可能服务器接受这么多次吧。肯定还有个统一提交的地方。

登录提交

我们完整的再走一次流程。把滑块也给滑过去。 此时发现一个请求
uc/loginService
这个请求应该大概率是提交的地方。
notion image
这里我们再走一下流程搜索 aksParamsU aksParamsB
如下图。 aksParamsU
notion image
notion image
aksParamsB
notion image
notion image
这里aksParamsU aksParamsB发现都是公用的encrypte 函数。 这里我也复制下来了
function encrypte(data) { if (checkInitStatus() && !isBlank(data)) { try { // const data_ = decodeURIComponent(data) return encodeURIComponent(SummerCryptico.encryptData(publicKey, data + "")) } catch (e) { return data } } else { return data } }
扣下来大概两千多行。
notion image
这里可以发现 除了常规加密 还带了一个
publicKey
这里public的生成经过断点分析后可知由最开始初始化的
init请求
提供。
notion image
notion image
这里我们把data 拷贝下来分析一下。 这个参数还挺多的。
notion image
这里往上找堆栈
notion image
notion image
(发现和上文我们拷贝的参数是一样的。)这里继续往这个getEntryptPwd下走 这里在走断点的时候发现 文中的 publickey如下所示
notion image
然后把函数扣下来加密 就是密码的加密了。
notion image
notion image
大概随便补一下就出来了。
notion image

总结

很好 这里该解密的都解密的都解密出来了。 这里简单叙述一下流程 其实就三个请求。
  1. g请求拿到验证码 a. 但是 e呢 需要访问fcf请求 b. fcf请求需要逆向e,g,d
  1. s请求根据g请求返回结果 a. e参数同上 b. d参数是通过JDJRValidate.getCoordinate 加密轨迹得到。
  1. loginService请求 发起请求。并且整个从参数加密 a. aksParamsU 与 aksParamsB都是统一加密方式。不同的是加密的明文 b. 明文的密码 又是一段加密代码。

结语

本文关于代码部分的加密参数。可以看下文详解。
https://wx.zsxq.com/dweb2/article?groupId=51112885255144