参数跟丢了之JS生成器和包装器

news2024/11/24 15:59:11

如需转载请注明出处.欢迎小伙伴一起讨论技术.

逆向网址:aHR0cHM6Ly91bmlvbi5qZC5jb20vcHJvTWFuYWdlci9pbmRleD9wYWdlTm89MQ==

跟踪接口:aHR0cHM6Ly9hcGkubS5qZC5jb20vYXBp

跟踪参数:h5st

本文目标:记录学习下自定义的生成器和包装器,不做具体的参数加密逻辑分析

直接启动器进入,跟战后找到以下代码位置.

问题:跟栈的时候在case20的位置找到最终h5st的结果值,再往上跟栈找不到生成和拼接h5st的位置

那么就尝试理解下这段代码

function X() {
    return (X = (0,
        u.Z)(h().mark((function e(t) {
            var n, o, a, i, r, l, s, c, d, u, p, f, g, v, m, b, x, w, _, y, C;
            return h().wrap((function (e) {
                for (; ;)
                    switch (e.prev = e.next) {
                        case 0:
                            return n = t.functionId,
                                o = t.method,
                                a = void 0 === o ? "GET" : o,
                                i = t.params,
                                r = t.isEncode,
                                l = void 0 === r || r,
                                s = t.needCode,
                                c = void 0 !== s && s,
                                d = t.appid,
                                u = void 0 === d ? M.ZP.APP_ID.UNION_PC : d,
                                p = t.payload,
                                f = void 0 === p ? {} : p,
                                g = "https://api.m.jd.com/api?",
                                v = $().get("__jda"),
                                m = null == v ? void 0 : v.split(".")[1],
                                b = {
                                    functionId: n,
                                    appid: u,
                                    _: Date.now(),
                                    loginType: "3",
                                    uuid: m,
                                    "x-api-eid-token": Q
                                },
                                e.prev = 5,
                                x = new window.ParamsSign({
                                    appId: "586ae"
                                }),
                                i = H(H({}, i), {}, {
                                    clientPageId: "jingfen_pc"
                                }),
                                w = {
                                    functionId: n,
                                    appid: u,
                                    body: F()(k()(i)).toString()
                                },
                                e.next = 12,
                                x.sign(w);
                        case 12:
                            _ = e.sent,
                                y = _.h5st,
                                b = H(H({}, b), {}, {
                                    h5st: encodeURI(y)
                                }),
                                e.next = 20;
                            break;
                        case 17:
                            e.prev = 17,
                                e.t0 = e.catch(5),
                                console.log(e.t0);
                        case 20:
                            "POST" === a ? (C = "body=".concat(l ? encodeURIComponent(k()(i)) : k()(i)),
                                f.data = C) : b.body = l ? encodeURIComponent(k()(i)) : i,
                                g += (0,
                                    Z.L7)(b),
                                f.extendParams || (f.extendParams = {});
                            try {
                                n && (f.extendParams.functionId = n),
                                    i && i.funName && (f.extendParams.funName = i.funName)
                            } catch (e) {
                                console.log("error: ", e)
                            }
                            return e.next = 26,
                                J(H(H({
                                    method: a,
                                    url: g
                                }, f), {}, {
                                    withCredentials: !0,
                                    needCode: c
                                })).then((function (e) {
                                    return !e.page && e.pageNo && (e.page = {
                                        pageNo: e.pageNo,
                                        pageSize: e.pageSize,
                                        hasNext: e.hasNext,
                                        totalCount: e.total || e.totalNum
                                    }),
                                        e
                                }
                                ));
                        case 26:
                            return e.abrupt("return", e.sent);
                        case 27:
                        case "end":
                            return e.stop()
                    }
            }
            ), e, null, [[5, 17]])
        }
        )))).apply(this, arguments)
}

知识点1:    (0,u.Z),这种写法;

        作用1,在 JavaScript 中,u.Z 是一个函数。如果你直接调用 u.z(),那么 u将成为函数 Z的上下文(即 this),而 (0, u.Z) 的写法可以确保 u.Z 在全局上下文或其他上下文中被调用,避免 this 被意外改变

        作用2,如果代码经过工具(比如 Babel)处理,它可能将一些较复杂的函数调用转化为 (0, u.Z) 形式。这样做的目的是保证代码在不同环境下都能正常工作,特别是在模块系统中,有时需要显式地调用函数而不是通过方法调用

知识点2:h().mark函数,进入mark函数,扣下主要代码

var h = "suspendedStart"
    , d = "suspendedYield"
    , f = "executing"
    , p = "completed"
    , v = {};
function g() { }
function m() { }
function b() { }
var y = {};
s(y, i, (function () {
    return this
}
));
//E的原型是一个数组
var w = Object.getPrototypeOf
    , _ = w && w(w(M([])));
