首页 > 其他分享 >JS逆向实战3——AESCBC 模式解密

JS逆向实战3——AESCBC 模式解密

时间:2022-08-29 13:00:23浏览次数:58  
标签:decrypted AESCBC self 解密 js JS str sign data

爬取某省公共资源交易中心

通过抓包数据可知

这个data是我们所需要的数据,但是已经通过加密隐藏起来了

分析

  1. 首先这是个json文件,我们可以用请求参数一个一个搜
    但是由于我们已经知道了这是个json
    所以我们可以直接偷个懒
  2. 直接搜索json.parse


然后还看见了state 刚好也是返回的值

3. 根据上述请求参数我们看见了ts是一个时间戳,
然后往周围找找

所以可以判断这是个AES加密

基本这个函数就是AES加密的,我们把代码抠出来就能直接运行了,但是抠出来之后发现
这就是个常规AES加密,所以我们直接通过python改写

Python代码

# -*- coding: utf-8 -*-
# @Time    : 2022/7/13 16:39
# @Author  : lzc
# @Email   : [email protected]
# @File    : FuJianPublicResourceCenter.py
# @Software: PyCharm
import base64
import datetime
import hashlib
import json
import time
import requests
from Cryptodome.Cipher import AES



class PublicResourceCenter:

    item = {}
    session = requests.session()

    list_url = '(为保证网站安全性)'

    detail_post_url = "(为保证网站安全性)"

    API = APIInvoke()

    secret_key = 'BE45D593014E4A4EB4449737660876CE'[0:32]  # 密钥

    iv = "A8909931867B0425"[0:16]  # 初始向量

    # 需要补位,str不是16的倍数那就补足为16的倍数
    def add_to_16(self, value):
        while len(value) % 16 != 0:
            value += '\0'
        return str.encode(value)

    # 解密方法
    def aes_decrypt(self, key, t, iv):
        aes = AES.new(self.add_to_16(key), AES.MODE_CBC, self.add_to_16(iv))  # 初始化加密器
        base64_decrypted = base64.decodebytes(t.encode(encoding='utf-8'))  # 优先逆向解密 base64 成 bytes
        decrypted_text = str(aes.decrypt(base64_decrypted), encoding='utf-8').replace('\0', '')  # 执行解密密并转码返回str
        return decrypted_text

    def less_data(self, less_data):
        now = datetime.datetime.now()
        # 在获取超过当前时间30天的时间
        delta = datetime.timedelta(days=less_data)
        n_days = now - delta
        return str(n_days).split(' ')[0]

    def get_sign_data(self, sign):
        # md5 加密
        portal_sign = hashlib.md5(sign.encode(encoding='utf-8')).hexdigest()

        return portal_sign

    def timestamp(self, shijian):
        s_t = time.strptime(shijian, "%Y-%m-%d %H:%M:%S")
        mkt = int(time.mktime(s_t))
        return mkt

    def parse(self):
        padding = lambda detail_decrypted_str: detail_decrypted_str[:detail_decrypted_str.rfind("}") + 1]

        for url in range(1, 6):
            ts = int(time.time() * 1000)
            # 封装请求体
            js_data = {"pageNo": url, "pageSize": 20, "total": 5679, "AREACODE": "", "M_PROJECT_TYPE": "",
                       "KIND": "GCJS",
                       "GGTYPE": "1", "PROTYPE": "", "timeType": "6", "BeginTime": f"{self.less_data(180)} 00:00:00",
                       "EndTime": f"{self.less_data(0)} 23:59:59", "createTime": [], "ts": ts}
            # 伪装sign
            sign = f'3637CB36B2E54A72A7002978D0506CDFBeginTime{js_data["BeginTime"]}createTime[]EndTime{js_data["EndTime"]}GGTYPE{js_data["GGTYPE"]}KIND{js_data["KIND"]}pageNo{js_data["pageNo"]}pageSize{js_data["pageSize"]}timeType{js_data["timeType"]}total{js_data["total"]}ts{js_data["ts"]}'
            # 执行公用的方法  返回值是未经过加密的 数据
            encrypted_str = self.encrypted_str_get(self.list_url, js_data, sign)
            # 执行AES解密的方法 把 key 和IV 传入
            decrypted_str = self.aes_decrypt(self.secret_key, encrypted_str, self.iv)
            js_text = json.loads(padding(decrypted_str))
            for data in js_text['Table']:
                self.item['title_name'] = data['NAME'].replace("<br>", "")
                self.item['title_date'] = data.get('TM')
                self.item[
                    'title_url'] = f"https://ggzyfw.fujian.gov.cn/web/index.html#/business/detail?cid={data['M_ID']}&type={data['KIND']}"
                if self.item['title_date'] is None:
                    self.item['title_date'] = time.strftime('%Y-%m-%d %H:%M:%S')
                # 封装请求体
                # 1657709230
                # 执行js代码
                payload = {"m_id": data['M_ID'], "type": data['GGTYPE'], "ts": int(time.time() * 1000)}
                # 伪装详情页的sign sign = "3637CB36B2E54A72A7002978D0506CDFm_id216262ts1657708358505type1"
                detail_sign = f"3637CB36B2E54A72A7002978D0506CDFm_id{payload['m_id']}ts{payload['ts']}type{payload['type']}"
                # 执行公用的方法  返回值是未经过加密的 数据
                encrypted_str = self.encrypted_str_get(self.detail_post_url, payload, detail_sign)
                # 执行AES解密的方法 把 key 和IV 传入
                detail_decrypted_str = self.aes_decrypt(self.secret_key, encrypted_str, self.iv)
                content_html = json.loads(padding(detail_decrypted_str))
                self.item['content_html'] = content_html.get("Contents", "")
                self.API.data_update(self.item)
        self.close()

    def encrypted_str_get(self, url, js_data, sign):
        portal_sign = self.get_sign_data(sign)
        headers = {
            'portal-sign': portal_sign,
            'Content-Type': 'application/json;charset=UTF-8',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                          'Chrome/103.0.0.0 Safari/537.36',
        }

        response = self.session.post(url, headers=headers, json=js_data)

        encrypted_str = response.json()

        return encrypted_str['Data']

    def close(self):
        self.session.close()


