首页 > 其他分享 >逆向实战33——某东登录参数与流程分析(包含滑块)

逆向实战33——某东登录参数与流程分析(包含滑块)

时间:2024-03-08 10:11:07浏览次数:26  
标签:这个 加密 这里 滑块 33 某东 参数 data 请求

声明

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

目标网站

aHR0cHM6Ly9wYXNzcG9ydC5qZC5jb20vbmV3L2xvZ2luLmFzcHg/UmV0dXJuVXJsPWh0dHBzJTNBJTJGJTJGd3d3LmpkLmNvbSUyRg==

前言

上次介绍了H5st的加密。这次来研究一下模拟登陆。即登录+滑块
这里先贴一张图 下图所示 是登录要的所有参数。至于所得所有参数 怎么来的? 如何来的?请往下看。

有能力的同学可以加下本人星球哦

https://t.zsxq.com/17OvVkJha

本文详细原文

https://mp.weixin.qq.com/s/D2MTec5F92GoSho0af26ww

接口分析

参数过多。这里直接步入正题。
首先打开一个无痕浏览器(这很重要)

关注一下这个slide/g.html请求。 发现这里只有一个 e 请求是会改变的。但是好像写死也没问题。

如下图然后往后看有很多个请求。但请求都大同小异啊。这里不卖关子了。请求是绑定的鼠标事件。每次移动鼠标都有请求发过来。


进栈点看看。

这里发现d的结果已经出来 往上走。

这里发现 C(a)的值就是生成d的参数。
这里 传参a

c函数如下

这里我扣下来了。

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值了。
这里继续往下 下断点。

然后我们移动鼠标就会有请求发过来。
发现这个地方 就是监听鼠标的事件。

这里不扯这个了。继续回头来走这个流程
然后我们输完密码 发现又有个 slide/s.html请求

然后它的返回值是fail 意思是滑动失败

然后随后又发了个slide/g.html请求。

那这样的话。我们是不是可以简单梳理一下。

  • g请求拿验证码
  • s请求返回结果

那这个g请求中的e是什么?
我们找一下 第二个堆栈


那这个方法中如何获取eid
我们继续追栈进去

继续进这个 a = getJdEid()['eid']
好了 进去一个虚拟机了


然后发现 这个 eid 居然在这个fcf.html 请求中

然后要访问这个请求 需要三个加密方法。
分别为 a, g , d.

嫌麻烦可以把 e 参数写死 能不能成功我就不知道了。

fcf接口加密分析

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

这里我们一个一个看把

z(a)参数分析



如上图 传递了很多参数。其中要注意的是 fc fp jtb

这里其实可以全拉下来补环境。但是我感觉有点麻烦了。
可以一个一个去扣下。
这里tdencrypt 函数很好扣。
如下图所示

这里抠出来了。但是传参我们还没扣。
fc
fc是eid 测试下来可以为空;
**fp **
fp 如下图

继续往上追

然后我们全局搜索_JdJrTdRiskFpInfo

然后我们进去get这个方法

把这个方法全扣下来
然后补一下环境。

ok 这样就出结果了
jtb
jtb就是jd_shadow__

这里往上找 终于找到加密的地方是个自执行函数。用了什么加密就不说了 一目了然

这里给他扣下来。发现扣下来执行结果是undefined
这里有两种结果。第一种是异常了。第二种是加密的值就是undefined

这里发现 加密了r值 而r一开始是个数组,添加了一些数组然后拼接成字符串。

然后修修补补 最后修改一下 运行就行。

n(g,d)参数分析


如上图 g 和 d 参数都被赋值给了 n。
g
n.g = td_collect.tdencrypt(u); 这里就直接伪造u就可以了 tdencrypt上文 搞z的时候已经写好了。

d
n.d = _JdJrRiskClientCollectData;

但是 td_collect.collect() 这个 应该是很多环境检测。我们进去看看。
至于我为什么笃定是环境检测。因为上一篇h5st中collect函数也是。
如下图 是collect() 函数。这里我们直接滑到最低。

直接把g全弄下来构造环境即可。

至此 a, g , d 全部搞定。全部搞定就可以获得eid了。

这里扣不扣代码和补环境差不多 都是两千多行。
这部分的代码 我放到星球里了。

滑块分析

s请求。
这里我们先看 s 请求。

这里我们需要逆向的参数是 d 其他的值 有的是通过 g 有的是可以写死。
这里 o 是用户账号 但是密码不在这个请求里。

这里我们直接进 下图这个栈 通过这个栈跟。


然后到达 submit 函数

继续追 到 a['getCoordinate'](b) 这个地方就是生成d的地方。其他值 生成的逻辑大家也可以看看。
这里我们发现 还是没有发现密码的参数是哪个?

这里可以把 这个函数抠出来。
这个抠出来的逻辑 巨!!!简单。不说了 如下图所示

g请求
搞完了s 我们来继续请求g 这里之所以倒退 主要是其他值生成的逻辑 我们可以提前看看。就可以找到要拿哪些需要的参数了
先访问这个请求。

这里值得注意的是这个 challenge 是验证码ID 也需要提出来。

其他的参数更简单了 提取出s需要的参数就行了。

密码加密

但是这里有另一个问题。
s请求和 g 请求都搞了。但是我们一直没找到密码的加密参数啊
这里重新走一遍流程。
这里发现,我们鼠标即使不动。在输入密码的时候 依然有很多请求发过去。那这个是怎么回事?

这里继续在这个C(a)这个地方打断点。并且埋点,看看整体的逻辑。

console.log(a,">>>>>",C(a));false

这里为什么这么写就不用多说了 。之前xhs写过了。

这里 elementId: "nloginpwd" 暴露了这是密码加密的地方。并且传递密码还是通过每次的键盘事件。