_ && _ !== n && o.call(_, i) && (y = _);
var E = b.prototype = g.prototype = Object.create(y);
//...省略一大段
t.mark = function (t) {
    return Object.setPrototypeOf ? Object.setPrototypeOf(t, b) : (t.__proto__ = b,
        s(t, l, "GeneratorFunction")),
        //返回一个对象,设置该对象继承E的原型
        t.prototype = Object.create(E),
        t
}

从上面可以看出,最终t是返回一个生成器函数

知识点3:h().wrap,扣下主要代码

//包装器
function c(t, e, n, o) {
    var r = e && e.prototype instanceof g ? e : g
        , i = Object.create(r.prototype)
        , a = new C(o || []);
    //生成器的核心逻辑
    return i._invoke = function (t, e, n) {
        //o为记录状态,next、throw 或 return
        var o = h;
        return function (r, i) {
            if (o === f)
                throw new Error("Generator is already running");
            if (o === p) {
                if ("throw" === r)
                    throw i;
                return A()
            }
            for (n.method = r,
                n.arg = i; ;) {
                var a = n.delegate;
                if (a) {
                    var l = O(a, n);
                    if (l) {
                        if (l === v)
                            continue;
                        return l
                    }
                }
                if ("next" === n.method)
                    n.sent = n._sent = n.arg;
                else if ("throw" === n.method) {
                    if (o === h)
                        throw o = p,
                        n.arg;
                    n.dispatchException(n.arg)
                } else
                    "return" === n.method && n.abrupt("return", n.arg);
                o = f;
                //代用传下来的函数,在u中调用
                var s = u(t, e, n);
                if ("normal" === s.type) {
                    if (o = n.done ? p : d,
                        s.arg === v)
                        continue;
                    return {
                        value: s.arg,
                        done: n.done
                    }
                }
                "throw" === s.type && (o = p,
                    n.method = "throw",
                    n.arg = s.arg)
            }
        }
    }(t, n, a),
        i
}
function u(t, e, n) {
    try {
        return {
            type: "normal",
            //最终调用位置,使用call方法
            arg: t.call(e, n)
        }
    } catch (t) {
        return {
            type: "throw",
            arg: t
        }
    }
}
//把包装器暴露c函数,让外部使用wrap方法调用
t.wrap = c;

wrap方法是一个包装器,里面封装了一个生成器

那么理解了关键的两个函数mark和wrap,大概就知道wrap里面的参数中的匿名函数什么时候执行

a 使用next方法每次调用生成器,进入生成器i._invoke

b 生成器内部调用u函数,最后使用call方法调用匿名函数

c 在匿名函数中每个case的结尾都会定义下一次执行的case

最后推测h5st参数是在匿名函数中case0位置生成,但是在case0代码块并没有发现拼接h5st参数的位置,而关键点是在window.ParamsSign这个类中,关键的加密逻辑都在里面

最终的生成结果会在s对象的PromiseResult属性中,这也是很坑的,很容易看不到导致跟丢了参数;

就可以回答开始提出的问题,在case20处可以看到h5st的结果,case处没有找到拼接h5st处的地

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【浪潮商城-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 1. 暴力破解密码,造成用户信息泄露 2. 短信盗刷的安全问题,影响业务及导致用户投诉 3. 带来经济损失,尤其是后付费客户,风险巨大,造…

openGauss数据库-头歌实验1-5 修改数据库

一、查看表结构与修改表名 (一)任务描述 本关任务:修改表名,并能顺利查询到修改后表的结构。 (二)相关知识 为了完成本关任务,你需要掌握: 1.如何查看表的结构; 2.如…

linux 磁盘配额 quota

增加一个facl的的知识点: linux中默认的文件系统支持facl,如果是新挂载的分区,则不支持facl应用。需要在挂载文件系统时使用-o acl选项来启用facl支持。如下图显示 在/etc/fstab添加defaults,acl 1.启用磁盘配额功能:修改/etc/f…

进程和线程概念

进程 进程是系统进程资源分配和调度的一个独立单位。 进程的状态与转换 就绪 -> 阻塞 -> 执行 另外还有一个挂起操作,可将进程转入静止状态,知道激活操作,程序将恢复原有状态。 线程 线程更加轻量,作为调度和分派的基本…

三周精通FastAPI:27 使用使用SQLModel操作SQL (关系型) 数据库

官网文档:https://fastapi.tiangolo.com/zh/tutorial/sql-databases/ SQL (关系型) 数据库 FastAPI不需要你使用SQL(关系型)数据库。 但是您可以使用任何您想要的关系型数据库。 这里我们将看到一个使用SQLModel的示例。 SQLModel是在SQLAlchemy和Pydantic的基础…

Java 并发编程学习笔记

