Python还原CryptoJs_AES_CBC模式_js逆向学习

一、前言
1、Redeme
  • 如果对AES加密解密了解的话,可以跳过目录二,直接看目录三目录四实例操作;
  • 本博文主要是对js里面CryptoJS进行逆向,并用python进行还原实现,只用于js逆向交流学习
二、对称加密解密AES
1、对称加密与非对称加密
  • 对称加密:加密和解密时使用同一个密钥,加密速度非常快,适合经常发送数据的场合;缺点是密钥的传输比较麻烦;
加密_密钥K
解密_密钥K
明文
密文
  • 非对称加密:加密和解密时使用不同密钥,是用数学上的难解问题构造的,通常加密解密的速度比较慢,适合偶尔发送数据的场合,优点是密钥传输方便;常见的非对称加密算法为RSA、ECC和EIGamal;
加密_密钥A _公钥
解密_密钥B_私钥
明文
密文
2、AES对称加密介绍
  • AES(Advanced Encryption Standard),是美国联邦政府采用的一种高级加密标准,这个标准用来替代原先的DES,也是最常见的对称加密算法;
  • AES只有一个密钥key,其加密与解密需要双方确定好key,且密钥key 长度必须为16(AES-128)、24(AES-192)、或32(AES-256)Bytes 长度,分别对应了不同的算法;
  • 密钥越长,安全性越高,但加解密花费时间也越长,默认的是16字节(AES-128),其安全性完全够用;
  • AES只是个基本算法,实现AES有几种模式,主要有ECB、CBC、CFB、OFB、CTR:
3、实现AES的4种模式
  • ECB模式(电子密码本模式:Electronic codebook):ECB是最简单的块密码加密模式,加密前根据加密块大小(如AES为128位)分成若干块,之后将每块使用相同的密钥单独加密,解密同理
  • CBC模式(密码分组链接:Cipher-block chaining):CBC模式对于每个待加密的密码块在加密前会先与前一个密码块的密文异或然后再用加密器加密。第一个明文块与一个叫初始化向量的数据块异或
  • CFB模式(密文反馈:Cipher feedback):与ECB和CBC模式只能够加密块数据不同,CFB能够将块密文(Block Cipher)转换为流密文(Stream Cipher)
  • OFB模式(输出反馈:Output feedback):OFB是先用块加密器生成密钥流(Keystream),然后再将密钥流与明文流异或得到密文流,解密是先用块加密器生成密钥流,再将密钥流与密文流异或得到明文,由于异或操作的对称性所以加密和解密的流程是完全一样的
三、网站案例分析
1、准备工作
  • 网址源:由于只是用于学习记录,网址源就不提供了
  • chrome浏览器开发者工具分析
2、分析js流程步骤
  • (1) 网站描述:每次翻页的post请求参数与响应页都已加密, 如下图,那咱们今天就是如何看前端是如何用js加密解密?
    在这里插入图片描述
    在这里插入图片描述
  • (2)调试入口:如果通过全局搜索找不到加密,可以通过Initiator(我理解为js的调用栈,越下面是js脚本调用的最初,最上面是末尾),尝试从其中一个调用栈点击去加断点,然后翻页debugger查看js是如何运行的
    在这里插入图片描述
  • (3)开始调试:点进去后,左下角花括号格式化下{}, 在定义变量的位置加个断点,如果直接在点击去的位置加断点,翻页可能无法中断;然后翻页,会在断点处中断;接着调试,隐约觉得a这个参数是原始请求的post参数,接着继续调试;注意:右上角几个都是调试的,如果一直死循环卡在某个函数调试中,记得点击向上的箭头跳出函数(可连续点多次)
    在这里插入图片描述
  • (4)加密函数的发现:就这么debug下去,终于发现了加密的关键函数,经过加密后e.data就是加密后的请求参数,在这里先加个断点,然后我们继续往下调试,稍后再研究这个函数内部调用的是什么~
    e.data = o.default.aes_encrypt(JSON.stringify(l))
    
    在这里插入图片描述
  • (5)解密函数的发现:当调试到这里的时候,我发现响应内容被解密了,这个e.data就是解密后的内容;
    e.data = o.default.aes_decrypt(e.data)
    
    在这里插入图片描述
  • (6)接下来我们来看具体内部加密解密是怎么执行的,接着调试调试,其实js加密解密是用了AES的CBC模式加密,采用Pkcs7填充,在这个调试中,你需要通过调试去找密钥key和偏移量,然后就可以还原js函数了
    在这里插入图片描述
