将安全君呀设为"星标⭐️"
第一时间收到文章更新
声明: 安全君呀 公众号文章中的技术只做研究之用,禁止用来从事非法用途,如有使用文章中的技术从事非法活动,一切后果由使用者自负,与本公众号无关。
文章声明:本篇文章内容部分选取网络,如有侵权,请告知删除。
一 逆向加密模块
1,Python中运行JS代码
1.1 解决中文乱码或者报错问题
import subprocess from functools import partial subprocess.Popen = partial(subprocess.Popen, encoding='utf-8') import execjs
1.2 常用函数
print(execjs.get().name) # 获取js代码执行环境 res = execjs.eval(js)# 执行一段js代码 #先编译 jj = execjs.compile("""function an(a, b){ return a + b} """) # call() 运行代码中的xxx函数. 后续的参数是xxx的参数 ret = jj.call("an", 10, 20) #读取js文件 f = open("01.js",mode="r",encoding="utf-8") js_code = f.read() obj = re.compile(r"window._INIT_STATE__ = (?P.*?);",re.S) # 正则表达式 code = obj.search(js_code).group("code") #匹配正则表达式 print(type(code))#这里的code是字符串 # execjs这个库会把运行的结果自动转化成对象 result = execjs.eval(code)# 拿到的是一个JS代码运行的结果 print(result) #是个字典,Python会自动转换成字典 print(type(result)) # dict
2,CryptoJS加密特征
function b(a, b) { var c = CryptoJS.enc.Utf8.parse(b) , d = CryptoJS.enc.Utf8.parse("0102030405060708") , e = CryptoJS.enc.Utf8.parse(a) , f = CryptoJS.AES.encrypt(e, c, { iv: d, mode: CryptoJS.mode.CBC }); return f.toString() } #转换为UTF8 CryptoJS.enc.Utf8 # 转换为base64 CryptoJS.enc.Base64
3,RAS加密特征
setMaxDigits, RSAKeyPair, encryptedString
4,md5加密解密
from hashlib import md5 obj = md5() obj.update("alex".encode("utf-8")) # obj.update("wusir".encode('utf-8'))# 可以添加多个被加密的内容 bs = obj.hexdigest() print(bs) # 加盐 from hashlib import md5 salt = "我是盐.把我加进去就没人能破解了" obj = md5(salt.encode("utf-8"))# 加盐 obj.update("alex".encode("utf-8")) bs = obj.hexdigest() print(bs)
5,傻系列加密
sha1,sha256,sha512用法跟md5一样
from hashlib import sha1, sha256 sha = sha256(b'salt') sha.update(b'alex') print(sha.hexdigest())
6,URLencode
from urllib.parse import quote, unquote, quote_plus, unquote_plus, urlencode # 单独编码字符串 用 quote wq = "米饭怎么吃" print(quote(wq))# %E7%B1%B3%E9%A5%AD%E6%80%8E%E4%B9%88%E5%90%83 print(quote(wq, encoding="gbk")) # %C3%D7%B7%B9%D4%F5%C3%B4%B3%D4 # 多个数据统一进行编码 用urlencode ,比如字典进行编码 dic = { "wq": "米饭怎么吃", "new_wq": "想怎么吃就怎么吃" } print(urlencode(dic))# wq=%E7%B1%B3%E9%A5%AD%E6%80%8E%E4%B9%88%E5%90%83&new_wq=%E6%83%B3%E6%80%8E%E4%B9%88%E5%90%83%E5%B0%B1%E6%80%8E%E4%B9%88%E5%90%83 print(urlencode(dic, encoding="utf-8"))# 也可以指定字符集 # 一个完整的url编码过程 base_url = "http://www.baidu.com/s?" params = { "wd": "大王" } url = base_url + urlencode(params) print(url)# http://www.baidu.com/s?wd=%E5%A4%A7%E7%8E%8B #解码 s = "http://www.baidu.com/s?wd=%E5%A4%A7%E7%8E%8B" print(unquote(s))# http://www.baidu.com/s?wd=大王 print(quote("a /b/c=", safe=""))# 传递safe=""可以保持和浏览器一致 print(quote_plus("a /b/c="))
7,base64编码
import base64 bs = "我要吃饭".encode("utf-8") # 把字节转化成b64 print(base64.b64encode(bs).decode()) # 把b64字符串转化成字节 s = "5oiR6KaB5ZCD6aWt" print(base64.b64decode(s).decode("utf-8")) #base64报错问题 import base64 s = "ztKwrsTj0b0" bb = base64.b64decode(s) print(bb) 此时运行出现以下问题 Traceback (most recent call last): File "D:/PycharmProjects/rrrr.py", line 33, in
8,AES加密
1,加密规则
第一种
# AES加密 from Crypto.Cipher import AES import base64 """ 长度 16: *AES-128* 24: *AES-192* 32: *AES-256* MODE 加密模式.常见的 ECB可以没有iv CBC 需要iv的 """ # 创建加密器 注意秘钥和iv必须是16个字节 aes = AES.new( key= b"alexissbalexissb", mode=AES.MODE_CBC, iv=b"0102030405060708") # 分别是秘钥,模式,iv data = "我吃饭了" # 加密的内容必须是字节,所以先进行编码 data_bs = data.encode("utf-8") # 需要加密的数据必须是16的倍数 # 填充规则: 缺少数据量的个数 * chr(缺少数据量个数) pad_len = 16 - len(data_bs) % 16 data_bs += (pad_len * chr(pad_len)).encode("utf-8") # 再对编码后的字节进行加密 bs = aes.encrypt(data_bs) #用base64对结果进行编码 result = base64.b64encode(bs).decode()
第二种,用pad对字节进行填充达到规定的长度
# AES加密 from Crypto.Cipher import AES import base64 from Crypto.Util.Padding import pad """ 长度 16: *AES-128* 24: *AES-192* 32: *AES-256* MODE 加密模式.常见的 ECB可以没有iv CBC 需要iv的 """ # 创建加密器 注意秘钥和iv必须是16个字节 aes = AES.new( key= b"alexissbalexissb", mode=AES.MODE_CBC, iv=b"0102030405060708") # 分别是秘钥,模式,iv data = "我吃饭了" # 加密的内容必须是字节,所以先进行编码 data_bs = data.encode("utf-8") # 需要加密的数据必须是16的倍数 # 用pad工具进行填充 data_bs = pad(data_bs,16) # 再对编码后的字节进行加密 bs = aes.encrypt(data_bs) #用base64对结果进行编码 result = base64.b64encode(bs).decode() print(result)
2, 加密结果转换base64,hex
# 转换成base64 bs是AES加密得到的字节 result = base64.b64encode(bs).decode() #转换成16进制 import binascii res = binascii.b2a_hex(bs).decode() # 也可以转换成16进制,跟上面一个效果一样 bs.hex()
3,解密规则
from Crypto.Util.Padding import pad,unpad # base64编码后的密文 s = '9noPO0fcQizMbPkXcVOTDg==' # 创建解密器 aes = AES.new(key= b"alexissbalexissb", mode=AES.MODE_CBC, iv=b"0102030405060708") # 首先把base64编码转换成正常的字节 data = base64.b64decode(s) res = aes.decrypt(data) # 明文有可能有问题,因为字节是填充过得 # 用unpad 去除填充的内容,注:需要导入unpad res = unpad(res,16) # 得到明文 mingwen = res.decode("utf-8") print(mingwen)
9,DES加密
1,加密规则
from Crypto.Cipher import DES from Crypto.Util.Padding import pad,unpad import base64 mingwen = '艾尼在学爬虫' # DES key 是 8个字节 # iv 在CBC 模式下使用 长度8个字节 des = DES.new(key=b'aininora', mode=DES.MODE_CBC,iv=b'ainiaini') # 明文进行编码 data = mingwen.encode('utf-8') # 对编码后的字节进行填充 r = pad(data,8) # 对填充后的字节进行des加密后的字节 res = des.encrypt(r) # 对加密后的字节进行base64编码 base64_res = base64.b64encode(res).decode() print(base64_res)
2,DES解密规则
from Crypto.Cipher import DES from Crypto.Util.Padding import pad,unpad import base64 #base64密文 miwen = 't4TYyzRnIkmVmI81n+cdsVQfprHN5AtG' #转换成base64字节 base64_byt = base64.b64decode(miwen) # 创建解密器对象 des = DES.new(key=b'aininora', mode=DES.MODE_CBC,iv=b'ainiaini') # 进行解密 r = des.decrypt(base64_byt) # 得到的结果去掉填充部分 data = unpad(r,8) # 对得到的字节进行解码 mingwen = data.decode('utf-8') print(mingwen)
注:DES3 与AES,DES加密,解密规则一样,都是兄弟
注:js里的秘钥可以超过8位,js默认去前八位进行解密
10,RSA加密
1,RSA生成秘钥和公钥
#生成和处理秘钥的 from Crypto.PublicKey import RSA # 加密和解密 from Crypto.Cipher import PKCS1_v1_5 import base64 # 生成私钥 #bits = 2048 是秘钥的长度 rsa_key = RSA.generate(bits=2048) # 把秘钥导出来 # 秘钥的本质是字节 # export_key 有个参数叫format,默认为PEM,背后的含义是把秘钥转换成了base64 key = rsa_key.export_key().decode() with open('./rsa_miyao.pem',mode='w',encoding='utf-8') as f: f.write(key) # 把format换成DER,拿到的是字节 # key = rsa_key.export_key(format='DER') # 把字节手动转换成base64 # result = base64.b64encode(key).decode() #生成公钥 public_key = rsa_key.public_key() # 把公钥导出来 p_key = public_key.export_key() with open('./rsa_gongyao.pem',mode='wb') as f: f.write(p_key)
2, RSA进行加密
#加密解密 from Crypto.Cipher import PKCS1_v1_5 #加载key from Crypto.PublicKey import RSA import base64 # 导入的key可以是PEM格式的秘钥,或者是直接形式的秘钥也可以 # 读取秘钥 f = open('./rsa_gongyao.pem',mode='r',encoding='utf-8') # 拿到已经生成好的秘钥 pub_key = f.read() f.close() mingwen = "我要好好学习爬虫" rsa_key = RSA.importKey(pub_key) # 生成加密对象 rsa = PKCS1_v1_5.new(key=rsa_key) # 对明文进行编码,处理成字节 mingwen_bs = mingwen.encode('utf-8') # 对明文字节进行加密,得到密文字节 mi_bs = rsa.encrypt(mingwen_bs) # 转换成base64 base_64 = base64.b64encode(mi_bs).decode() #rsa每次加密后的结果可能不一样 print(base_64) # 如果用了没有填充的算法,那每一次算出来的结果固定的 # 如果同一个明文反复计算结果是一样的那么考虑用js来完成逆向工作
2.1 第二中加密方法
// JSEncrypt // setPublicKey // 用的是固定的第三方库,库的名字叫jsencrypt // 但是这个库只能在浏览器环境使用 // 我们用的是Node环境,所以不能直接是哟和 // 我们需要换一个库, 名字叫 node-jsencrypt // 安装 npm install node-jsencrypt var {JSEncrypto} = require('node-jsencrypt') var o = new JSEncrypto.setPublicKey('xxxxxxxxxxxxxxxxxxxxxxxx') r = o.encrypt("加密的内容") // 可以直接把网站的内容拿过来
3,RSA特殊解密
3.1 第一特征
1,如果用了没有填充的算法,那每一次算出来的结果固定的
2,如果同一个明文反复计算结果是一样的那么考虑用js来完成逆向工作
// 特征: // "010001" -> 这是16进制 -> 65537 // setMaxDigits // RSAKeyPair // encryptedString const { setMaxDigits, RSAKeyPair, encryptedString } = require("./Ras加密"); function c(a,b,c){ var d,e; return setMaxDigits(131), d = new RSAKeyPair(b,"",c), e = encryptedString(d,a) }
3,用RSA.js文件解决问题
例如:网易云案例
const CryptoJS = require("crypto-js") var window = this const { setMaxDigits, RSAKeyPair, encryptedString } = require("./Ras加密"); !function() { function a(a) { var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = ""; for (d = 0; a > d; d += 1) e = Math.random() * b.length, e = Math.floor(e), c += b.charAt(e); return c } function b(a, b) { var c = CryptoJS.enc.Utf8.parse(b) , d = CryptoJS.enc.Utf8.parse("0102030405060708") , e = CryptoJS.enc.Utf8.parse(a) , f = CryptoJS.AES.encrypt(e, c, { iv: d, mode: CryptoJS.mode.CBC }); return f.toString() } function c(a, b, c) { var d, e; return setMaxDigits(131), d = new RSAKeyPair(b,"",c), e = encryptedString(d, a) } function d(d, e, f, g) { var h = {} , i = a(16); return h.encText = b(d, g), h.encText = b(h.encText, i), h.encSecKey = c(i, e, f), h } function e(a, b, d, e) { var f = {}; return f.encText = c(a + e, b, d), f } window.asrsea = d, window.ecnonasr = e }(); var params = { csrf_token: "", encodeType: "aac", ids: "[1325905146]", level: "standard" } var second = '010001' var third = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7' var forth = '0CoJUm6Qyw8W8jud' function fn(params) { return window.asrsea(JSON.stringify(params),second,third,forth)
4, RSA普通解密
#加密解密 from Crypto.Cipher import PKCS1_v1_5 #加载key from Crypto.PublicKey import RSA import base64 f = open('./rsa_miyao.pem',mode='r',encoding='utf-8') # 拿到已经生成好的秘钥 pri_key = f.read() f.close() # 拿到秘钥 rsakey = RSA.importKey(pri_key) # 生成解密器对象 rsa = PKCS1_v1_5.new(key=rsakey) miwen = 'mmf28CJEtFU2Y6C/qx10xoaRmsiY2at3LBjHR5DFdnG9V+5sGPFaMGDGM4OBVWKKJNuSFZgGL9Y409mbh32IKRL4TZYnc0RvJH/0t38d7AmnqnHAyTRUvpKlPzzJg559md6BcTA/ZpYZ4WAtXRuysMvuPTdlRvog2ceGJDXURajU3KyzHXFA9Hc+AamVL75D+YKrOB6n9YeV7n4+DK5mqouNlLp6Plee39vYBzN0IKkzyD6RatmVVUIxJCsUJmeJgIdnBGEuRA9bGNOG3VQa7NF/syWjiRNbKYz+KZHx+RtQ9GuzmPhtJbjh8anPeR2kzNwgfD1HiKhIBDQKVQH/eA==' #对密文进行base64解码转换成字节 base64_2bs = base64.b64decode(miwen) #对拿到的字节进行rsa解密得到明文字节 # 解密第二个参数给个None,意思是解密时出错了返回None mingwen_bs = rsa.decrypt(base64_2bs,None) #对明文字节进行解码得到明文 mingwen = mingwen_bs.decode('utf-8') print(mingwen)
原文始发于微信公众号(安全君呀):逆向加密模块总结
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论