参考资料: JAVA并发专题 - 终有救赎的专栏 - 掘金 Java并发编程学习路线(建议收藏��) | Java程序员进阶之路x沉默王二 面试题目: JUC第一讲:Java并发知识体系详解 面试题汇总(P6熟练 P7精通…

Docker篇(基础命令)

目录 一、启动与停止 二、镜像相关的命令 1. 查看镜像 2. 搜索镜像 3. 拉取镜像 4. 删除镜像 三、容器创建与启动容器 1. 查看容器 2. 创建容器 交互式方式创建容器 守护式方式创建容器 3. 容器启动与停止 四、容器操作命令 1. 文件拷贝 2. 目录(文件…

qt QColorDialog详解

1、概述 QColorDialog是Qt框架中的一个对话框类,专门用于让用户选择颜色。它提供了一个标准的颜色选择界面,其中包括基本的颜色选择器(如调色板和颜色轮)、自定义颜色输入区域以及预定义颜色列表。QColorDialog支持RGB、HSV和十六…

算法练习:904. 水果成篮

题目链接:904. 水果成篮。 题目意思就是可以选取两个种类的水果不能超过两个种类,该种类个数没有限制, 但是一旦超过两个种类的水果就要停止计数。 示例中数组编号就是就是种类,就是不能出现三个不同编号的数。 1.暴力解法&…

JAVA WEB — HTML CSS 入门学习

本文为JAVAWEB 关于HTML 的基础学习 一 概述 HTML 超文本标记语言 超文本 超越文本的限制 比普通文本更强大 除了文字信息 还可以存储图片 音频 视频等标记语言 由标签构成的语言HTML标签都是预定义的 HTML直接在浏览器中运行 在浏览器解析 CSS 是一种用来表现HTML或XML等文…

深度学习:卷积神经网络中的im2col

im2col 是一种在卷积神经网络(CNN)中常用的技术,用于将输入图像数据转换为适合卷积操作的矩阵形式。通过这种转换,卷积操作可以被高效地实现为矩阵乘法,从而加速计算。 在传统的卷积操作中,卷积核&#xff…

【论文阅读】Associative Alignment for Few-shot Image Classification

用于小样本图像分类的关联对齐 引用:Afrasiyabi A, Lalonde J F, Gagn C. Associative alignment for few-shot image classification[C]//Computer Vision–ECCV 2020: 16th European Conference, Glasgow, UK, August 23–28, 2020, Proceedings, Part V 16. Spri…

HCIP-HarmonyOS Application Developer V1.0 笔记(五)

弹窗功能 prompt模块来调用系统弹窗API进行弹窗制作。 当前支持3种弹窗API,分别为: 文本弹窗,prompt.showToast;对话框,prompt.showDialog;操作菜单,prompt.showActionMenu。 要使用弹窗功能&…

【办公类-04-04】华为助手导出照片视频分类(根据图片、视频的文件名日期导入“年-月-日”文件夹中,并转移到“年-月”文件中整理、转移到“年”文件夹中整理)

背景需求 最近带班,没有时间整理照片,偶尔导一次,几个月的照片。发现用电脑版“华为手机助手“中的WLAN连接”与华为手机的“华为手机助手”连接,速度更快、更稳定,不会出现数据线连接时碰碰就断网的问题 1、先打开电…

人工智能技术:未来生活的“魔法师”

想象一下,未来的某一天,你醒来时,智能助手已经为你准备好了早餐,你的智能家居系统根据你的心情和日程安排调整了室内的光线和音乐,而你的自动驾驶汽车已经在门口等你。这不是科幻小说,这是人工智能技术为我…

Golang | Leetcode Golang题解之第538题把二叉搜索树转换为累加树

题目: 题解: func getSuccessor(node *TreeNode) *TreeNode {succ : node.Rightfor succ.Left ! nil && succ.Left ! node {succ succ.Left}return succ }func convertBST(root *TreeNode) *TreeNode {sum : 0node : rootfor node ! nil {if n…

信号带宽和上升沿的关系:【图文讲解】

目录 1:什么是信号带宽 2:带宽计算公式 3:实际应用 这里讨论的信号,是指数字信号,默认为方波信号。 方波是一种非正弦曲线的波形,具有明确的“高”和“低”两个电平值,且占空比(…

大数据新视界 -- 大数据大厂之 Impala 性能优化:从数据压缩到分析加速(下)(8/30)

💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

SpringAI QuickStart

Spring AI 官方文档:Spring AI Spring AI 是一个面向 AI 工程的应用框架,其目标是将 Spring 生态系统的可移植性和模块化设计等设计原则应用到AI 领域,并推动将 POJO 作为应用的构建块应用于 AI 领域。 其特点是跨 AI 供应商支持的便携式 A…