0%

逆向常见加密算法

  • 逆向常见加密算法


Base

base16

替换表

0123456789ABCDEF

特征

  • 即16进制转换,密文只包含([0-9], [A-F])

base32

替换表

ABCDEFGHIJKLMNOPQRSTUVWXYZ234567

特征

  • 一般来讲密文中字母会多于数字,而且末尾有多个等号

  • eg:

    • 明文:UKFC-UmVfX1BvaW50
    • 密文:KVFUMQZNKVWVMZSYGFBHMYKXGUYA====

base58

替换表

ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz123456789

特征:

  • 结尾无等号

base64

替换表

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

特征

  • 末尾有1到2个等号

  • 密文长度为4的倍数

  • eg:

    • 明文:Re__Point
    • 密文:UmVfX1BvaW50Xw==

网站

base85

替换表

$%()*+,-./0123456789:;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~

特征

  • 等号可能出现在密文中间且密文杂乱
  • eg:

图片

替换表

base91

!”#$%&()*+,./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~

base92

!#$%&’()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz{|}~

base94

!”#$%&’()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~

base100

  • 密文为emoji

RC4

  • 一个核心是逐字节异或的加密算法

加解密过程

c++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void rc4_init(unsigned char* s, unsigned char* key, int len){
int i = 0, j = 0;
char k[256] = { 0 };
for (i = 0; i<256; i++)
{
s[i] = i;
k[i] = key[i%len]; //密钥填充
}
for (i = 0; i<256; i++)
{
j = (j + s[i] + k[i]) % 256;
swap(s[i],s[j]);
}
}

void rc4_crypt(unsigned char* s, unsigned char* Data, int len){
int i = 0, j = 0, t = 0;
unsigned int k = 0;
for (k = 0; k<len; k++)
{
i = (i + 1) % 256;
j = (j + s[i]) % 256;
swap(s[i],s[j]);
t = (s[i] + s[j]) % 256;
Data[k] ^= s[t]; //xor data
}
}

python

1
2
3
4
5
6
7
from Crypto.Cipher import ARC4
key = b"UKFC"
data = b'Re__Point'
rc4 = ARC4.new(key)
data = rc4.decrypt(data)
print(data)
# b'v9\xfb&\x0bgS\x95<'

特征识别

  • 初始化和加密分离
  • sbox初始化 s[i] = i,密钥填充
  • 取模运算,对明文处理只有最后一部分

Tea系列

tea

1
2
3
4
5
6
7
8
9
10
11
void encrypt(uint32_t* v, uint32_t* k) {  
uint32_t delta=0x9e3779b9;
uint32_t v0 = v[0], v1 = v[1], sum = 0;
for (int i = 0; i < 32; i++) {
sum += delta;
v0 += ((v1<<4) + k[0]) ^ (v1 + sum) ^ ((v1>>5) + k[1]);
v1 += ((v0<<4) + k[2]) ^ (v0 + sum) ^ ((v0>>5) + k[3]);
}
v[0] = v0;
v[1] = v1;
}

xtea

1
2
3
4
5
6
7
8
9
10
void encrypt(uint32_t* v, uint32_t* k) {  
unsigned int i;
uint32_t v0=v[0], v1=v[1], sum=0, delta=0x9E3779B9;
for (i=0; i < 32; i++) {
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
sum += delta;
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
}
v[0]=v0; v[1]=v1;
}

xxtea

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
v = 明文
k = 密钥
n = len(v)
rounds = 6 + int(52 / n)
sum = c_uint32(0)
z = v[n - 1].value
while rounds > 0:
sum.value += DELTA
e = (sum.value >> 2) & 3
p = 0
while p < n - 1:
y = v[p + 1].value
v[p].value += (((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum.value ^ y) + (k[(p & 3) ^ e] ^ z)))
z = v[p].value
p += 1
y = v[0].value
v[n - 1].value += (((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum.value ^ y) + (k[(p & 3) ^ e] ^ z)))
z = v[n - 1].value
rounds -= 1

特征识别

  • 常量特征:delta 0x9e3779b9

  • 密钥特征:4个32位字符

  • 明文输入:32位字符为单位

  • 异或&移位 特征

块加密

AES

加解密

AES加密

  • AES的明文分组长度为128位(16字节),即明文长度需为16的倍数【不进行填充的情况下】
  • 密钥长度可以为128位(16字节)、192位(24字节)、256位(32字节)
    1
    2
    3
    4
    5
    6
    7
    8
    from Crypto.Cipher import AES
    from Crypto.Util.number import *
    c = b'Re__Point\x00\x00\x00\x00\x00\x00\x00' # 明文
    key = long_to_bytes(0xcb8d493521b47a4cc1ae7e62229266ce) #密钥
    aes = AES.new(key, mode=AES.MODE_ECB)
    m = aes.encrypt(c)
    print(m)
    # b'\x8c\xfb\xf36\xe6\x10\xaaU\x90\xdc\xbdR.\xa3m.'
    AES解密
