发布时间:2026/7/21 10:45:17
网页加密逆向分析:Python脚本实现AES/DES/RSA算法调试与解密 1. 项目概述为什么我们需要一个“万能”的加密调试脚本在Web安全、爬虫开发或者日常的逆向分析工作中我们经常会遇到一个令人头疼的“黑盒”网页前端的数据加密。你打开浏览器的开发者工具看到网络请求里提交的是一串毫无意义的密文比如dataU2FsdGVkX1...或者sign7a8f9b0c1d...。你知道这背后可能是AES、DES、RSA或者是它们与Base64、Hex编码的组合但具体是哪种算法、什么模式、填充方式、密钥和初始向量IV是什么往往需要花费大量时间去猜测、验证和调试。传统的做法是什么通常是“三板斧”第一在浏览器控制台里下断点追踪JavaScript的加密函数调用栈试图找到核心的加密库或代码片段第二将找到的代码片段复制出来在Node.js或本地环境中尝试复现第三如果代码被混淆或难以直接提取就需要手动模拟其逻辑或者使用更底层的工具去Hook。这个过程不仅耗时而且极易出错一个参数不对比如CBC模式忘了IV或者PKCS7填充理解有误就会导致整个解密失败。这个名为“逆向分析不求人一个脚本搞定AES/DES/RSA等常见网页加密算法调试”的项目其核心价值就在于提供一个一体化的、可交互的调试环境。它不是一个简单的加解密库调用封装而是一个集成了算法识别、参数提取、实时调试和结果验证的“瑞士军刀”。想象一下你不再需要反复在多个工具和代码片段之间切换而是有一个统一的界面可以快速输入密文、尝试不同的算法组合、动态调整密钥和参数并立即看到解密结果或加密输出。这对于逆向工程师、安全研究员和需要处理加密接口的开发者来说能极大提升工作效率把精力从繁琐的调试过程转移到核心的逻辑分析上。2. 脚本核心设计与架构思路2.1 设计目标与核心功能拆解这个脚本的设计首要目标是降低调试门槛和提升分析效率。因此它的功能模块必须围绕“常见”和“调试”这两个关键词来构建。核心功能模块包括算法支持库这是基石。必须完整支持对称加密AES、DES、3DES、非对称加密RSA以及常见的编码Base64、Hex。对于每种算法需要支持其主流的工作模式和填充方式。例如AES需支持 ECB、CBC、CFB、OFB、CTR 等模式以及 PKCS7、ZeroPadding 等填充。DES同样支持 ECB、CBC 等模式。RSA需支持 PKCS1_v1_5 和 OAEP 填充并能处理公钥加密/私钥解密、私钥签名/公钥验签等场景。智能参数推断与尝试模块这是“智能”的体现。给定一段密文和可能的明文或已知的加密特征脚本应能自动尝试一些常见的组合。例如先尝试 Base64 解码如果失败则尝试 Hex 解码对于对称加密尝试常见的密钥长度AES-128/192/256 DES-56对于 RSA尝试解析常见的 PEM 或 DER 格式密钥。交互式调试控制台这是“调试”的核心。提供一个命令行或简易图形界面允许用户输入密文支持文件载入。选择或输入算法、模式、填充。输入密钥、IV 等参数。实时执行加密/解密操作并查看结果。方便地修改任意参数并重新执行形成调试闭环。上下文保存与对比功能在调试过程中用户可能会尝试多种组合。脚本应能保存不同的参数配置和对应的结果方便横向对比快速排除错误选项。2.2 技术选型为什么是 Python选择 Python 作为实现语言几乎是必然的。原因如下丰富的密码学库cryptography和pycryptodome是两个非常成熟且功能全面的库几乎涵盖了所有需要的加密算法和模式。cryptography更偏向于提供安全、高级的 API而pycryptodome则提供了更底层的控制两者结合使用能覆盖所有场景。强大的交互与胶水特性Python 可以轻松构建命令行交互界面使用argparse、click或cmd模块也可以集成简单的 GUI如tkinter。其快速的脚本化特性非常适合这种需要反复尝试、修改的调试工作。广泛的社区与生态在逆向分析和安全领域Python 是事实上的标准语言之一有大量的相关工具和代码片段可供参考和集成。注意虽然 JavaScript 也是网页加密的“原生”语言但在本地调试环境中Python 的库更稳定、功能更统一且更容易与系统其他工具链集成。我们脚本的目标是分析网页加密而不是在浏览器环境里执行它。2.3 整体工作流设计一个高效的调试脚本其工作流应该符合分析人员的直觉信息输入阶段用户提供“线索”。这可能是一段网络抓包得到的密文ciphertext一段已知的对应明文plaintext或者一个从网页中提取出的 JavaScript 加密函数片段。预处理阶段脚本自动对密文进行预处理尝试如 Base64/Hex 解码判断其二进制长度为后续算法猜测提供依据例如解码后长度为16字节的倍数很可能是AES CBC加密的数据块。算法猜测与尝试阶段基于输入和预处理信息脚本给出几种最可能的算法和参数组合建议。用户也可以手动选择。交互调试阶段用户在一个界面中设置算法类型、模式、填充、密钥、IV等所有参数。脚本执行操作并返回结果。用户可以实时修改任何参数比如把CBC换成ECB或者修改一个密钥字符并立即看到新结果。验证与输出阶段当解密结果变得可读例如出现了预期的JSON结构或明文文本脚本应能高亮显示成功。同时生成一份可复现的配置报告或代码片段如Python代码方便后续集成到爬虫或其他工具中。3. 核心模块详解与实现要点3.1 加密算法引擎的封装这是脚本最核心的部分必须做到既全面又灵活。我们以cryptography和pycryptodome为基础进行封装。# 示例一个统一的对称加密解密函数框架 from Crypto.Cipher import AES, DES from Crypto.Util.Padding import pad, unpad import base64 class SymmetricCryptoHelper: def __init__(self): self.supported_algorithms {AES: AES, DES: DES} self.supported_modes { ECB: None, # ECB模式不需要IV CBC: 需要IV, CFB: 需要IV, OFB: 需要IV, CTR: 需要nonce, # CTR模式使用nonce而非IV } def decrypt(self, algorithm, mode, ciphertext, key, ivNone, paddingPKCS7): 对称解密 :param algorithm: AES or DES :param mode: ECB, CBC, etc. :param ciphertext: bytes类型密文 :param key: bytes类型密钥 :param iv: bytes类型初始向量ECB模式为None :param padding: 填充方式 :return: bytes类型明文 # 1. 根据算法和模式创建cipher对象 cipher_class self.supported_algorithms.get(algorithm.upper()) if not cipher_class: raise ValueError(f不支持的算法: {algorithm}) if mode.upper() ECB: cipher cipher_class.new(key, cipher_class.MODE_ECB) elif mode.upper() CBC: if iv is None: raise ValueError(f{mode}模式需要IV参数) cipher cipher_class.new(key, cipher_class.MODE_CBC, iv) # ... 其他模式处理 else: raise ValueError(f不支持的模式: {mode}) # 2. 执行解密 decrypted_data cipher.decrypt(ciphertext) # 3. 去除填充 if padding.upper() PKCS7: # 注意PyCryptodome的unpad函数 decrypted_data unpad(decrypted_data, cipher_class.block_size) elif padding ZERO: # 处理ZeroPadding去除末尾的零字节 decrypted_data decrypted_data.rstrip(b\x00) # ... 其他填充处理 return decrypted_data def encrypt(self, algorithm, mode, plaintext, key, ivNone, paddingPKCS7): 对称加密逻辑与decrypt对称 # ... 实现填充和加密逻辑 pass实现要点与避坑指南数据格式统一内部处理全部使用bytes类型。所有字符串输入密钥、IV、密文都需要明确指定编码如.encode(utf-8)或进行解码如base64.b64decode。密钥长度管理AES 密钥必须是 16AES-128、24AES-192或 32AES-256字节。DES 密钥是 8 字节。脚本应能自动检查长度并给出提示或尝试补全/截断这是一个常见的调试点很多网页实现会使用字符串直接作为密钥可能长度不对。IV 的重要性对于 CBC、CFB 等模式IV 必须与密钥一起使用且每次加密最好使用随机 IV。在调试时IV 通常可以从网络请求或前端代码中找到有时是固定的有时是随密文一起传输比如Salted__开头的 OpenSSL 格式密文。我们的脚本需要能灵活处理 IV 的输入直接输入、从密文指定位置提取等。填充处理这是另一个高频错误点。PKCS7 是最常见的。要特别注意解密后调用unpad时如果填充不正确会直接抛出异常这本身就是一个重要的调试信号说明密钥或模式可能错了。3.2 RSA 加密的特殊处理RSA 的调试比对称加密更复杂因为它涉及密钥格式。from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_v1_5, PKCS1_OAEP class RSACryptoHelper: def __init__(self): pass def load_key(self, key_str, key_typeauto): 加载RSA密钥支持PEM和DER格式自动识别 :param key_str: 密钥字符串或字节 :param key_type: auto, pem, der, public, private if isinstance(key_str, str): key_str key_str.encode() try: # 尝试自动识别 key RSA.import_key(key_str) return key except (ValueError, IndexError, TypeError) as e: raise ValueError(f密钥加载失败: {e}。请检查密钥格式(PEM/DER)是否正确。) def decrypt_with_private(self, ciphertext, private_key, paddingPKCS1_v1_5): 使用私钥解密 ciphertext self._ensure_bytes(ciphertext) if padding PKCS1_v1_5: cipher PKCS1_v1_5.new(private_key) sentinel bDECRYPTION_FAILED # 用于判断解密是否成功 plaintext cipher.decrypt(ciphertext, sentinel) if plaintext sentinel: raise ValueError(解密失败可能是密钥不匹配或填充错误。) elif padding OAEP: cipher PKCS1_OAEP.new(private_key) plaintext cipher.decrypt(ciphertext) return plaintext def encrypt_with_public(self, plaintext, public_key, paddingPKCS1_v1_5): 使用公钥加密 # ... 类似实现 passRSA调试的独特挑战密钥格式网页中使用的 RSA 公钥可能以多种形式出现标准的 PEM 格式-----BEGIN PUBLIC KEY-----、裸的 Base64 编码的 DER 数据、甚至是以 JavaScript 对象形式存在的n和e参数。脚本需要具备强大的密钥解析和转换能力。填充方案PKCS1_v1_5较旧存在潜在风险但仍被大量使用。OAEP更安全。在调试时如果一种填充方式失败应立即尝试另一种。分段加密RSA 加密有长度限制。过长的明文需要先进行分段或者更常见的做法是用 RSA 加密一个随机的对称密钥再用该对称密钥加密实际数据。脚本需要能处理这种混合加密体系。3.3 交互式调试控制台的构建为了让脚本“好用”一个友好的交互界面至关重要。我们可以使用cmd模块构建一个简单的命令行循环或者用argparse构建一个参数丰富的命令行工具。这里展示一个简易的交互思路import json class CryptoDebuggerCLI: def __init__(self): self.sym_helper SymmetricCryptoHelper() self.rsa_helper RSACryptoHelper() self.current_context {} # 保存当前调试的所有参数 def start_interactive(self): print( 网页加密算法交互调试器 ) print(命令: set [参数] [值], try, reset, show, exit) while True: cmd input(\ndebug ).strip().split() if not cmd: continue if cmd[0] set: self._handle_set(cmd[1:]) elif cmd[0] try: self._try_decrypt() elif cmd[0] show: print(json.dumps(self.current_context, indent2, defaultstr)) elif cmd[0] reset: self.current_context {} print(上下文已重置。) elif cmd[0] exit: break def _handle_set(self, args): # 处理 set ciphertext base64 U2FsdGVkX19... # 处理 set algorithm AES # 处理 set mode CBC # 处理 set key mypassword # 处理 set iv 0000000000000000 # 处理 set padding PKCS7 pass def _try_decrypt(self): # 根据 current_context 中的参数调用相应的解密函数 # 并打印结果 try: algo self.current_context.get(algorithm, ).upper() if algo in [AES, DES]: # 调用对称解密 result self.sym_helper.decrypt(...) print(f[成功] 解密结果: {result.decode(utf-8, errorsignore)}) elif algo RSA: # 调用RSA解密 result self.rsa_helper.decrypt_with_private(...) print(f[成功] 解密结果: {result.decode(utf-8, errorsignore)}) except Exception as e: print(f[失败] 错误信息: {e}) # 这里可以加入更详细的错误分析比如提示“可能是IV错误”或“填充不匹配”这个简单的 CLI 允许用户一步步设置参数并随时执行尝试。更高级的版本可以加入历史记录、参数预设模板、自动从网络请求复制cURL命令并解析等功能。4. 实战调试流程与案例拆解让我们通过一个模拟的真实案例来演示如何使用这个脚本进行调试。场景你在分析一个登录请求发现提交的密码字段encryptedPassword是一个很长的 Base64 字符串。通过浏览器开发者工具你在一个名为crypto.js的文件中找到了疑似加密函数CryptoJS.AES.encrypt(password, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 })。4.1 第一步信息收集与初始化提取密文从网络请求中复制encryptedPassword的值例如U2FsdGVkX1WpqZQvRgBz3K4J8mH6qLtN0xYy7zA1c。提取参数算法很明显是 AES。模式CBC从代码中得知。填充Pkcs7。密钥 (key)和IV这是未知的。你需要进一步搜索。可能在同一个 JS 文件中定义为常量如const key CryptoJS.enc.Utf8.parse(1234567890123456);。也可能通过其他 API 动态获取。假设我们最终找到key是字符串mySecretKey12345iv是字符串initVector000000。启动调试脚本运行我们的crypto_debugger.py进入交互模式。4.2 第二步参数设置与初步尝试在调试器中我们逐步设置参数debug set algorithm AES debug set mode CBC debug set padding PKCS7 debug set ciphertext base64 U2FsdGVkX1WpqZQvRgBz3K4J8mH6qLtN0xYy7zA1c debug set key mySecretKey12345 debug set iv initVector000000 debug try [失败] 错误信息ValueError: Incorrect AES key length (15 bytes)脚本立即给出了错误反馈密钥长度不对。AES 密钥需要 16、24 或 32 字节。mySecretKey12345只有 15 个字符。这是一个非常典型的坑很多前端开发者直接用字符串做密钥而 CryptoJS 库内部会使用一个基于字符串的密钥派生函数如 OpenSSL 的EVP_BytesToKey而不是直接使用字符串的字节。4.3 第三步调整策略与深入分析我们需要知道 CryptoJS 是如何处理字符串密钥的。查阅资料或经验可知CryptoJS.AES.encrypt 在传递字符串密钥时实际上会使用一个加盐Salted的密钥派生过程并且密文开头会包含Salted__标识和盐值。我们看到的密文U2FsdGVkX1...正是这种格式的 Base64 编码。修改密文理解U2FsdGVkX1解码后的前8个字节就是Salted__。这意味着我们的脚本需要支持OpenSSL 兼容的密钥派生。更新脚本功能我们在SymmetricCryptoHelper中添加一个方法使用Crypto.Protocol.KDF.PBKDF2或EVP_BytesToKey算法结合从密文头部提取的“盐”来从字符串密码派生出真正的密钥和 IV。重新尝试这次我们不再直接设置key和iv而是设置一个password参数并选择key_derivation: openssl_evp选项。debug set password mySecretKey12345 debug set key_derivation openssl_evp debug try [成功] 解密结果myActualPassword123成功我们得到了明文密码。4.4 第四步生成可复现代码调试成功后脚本不应只显示结果。它应该能输出一份可以直接用于爬虫或其它工具的 Python 代码。# 脚本自动生成的复现代码 from Crypto.Cipher import AES from Crypto.Protocol.KDF import EVP_BytesToKey from Crypto.Util.Padding import unpad import base64 def decrypt_password(encrypted_b64): # 1. Base64解码 encrypted_data base64.b64decode(encrypted_b64) # 2. 提取盐Salted__ 后的8字节 salt encrypted_data[8:16] ciphertext encrypted_data[16:] # 3. 使用EVP_BytesToKey派生密钥和IV password bmySecretKey12345 key_iv EVP_BytesToKey(password, salt, 3216, count1) # AES-256 16字节IV key key_iv[:32] iv key_iv[32:] # 4. 解密 cipher AES.new(key, AES.MODE_CBC, iv) decrypted cipher.decrypt(ciphertext) # 5. 去除PKCS7填充 plaintext unpad(decrypted, AES.block_size) return plaintext.decode(utf-8) # 使用 encrypted U2FsdGVkX1WpqZQvRgBz3K4J8mH6qLtN0xYy7zA1c print(decrypt_password(encrypted)) # 输出: myActualPassword123这个功能极大地提升了从“分析”到“应用”的效率。5. 常见问题排查与调试心法在实际使用中你会遇到各种各样的问题。下面是一个快速排查清单和心法。5.1 问题速查表问题现象可能原因排查步骤解密后是乱码1. 算法/模式/填充错误2. 密钥错误3. IV错误CBC等模式4. 数据编码问题如该用Base64解码却没解1. 确认前端使用的加密库CryptoJS, forge, 原生WebCrypto。2. 检查密钥长度和格式字符串需注意编码和派生。3. 确认IV是否存在、是否正确提取。4. 尝试不同的填充方式PKCS7, ZeroPadding。5. 将解密出的二进制数据用多种编码utf-8, gbk, latin1尝试解码。解密时报错Padding is incorrect1. 密钥错误导致解密出的数据末尾填充字节无效2. 密文被截断或损坏3. 模式不匹配如ECB当CBC用1. 这是最强烈的信号说明密钥基本错误。优先检查密钥。2. 确认密文完整没有丢失等Base64填充字符。3. 换用ZeroPadding或无填充模式试试如果原始数据恰好是块大小的倍数。RSA解密失败提示密钥不匹配1. 使用了错误的密钥公钥/私钥颠倒2. 密钥格式错误PEM头尾缺失、Base64解码错误3. 填充方案不匹配PKCS1_v1_5 vs OAEP1. 确认是用私钥解密且该私钥与加密用的公钥配对。2. 用脚本的load_key功能验证密钥是否能被正确解析。3. 切换填充方案尝试。密文长度奇怪1. 包含了额外的头信息如Salted__2. 使用了流加密模式CFB, OFB, CTR导致密文长度等于明文长度3. 经过了多重编码/加密1. 查看密文二进制头部识别特征Salted__, ASN.1结构等。2. 对称加密中ECB/CBC模式密文长度通常是块大小的整数倍如果不是考虑流模式或填充问题。3. 尝试剥离可能的层层编码Base64 - Hex - Raw bytes。5.2 调试心法与高级技巧从已知点突破如果可能先构造一个已知明文和密文对。例如在目标网页上用简单的输入如test进行提交捕获加密后的数据。然后用你的脚本尝试各种组合去解密这个已知密文一旦成功参数就完全确定了。这是最可靠的方法。关注控制台与堆栈现代浏览器开发者工具非常强大。在加密函数如encrypt上打上XHR/fetch断点或事件监听器断点可以精准定位到加密发生的时刻直接查看调用时传入的参数值比静态分析代码快得多。利用“对称性”验证当你的脚本配置了一套参数后不要只用于解密。尝试用这套参数去加密一个已知字符串看生成的密文是否与目标网站产生的密文结构相似例如是否有相同的Salted__前缀长度是否一致。这能有效验证你的参数是否在同一个“频道”上。处理“动态密钥”越来越多的网站使用动态密钥或一次性的Token。密钥可能来自一个先前的API响应。此时你的脚本需要具备“上下文”管理能力能够将多个网络请求关联起来自动提取并应用动态变化的参数。编码是隐形杀手UTF-8、Latin-1、UTF-16LE……字符串到字节的转换编码不一致是导致调试失败的常见原因。确保你的脚本在各个环节前端JS模拟、密钥处理、IV处理使用的编码与目标网站完全一致。一个技巧是在浏览器控制台里打印出关键变量的charCodeAt或byteLength与你的Python脚本中len(key.encode(xxx))的结果进行对比。最后这个脚本的价值在于它将零散的知识和工具整合成了一个连贯的工作流。它不能替代你对密码学基础的理解但能把你从重复性的、机械的试错中解放出来让你更专注于逻辑分析和逆向思维本身。当你下次再面对一团加密数据时希望你的第一反应是从容地打开这个调试器而不是感到无从下手。