3、本地运行前端抠出来的CryptoJS脚本
  • 前端定义的n其实就是CryptoJS我并没有直接复制,而是通过本地的node直接导入CryptoJS库,此时只需要将关键代码扣出来即可;
  • 本地需安装node环境,然后再安装crypto-js库: npm install crypto-js
  • 重要参数:key是密钥;iv是密钥偏移量;未指定模式默认CBC模式;padding是用来填充数据的;
    var CryptoJS = require("crypto-js");
    var encrypt_req = function(e, l) {
        return e = CryptoJS.enc.Utf8.parse(e),
        l = CryptoJS.enc.Utf8.parse(l),
        CryptoJS.AES.encrypt(l, e, {
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7,
            iv: e
        }).toString()
    }
    
    var decrypt_req = function(e, l) {
        e = CryptoJS.enc.Utf8.parse(e);
        var a = CryptoJS.AES.decrypt(l, e, {
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7,
            iv: e
        });
        return CryptoJS.enc.Utf8.stringify(a).toString()
    }
    // CBC模式加密
    console.log(encrypt_req("8c18266c4e8fa5de", '{"Type":0,"page":3,"expire":1596461032894}'));
    // CBC模式解密
    console.log(decrypt_req("8c18266c4e8fa5de", '7zHGSW218ARpzbHHsA90NuWHufnCLJo94vGad3zzkANQ3sFIWhHY6pDLzelv9XUO'));
    
四、通过Python还原CryptoJS
1、AES_CBC模式参数
  • key:加密的时候用秘钥,解密的时候需要同样的秘钥才能解出来,必须是16位字节或者24位字节或者32位字节
  • 字符串:加密或解密的参数,字节长度需要是16位的倍数
  • 模式:aes 加密常用的有 ECB 和 CBC 模式等
  • iv:偏移量 ,这个参数在 ECB 模式下不需要,在 CBC 模式下需要。
2、Python模拟上面的CryptoJS脚本
  • python调用js三种方式:要么还原js;要么通过execjs脚本执行,要么通过node布服务执行;
  • python安装Cryptojs的库:pip install pycryptodome
from Crypto.Cipher import AES
import base64
from Crypto.Util.Padding import pad
import json


def aes_cbc_encrypt_text(decrypt_text: str, key: str, iv: str) -> str:
    """
    加密AES_CBC的明文
    :param decrypt_text: 明文
    :param key: 密钥
    :param iv: 密钥偏移量
    :return: 密文
    """
    aes2 = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv.encode('utf-8'))
    encrypt_text = aes2.encrypt(pad(decrypt_text.encode('utf-8'), AES.block_size, style='pkcs7'))
    encrypt_text = str(base64.encodebytes(encrypt_text), encoding='utf-8').replace("\n", "")
    return encrypt_text


def aes_cbc_decrypt_js_text(encrypt_text: str, key: str, iv: str) -> str:
    """
    解密AES_CBC的密文
    :param encrypt_text: 密文
    :param key: 密钥
    :param iv: 密钥偏移量
    :return:解密后的数据
    example_url_learn_js_base64: aHR0cDovL2NyZWRpdC5jdXN0b21zLmdvdi5jbi8=
    """
    decode_encrypt_text = base64.b64decode(encrypt_text)
    # 初始化AES对象时传入与加密时的相同的密钥、加密模式和iv
    aes2 = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv.encode('utf-8'))
    decrypt_text = aes2.decrypt(decode_encrypt_text).decode('utf8')
    decrypt_text = decrypt_text.replace(b'\x00'.decode(), "").replace("", "")
    return decrypt_text


"""由于只是用于学习,原网站的key和iv我已保密, 以下脚本并不能直接运行"""
# AES_CBC加密模式
decrypt_str = '{"Type":0,"page":3,"expire":1596461032894}'
key_str = "55****"
iv_str = "55****"
encrypt_str = aes_cbc_encrypt_text(decrypt_str, key_str, iv_str)
print(encrypt_str)

# AES_CBC解密模式
encrypt_str = "待解密字符串, 需自己替换,为保证原网站安全,暂不放"
key_str = "0a1******"
iv_str = "0a1******"
decrypt_str = aes_cbc_decrypt_js_text(encrypt_str, key_str, iv_str)
print(json.loads(decrypt_str)['list'])
  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值