爬虫记录——第三方钱包加密参数逆向

情景:

某平台支付订单时,采用抢单模式:同一个商品可被多个人下单,先付款成功者,才可获得商品。该平台对接了第三方钱包负责用户的支付功能。
需求:

新的抢单模式,导致曾经实现简单地对平台商品进行锁单的功能,不再满足对平台商品进行抢购的要求,需要实现下单后的余额支付功能。
问题分解:

1):获取支付链接(得到请求参数uuid与mer_cust_id)

2):确定所需请求

3):逆向请求中的加密参数
一:获取支付链接(简略,各网站不同)

点击平台订单界面的立即支付后,跳转到第三方钱包支付界面

将这一过程通过浏览器自带的开发者工具进行抓包,找到会话发起请求

通过python模拟请求,查看返回数据,发现支付链接

复制代码
def pay(self, o_id):
    data = {
        "id": o_id,
        "pay_type": "140",
        "return_url": "https://h5.XXX.XXX/#/pages/userCenter/orderDetail?order_id={}".format(o_id),
        "timestamp": self.s_t()
    }
    self.h['x-token'] = self.my_md5(self.s10_format(o_id))
    r = requests.post("https://pay.XXX.XXX/pay/order/submit",data=json.dumps(data), headers=self.h)
    print(r.text)
    url = json.loads(r.text)['data']
# {"code":1,"msg":"发起支付","time":"17093XXXXX","data":"https:\/\/hfpay.cloudpnr.com\/h5\/pages\/cashier\/index?uuid=hfpwallet6666000137XXXpay84ddcd15-9033-4e42-8163-0c128223603e","test":0} 

二:请求分析

通过手动支付,记录该过程中出现的各请求,经过测试发现必要请求如下:

1):支付密码检验

复制代码
data ={
    "password": Triple DES生成的以等号结尾的12位密文;
}
h = {"Content-Type":"application/json", "Uuid": hfpwallet6666000137XXXpay84ddcd15-9033-4e42-8163-0c128223603e, "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36", 'check_value': hmac_sha256生成的64位密文, 'mer_cust_id': '6666000137XXX', 'Hide_head': '0'}
r = requests.post("https://hfpay.cloudpnr.com/api/hfpwalleth5/transpasswordcheck", data=json.dumps(data), headers=h)

2):状态确定?

复制代码
data = {
    "trans_type": "30",
    "dev_info_json": '{"devType":"2","devSysType":"H5","mobileFlag":"Y"}'
}
r = requests.post("https://hfpay.cloudpnr.com/api/hfpwalleth5/transverifyquery", data=json.dumps(data), headers=h)

3):支付

复制代码
data = {
  "dev_info_json": '{"devType":"2","devSysType":"H5","mobileFlag":"Y"}'
}
r = requests.post("https://hfpay.cloudpnr.com/api/hfpwalleth5/balancepay", data=json.dumps(data), headers=h)

PS:对于单个用户而言,虽然该钱包的支付过程采用了加密算法,请求需携带加密参数check_value,支付密码加密过程所需参数uuid中pay之后的内容会发生变化,然而每次check_value与password的值都是固定的,造成这一结果的原因在下文加密参数逆向中进行了推测

三:加密参数逆向

1):password

以支付密码检验为例,通过开发者工具对该请求的调用堆栈进行分析,发现其中有个匿名函数对传入的明文密码111111进行了加密并赋值给了password

跟栈进入,打上断点进行调试

显然发现其调用了TripleDES进行加密,key为uuid,iv为chinapnr,mode为CBC,pad为pkcs7

使用python进行算法模拟,发现直接传入uuid报错ValueError: Invalid triple DES key size. Key must be either 16 or 24 bytes long,后查询发现其解决办法为直接截断选择前24位。

又根据使用该处理办法之后的python模拟结果正确以及多次请求中相同密码明文的密文不变,故推测js的TripleDES加密算法也采用了此处理办法,而调用的时候似乎忽略了这一问题。

所以每次pay之后生成的随机字符串就这样被截断,不参与加密过程,其密文对于各用户而言也就不变(笑

下附python模拟代码

复制代码
import pyDes
# 定义密钥,长度必须为8个字符(64位)
key = 'hfpwalletXXXpayf92b7651-0007-45f8-95b8-4517e7cdb47d'
# 定义初始化向量,长度为8个字符(64位)
iv = b'chinapnr'
# 创建加密器
k = pyDes.triple_des('hfpwalletXXX', pyDes.CBC, iv, pad=None, padmode=pyDes.PAD_PKCS5)
# 要加密的明文
data = '111111'
# 加密
cipher_text = k.encrypt(data)
# 解密
plain_text = k.decrypt(cipher_text)
import base64
print('加密前的明文:', data)
print('加密后的密文:', base64.b64encode(cipher_text).decode() )
print('解密后的明文:', plain_text)

参考:https://www.jianshu.com/p/1a0dde3f1b57

2):check_value

步骤如下:

通过开发者工具进行搜索很明显地发现check_value参数由aes加密算法得到,key为固定的chinapnr

在该步骤打上断点之后,再次手动进行支付,以支付密码检验请求为例

发现明文为{password: 'oO4Ruxbd1X8='},其中oO4Ruxbd1X8=为明文支付密码111111的加密密文,假定明文为请求载荷,即post请求中所携带的data数据

跟栈进入,发现所采用的为hmac_sha256算法加密,通过控制台输出本次的加密结果进行后续验证

通过python进行算法模拟

复制代码
import hmac
import hashlib
def hmac_sha256(key, message):
    return hmac.new(key.encode('utf-8'), message.encode('utf-8'),
                    hashlib.sha256).hexdigest()

print(hmac_sha256("chinapnr","password=oO4Ruxbd1X8="))
#e24378626f029eb351656b637d7991fc5fb853db749c6b9c9e69ecc0a1ab2087

通过对后续请求调用该函数时传入的参数进行对照确定,明文为请求载荷。

至此,加密参数分析完毕,整个需求也实现完毕。

相关推荐
zzzzzz3101 天前
当产品经理说这个很简单:我用Python自动化处理奇葩需求的实战指南
python·pycharm·产品经理
雪隐1 天前
个人电脑玩AI-06让5060 Ti给你打工——不光能画画,Qwen3-TTS还能学人说话,连我老板都信了!
人工智能·后端·python
兵慌码乱1 天前
面向桌面端的资产管理系统分层架构设计与核心模块实现
python·系统架构·sqlite·pyqt5·数据库设计·桌面应用开发·mvc架构
hboot2 天前
AI工程师第三课 - 机器学习基础
python·scikit-learn·kaggle
顾林海2 天前
Agent入门阶段-编程基础-Python:流程控制
python·agent·ai编程
呱呱复呱呱2 天前
Django CBV 源码解读:一个请求是怎么找到你的 get() 方法的
python·django
Caco_D2 天前
一行代码抓遍全网 20 个热榜!Aneiang.Pa 4.0 发布 — 极简 .NET 爬虫库
爬虫·.net
曲幽2 天前
刚部署的 LibreTranslate 频频翻车?我掏出了 20 年前的 StarDict 词典,用 FastAPI 搭了个本地词典翻译 API
python·fastapi·web·translate·goldendict·libretranslate·stardict·pystardict
荣码2 天前
用Streamlit给AI应用套个界面,10行代码出Web页面
java·python
兵慌码乱2 天前
基于Python+PyQt5+SQLite的药房管理系统实现:事务一致性与界面解耦全流程解析
python·sqlite·信号与槽·pyqt5·数据库设计·桌面应用开发·事务处理