但是这每次传。总不可能服务器接受这么多次吧。肯定还有个统一提交的地方。

登录提交

我们完整的再走一次流程。把滑块也给滑过去。
此时发现一个请求uc/loginService 这个请求应该大概率是提交的地方。

这里我们再走一下流程搜索 aksParamsU aksParamsB

如下图。
aksParamsU


aksParamsB

这里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
        }
    }

扣下来大概两千多行。

这里可以发现 除了常规加密 还带了一个 publicKey
这里public的生成经过断点分析后可知由最开始初始化的init请求提供。


这里我们把data 拷贝下来分析一下。
这个参数还挺多的。

这里往上找堆栈


(发现和上文我们拷贝的参数是一样的。)

这里继续往这个getEntryptPwd下走
这里在走断点的时候发现 文中的 publickey如下所示

然后把函数扣下来加密 就是密码的加密了。


大概随便补一下就出来了。

总结

很好 这里该解密的都解密的都解密出来了。
这里简单叙述一下流程
其实就三个请求。

  1. g请求拿到验证码
    a. 但是 e呢 需要访问fcf请求
    b. fcf请求需要逆向e,g,d
  2. s请求根据g请求返回结果
    a. e参数同上
    b. d参数是通过JDJRValidate.getCoordinate 加密轨迹得到。
  3. loginService请求 发起请求。并且整个从参数加密
    a. aksParamsU 与 aksParamsB都是统一加密方式。不同的是加密的明文
    b. 明文的密码 又是一段加密代码。

结语

本文关于代码部分的加密参数。可以看下文详解。

https://wx.zsxq.com/dweb2/article?groupId=51112885255144

标签:这个,加密,这里,滑块,33,某东,参数,data,请求
From: https://www.cnblogs.com/zichliang/p/18052028

相关文章

  • Sealos 给全体用户献上开春福利!降价 33.5%~73.4%
    Sealos经过23年一年的迭代,获得了用户的广泛好评,注册用户已破十万,应用数量也突破一万,24年的工作重心会放在价格上,在我们不死掉的情况下尽可能为用户谋福利!好消息是Sealos与各大云厂商深度合作,加上Sealos本身的多租户云版拼多多的业务模式,终于能把价格打下来了!本次我们同......
  • AT_abc338_f [ABC338F] Negative Traveling Salesman 题解
    分析考虑状压。定义状态函数\(f_{i,j}\)表示在经过点的情况为\(i\)且最后停在点\(j\)的最小花费。那有:\(f_{i,j}=\min\{f_{i',k}+w_{k\toj}|k\toj\}\)。然后就过不了样例一。根据样例一,可以发现\(f_{3,2}=f_{2,2}+w_{2\to1}+w_{1\to2}\)。也就是说我们在原本已经走......
  • P2330 [SCOI2005] 繁忙的都市
    原题链接题解最小生成树和最短路不一样的兄弟code#include<bits/stdc++.h>usingnamespacestd;intfa[306]={0};intfinds(intnow){return(fa[now]==now?now:finds(fa[now]));}structnode{intx,y,v;booloperator<(constnode&b)const{returnv<b.v;}......
  • 33. 搜索旋转排序数组(中)
    目录题目二分搜索题目整数数组nums按升序排列,数组中的值互不相同。在传递给函数之前,nums在预先未知的某个下标k(0<=k<nums.length)上进行了旋转,使数组变为[nums[k],nums[k+1],...,nums[n-1],nums[0],nums[1],...,nums[k-1]](下标从0开始计数)。例如,[0,1......
  • P1332 血色先锋队
    思路:BFS这道题思路挺简单的。每个被感染的设置被感染的时间,然后将其放到队列中。已经被感染的就不要重复设置值了。#include<bits/stdc++.h>usingnamespacestd;constintmaxn=505;intn,m,a,b;pair<int,int>pr;intdx[4]={0,-1,1,0},dy[4]={-1,0,0,1......
  • 洛谷题单指南-搜索-P1433 吃奶酪
    原题链接:https://www.luogu.com.cn/problem/P1433题意解读:计算经过所有奶酪一次的总路径最短,可以采用dfs、dp等方法。解题思路:最直接的思路是DFS,暴搜所有的路径方案,计算最小距离,n最大是15,复杂度为15!≈10^12,必定会超时,先保证正确性,得到部分分:50分代码:#include<bits/stdc++.h......
  • AT_abc331_f [ABC331F] Palindrome Query 题解
    分析线段树。每个节点维护两个值:$s[l\dotsr]$和$s[r\dotsl]$。判断字串是否是回文直接就是询问的答案维护出来的两个值是否相同。首先想到用线段树暴力维护。第一个值很显然是两个儿子的第一个值加起来,第二个值是反着加起来。得到很酷的代码:ilvoidup(intnow){ tr[now......
  • AT_abc335_f [ABC335F] Hop Sugoroku 题解
    比E简单。分析考虑暴力DP。定义状态函数$f_i$表示最后一个黑点为$i$时的方案数,有:$f_i=\sum\limits_{j=1}^{i-1}f_j[(i-j)\bmodval_j=0]$。不难发现在使用刷表法的时候,转移代码:for(reintj=1;i+val[i]*j<=n;++j)f[i+val[i]*j]=(f[i+val[i]*j]+f[i])%p;这玩意复杂......
  • Vue学习笔记33-生命周期
    示例一: <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><title>引入生命周期</title>......
  • 20233.5
    int类型占四个字节,而byte类型占一个字节int占4个字节,即表示int类型的存储大小为4个字节。如果转成十进制来说就是“-2147483648~2147483647”即:int只能存放这么大的数字。。。超出范围则溢出。。。再来说bytebyte最大能够存放-128~127的数值。那为什么是-128~127这个跟字......