avatar

RE crypto

reverse之密码算法

1.base64编码

加密原理

base64加密流程,将三个八字节数据为一组合成一个24位的数据,再把这24位重新拆分成4组6位为一组的数据,将6位一组的数据作为字母表下标,因此重新生成编码

字母表如下:

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

若加密字符长度求余3为1 ,则将其余下的一位用0补至12位,重新生成两个字符最后再加上两个’=’

若加密字符长度求余3为2,则将其余下的两位用0补至18位,重新生成三个字符最后再加上一个’=’

例如字符串’1’编码后

'1’转换为二进制0011 0001 前6位为0011 00 对应着index为12 为字符M 最后两位01补齐后为010000 index为16

对应着Q 所以’1’的base64编码为MQ==

因此base64长度若原长度能够被3整除,则加密长度为原长度的4/3倍

否则为原长度的4/3倍+4

'12’的字符串编码?

base64 In CTF

easy Base64

提示:简单的base64

1
2
3
4
5
6
7
8
9
10
11
12
13
import base64

s ="e3nifIH9b_C@n@dH"

flag =""

for i in range(len(s)):

flag += chr(ord(s[i])- i)

flag = base64.b64decode(flag)

print(flag)

changed Base64

提示:字母表变换

1
2
3
4
5
6
7
8
9
10
11
12
#include<stdio.h>
#include<Windows.h>
int main()
{
char arr[] = "8F]Z:F)&=E$T+S%4,6PU:#1M5T4Q5D,]";
char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
for (int i = 0; i < sizeof(arr) / sizeof(char); i++)
{
printf("%c", base64_table[arr[i] - 32]);
}
system("pause");
}

得到结果Ym96amJGdlE0LzFUMWw1aDRtV0UxVkM9进行base64解密得到结果bozjbFvQ4/1T1l5h4mWE1VC=

再换表解密得到结果

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
import binascii
base64_table='OPQRSTUVWXYZ0123456789+/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN'
base_encode=str(raw_input(u"请输入解密字符"))
counter=base_encode.count("=")
length=len(base_encode)
encode=""
encode_re=""
if(counter==2):
a=base64_table.find(base_encode[length-4:length-3])#取前六位
a=a<<2
b=base64_table.find(base_encode[length-3:length-2])#取2位
b=b>>4
encode_re=chr(a+b)
if(counter==1):
a=base64_table.find(base_encode[length-4:length-3])#第一个字符前6位
a=a<<2
b=base64_table.find(base_encode[length-3:length-2])#第二个字符前2位
b=b>>4
encode_re1=chr(a+b)
a=base64_table.find(base_encode[length-3:length-2])#第二个字符后4位
a=(a&0xf)<<4
b=base64_table.find(base_encode[length-2:length-1])#第三个字符前4位
b=b>>2
encode_re2=chr(a+b)
encode_re=encode_re1+encode_re2
length=length-4
if(counter==0):
length=length+4
for i in range(0,length,4):#以4个字符为一组
a=base64_table.find(base_encode[i:i+1])#第一个字符6位
a=a<<2
b=base64_table.find(base_encode[i+1:i+2])#第二个字符前2位
b=b>>4
encode=encode+chr(a+b)
a=base64_table.find(base_encode[i+1:i+2])#第二个字符后4位
a=((a&0xf)<<4)
b=base64_table.find(base_encode[i+2:i+3])#第三个字符前4位
b=b>>2
encode=encode+chr(a+b)
a=base64_table.find(base_encode[i+2:i+3])#取第三个字符后2位
a=(a&3)<<6
b=base64_table.find(base_encode[i+3:i+4])#取第四个字符6位
encode=encode+chr(a+b)
encode=encode+encode_re
print encode
print( binascii.b2a_hex(encode))
print('\n')

2.RC4加密

加密原理

初始化长度为256的S盒。第一个for循环将0到255的互不重复的元素装入S盒。第二个for循环根据密钥打乱S盒。