1
2
3
4
5
6
7
8
from Crypto.Cipher import AES
from Crypto.Util.number import *
m = b'\x8c\xfb\xf36\xe6\x10\xaaU\x90\xdc\xbdR.\xa3m.' # 密文
key = long_to_bytes(0xcb8d493521b47a4cc1ae7e62229266ce) #密钥
aes = AES.new(key, mode=AES.MODE_ECB)
c = aes.decrypt(m)
print(c)
# b'Re__Point\x00\x00\x00\x00\x00\x00\x00'

特征识别

  • sbox 16*16 常量特征
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    unsigned char S[256] = {
    0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
    0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
    0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
    0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
    0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
    0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
    0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
    0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
    0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
    0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
    0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
    0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
    0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
    0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
    0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
    0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
    };
  • 加密过程:密钥扩展–>轮密钥生成–>字节替换、行移位–>列替换和轮密钥加
  • 密钥长度和轮数的对应
    • 128bits–>10rounds
    • 192bits–>12rounds
    • 256bits–>14rounds

DES

DES加密

  • 明文的长度必须是8的倍数
  • 密钥:8bytes
    1
    2
    3
    4
    5
    6
    7
    8
    from Crypto.Cipher import DES
    from Crypto.Util.number import *
    c = b'Re__Point\x00\x00\x00\x00\x00\x00\x00' # 明文
    key = b'ctfctfct' #密钥
    des = DES.new(key, mode=DES.MODE_ECB)
    m = des.encrypt(c)
    print(m)
    # b'\x9d\x16\xa0\xba \xac\xd0\xfd\x80Bq\xaf\xe6`\xbcN'

DES解密

python

1
2
3
4
5
6
7
8
from Crypto.Cipher import DES
from Crypto.Util.number import *
m = b'\x9d\x16\xa0\xba \xac\xd0\xfd\x80Bq\xaf\xe6`\xbcN'
key = b'ctfctfct' #密钥
des = DES.new(key, mode=DES.MODE_ECB)
c = des.decrypt(m)
print(c)
b'Re__Point\x00\x00\x00\x00\x00\x00\x00'

C#

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
using System.Security.Cryptography;
using System.Text;
string encryptKey = "test";
string EncryptData = "xZWDZaKEhWNMCbiGYPBIlY3+arozO9zonwrYLiVL4njSez2RYM2WwsGnsnjCDnHs7N43aFvNE54noSadP9F8eEpvTs5QPG+KL0TDE/40nbU=";
string Decrypt(string str)
{
try
{
byte[] bytes = Encoding.Unicode.GetBytes(encryptKey);
byte[] buffer = Convert.FromBase64String(str);
DESCryptoServiceProvider cryptoServiceProvider = new DESCryptoServiceProvider();
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, cryptoServiceProvider.CreateDecryptor(bytes, bytes), CryptoStreamMode.Write);
cryptoStream.Write(buffer, 0, buffer.Length);
cryptoStream.FlushFinalBlock();
byte[] array = memoryStream.ToArray();
cryptoStream.Close();
memoryStream.Close();
return Encoding.Unicode.GetString(array);
}
catch
{
return str;
}
}
string res = Decrypt(EncryptData);
Console.WriteLine(res);

des

Blowfish

  • 常量特征 –> 16进制的 pai hex数据填充PBOX
    1
    2
    3
    4
    5
    p[0] = 0x243F6A88
    P[1] = 0X85A308D3
    P[2] = 0X13198A2E
    P[3] = 0X03707344
    ...
  • 对称加密
  • 密钥长度不定–>32-448位

国密SM4

加解密

python自带库安装

pip install gmssl

SM4加密

1
2
3
4
5
6
7
8
9
10
11
12
13
from gmssl import sm4

key = b"UKFCUKFCUKFCUKFC"
strData = b'Re__Point'

enc = sm4.CryptSM4()
enc.set_key(key, sm4.SM4_ENCRYPT)
res = enc.crypt_ecb(strData)

print("bytes密文:", res)
print("hex密文:", res.hex())
# bytes密文: b"\xa0'&\x04e.:i\x0fXYX\x85\xcc\xad\xe7"
# hex密文: a0272604652e3a690f58595885ccade7

SM4解密

1
2
3
4
5
6
7
8
9
10
11
12
13
from gmssl import sm4