相关新闻

2026/7/21 10:45:17

addr2line解析不出来行号的解决方式(汇编解析高阶版)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: addr2line解析不出来行号的解决方式(汇编解析高阶版) 目录 一、问题背景 二、问题分析过程 2.1:基于crash堆栈分析 2.2 :addr2line正常解析 2.3 :llvm-addr2line正常解析

2026/7/21 10:45:17

ZooKeeper:全景速查手册(完整版·多表格体系梳理)

一、ZooKeeper 核心定位与本质(一句话吃透)ZooKeeper 是 Apache 开源的、分布式协调中间件,专门用于解决分布式系统中多服务之间的数据同步、状态协调、统一管理、选主、注册发现问题。在微服务与分布式架构体系中:Nacos&#xff…

2026/7/21 10:45:17

抖音下载器终极指南:从素材焦虑到创作自由的技术方案

抖音下载器终极指南:从素材焦虑到创作自由的技术方案 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback suppor…

2026/7/22 1:53:17

MCP与FC协议对比:微服务与Serverless通信技术解析

1. 从面试题看技术选型本质这道来自阿里的面试题看似在比较两种技术协议,实则考察的是候选人对分布式系统通信范式的深度理解。我在2018年第一次接触Harness平台时,也曾被MCP和FC的概念困扰——它们都出现在服务调用的上下文里,但设计哲学却截…

