参考自 https://www.cnblogs.com/Moomin/p/15004170.html#aes
Base64
识别
一个索引串ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
IO
可能做魔改调整, 6位索引一个ascii码的索引换掉,此时我们用bytes.maketrans方法定义一个转换函数即可。
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
| import base64 encoded_data = base64.b64encode(data.encode('utf-8')) decoded_data = base64.b64decode(encoded_data).decode('utf-8')
custom_alphabet = "ZYXABCDEFGHIJKLMNOPQRSTUVWzyxabcdefghijklmnopqrstuvw0123456789+/"
custom_b64encode_table = bytes.maketrans( b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", custom_alphabet.encode('utf-8') ) custom_b64decode_table = bytes.maketrans( custom_alphabet.encode('utf-8'), b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" )
def custom_b64encode(data): encoded = base64.b64encode(data) return encoded.translate(custom_b64encode_table)
def custom_b64decode(data): translated = data.translate(custom_b64decode_table) return base64.b64decode(translated)
encoded_data = custom_b64encode(data.encode('utf-8')) decoded_data = custom_b64decode(encoded_data).decode('utf-8')
|
RC4
识别
对称,流加密,2个核心,初始化S盒,加密和解密是对称的。识别方式主要是看一个256次的for循环,尤其是s盒初始化函数,其对256字节的数组按照下标从0开始赋值,这一特征比较明显。
其他特征可以参考下面的代码。
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 28 29 30 31
| void rc4_init(unsigned char*s,unsigned char*key,unsigned long Len) { int i=0,j=0; unsigned char tmp = 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; tmp=s[i]; s[i]=s[j]; s[j]=tmp; } }
void rc4_crypt(unsigned char*s,unsigned char*Data,unsigned Long Len) { int i=0,j=0,t=0; unsigned long k=0; unsigned long tmp; for(k=0;k<Len;k++){ i=(i+1)%256; j=(j+s[i])%256; tmp=s[i]; s[i]=s[j]; s[j]=tmp; t=(s[i]+s[j])%256; Data[k]^=s[t]; } }
|
IO
需求crypto模块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| from Crypto.Cipher import ARC4 from Crypto.Random import get_random_bytes
key = get_random_bytes(16)
cipher = ARC4.new(key)
data = "Hello, World!" encrypted_data = cipher.encrypt(data.encode('utf-8')) print(f"Encrypted: {encrypted_data}")
cipher = ARC4.new(key)
decrypted_data = cipher.decrypt(encrypted_data).decode('utf-8') print(f"Decrypted: {decrypted_data}")
|
注意的是,rc4是一个流加密算法,每次初始化只能获得一个固定的加密器,即new一次之后,后续调用encrypt时会一直“继续”当前的加密,即假设几次需要加密的明文是连续的。如果题目中的rc4每次调用都走了一遍初始化流程,则io也需要对应的每次都new一个新的加密器——即使密钥没有发生变化。
另外,rc4作为对称加密,加解密算法是一样的。
AES
识别
老生常谈,标准AES的识别就是其独有的S盒内容。其S盒和逆S盒数据如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 0 1 2 3 4 5 6 7 8 9 A B C D E F 0 63 7c 77 7b f2 6b 6f c5 30 1 67 2b fe d7 ab 76 1 ca 82 c9 7d fa 59 47 f0 ad d4 a2 af 9c a4 72 c0 2 b7 fd 93 26 36 3f f7 cc 34 a5 e5 f1 71 d8 31 15 3 4 c7 23 c3 18 96 5 9a 7 12 80 e2 eb 27 b2 75 4 9 83 2c 1a 1b 6e 5a a0 52 3b d6 b3 29 e3 2f 84 5 53 d1 0 ed 20 fc b1 5b 6a cb be 39 4a 4c 58 cf 6 d0 ef aa fb 43 4d 33 85 45 f9 2 7f 50 3c 9f a8 7 51 a3 40 8f 92 9d 38 f5 bc b6 da 21 10 ff f3 d2 8 cd c 13 ec 5f 97 44 17 c4 a7 7e 3d 64 5d 19 73 9 60 81 4f dc 22 2a 90 88 46 ee b8 14 de 5e b db a e0 32 3a a 49 6 24 5c c2 d3 ac 62 91 95 e4 79 b e7 c8 37 6d 8d d5 4e a9 6c 56 f4 ea 65 7a ae 8 c ba 78 25 2e 1c a6 b4 c6 e8 dd 74 1f 4b bd 8b 8a d 70 3e b5 66 48 3 f6 e 61 35 57 b9 86 c1 1d 9e e e1 f8 98 11 69 d9 8e 94 9b 1e 87 e9 ce 55 28 df f 8c a1 89 d bf e6 42 68 41 99 2d f b0 54 bb 16
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 0 1 2 3 4 5 6 7 8 9 A B C D E F 0 52 9 6a d5 30 36 a5 38 bf 40 a3 9e 81 f3 d7 fb 1 7c e3 39 82 9b 2f ff 87 34 8e 43 44 c4 de e9 cb 2 54 7b 94 32 a6 c2 23 3d ee 4c 95 b 42 fa c3 4e 3 8 2e a1 66 28 d9 24 b2 76 5b a2 49 6d 8b d1 25 4 72 f8 f6 64 86 68 98 16 d4 a4 5c cc 5d 65 b6 92 5 6c 70 48 50 fd ed b9 da 5e 15 46 57 a7 8d 9d 84 6 90 d8 ab 0 8c bc d3 a f7 e4 58 5 b8 b3 45 6 7 d0 2c 1e 8f ca 3f f 2 c1 af bd 3 1 13 8a 6b 8 3a 91 11 41 4f 67 dc ea 97 f2 cf ce f0 b4 e6 73 9 96 ac 74 22 e7 ad 35 85 e2 f9 37 e8 1c 75 df 6e a 47 f1 1a 71 1d 29 c5 89 6f b7 62 e aa 18 be 1b b fc 56 3e 4b c6 d2 79 20 9a db c0 fe 78 cd 5a f4 c 1f dd a8 33 88 7 c7 31 b1 12 10 59 27 80 ec 5f d 60 51 7f a9 19 b5 4a d 2d e5 7a 9f 93 c9 9c ef e a0 e0 3b 4d ae 2a f5 b0 c8 eb bb 3c 83 53 99 61 f 17 2b 4 7e ba 77 d6 26 e1 69 14 63 55 21 c 7d
|
前4个字节就够了,search一下发现了基本100%是AES。相关函数全跳过就行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| graph TD A[明文] -->|分组| B[初始轮密钥加] B --> C[轮函数] C -->|重复Nr-1次| D[最终轮] D --> E[密文]
subgraph 轮函数 C1[字节代换] --> C2[行移位] C2 --> C3[列混淆] C3 --> C4[轮密钥加] end
subgraph 最终轮 D1[字节代换] --> D2[行移位] D2 --> D3[轮密钥加] end
|
可能有魔改,如果识别算法的话重点在以下:
IO
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| from Crypto.Cipher import AES from Crypto.Random import get_random_bytes from Crypto.Util.Padding import pad, unpad
key = get_random_bytes(16) iv = get_random_bytes(16)
cipher = AES.new(key, AES.MODE_CBC, iv)
data = "Hello, World!" padded_data = pad(data.encode('utf-8'), AES.block_size) encrypted_data = cipher.encrypt(padded_data) print(f"Encrypted: {encrypted_data}")
cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted_data = unpad(cipher.decrypt(encrypted_data), AES.block_size).decode('utf-8') print(f"Decrypted: {decrypted_data}")
|
TEA
目前没遇见过,只能抄了
tea也是一个简单的对称加密算法,初始化一个128位密钥,按64位分组处理明文。其中有一个magic_number DELTA:
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| #include<stdio.h> #include<stdint.h> #define DELTA 0x9981abcd
void tea_encrypt(unsigned int* v, unsigned int* key) { unsigned int l = v[0], r = v[1], sum = 0; for (size_t i = 0; i < 32; i++) { l += (((r << 4) ^ (r >> 5)) + r) ^ (sum + key[sum & 3]); sum += DELTA; r += (((l << 4) ^ (l >> 5)) + l) ^ (sum + key[(sum >> 11) & 3]); } v[0] = l; v[1] = r; }
void tea_decrypt(unsigned int* v, unsigned int* key) { unsigned int l = v[0], r = v[1], sum = 0; sum = DELTA * 32; for (size_t i = 0; i < 32; i++) { r -= (((l << 4) ^ (l >> 5)) + l) ^ (sum + key[(sum >> 11) & 3]); sum -= DELTA; l -= (((r << 4) ^ (r >> 5)) + r) ^ (sum + key[sum & 3]); } v[0] = l; v[1] = r; }
int main(int argc, char const *argv[]) { unsigned int key1[4]={0xa3eeb7be,0x50e7de9a,0x6dbcc2bc,0x78591fad}; unsigned int key2[4]={0x78591fad,0x6dbcc2bc,0xa3eeb7be,0x50e7de9a}; unsigned int v1[2] = {0x556E2853,0x4393DF16}; unsigned int v2[2] = {0x1989FB2B,0x83F5A243}; tea_decrypt(v1,key1); printf("tea_decrypt:%x %x\n",v1[0],v1[1]); tea_decrypt(v2,key2); printf("tea_decrypt:%x %x\n",v2[0],v2[1]); return 0; }
|
其中默认的DELTA一般为 0x9e3779b9 或者 0x61c88647(分别是加和减,其实影响是等价的)
魔改算法一般会修改这个DELTA值,不过识别也很容易,这个值太孤立了。
IO
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 28 29 30 31 32 33 34 35 36 37
| DELTA = 0x9981abcd
def tea_encrypt(v, key): l, r = v[0], v[1] sum = 0 for _ in range(32): l += (((r << 4) ^ (r >> 5)) + r) ^ (sum + key[sum & 3]) sum += DELTA r += (((l << 4) ^ (l >> 5)) + l) ^ (sum + key[(sum >> 11) & 3]) return [l, r]
def tea_decrypt(v, key): l, r = v[0], v[1] sum = DELTA * 32 for _ in range(32): r -= (((l << 4) ^ (l >> 5)) + l) ^ (sum + key[(sum >> 11) & 3]) sum -= DELTA l -= (((r << 4) ^ (r >> 5)) + r) ^ (sum + key[sum & 3]) return [l, r]
key1 = [0xa3eeb7be, 0x50e7de9a, 0x6dbcc2bc, 0x78591fad] key2 = [0x78591fad, 0x6dbcc2bc, 0xa3eeb7be, 0x50e7de9a] v1 = [0x556E2853, 0x4393DF16] v2 = [0x1989FB2B, 0x83F5A243]
encrypted_v1 = tea_encrypt(v1, key1) encrypted_v2 = tea_encrypt(v2, key2) print(f"Encrypted v1: {encrypted_v1}") print(f"Encrypted v2: {encrypted_v2}")
decrypted_v1 = tea_decrypt(encrypted_v1, key1) decrypted_v2 = tea_decrypt(encrypted_v2, key2) print(f"Decrypted v1: {decrypted_v1}") print(f"Decrypted v2: {decrypted_v2}")
|
MD5
识别
128位散列值,需要一个context结构体,分三步,init,updatestring和final
其中init过程会将context初始化为4个固定的magic_number:
1 2 3 4 5 6 7 8 9 10
| void MD5Init (MD5_CTX *context)
{ context->count[0] = context->count[1] = 0; context->state[0] = 0x67452301; context->state[1] = 0xefcdab89; context->state[2] = 0x98badcfe; context->state[3] = 0x10325476; }
|
IO
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import hashlib
data = "Hello, World!"
md5_hash = hashlib.md5()
md5_hash.update(data.encode('utf-8'))
hash_value = md5_hash.hexdigest()
print(f"MD5 Hash: {hash_value}")
|