1
2
3
4
5
6
7
8
for i from 0 to 255
S[i] := i
endfor
j := 0
for( i=0 ; i<256 ; i++)
j := (j + S[i] + key[i mod keylength]) % 256
swap values of S[i] and S[j]
endfor

下面i,j是两个指针。每收到一个字节,就进行while循环。通过一定的算法((a),(b))定位S盒中的一个元素,并与输入字节异或,得到k。循环中还改变了S盒(©)。如果输入的是明文,输出的就是密文;如果输入的是密文,输出的就是明文。

1
2
3
4
5
6
7
8
9
i := 0
j := 0
while GeneratingOutput:
i := (i + 1) mod 256 //a
j := (j + S[i]) mod 256 //b
swap values of S[i] and S[j] //c
k := inputByte ^ S[(S[i] + S[j]) % 256]
output K
endwhile

RC4 in CTF

题目RC4&BASE64

首先RC4解密

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
64
65
66
67
68
69
70
71
72
73
#include<stdio.h>
#include<string>
#include<windows.h>
void rc4_init(unsigned char*s, unsigned char*key, unsigned long Len)
{
int i = 0, j = 0;
//char k[256]={0};
unsigned 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];
printf("copy for dongdeng");
s[i] = s[j];//交换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 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];
}
}
int main()
{
unsigned char s[256] = { 0 }, s2[256] = { 0 };//S-box
char key[256] = { "flag{this_is_not_the_flag_hahaha}" };
BYTE pData[47] = {
0x20, 0xC3, 0x1A, 0xAE, 0x97, 0x3C, 0x7A, 0x41, 0xDE, 0xF6, 0x78, 0x15,
0xCB, 0x4B, 0x4C, 0xDC, 0x26, 0x55, 0x8B, 0x55, 0xE5, 0xE9, 0x55, 0x75, 0x40, 0x3D, 0x82, 0x13,
0xA5, 0x60, 0x13, 0x3B, 0xF5, 0xD8, 0x19, 0x0E, 0x47, 0xCF, 0x5F, 0x5E, 0xDE, 0x9D, 0x14, 0xBD
};//填写加密数据
unsigned long len = strlen((char *)pData);
int i;

printf("pData=%s\n", pData);
printf("key=%s,length=%d\n\n", key, strlen(key));
rc4_init(s, (unsigned char*)key, strlen(key));//已经完成了初始化
printf("完成对S[i]的初始化,如下:\n\n");
for (i = 0; i<256; i++)
{
printf("%02X", s[i]);
if (i && (i + 1) % 16 == 0)putchar('\n');
}
printf("\n\n");
for (i = 0; i<256; i++)//用s2[i]暂时保留经过初始化的s[i],很重要的!!!
{
s2[i] = s[i];
}
//printf("已经初始化,现在加密:\n\n");
//rc4_crypt(s, (unsigned char*)pData, len);//加密
//printf("pData=%s\n\n", pData);
//printf("已经加密,现在解密:\n\n");
//rc4_init(s,(unsigned char*)key,strlen(key));//初始化密钥
rc4_crypt(s2, (unsigned char*)pData, len);//解密
printf("pData=%s\n\n", pData);
system("pause");
return 0;
}

得到结果ZeptZ3l5UHQra25nd19yYzMrYR5wX2Jtc2P2VF9gYNM9