key = b"UKFCUKFCUKFCUKFC"
m = b"\xa0'&\x04e.:i\x0fXYX\x85\xcc\xad\xe7"
# hexstr = 'a0272604652e3a690f58595885ccade7'
# m = bytes.fromhex(hexstr)

enc = sm4.CryptSM4()
enc.set_key(key, sm4.SM4_DECRYPT)
res = enc.crypt_ecb(m)

print("bytes明文:", res)
# bytes明文: b'Re__Point'

加解密的API输入输出默认都是bytes,不是记得转一下,像fromhex什么的。

加解密的唯一区别就是对于key的处理,SM4_ENCRYPTSM4_DECRYPT

特征识别

  • 分组长度、密钥长度为128bit
  • 32轮运算+反序变换
  • sbox常量特征
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    SBOX = [
    0xD6, 0x90, 0xE9, 0xFE, 0xCC, 0xE1, 0x3D, 0xB7, 0x16, 0xB6, 0x14, 0xC2, 0x28, 0xFB, 0x2C, 0x05, 0x2B, 0x67, 0x9A,
    0x76, 0x2A, 0xBE, 0x04, 0xC3, 0xAA, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, 0x9C, 0x42, 0x50, 0xF4, 0x91, 0xEF,
    0x98, 0x7A, 0x33, 0x54, 0x0B, 0x43, 0xED, 0xCF, 0xAC, 0x62, 0xE4, 0xB3, 0x1C, 0xA9, 0xC9, 0x08, 0xE8, 0x95, 0x80,
    0xDF, 0x94, 0xFA, 0x75, 0x8F, 0x3F, 0xA6, 0x47, 0x07, 0xA7, 0xFC, 0xF3, 0x73, 0x17, 0xBA, 0x83, 0x59, 0x3C, 0x19,
    0xE6, 0x85, 0x4F, 0xA8, 0x68, 0x6B, 0x81, 0xB2, 0x71, 0x64, 0xDA, 0x8B, 0xF8, 0xEB, 0x0F, 0x4B, 0x70, 0x56, 0x9D,
    0x35, 0x1E, 0x24, 0x0E, 0x5E, 0x63, 0x58, 0xD1, 0xA2, 0x25, 0x22, 0x7C, 0x3B, 0x01, 0x21, 0x78, 0x87, 0xD4, 0x00,
    0x46, 0x57, 0x9F, 0xD3, 0x27, 0x52, 0x4C, 0x36, 0x02, 0xE7, 0xA0, 0xC4, 0xC8, 0x9E, 0xEA, 0xBF, 0x8A, 0xD2, 0x40,
    0xC7, 0x38, 0xB5, 0xA3, 0xF7, 0xF2, 0xCE, 0xF9, 0x61, 0x15, 0xA1, 0xE0, 0xAE, 0x5D, 0xA4, 0x9B, 0x34, 0x1A, 0x55,
    0xAD, 0x93, 0x32, 0x30, 0xF5, 0x8C, 0xB1, 0xE3, 0x1D, 0xF6, 0xE2, 0x2E, 0x82, 0x66, 0xCA, 0x60, 0xC0, 0x29, 0x23,
    0xAB, 0x0D, 0x53, 0x4E, 0x6F, 0xD5, 0xDB, 0x37, 0x45, 0xDE, 0xFD, 0x8E, 0x2F, 0x03, 0xFF, 0x6A, 0x72, 0x6D, 0x6C,
    0x5B, 0x51, 0x8D, 0x1B, 0xAF, 0x92, 0xBB, 0xDD, 0xBC, 0x7F, 0x11, 0xD9, 0x5C, 0x41, 0x1F, 0x10, 0x5A, 0xD8, 0x0A,
    0xC1, 0x31, 0x88, 0xA5, 0xCD, 0x7B, 0xBD, 0x2D, 0x74, 0xD0, 0x12, 0xB8, 0xE5, 0xB4, 0xB0, 0x89, 0x69, 0x97, 0x4A,
    0x0C, 0x96, 0x77, 0x7E, 0x65, 0xB9, 0xF1, 0x09, 0xC5, 0x6E, 0xC6, 0x84, 0x18, 0xF0, 0x7D, 0xEC, 0x3A, 0xDC, 0x4D,
    0x20, 0x79, 0xEE, 0x5F, 0x3E, 0xD7, 0xCB, 0x39, 0x48]
  • 密钥扩展左移13、23位,常量
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    FK = {0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc};
    CK = {
    0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
    0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
    0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
    0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
    0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
    0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
    0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
    0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279
    };
  • 加密过程线性变换左移2、10、18、24位

Hash