if __name__ == '__main__':
    pr = PublicResourceCenter()
    pr.parse()


标签:decrypted,AESCBC,self,解密,js,JS,str,sign,data
From: https://www.cnblogs.com/zichliang/p/16635595.html

相关文章

  • vue+elementUI+sortablejs --- el-table列表拖拽
    前言:最近很多需求都与拖拽有关,一般拖拽用的都是 vuedraggable 但是要是在el-table列表里面拖拽当用vuedraggable去包裹table列表包外层只能拖动整个列表包里面数......
  • C# webApi接受JSON格式参数
    [HttpPost]publicstringTestData(){try{//接收post传入的数据varrequest......
  • JS逆向实战2--cookie-AcwScV2加密—某招标信息网
    cookies的获取首先拿到第一次访问原链接拿到acw_tc的值,然后放到session中去再用这个session再次访问原链接拿到js加载的加密的真实数据。用了一些反混淆。最后获取这......
  • vue项目mixin.js的使用及注意详解
     简单的介绍下mixin(混入):官方介绍:混入(mixin)提供了一种非常灵活的方式,来分发Vue组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有......
  • identity4 系列————纯js客户端案例篇[四]
    前言前面已经解释了两个案例了,通信原理其实已经很清楚了,那么纯js客户端是怎么处理的呢?正文直接贴例子哈。https://github.com/IdentityServer/IdentityServer4/tree/ma......
  • js 判断 数字数组 是否 连续
    预期[1,2,3,4,5]=>true[1,2,3,5,6]=>false代码//判断一串数字是否是连续的constisContinuityNum=(num:number[]|number)=>{letarray=[];if(num......
  • stream.sum List和json互转
    原文链接:https://blog.csdn.net/fighting_xuan/article/details/112609463https://blog.csdn.net/weixin_49186526/article/details/116098255//这两部分效果相同mo......
  • 如何在 React JS 中隐藏网站源代码?
    如何在ReactJS中隐藏网站源代码?“成长的关键是将更高维度的意识引入我们的意识。”老子最近我在使用React进行开发时遇到的问题是,当我打开控制台进行检查时,我导......
  • [Typescript] Step1 & 2 for converting a js app to ts
    1.Compilingin"loosemode"StartwithalltestspassingRenameall.jsto.ts,allowingimplicitanyFixonlythingsthatarenottype-checking,orcausing......
  • JMeter 后置处理器之JSON提取器
    后置处理器之JSON提取器By:授客QQ:1033553122测试环境JMeter5.4.1插件介绍JSON后置处理器(PostProcessor)允许使用JSONPath语法从JSON格式的响应中提取数据。类似正......