接着变种base64解密

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
import binascii
base64_table='ABCDEFGHIJSTUVWKLMNOPQRXYZabcdqrstuvwxefghijklmnopyz0123456789+/'
base_encode=str(raw_input(u"请输入解密字符"))
counter=base_encode.count("=")
length=len(base_encode)
encode=""
encode_re=""
if(counter==2):
a=base64_table.find(base_encode[length-4:length-3])#取前六位
a=a<<2
b=base64_table.find(base_encode[length-3:length-2])#取2
b=b>>4
encode_re=chr(a+b)
if(counter==1):
a=base64_table.find(base_encode[length-4:length-3])#第一个字符前6
a=a<<2
b=base64_table.find(base_encode[length-3:length-2])#第二个字符前2
b=b>>4
encode_re1=chr(a+b)
a=base64_table.find(base_encode[length-3:length-2])#第二个字符后4
a=(a&0xf)<<4
b=base64_table.find(base_encode[length-2:length-1])#第三个字符前4
b=b>>2
encode_re2=chr(a+b)
encode_re=encode_re1+encode_re2
length=length-4
if(counter==0):
length=length+4
for i in range(0,length,4):#以4个字符为一组
a=base64_table.find(base_encode[i:i+1])#第一个字符6
a=a<<2
b=base64_table.find(base_encode[i+1:i+2])#第二个字符前2
b=b>>4
encode=encode+chr(a+b)
a=base64_table.find(base_encode[i+1:i+2])#第二个字符后4
a=((a&0xf)<<4)
b=base64_table.find(base_encode[i+2:i+3])#第三个字符前4
b=b>>2
encode=encode+chr(a+b)
a=base64_table.find(base_encode[i+2:i+3])#取第三个字符后2
a=(a&3)<<6
b=base64_table.find(base_encode[i+3:i+4])#取第四个字符6
encode=encode+chr(a+b)
encode=encode+encode_re
print encode
print( binascii.b2a_hex(encode))
print('\n')

3.TEA系列(微型加密算法)

特征

含有Golden Ratio=0x9E3779B9

密钥长度为16byte(128位)

TEA

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
#include <stdio.h>
#include <stdint.h>

//加密函数
void encrypt (uint32_t* v, uint32_t* k) {
uint32_t v0=v[0], v1=v[1], sum=0, i; /* set up */
uint32_t delta=0x9e3779b9; /* a key schedule constant */
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */
for (i=0; i < 32; i++) { /* basic cycle start */
sum += delta;
v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
} /* end cycle */
v[0]=v0; v[1]=v1;
}
//解密函数
void decrypt (uint32_t* v, uint32_t* k) {
uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, i; /* set up */
uint32_t delta=0x9e3779b9; /* a key schedule constant */
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */
for (i=0; i<32; i++) { /* basic cycle start */
v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
sum -= delta;
} /* end cycle */
v[0]=v0; v[1]=v1;
}

int main()
{
uint32_t v[2]={1,2},k[4]={2,2,3,4};
// v为要加密的数据是两个32位无符号整数
// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
printf("加密前原始数据:%u %u\n",v[0],v[1]);
encrypt(v, k);
printf("加密后的数据:%u %u\n",v[0],v[1]);
decrypt(v, k);
printf("解密后的数据:%u %u\n",v[0],v[1]);
return 0;
}

XTEA

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
#include <stdio.h>
#include <stdint.h>

/* take 64 bits of data in v[0] and v[1] and 128 bits of key[0] - key[3] */

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;
}

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;//num_rounds建议取值为32
// v为要加密的数据是两个32位无符号整数
// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
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

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
64
65
#include <stdio.h>
#include <stdint.h>
#define DELTA 0x9e3779b9
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))

void btea(uint32_t *v, int n, uint32_t const key[4])
{
uint32_t y, z, sum;
unsigned p, rounds, e;
if (n > 1) /* Coding Part */
{
rounds = 6 + 52/n;
sum = 0;
z = v[n-1];
do
{
sum += DELTA;
e = (sum >> 2) & 3;
for (p=0; p<n-1; p++)
{
y = v[p+1];
z = v[p] += MX;
}
y = v[0];
z = v[n-1] += MX;
}
while (--rounds);
}
else if (n < -1) /* Decoding Part */
{
n = -n;
rounds = 6 + 52/n;
sum = rounds*DELTA;
y = v[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];
y = v[0] -= MX;
sum -= DELTA;
}
while (--rounds);
}
}