2026/7/22 1:53:17

Unity集成WebP插件实战:优化移动端图片资源与内存管理

1. 项目概述:为什么Unity开发者需要关注WebP?如果你在Unity项目里处理过大量图片资源,尤其是针对移动平台,那你一定对包体大小和内存占用这两个“老大难”问题深有体会。一张1024x1024的PNG贴图,轻松就能吃掉好几兆的磁…

2026/7/22 1:53:17

M4Markets:“退休组合风险集中显现”

雅虎财经报道,IBM股价在7月14日单日下跌约25%,创下公司历史上极为罕见的跌幅,长期依赖单一蓝筹股收息的退休投资者因此承受冲击,平台认为,这暴露了集中持仓在提款阶段的真实风险。报道称,IBM一季度调整后每…

2026/7/22 1:48:17

基于Opencode开发的博客系统

免费的开源项目,有国外国内免费提供的大模型,这个项目就是用免费大模型30分钟跑出来的,大家可以试试 项目地址:https://gitee.com/laughing-foolishly-loud/jiyuopencodekaifadebokexitong.git

2026/7/20 6:33:00

Unity与Python本地通信:基于Flask的跨语言数据交换实战

1. 项目概述:为什么我们需要一个本地通信服务器?在游戏开发、数字孪生、仿真训练等众多领域,Unity作为强大的实时3D内容创作平台,其核心逻辑通常由C#驱动。然而,当我们需要进行复杂的数据分析、机器学习推理、科学计算…

