前言
我们在做对爬取网站破解的时候,经常会有加密参数逆向解析的时候,这个时候我们往往会使用到各种加密算法、混淆、编码对参数进行解析,我们一般是根据每个算法都有其独特的特征去破解,虽然有一些网站参数是自己定义的,但是大多数网站都是使用官方通报的算法,在各大网站没有自己精加工的情况下,我们如果能熟悉这些算法的规律,通过密文我们就能轻松猜测出这个参数用的是哪种算法、混淆、编码,从而大大加快我们的爬虫工程开发!所以我们有必要去熟悉常见的这些东西。
本篇文章将讲述一些编码和加密算法的规律。
算法:MD5、SHA 系列、HMAC 系列、RSA、AES、DES、3DES、RC4、Rabbit、SM 系列
编码:Base 系列、Unicode、Escape、URL、Hex
混淆:Obfuscator、JJEncode、AAEncode、JSFuck、Jother、Brainfuck、Ook!、Trivial brainfuck substitution
其他:恺撒密码、栅栏密码、猪圈密码、摩斯密码、培根密码、维吉尼亚密码、与佛论禅、当铺密码
加密算法
MD5
MD5信息摘要算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。MD5由美国密码学家罗纳德·李维斯特(Ronald Linn Rivest)设计,于1992年公开,用以取代MD4算法。这套算法的程序在 RFC 1321 标准中被加以规范。1996年后该算法被证实存在弱点,可以被加以破解,对于需要高度安全性的数据,专家一般建议改用其他算法,如SHA-2。2004年,证实MD5算法无法防止碰撞(collision),因此不适用于安全性认证,如SSL公开密钥认证或是数字签名等用途。
其密文的主要规律如下:
- 密文一般为 16 位或者 32 位,其中 16 位是取的 32 位第 9~25 位的值;
- 组成方式为字母(a-f)和数字(0-9)混合,字母可以全部是大写或者小写。
除了通过密文特征来判断以外,我们还可以搜索源代码,标准 MD5 的源码里是包含了一些特定的值的,没有这些特定值,就无法实现 MD5:
- 0123456789ABCDEF、0123456789abcdef
- 1732584193、-271733879、-1732584194、271733878
PS:某些特殊情况下,密文的长度也有可能不止 16 位或者 32 位
如下示例:
编码类型 | 示例一 | 示例二 |
---|---|---|
明文 | 123456 | admin |
MD5 (16 位小写) | 49ba59abbe56e057 | 7a57a5a743894a0e |
MD5 (16 位大写) | 49BA59ABBE56E057 | 7A57A5A743894A0E |
MD5 (32 位小写) | e10adc3949ba59abbe56e057f20f883e | 21232f297a57a5a743894a0e4a801fc3 |
MD5 (32 位大写) | E10ADC3949BA59ABBE56E057F20F883E | 21232F297A57A5A743894A0E4A801FC3 |
SHA 系列
安全散列算法(英语:Secure Hash Algorithm,缩写为SHA)是一个密码散列函数家族,是FIPS所认证的安全散列算法。能计算出一个数字消息所对应到的,长度固定的字符串(又称消息摘要)的算法。且若输入的消息不同,它们对应到不同字符串的机率很高。
SHA 是比 MD5 更安全一点的摘要算法,SHA 通常指 SHA 家族算法,分别是 SHA-1、SHA-2、SHA-3,其中 SHA-2 是 SHA-224、SHA-256、SHA-384、SHA-512 的并称,SHA-3 是 SHA3-224、SHA3-256、SHA3-384、SHA3-512、SHAKE128、SHAKE256 的并称,其名字的后缀的数字就代表了结果的大小(bit),注意,SHAKE 算法结果的大小并不是固定的,其他算法特征如下:
- SHA-1:字母(a-f)和数字(0-9)混合,固定位数 40 位;
- SHA-224/SHA3-224:字母(a-f)和数字(0-9)混合,固定位数 56 位;
- SHA-256/SHA3-256:字母(a-f)和数字(0-9)混合,固定位数 64 位;
- SHA-384/SHA3-384:字母(a-f)和数字(0-9)混合,固定位数 96 位;
- SHA-512/SHA3-512:字母(a-f)和数字(0-9)混合,固定位数 128 位。
编码类型 | 示例 |
---|---|
明文 | 123456 |
SHA-1 | 7c4a8d09ca3762af61e59520943dc26494f8941b |
SHA-256 | 8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92 |
SHA3-256 | c888c9ce9e098d5864d3ded6ebcc140a12142263bace3a23a36f9905f12bd64a |
HMAC
HMAC是密钥相关的哈希运算消息认证码(Hash-based Message Authentication Code)的缩写,由H.Krawezyk,M.Bellare,R.Canetti于1996年提出的一种基于Hash函数和密钥进行消息认证的方法,并于1997年作为RFC2104被公布,并在IPSec和其他网络协议(如SSL)中得以广泛应用,现在已经成为事实上的Internet安全标准。它可以与任何迭代散列函数捆绑使用。
规律
在HMAC的定义中用到一个密码散列函数H和一个密钥K。假设H是一个能够对明文进行分组循环压缩的散列函数,B为散列函数的明文分组长度(byte),在上述的散列函数中B=64,L为散列函数的输出长度(byte),MD5中L=16,SHA-1中L=20。认证密钥K可以为任意长度,一般密钥长度应大于明文分组的长度,将密钥的第一次散列值作为HMAC真正使用的密钥,密钥的最小推荐长度为Lbytes。
再定义两个不同的固定字符串ipad和opad如下(“i”和“o”表示内部和外部):
- ipad=一个字节(byte)的0x36重复B次;
- opad=一个字节(byte)的0x5C重复B次。
若以“text”作为要计算HMAC的明文,则作如下操作:
- H(K XOR opad,H(K XOR ipad,text))
也就是说,操作步骤如下:
- 在密钥K后面填充0,使其成为长度为Bbyte的字符串;如:K是20bytes的字符串,B=64,则要填充44个字节的0x00。
- 用第一步得到的Bbyte的字符串与ipad作XOR(按位异或);
- 将数据流text附加到第(2)步产生的Bbyte字符串后面;
- 对第(3)产生的数据流用散列函数H计算消息摘要;
- 用第一步得到的Bbyte的字符串与opad作XOR(按位异或);
- 将第(4)生成的消息摘要附加到第(5)步的Bbyte字符串之后;
- 对第(6)产生的数据流用散列函数H计算消息摘要,作为输出
在前端JS中通常写法是:
function HmacSHA1Encrypt(word, key) {
return CryptoJS.HmacSHA1(word, key).toString();
}
示例:
编码类型 | 示例 |
---|---|
明文 | 123456 |
HMAC-MD5 | 432bb95bb00005ddce4a1c757488ed95 |
HMAC-SHA-1 | 37a04076b7736c44460d330ee0d00014428b175e |
HMAC-SHA-256 | 50cb1345366df11140fb91b43caaf69627e3f5529705ddf6b0d0cae67986e585 |
HMAC-SHA3-256 | b808ed9f66436e89fba527a01d1d6044318fea8599d9f39bfb6bec4843964bf3 |
RSA
RSA是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的 [1] 。
JS常用关键词:
搜索关键词 new JSEncrypt(),JSEncrypt 等,一般会使用 JSEncrypt 库,会有 new 一个实例对象的操作;
搜索关键词 setPublicKey、setKey、setPrivateKey、getPublicKey 等,一般实现的代码里都含有设置密钥的过程
Rabbit、RC4、AES、DES、3DES 等
这类算法一般是没有固定长度的,一般是用纯 javascript 写的加密算法类库crypto-js 来实现。
CryptoJS = require("crypto-js")
# 输出BASE64 或者HEX
# 密码
# 字符集UTF-8
var key = CryptoJS.enc.Utf8.parse("0123456789abcdef");
# 偏移
var iv = CryptoJS.enc.Utf8.parse("0123456789abcdef");
function AESEn(word) {
#密文
var srcs = CryptoJS.enc.Utf8.parse(word);
var encrypted = CryptoJS.AES.encrypt(srcs, key, {
#偏移
iv: iv,
#加密模式
mode: CryptoJS.mode.CBC,
#填充
padding: CryptoJS.pad.Pkcs7
});
return encrypted.toString();
}
function AESDe(word) {
var srcs = word;
var decrypt = CryptoJS.AES.decrypt(srcs, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return decrypt.toString(CryptoJS.enc.Utf8);
}
console.log(AESEn("齐天大圣哮天犬猪八戒如来来加密"))
console.log(AESDe("gmBSsOPuAChc39VxRaE68NXGSpafCq6sau/lxUeh8vE6ODlRKuWjsgfkt99eIYvp"))
在控制台可搜索关键:”CryptoJS、crypto-js、iv、mode、padding、createEncryptor、createDecryptor
SM 系列
SM3是中华人民共和国政府采用的一种密码散列函数标准,由国家密码管理局于2010年12月17日发布。相关标准为“GM/T 0004-2012 《SM3密码杂凑算法》”。
在商用密码体系中,SM3主要用于数字签名及验证、消息认证码生成及验证、随机数生成等,其算法公开。据国家密码管理局表示,其安全性及效率与SHA-256相当。
其余简介我就不多描述了,上关键词:
- FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF
- FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC
- getPublicKeyFromPrivateKey、doEncrypt、doDecrypt、doSignature
- SM2、SM3、SM4
编码系列
BASE系列编码
这里我们最常用的编码base64,其他系列包括Base16、Base32、Base58、Base85、Base100
规律 :
编码名 | 规律 | 示例一 | |
---|---|---|---|
Base16 | 结尾没有等号,数字要多于字母 | 3031323334353637383930 | |
Base32 | 字母要多于数字,明文数量超过 10 个,结尾可能会有很多等号 | GAYTEMZUGU3DOOBZGA====== | |
Base58 | 结尾没有等号,字母要多于数字 | cX8j8pvGzppMKVb | |
Base64 | 一般情况下结尾都会有 1 个或者 2 个等号,明文很少的时候可能没有 | MDEyMzQ1Njc4OTA= | |
Base85 | 等号一般出现在字符串中间,含有一些奇怪的字符 | 0JP==1c70M3&rY | |
Base100 | 密文由 Emoji 表情组成 | 🐨👪 |
Unicode 编码
又被成为统一码(Unicode),也叫万国码、单一码,是计算机科学领域里的一项业界标准,包括字符集、编码方案等。Unicode是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。
其主要特征如下:
- 以 \u、&# 或 &#x 开头
url 和Hex 编码
这两种编码基本一致,但是两种有一点不同就是Hex会把特殊符号中(&、?、 /、=) 、关键字中(http、https)全部转换,而url 编码不会转换。
示例:
编码 | 示例 |
明文 | https://www.baidu.com |
urlencode | https%3A%2F%2Fwww.baidu.com%2F |
hex | %68%74%74%70%73%3a%2f%2f%77%77%77%2e%6b%75%61%69%64%61%69%6c%69%2e%63%6f%6d%2f |
混淆系列
此系列很重要,一般安防意识比较强的网站 都会使用混淆:
Jother
jother混淆特征:
一般由8个字符组成:[]()!+{}
混淆示例代码:
({}+[])[+!![]]+({}[[]]+[])[+!![]])()
JSFuck
和上面一个混淆工具jother很像,但是区别是jsfuck没有{}
混淆特征:
一般由8个字符组成:[]()!+
混淆示例代码:
(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]
Brainfuck
Brainfuck是一种极小化的计算机语言,它是由Urban Müller在1993年创建的。由于fuck在英语中是脏话,这种语言有时被称为brainf*ck或brainf**k,甚至被简称为BF。
混淆特征:
仅由 <>+-.[]
组成,大量的 +-
符号
混淆示例:
明文 | 混淆 |
大师傅还是很帅 | +[------->+++<]>++.>++++++++.[++>-<]>+.[--->+<]>+.--[->+++++<]>+.--[->+++<]>+.>+++++. |
Ook!
Ook!也是一种混淆,他和bf类似,但是混淆符号有差异。
混淆特征:
仅由 3 种符号组成 Ook.、Ook?、Ook!
混淆示例:
明文 | 混淆 |
大师傅还是很帅 | Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. .........有点多 不多余展示 |
Obfuscator
Obfuscator 就是混淆的意思,简称 OB 混淆
- 由一个大数组或者含有大数组的函数、一个自执行函数、解密函数和加密后的函数四部分组成;
- 函数名和变量名通常以 _0x 或者 0x 开头,后接 1~6 位数字或字母组合;
- 自执行函数,进行移位操作,有明显的 push、shift 关键字;
- 混淆示例地址JavaScript Obfuscator Tool
混淆示例:
混淆前:
function jian() {
console.log("Hello World!");
}
jian();
混淆后:
(function (_0x1b7b4b, _0x29886d) {
var _0x3de03d = _0x22bd,
_0x2c5c19 = _0x1b7b4b();
while (true) {
try {
var _0x26bec7 = -parseInt(_0x3de03d(344)) / 1 + parseInt(_0x3de03d(347)) / 2 * (-parseInt(_0x3de03d(350)) / 3) + parseInt(_0x3de03d(354)) / 4 * (parseInt(_0x3de03d(353)) / 5) + -parseInt(_0x3de03d(348)) / 6 * (-parseInt(_0x3de03d(356)) / 7) + -parseInt(_0x3de03d(345)) / 8 + -parseInt(_0x3de03d(346)) / 9 * (-parseInt(_0x3de03d(352)) / 10) + -parseInt(_0x3de03d(355)) / 11;
if (_0x26bec7 === _0x29886d) {
break;
} else {
_0x2c5c19["push"](_0x2c5c19["shift"]());
}
} catch (_0x50c942) {
_0x2c5c19["push"](_0x2c5c19["shift"]());
}
}
})(_0x374c, 785369);
function _0x22bd(_0x613c79, _0xbe5f13) {
var _0x374c68 = _0x374c();
return _0x22bd = function (_0x22bd09, _0x2eddf9) {
_0x22bd09 = _0x22bd09 - 344;
var _0x4549ab = _0x374c68[_0x22bd09];
return _0x4549ab;
}, _0x22bd(_0x613c79, _0xbe5f13);
}
function _0x374c() {
var _0x24c503 = ["30igxpoA", "10785yFNlPt", "1244ZTrSFN", "571505UtYPRX", "7315385kFRkbT", "442748clRNSy", "5827608DQYWrU", "4223475CZpVHY", "32SJBUmD", "6MFYfBp", "log", "209097QahEQl", "Hello World!"];
_0x374c = function () {
return _0x24c503;
};
return _0x374c();
}
function jian() {
var _0x1c02dc = _0x22bd;
console[_0x1c02dc(349)](_0x1c02dc(351));
}
jian();