int main()
{
uint32_t v[2]= {1,2};
uint32_t const k[4]= {2,2,3,4};
int n= 2; //n的绝对值表示v的长度,取正表示加密,取负表示解密
// v为要加密的数据是两个32位无符号整数
// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
printf("加密前原始数据:%u %u\n",v[0],v[1]);
btea(v, n, k);
printf("加密后的数据:%u %u\n",v[0],v[1]);
btea(v, -n, k);
printf("解密后的数据:%u %u\n",v[0],v[1]);
return 0;
}

TEA in CTF

例题:Tea相关

认清三种TEA加密

解密代码

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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include<Windows.h>
#include <stdint.h>
#define DELTA 0x9e3779b9
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))
void btea(uint32_t *v, int n, uint32_t const key[4])
{
uint32_t y, z, sum;
unsigned p, rounds, e;
if (n > 1) /* Coding Part */
{
rounds = 6 + 52 / n;
sum = 0;
z = v[n - 1];
do
{
sum += DELTA;
e = (sum >> 2) & 3;
for (p = 0; p<n - 1; p++)
{
y = v[p + 1];
z = v[p] += MX;
}
y = v[0];
z = v[n - 1] += MX;
} while (--rounds);
}
else if (n < -1) /* Decoding Part */
{
n = -n;
rounds = 6 + 52 / n;
sum = rounds*DELTA;
y = v[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];
y = v[0] -= MX;
sum -= DELTA;
} while (--rounds);
}
}
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;
}
void decrypt(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0xC6EF3720, i; /* set up */
uint32_t delta = 0x9e3779b9; /* a key schedule constant */
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; /* cache key */
for (i = 0; i<32; i++) { /* basic cycle start */
v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
sum -= delta;
} /* end cycle */
v[0] = v0; v[1] = v1;
}

int main()
{
unsigned int v[2] = { 0xE96DCB1C,0x5434E1AC };
unsigned int key[4] = { 0x656d6f63, 0x7469775f, 0x656d5f68, 0x646E655f };
printf("解密后的数据:%x %x\n", v[0], v[1]);
btea(v, -2, key);
printf("解密后的数据:%x %x\n", v[0], v[1]);
decipher(32, v, key);
printf("解密后的数据:%x %x\n", v[0], v[1]);
decrypt(v, key);
printf("解密后的数据:%x %x\n", v[0], v[1]);
system("pause");

}

4.SM4

国密SM4(无线局域网SMS4)算法, 一个分组算法, 分组长度为128bit, 密钥长度为128bit(长度为16位)

特征

  • 系统参数FK 0xA3B1BAC6 0x56AA3350 0x677D9197 0xB27022DC
  • S盒

SM4 in CTF

找到关键点判断SM4:解密

1
2
3
4
5
6
from pysm4 import encrypt, decrypt
mk = 0x636F6D655F776974685F6D655F656E64
cipher_num = 0xbc0d155d831fc8ff94f2340a42441486
clear_num = decrypt(cipher_num, mk)
print hex(clear_num)
print hex(clear_num)[2:-1].decode("hex")

5.MD5

特征

5个初始变量

1
2
3
4
var int h0 := 0x67452301
var int h1 := 0xEFCDAB89
var int h2 := 0x98BADCFE
var int h3 := 0x10325476

MD5 in ctf

MD5解密

6.RSA

简介

RSA加密算法是一种非对称加密算法,在公开密钥加密电子商业中被广泛使用

加密原理

  • 公开密钥 n,e
  • m为原信息
  • c为加密信息
  • d为解密密钥

加密过程:(m^e) mod n=c

解密过程:(c^d) mod n=m

RSA in CTF

利用gmpy2库解方程组

1
2
3
4
5
6
7
import gmpy2
n=103461035900816914121390101299049044413950405173712170434161686539878160984549
phin=282164587459512124844245113950593348270*366669102002966856876605669837014229418
e=65537
d=gmpy2.invert(e,phin)
m=gmpy2.powmod(0xad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35,d,n)
print hex(m)[2:].decode("hex")
Author: L0x1c
Link: https://l0x1c.github.io/2020/01/10/2020-1-2/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Donate
  • 微信
    微信
  • 支付寶
    支付寶