当前位置: 首页 > news >正文

<span class=“js_title_inner“>哦豁,我又成功逆向了一个sign</span>

大家在写脚本的时候,经常会遇到突然冒出个加密参数,然后就卡壳了。

有的人瞬间就不知所措就放弃了,有的人愿意多花费半小时,就成功逆向出来了。

前两天群友找我写个APP的脚本,一开始都还挺顺利,后面遇到了个签名参数 sign ,今天花了点时间给他折腾出来了,讲一下思路,很多简单加密都可以参考。

这是个POST请求,格式大致如下:

url = "https://****/api/sendIntegral" body = { "phone": phone, "integral": integral, "token": token, "sign": "982e876fc19b5d497376aa04a64cbe51cd4bd52ee0ab11919bf89b94c0a523aa" }

从上面可以看出 sign 是一串长度64个字符的字符串,首先猜它是SHA256加密。为啥这样猜?仅凭那丁点经验!

再凭借一点经验,sign 是几个参数用 & 拼接,再用SHA256加密得到的。我做了类似以下的尝试:

#随便排序SHA256("phone=135***&integral=123&token=789")#按参数名的字母顺序排序SHA256("integral=123&phone=135***&token=789")

最终都得不到想要的结果,所以可能的原因有2个:一是加密算法不对;二是加密参数不对或顺序不对。

多次尝试后,我感觉是加密算法不对,应该是HmacSHA256 ,这个和 SHA256 不是一个东西,最直观的区别是差个密钥,其他区别自行查阅:

对比维度SHA256HmacSHA256
密钥需求

无需密钥,仅依赖输入数据

必须提供密钥,密钥是计算的核心要素

主要用途

数据完整性校验(如文件校验、密码存储哈希)

消息认证(验证数据完整性 + 发送者身份)

安全性

仅能确保数据未被篡改,无法验证来源

既能确保数据未被篡改,又能验证来源合法性

输出唯一性

相同输入必产生相同输出

相同输入 + 相同密钥才产生相同输出

假设我的判断是对的,我现在就需要个密钥才能计算sign值,要这个密钥抓包是不可能抓得到的,所以只能去从源码中去捞相关信息,APP逆向我不会。凑巧,它有小程序,所以转战反编译小程序。

关于反编译小程序,查看这篇文章 👉 微信小程序解包

解包完成后,只有以下内容:

大致翻一翻,可以确认功能都在 app-service.js 里。为啥?因为它体积最大

打开这个js文件,直接搜索我们要的那个POST请求的关键词sendIntegral找到以下相关代码块:

