TEA加密
特征
有个delta
加解密密钥,4个32位无符号整数
两个传入左值与右值
加密脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
特别提醒,一定要uint32_t 或者unsigned int
*/
void tea_enc(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1];
uint32_t sum = 0;
uint32_t delta = 0xd33b470;
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;
}
解密脚本
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
/*
特别提醒,一定要uint32_t 或者unsigned int
*/
#include <stdint.h>
#include <stdio.h>
void tea_dec(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1]; // v0、v1分别是密文的左、右半部分
uint32_t delta = 0xd33b470; //作为sum每次累加的变化值,题目中往往会修改此值
uint32_t sum = 32 * delta; //此处需要分析32轮加密结束后sum的值与delta的变化, 以此处加密为例子,32轮每次sum+=delta,因此最后sum=32*delta
for (int i = 0; i < 32; i++) { // tea加密进行32轮
//根据加密时的顺序颠倒下面3行的顺序,将加法改为减法(异或部分都是整体,不用管),就是逆向解密过程
v1 -= ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3]);
v0 -= ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1]);
sum -= delta;
}
// 解密后的内容要还给v数组
v[0] = v0;
v[1] = v1;
}
int main() {
// k为加解密密钥,4个32位无符号整数,密钥长度为128位
uint32_t k[4] = {1, 2, 3, 4};
// v为要加解密的数据,两个32位无符号整数
//但是稍微难一点点的都不会直接加密两个uint32_t,除非签到题。像这里的例子就是给了32个uint8_t
//(常见的题目还有给几个uint32_t的,其实无非是拆开写成0x17、0x65...和连着写成0x1765的区别)
//在后面的循环里每次传两组,每组4个组成uint32_t用于tea算法
int8_t input[32] = {0x17, 0x65, 0x54, 0x89, 0xed, 0x65, 0x46, 0x32, 0x3d, 0x58, 0xa9, 0xfd, 0xe2, 0x5e, 0x61, 0x97,
0xe4, 0x60, 0xf1, 0x91, 0x73, 0xe9, 0xe9, 0xa2, 0x59, 0xcb, 0x9a, 0x99, 0xec, 0xb1, 0xe1, 0x7d};
for (int i = 0; i < 32; i += 8) {
//每组4个组成uint32_t用于tea算法,tea算法每次加解密操作的v一定是两个uint_32,至于怎么传入两个uint_32,题目有各种呈现方式,需要做题者自行分析
uint32_t v[2] = {*(uint32_t*)&input[i], *(uint32_t*)&input[i + 4]};
tea_dec(v, k);
// tea输出字符的固定算法,外层循环两次是因为明文分为左半和右半两个uint32_t
// 内层循环4次是因为一个字符占1个字节即8位,每次&0xff可以摘下最后1字节打印出对应ASCII字符,然后>>8准备下一字节
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 4; k++) {
printf("%c", v[j] & 0xff);
v[j] >>= 8;
}
}
}
return 0;
}
XTEA加密
特征
同tea
放到delta自增过程放中间
加密脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*
特别提醒,一定要uint32_t 或者unsigned int
*/
void encipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]){
unsigned int i;
uint32_t v0=v[0],v1=v[1],sum=0,delta=0x9E3779B9;
for(i=0;i<num_rounds;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;
}
解密脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void decipher(unsigned int num_rounds,uint32_t v[2],uint32_t const key[4]){
unsigned int i;
uint32_t v0=v[0],v1=v[1],delta=0x9E3779B9,sum=delta*num_rounds;
for(i=0;i<num_rounds;i++){
v1-=(((v0<<4)^(v0>>5))+v0)^(sum+key[(sum>>11)&3]);
sum-=delta;
v0-=(((v1<<4)^(v1>>5))+v1)^(sum+key[sum&3]);
}
v[0]=v0;v[1]=v1;
}
int main(){
uint32_t v[2]={1,2};
uint32_t const k[4]={2,2,3,4};
unsigned int r=32; //这里是加密轮数,自己设置
printf("加密前原始数据:%u %u\n",v[0],v[1]);
encipher(r,v,k);
printf("加密后原始数据:%u %u\n",v[0],v[1]);
decipher(r,v,k);
printf("解密后原始数据:%u %u\n",v[0],v[1]);
return 0;
}
XXTEA加密
特征
同tea
常见do while语句
加解密脚本
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/*
特别提醒,一定要uint32_t 或者unsigned int
*/
#include <bits/stdc++.h>
using namespace std;
#define MX ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z))
void xxteaEncrtpy(uint32_t *v, size_t n, uint32_t *k)
{
uint32_t y, z, sum;
uint32_t p, rounds, e;
uint32_t delta = 0x9E3779B9;
rounds = 6 + 52 / n;
sum = 0;
z = v[n - 1];
do
{
sum += delta;
e = (sum >> 2) & 3; // 引入非线性计算,使得每次取出的key值缺少规律
for (p = 0; p < n - 1; p++)
{
y = v[p + 1];
z = v[p] += MX; // 每个块加密是增加的偏移量实际上由上一个块(z)和下一个块(y)的值和sum共同决定
}
y = v[0]; // 此处其实是循环加密的端点,当然可以对下标取模写进循环里
z = v[n - 1] += MX;
} while (--rounds); // 实际上是把相同的操作重复round轮
}
void xxteaDecrypt(uint32_t *v, size_t n, uint32_t *k)
{
uint32_t y, z, sum;
uint32_t p, rounds, e;
uint32_t delta = 0x9E3779B9;
rounds = 6 + 52 / n;
sum = rounds * delta;
y = v[0]; // n-1号块的下一个块是0号块
do
{
e = (sum >> 2) & 3;
for (p = n - 1; p > 0; p--) // 反向循环
{
z = v[p - 1]; // 因为是反着循环,所以这里是上一个块
y = v[p] -= MX; // 这里是也是取上一个和下一个块的值作为参数
}
z = v[n - 1]; // 0号块的上一个块是n-1号块
y = v[0] -= MX;
sum -= delta;
} while (--rounds);
}
int main()
{
uint32_t k[4] = {0x01234567, 0x89abcdef, 0xfedcba98, 0x76543210};
char v[] = "Eleven11";
xxteaEncrtpy((uint32_t *)v, strlen(v) / 4, k);
for (int i = 0; i < 8; i++)
printf("%c", v[i] & 0xFF);
printf("\n");
xxteaDecrypt((uint32_t *)v, strlen(v) / 4, k);
for (int i = 0; i < 8; i++)
printf("%c", v[i]);
printf("\n");
return 0;
}
base家族加密
特征
有base码表
1
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
加解密
用cyberchef
RC4家族加密
特征
%256 常见
有一个1-256长度的S盒子
用key生成s盒子
加密解密公用一个算法,可用动态调试解决
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
void rc4_init(unsigned char *s, unsigned char *key, unsigned long Len) //初始化函数 根据key定义s盒
{
int i =0, j = 0;
char k[256] = {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[i]和s[j] 生成新s盒
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 char tmp;
for(k=0;k<Len;k++) {
i=(i+1)%256;
j=(j+s[i])%256;
tmp = s[i];
s[i] = s[j]; //交换s[x]和s[y]
s[j] = tmp;
t=(s[i]+s[j])%256;
Data[k] ^= s[t];
}
}
AES加密
过程
a.加密过程简述:密钥扩展–字节替换–行移位–列混合–轮密钥加。
a) 先将密钥转化为4*4的矩阵进行扩展(这里的扩展会进行移位/异或的一系列操作)
b) 字节替换:AES有一个16×16=256长度的S盒用于替换字节,可以理解为二维数组。将原有字节,例如data=0xab,则替换为s盒中第a行第b列对应的值。(S盒的构造非常麻烦,所以一般是固定的,但也存在魔改AES的情况
c) 行移位:AES的操作基于4*4的矩阵进行,第i行循环左移i字节
d) 列混合:矩阵相乘
e) 轮密钥加:将数据与密钥进行异或
特征:
可能存在iv与key
AES会进行9次循环(准确来说是10次?),且一般在反汇编代码中,每个操作以函数的形式存在
密钥扩展存在轮常量:
1
1000000h, 2000000h, 4000000h, 8000000h, 10000000h, 20000000h, 40000000h, 80000000h, 1B000000h, 36000000h
存在S盒子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
uint8_t sbox[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
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//解密逆S盒子
uint8_t inVsbox[256] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
};
接着将魔改的S盒导入以下博客里的脚本就可以解密
https://blog.csdn.net/weixin_45582916/article/details/121429445
未魔改解密
1
2
3
4
5
6
7
8
9
10
from Crypto.Cipher import AES
from Crypto.Util.number import *
enc=0xBC0AADC0147C5ECCE0B140BC9C51D52B46B2B9434DE5324BAD7FB4B39CDB4B5B
key=0xcb8d493521b47a4cc1ae7e62229266ce
keyy=long_to_bytes(key)
encc=long_to_bytes(enc)
decrypt_str=AES.new(keyy,mode=AES.MODE_ECB)
flag=decrypt_str.decrypt(encc)
print(flag)
SM4加密
特征
一般不会魔改这个算法
128bit明文 128bit密钥 128bit密文
.data 段存在常量
1
2
3
4
5
6
7
8
9
10
11
12
FK为固定值: FK0 = (A3B1BAC6), FK1 = (56AA3350), FK2 = (677D9197), FK3 = (B27022DC)
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]
生成规则:
Ck(jk) = (4i + j) * 7
存在S盒
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
static const unsigned char SboxTable[16][16] =
{
{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}
};
流程
1.密钥拓展
2.加密
附上findcrypt识别规则:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
rule SM4_FK {
meta:
author = "Basstorm"
description = "Look for SM4_FKbox constants"
date = "2020-08"
strings:
$c0 = { C6 BA B1 A3 50 33 AA 56 97 91 7D 67 DC 22 70 B2 }
condition:
$c0
}
rule SM4_CK {
meta:
author = "Basstorm"
description = "Look for SM4_CKbox constants"
date = "2020-08"
strings:
$c0 = { 15 0E 07 00 31 2A 23 1C 4D 46 3F 38 69 62 5B 54 85 7E 77 70 A1 9A 93 8C }
condition:
$c0
}