2026/7/22 0:02:17

抓包代理链路下的 TLS 指纹变化分析 TLSFOWARD抓包工具

抓包代理链路下的 TLS 指纹变化分析:为什么调试环境会影响访问结果 摘要 在网页调试、接口联调、自动化巡检和授权采集排查中,抓包是常见手段。但很多开发者会遇到一个现象:正常访问页面时没有问题,一进入抓包或代理调试环境&…

2026/7/22 0:02:17

微信QQ聊天记录误删恢复与备份方案全指南

1. 聊天记录误删的常见场景与恢复思路作为一名长期关注数据安全的技术博主,我处理过上百起聊天记录误删的求助案例。手机误操作、系统升级失败、设备损坏是三大常见诱因。上周就遇到用户更新微信时断电,导致近两年的工作群聊记录全部消失的极端案例。不同…

2026/7/22 0:02:17

2026最新8款个人AI编程免费工具深度实测

作为一名全栈独立开发者,我最近半年一直在折腾副业项目,每个月在AI编程工具上的订阅费算下来其实也不算便宜。作为个人开发者,我们追求的就是用最少的成本获得最高效的开发体验。TRAE 基础版免费,字节跳动出品的国内首款 AI 原生 …

2026/7/21 20:02:44

3个高效策略:快速掌握Axure中文界面配置

3个高效策略:快速掌握Axure中文界面配置 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包。支持 Axure 11、10、9。不定期更新。 项目地址: https://gitcode.com/gh_mirrors/ax/axure-cn 还在为Axure RP的英文界面感…