zhuanjifen: function () {var t = this;this.$u.test.number(this.jisuanResult2) ? this.jisuanResult2 <= 0 ? this.$u.toast("转赠数量必须大于0") : e.showModal({ title: "确认要向" + this.info1.phone + "转赠" + this.jisuanResult2 + "个积分吗?", success: function (n) {if (n.confirm) { e.showLoading({ title: "加载中...", mask: !0 });var o = {}; o.token = e.getStorageSync("token"), o.phone = t.info1.phone, o.integral = t.jisuanResult2, o.descs1 = t.dimensionInfo.entName + ",消费" + t.moneyjisuan + "元,抵扣" + t.dimensionInfo.bili + "%," + t.info1.phone, o.descs2 = t.dimensionInfo.entName + ",消费" + t.moneyjisuan + "元,抵扣" + t.dimensionInfo.bili + "%," + t.userinfo.phone, o.money = t.moneyjisuan, o.dimensionNo = t.dimensionInfo.dimensionNo, o.bili = t.dimensionInfo.bili;var i = {}; i.token = e.getStorageSync("token"), i.integral = o.integral;var a = (0, d.generateSign)(i, "yd9349"); o.sign = a, t.$u.api.sendIntegral(o).then((function (n) { e.hideLoading(),200 == n.code ? (t.getUserInfo(), e.showModal({ title: n.msg, showCancel: !1 })) : e.showModal({ title: n.msg, showCancel: !1 }) })) } } }) : this.$u.toast("转赠数量格式有误,请输入本次消费金额")

注意上面代码块中的第20-24行。第24行定义了我们所需要的sign(o.sign)。它来自于变量a ,看起来是个奇葩的语法,但我们明显看到了个字符串"yd9349",它就是加密的密钥,所以这个加密算法是HmacSHA256。对于不懂js的我也实在看不懂,但没事,有AI! AI告诉我的答案:

1. 语法解析:(0, d.generateSign)(o, "yd9349")外层括号 (0, d.generateSign):这是一个逗号表达式(comma operator),逗号表达式会按顺序执行多个操作,并返回最后一个操作的结果。这里 0 是一个无意义的占位值,真正有效的是d.generateSign,因此整个表达式的结果等价于 d.generateSign(即获取到 d 对象中的 generateSign 函数)。函数调用 (o, "yd9349"):通过逗号表达式获取到函数后,直接以普通函数的形式调用,传入参数 o 和 "yd9349"。 2. 为什么要这样写?核心目的:统一 this 指向。****(后面我也不会,不看了哈哈) 3. 等价写法这种写法等价于先将函数赋值给一个临时变量,再调用var tempFunc = d.generateSign; // 剥离函数与原对象的关联var s = tempFunc(o, "yd9349"); // 以普通函数形式调用,this 指向全局/undefined

从上面的答案我们知道了真正执行的函数是d.generateSign,参数为(i, "yd9349"),整理一下就是d.generateSign(i, "yd9349")。 参数i 很明显就是由token和integral组成的(21-23行)。

那现在就搜索generateSign,找到其函数定义:

generateSign: function (e, t) {var a = Object.keys(e).sort().map((function (t) {return "".concat(t, "=").concat(e[t]) })).join("&");return console.log("sortedParams", a), s.HmacSHA256(a, t).toString()}

以上代码块第一行的参数e 即对应参数i,参数t 即对应密钥“yd9349”。代码段的功能是:

1. 排序键名:["integral", "token"](按字母顺序)。

2. 拼接参数:"integral=100&token=abc123"。

3.生成签名:通过 HmacSHA256 算法,用密钥"yd9349"对"integral=100&token=abc123"加密,得到最终签名字符串。

至此,sign 的加密算法就逆向完了,跑下脚本测试成功~

写在最后:

这是收了茶水费的脚本,APP和脚本就不方便分享了,主要提供一个思路,我觉得可以适用于很多简单的加密场景。这次比较简单不需要用到调试,直接框框一顿搜就可以了。有时候你觉得自己不会就不研究了,以后你再遇到依然不会。多研究多了解一点,都是在积攒经验。这也只是我众多逆向尝试中的一次成功经验,很多也是失败的。我没学过逆向,也没时间沉下心学,全靠每次多折腾那么半小时的,行就行,不行再说吧~

- End -

更多精彩文章

点击下方名片关注【偶尔敲代码】

http://www.jsqmd.com/news/336213/

相关文章:

  • 背包专题 - 古代王国寻宝问题
  • 2026年数据拉通与集成服务靠谱公司推荐汇总 - 品牌2025
  • <span class=“js_title_inner“>一个免费远程控制电脑及手机的神器</span>
  • Typora软件/markdown语法快速入门
  • <span class=“js_title_inner“>Fairy Mobile GUI Agent——RGR、OCA、EMA的综合落地</span>
  • 富马酰化如何成为代谢与表观遗传调控的新枢纽?
  • <span class=“js_title_inner“>提示词软件危机——Agentic AI系统的工程化挑战</span>
  • <span class=“js_title_inner“>15年前,小沈阳一个晚上爆红年赚上亿,如今却“销声匿迹”?</span>
  • 【Linux 进程实战】C 语言实现父子进程协作:定时日志生成 + 自动清理系统(附完整可运行代码)
  • 2026年激光测距仪制造企业综合实力排名,哪家性价比高选哪家 - 工业设备
  • AIGC 应用工程师(3-5 年)面试题精讲:从基础到实战的系统备战清单
  • <span class=“js_title_inner“>如何破解3D“创作鸿沟”?元境携手北航的这场高峰论坛将揭晓路径!</span>
  • <span class=“js_title_inner“>【观察】走进“AI数智南研”,体验智慧园区新标杆</span>
  • Linux命令-look(在已排序的文件中查找以特定字符串开头的行)
  • <span class=“js_title_inner“>LLM4SE的2025:LLM 改变了写代码的方式,但还没改变软件工程</span>
  • <span class=“js_title_inner“>欢迎申报2025数智产品用户选型年度大奖</span>
  • 202560202
  • <span class=“js_title_inner“>幂等性的劣化:从数学确定性到AI不确定性的演进</span>
  • <span class=“js_title_inner“>AI Coding评测,到底谁在“裸泳”?</span>
  • 2026年知名的装修板材/家具定制板材热门品牌厂家推荐 - 行业平台推荐
  • 基于PHP、asp.net、java、Springboot、SSM、vue3的酒店客房系统的设计与实现
  • <span class=“js_title_inner“>Agentic AI系统性工程框架——RGR、OCA与EMA三位一体方法论</span>
  • <span class=“js_title_inner“>正式裁员64796人,赔偿N+4!</span>
  • <span class=“js_title_inner“>年终总结 | AI 正在光速进化,而我们还得在 2026 年的泥潭里挣扎</span>
  • 【Linux 封神之路】进程进阶实战:fork/vfork/exec 函数族 + 作业实现(含僵尸进程解决方案)
  • <span class=“js_title_inner“>年度好物大赏 | 2025年“把钱花在了刀刃上”的幸福瞬间</span>
  • <span class=“js_title_inner“>Qwen3-Coder: 在世界中自主编程</span>
  • NestJS 路由顺序问题解除指南
  • 2026固生堂看病贵不贵真实反馈:药材与处方影响解析 - 品牌排行榜
  • 2026年口碑好的ELITE 700型X荧光分析仪/钢铁行业荧光分析仪厂家推荐与采购指南 - 行业平台推荐