前言
话说在一次的授权测试中,发现了一个有意思的站点,通篇密文,然后我便开始研究其中的解码方法,并附上一些知识点,正文如下。
十六进制解码条件
如果要解密一大串的十六进制编码的数据,第一步肯定要知道需要哪些必要条件才能进行解码啊,那么我们就需要知道以下信息:1. 加密算法:首先,你需要知道所使用的加密算法。常见的加密算法包括AES、DES、RSA等。在你的情况下,你提到是AES加密,这是非常常见且安全的一种对称加密算法。
2. 密钥:对于对称加密算法(如AES),你需要知道用于加密和解密的密钥。密钥的长度可以是128位、192位或256位,这取决于你选择的AES变体(AES-128、AES-192、AES-256)。
3. 初始化向量 (IV):对于某些模式(如CBC模式),你需要一个初始化向量(IV)。IV不需要是保密的,但必须与密文匹配。也就是说,如果你用相同的密钥和不同的IV加密两次,那么两次加密的结果将是不同的,但都可以被相同的密钥和IV解密。
4. 模式:AES可以与多种模式一起使用,如ECB、CBC、CFB、OFB等。不同的模式有不同的用途和安全性考虑。在ECB模式中,对于相同的明文内容,每次加密都会生成相同的密文。这意味着,如果使用相同的密钥对多个块进行加密,每个块都将生成相同的密文。而在CBC模式中,每个块的加密都取决于前一个块的密文。这意味着,对于相同的明文内容,每次加密都会生成不同的密文
5. 填充方案:某些模式需要特定的填充方案。例如,在CBC模式中,通常使用PKCS#7填充。
综上,我们需要知道它使用的加密算法、密钥、模式以及初始化向量IV值(只针对于某些模式),接下来我们进入实战分析。
JS算法逆向【AES算法】
1. 访问页面:
第一反应,直接扔到https://gchq.github.io/CyberChef/里解码,失败。
2. 回到原本的站点找寻解码方式,回到初始门户网站点击F12,开始全局搜索decrypt函数,尝试寻找其加密解密方式:
发现加解密算法为AES,模式有cbc模式,还有ecb模式。(这里下文会进行分点分析)
3. 继续基于AES的加密算法,检索AES,发现new AES的函数,这里传入的参数就是密钥,并把断点就打在key被赋值后,也就是下图中的this.prepare(),然后就发现密钥被打印在控制台了:
在控制台中输入this.key 【访问当前对象(this)有一个名为 key 的属性】
再输入this.key.toString(); 【获取 key 属性的值,并调用它的 toString() 方法。toString() 是一个内置方法,用于将一个对象转换为字符串表示形式。如果 key 是一个数字或其他非字符串类型,这将很有用,因为你可以得到一个字符串形式的表示。】4. 显示的密钥为:116, 104, 101, 45, 116, 101, 114, 114, 111, 114, 105, 115, 116, 115, 46, 46
看起来是一串字符的ASCII码值,用逗号分隔,故尝试将这些值转换回对应的字符。可以写个脚本进行解码,脚本如下:
# 定义密钥的ASCII码值列表 key_list = [116, 104, 101, 45, 116, 101, 114, 114, 111, 114, 105, 115, 116, 115, 46, 46] # 使用chr()函数将ASCII码值转换为字符,并使用join()函数连接成字符串 key_string = ''.join(chr(value) for value in key_list) print(key_string) # 输出: "th!te!tr!to!ti!ts!tu.u"
运行脚本输出结果为:the-terrorists..
也可以放到https://gchq.github.io/CyberChef/解一下,成功,结果为:the-terrorists..
5. 现在已知条件都差不多了,开始编写一个解密脚本,输出解密成功后的内容,但是从步骤2得知有ecb和cbc两个模式,怎么办呢,那就都尝试一下。
EBC模式
已知:密文(访问页面中的就是)、加密方式aes、密钥the-terrorists..
但是ECB模式不需要初始化向量。(所以ECB模式进行加密和解密可能会导致安全问题,因为它不提供真正的块加密的安全性,但是由此以来提高了加密速度)
解密脚本编写如下:
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import padding import binascii # 密钥和初始向量 key = b"the-terrorists.." iv = b"" # ECB模式不需要初始向量 # 十六进制密文 hex_ciphertext = "your-hex-ciphertext" # 将十六进制密文转换为二进制数据 ciphertext = binascii.unhexlify(hex_ciphertext) # 创建一个AES解密器对象 cipher = Cipher(algorithms.AES(key), modes.ECB(), backend=default_backend()) # 创建一个PKCS#7填充器对象 padder = padding.PKCS7(128).padder() # 解密数据(需要一个与加密时匹配的填充方案) decryptor = cipher.decryptor() decrypted_data = decryptor.update(ciphertext) + decryptor.finalize() # 去除填充字节(如果存在) unpadder = padding.PKCS7(128).unpadder() decrypted_data = unpadder.update(decrypted_data) + unpadder.finalize() # 将二进制数据转换为字符串 decrypted_text = decrypted_data.decode("utf-8") print("Decrypted Text:", decrypted_text)
cmd运行一下,发现报错:错误可能的原因包括:
问题出在解密过程中的去填充(unpadding)步骤。具体来说,cryptography库在尝试去除PKCS#7填充时遇到了无效的填充字节,导致了ValueError异常。
这个问题通常发生在解密的数据被篡改或损坏的情况下。如果加密和解密使用的是相同的密钥和算法,并且输入的数据是有效的密文,那么解密过程应该能够成功完成,不会出现这样的错误。
解决这个问题的方法是:
(1)检查密文:确保你使用的密文是有效的,并且没有被篡改。
(2)检查密钥和算法:确保你使用的密钥和加密算法与用于加密的密钥和算法匹配。
(3)检查填充方案:确保你在解密时使用的填充方案与加密时使用的填充方案一致。
(4)使用正确的库版本:确保你使用的cryptography库版本与加密时使用的版本兼容。
对于第一点,还有待商榷,那就先不管第一点,去尝试第二种模式CBC模式进行解密
CBC模式
已知:密文(访问页面中的就是)、加密方式aes、密钥the-terrorists..
CBC模式使用一个随机生成的初始化向量,使得相同的明文块加密为不同的密文块。(所以CBC模式相比ECB模式提高了安全性,但同时由于串行处理数据,使得加密速度很慢)
在前文“十六进制解码条件”中提到CBC模式需要一个初始化向量IV,在这里IV代码里没写,故CBC模式的IV被硬编码为全0的字节串。
初始化向量(IV)是一个用于加密算法的随机或伪随机的数值,通常与密钥一起使用来初始化密码算法的状态。在加密过程中,IV起着随机化的作用,以确保相同的明文在经过相同密钥的加密下产生不同的密文,增加密码强度。
综上,解密脚本编写如下:
#!/usr/bin/python from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.primitives import padding def decrypt_aes(key_str, ciphertext_hex): backend = default_backend() # 将密钥字符串转换为字节串 key = bytes(key_str, 'utf-8') # 将十六进制字符串转换为字节串 ciphertext = bytes.fromhex(ciphertext_hex) # 使用AES算法和CBC模式 cipher = Cipher(algorithms.AES(key), modes.CBC(bytes([0]*16)), backend=backend) decryptor = cipher.decryptor() # 解密密文 decrypted_data = decryptor.update(ciphertext) + decryptor.finalize() # 使用PKCS7填充,可以根据具体情况选择其他填充方式 unpadder = padding.PKCS7(128).unpadder() # 移除填充并返回解密后的数据 return unpadder.update(decrypted_data) + unpadder.finalize() def main(): # 提示用户输入密钥和密文 key_str = input("请输入密钥(字符串格式):") ciphertext_hex = input("请输入十六进制密文: ") try: decrypted_data = decrypt_aes(key_str, ciphertext_hex) print("Decrypted Data:", decrypted_data[16:].decode('utf-8')) #print(bytes.fromhex(decrypted_data.hex())) except Exception as e: print("Decryption error:", e) if __name__ == "__main__": main()
运行一下,成功解码:还可以使用在线解密工具https://www.toolhelper.cn/: 都可以成功解密,完结撒花!
最后
如果我即时去复现的话那么这个手机号中间4位是不会有****的,但是由于工作繁忙+期间站点停过,所以现在才有时间把这篇文章给梳理完,导致管理员已经把泄露的手机号打码了。
4A评测 - 免责申明
本站提供的一切软件、教程和内容信息仅限用于学习和研究目的。
不得将上述内容用于商业或者非法用途,否则一切后果请用户自负。
本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。
如果您喜欢该程序,请支持正版,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。敬请谅解!
程序来源网络,不确保不包含木马病毒等危险内容,请在确保安全的情况下或使用虚拟机使用。
侵权违规投诉邮箱:4ablog168#gmail.com(#换成@)