MD5加密

  • md5加密结果分为32位大小写,以及16位的大小写,所谓16位,就是把32位的中间16位拿出来作为密文
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import hashlib

# 待加密信息
str = 'Re__Point'

# 创建md5对象
hash = hashlib.md5()
hash.update(str.encode(encoding='utf-8'))

print('MD5 32位大写:' + hash.hexdigest().upper())
print('MD5 32位小写:' + hash.hexdigest())
print('MD5 16位大写:' + hash.hexdigest().upper()[8:24])
print('MD5 16位小写:' + hash.hexdigest()[8:24])
# MD5 32位大写:10003ED3EAC0EACE23903FE4E1C46AF9
# MD5 32位小写:10003ed3eac0eace23903fe4e1c46af9
# MD5 16位大写:EAC0EACE23903FE4
# MD5 16位小写:eac0eace23903fe4

C#版本

1
2
3
4
5
6
7
byte[] input = new byte[] { 0x52, 0x65, 0x5f, 0x5f, 0x50, 0x6f, 0x69, 0x6e, 0x74 };
byte[] hash = MD5.Create().ComputeHash(input);
foreach (byte b in hash)
{
Console.Write(b.ToString("X2"));
}
//10003ED3EAC0EACE23903FE4E1C46AF9

md5常量特征

1
2
3
4
5
ABCD
0x67452301
0x0EFCDAB89
0x98BADCFE
0x10325476
  • 常量表
    md5

  • 64轮移位表

md52

对于sha系列来讲,后面的256等数字代表的就是密文的长度

sha1加密

1
2
3
4
5
6
7
8
import hashlib

# 待加密信息
m = 'Re__Point'

m = hashlib.sha1(m.encode())
print(m.hexdigest())
# 58b5726286c194aadedb8f5eb487e4e3d4481599

sha224加密

1
2
3
4
5
6
7
8
import hashlib

# 待加密信息
m = 'Re__Point'

m = hashlib.sha224(m.encode())
print(m.hexdigest())
# d373adb1ba1aaade68e703c996b775fa4d28fb7590c4df7288ee9bf0

sha256加密

1
2
3
4
5
6
7
8
import hashlib

# 待加密信息
m = 'Re__Point'

m = hashlib.sha256(m.encode())
print(m.hexdigest())
# c5a537c99cba9982a8e31cadd728fd47551bf313a2427b3f433118dfa4ff1524

sha384加密

1
2
3
4
5
6
7
8
import hashlib

# 待加密信息
m = 'Re__Point'

m = hashlib.sha384(m.encode())
print(m.hexdigest())
# 5b3a57d15a71dd103865ba3fbdcce505b1b23ec2da90c589c576a6fdfbf3875ee63bf67b8defe665923cf7b761391961

sha512加密

1
2
3
4
5
6
7
8
import hashlib

# 待加密信息
m = 'Re__Point'

m = hashlib.sha512(m.encode())
print(m.hexdigest())
# fd4098f22c84a218cadba35eb36215422e76c407fa31ff00ce81b0f6ab4a1e79ead775fa7b504e39d3d25f52e6ebec74601d870ae3a7e438dcd997e573f67478

解密网站

CRC64

  • 多项式除法
    1
    2
    3
    4
    5
    6
    7
    CRC?
    for i in range(?):
    if (crcnum最高位) == 1:
    crcnum = (crcnum<<1) ^ poly
    else:
    crcnum <<= 1
    return crcnum
    还原:
1
2
3
4
5
6
7
CRC?
for i in range(?):
if (crcnum最低位) == 1:
crcnum = (crcnum ^ poly) >> 1
else:
crcnum >>= 1
return crcnum

RSA

1
2
3
4
5
6
7
8
9
10
11
12
13
14
typedef unsigned long long ll;
ll Pow(ll a, ll b)
{
ll res = 1; //初始化结果为1
//当指数不为0时继续计算
while(b)
{
if(b % 2 == 1) { res *= a; }
//将底数a扩大,指数b减半
a *= a;
b /= 2;
}
return res;
}

快速幂伪代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
__int64 __fastcall sub_DC3(__int64 a1, __int64 a2, __int64 a3)
{
__int64 result; // rax
__int64 v4; // [rsp+18h] [rbp-8h]

if ( a1 < 0 || a2 < 0 || a3 <= 0 )
exit(1);
v4 = a1 % a3;
if ( !a2 )
return 1LL;
if ( a2 == 1 )
return a1 % a3;
if ( (a2 & 1) == 0 )
return sub_DC3(v4 * v4 % a3, a2 / 2, a3) % a3;
result = a2 % 2;
if ( a2 % 2 == 1 )
return v4 * sub_DC3(v4, a2 - 1, a3) % a3;
return result;