base变、tea、rc4

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
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
# coding:utf-8

s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"


# s = "vwxrstuopq34567ABCDEFGHIJyz012PQRSTKLMNOZabcdUVWXYefghijklmn89+/"

def My_base64_encode(inputs):
# 将字符串转化为2进制
bin_str = []
for i in inputs:
x = str(bin(ord(i))).replace('0b', '')
bin_str.append('{:0>8}'.format(x))
# print(bin_str)
# 输出的字符串
outputs = ""
# 不够三倍数,需补齐的次数
nums = 0
while bin_str:
# 每次取三个字符的二进制
temp_list = bin_str[:3]
if (len(temp_list) != 3):
nums = 3 - len(temp_list)
while len(temp_list) < 3:
temp_list += ['0' * 8]
temp_str = "".join(temp_list)
# print(temp_str)
# 将三个8字节的二进制转换为4个十进制
temp_str_list = []
for i in range(0, 4):
temp_str_list.append(int(temp_str[i * 6:(i + 1) * 6], 2))
# print(temp_str_list)
if nums:
temp_str_list = temp_str_list[0:4 - nums]

for i in temp_str_list:
outputs += s[i]
bin_str = bin_str[3:]
outputs += nums * '='
print("Encrypted String:\n%s " % outputs)


def My_base64_decode(inputs):
# 将字符串转化为2进制
bin_str = []
for i in inputs:
if i != '=':
x = str(bin(s.index(i))).replace('0b', '')
bin_str.append('{:0>6}'.format(x))
# print(bin_str)
# 输出的字符串
outputs = ""
nums = inputs.count('=')
while bin_str:
temp_list = bin_str[:4]
temp_str = "".join(temp_list)
# print(temp_str)
# 补足8位字节
if (len(temp_str) % 8 != 0):
temp_str = temp_str[0:-1 * nums * 2]
# 将四个6字节的二进制转换为三个字符
for i in range(0, int(len(temp_str) / 8)):
outputs += chr(int(temp_str[i * 8:(i + 1) * 8], 2))
bin_str = bin_str[4:]
print("Decrypted String:\n%s " % outputs)


print()
print(" *************************************")
print(" * (1)encode (2)decode *")
print(" *************************************")
print()

num = input("Please select the operation you want to perform:\n")
if (num == "1"):
input_str = input("Please enter a string that needs to be encrypted: \n")
My_base64_encode(input_str)
else:
input_str = input("Please enter a string that needs to be decrypted: \n")
My_base64_decode(input_str)

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

在 Tea 算法中其最主要的识别特征就是 拥有一个 magic number :0x9e3779b9 。当然,这 Tea 算法也有魔改的,感兴趣的可以看 2018 0ctf Quals milk-tea。

概念

解析 TEA 加密算法(C语言、python):

TEA系列概述:

TEA算法是由剑桥大学计算机实验室的 David Wheeler 和 Roger Needham于1994年发明,TEA 是Tiny Encryption Algorithm的缩写,以加密解密速度快,实现简单著称。

TEA 算法每一次可以操作 64bit(8byte),采用 128bit(16byte) 作为 key,算法采用迭代的形式,推荐的迭代轮数是 64轮,最少 32 轮。

为解决 TEA 算法密钥表攻击的问题,TEA 算法先后经历了几次改进,从 XTEA 到 BLOCK TEA,直至最新的XXTEA。

XTEA 也称做 TEAN:

它使用与 TEA 相同的简单运算,但四个子密钥采取不正规的方式进行混合以阻止密钥表攻击。

Block TEA 算法可以对 32 位的任意整数倍长度的变量块进行加解密的操作:

该算法将 XTEA 轮循函数依次应用于块中的每个字,并且将它附加于被应用字的邻字。

XXTEA使用跟Block TEA相似的结构:

但在处理块中每个字时利用了相邻字,且用拥有两个输入量的 MX 函数代替了 XTEA 轮循函数。

上面提到的相邻字其实就是数组中相邻的项。

TEA 系列算法中均使用了一个 DELTA 常数,但 DELTA 的值对算法并无什么影响,只是为了避免不良的取值,推荐DELTA 的值取为黄金分割数 (5√-2)/2 与 232 的乘积,取整后的十六进制值为 0x9e3779B9,用于保证每一轮加密都不相同。

TEA 加密:

TEA算法介绍:

TEA 采用与 DES 算法类似的 Feistel 结构,迭代的每次循环使用加法和移位操作,对明文和密钥进行扩散和混乱,实现明文的非线性变换。TEA 密钥长度和迭代次数都是 DES 的两倍,抗“试错法”攻击的强度不低于 DES 算法。算法以32bits 的字为运算单位,而不是耗费计算能力的逐位运算。算法没有采用 DES 那样的转换矩阵,它安全、高效、占用存储空间少,非常适合在嵌入式系统中应用, 据说 QQ 就是使用 16 轮迭代的 TEA 算法。

加密过程:(解密过程逆过来即可)

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
28
29
30
31
32
33
34
35
36
#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;
uint32_t delta=0x9e3779b9;
uint32_t k0=k[0],k1=k[1],k2=k[2],k3=k[3];
for(i=0;i<32;i++){
sum+=delta;
v0+=((v1<<4)+k0)^(v1+sum)^((v1>>5)+k1);
v1+=((v0<<4)+k2)^(v0+sum)^((v0>>5)+k3);
}
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; //这里的sum是0x9e3779b9*32后截取32位的结果,截取很重要。
uint32_t delta=0x9e3779b9;
uint32_t k0=k[0],k1=k[1],k2=k[2],k3=k[3];
for (i=0;i<32;i++){
v1-=((v0<<4)+k2)^(v0+sum)^((v0>>5)+k3);
v0-=((v1<<4)+k0)^(v1+sum)^((v1>>5)+k1);
sum-=delta;
}
v[0]=v0;v[1]=v1;
}

int main()
{
uint32_t v[2]={1,2},k[4]={2,2,3,4};
printf("加密前的数据:%u %u\n",v[0],v[1]); //%u 以十进制形式输出无符号整数
encrypt(v,k);
printf("加密后数据:%u %u\n",v[0],v[1]);
decrypt(v,k);
printf("解密后数据:%u %u\n",v[0],v[1]);
return 0;
}

python脚本

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
from ctypes import *


def encrypt(v, k):
v0 = c_uint32(v[0])
v1 = c_uint32(v[1])
sum1 = c_uint32(0)
delta = 0x9e3779b9
for i in range(32):
sum1.value += delta
v0.value += ((v1.value << 4) + k[0]) ^ (v1.value + sum1.value) ^ ((v1.value >> 5) + k[1])
v1.value += ((v0.value << 4) + k[2]) ^ (v0.value + sum1.value) ^ ((v0.value >> 5) + k[3])
return v0.value, v1.value


def decrypt(v, k):
v0 = c_uint32(v[0])
v1 = c_uint32(v[1])
delta = 0x9e3779b9
sum1 = c_uint32(delta * 32)
for i in range(32):
v1.value -= ((v0.value << 4) + k[2]) ^ (v0.value + sum1.value) ^ ((v0.value >> 5) + k[3])
v0.value -= ((v1.value << 4) + k[0]) ^ (v1.value + sum1.value) ^ ((v1.value >> 5) + k[1])
sum1.value -= delta
return v0.value, v1.value


if __name__ == '__main__':
a = [1, 2]
k = [2, 2, 3, 4]
print("加密前数据:", a)
res = encrypt(a, k)
print("加密后的数据:", res)
res = decrypt(res, k)
print("解密后数据:", res)

原文链接:https://blog.csdn.net/xiao__1bai/article/details/123307059

XTEA加密

首先我们还是先了解一下XTEA算法

跟TEA算法很类似,差别就是将r的变化结果和l变化结果进行了交替赋值,同时位移次数进行了一些变化,也掺杂了一些与操作

这里是典型的XTEA加密和异或加密,但是根据给定的key和算法,计算出来的是一个假flag:
fakeflag_plz_Try_more_hard_to_find_the_true_flag

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

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; //这里是加密轮数,自己设置
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;
}

TEA例题

1、

先查壳,放入64

直接运行exe是个fakeflag哈哈哈哈哈

去string里面找关键语句,然后x快捷键去查看调用的函数

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
for ( j = 0; j < 10; ++j )
// 输入函数,scanf
sub_1400111FE("%x", &v8[j]);
// v7重新赋值
sub_140011339(v7);
// v8备份到v9
sub_140011145(v8, v9);
// v7为key,v8为输入的值,进行tea加密
sub_1400112B7(v8, v7);
// 验证加密的结果是否符合预期
v6 = sub_140011352(v8);
if ( v6 )
{
// sub_140011195 为打印函数
printf("you are right\n");
for ( k = 0; k < 10; ++k )
{
for ( m = 3; m >= 0; --m )
printf("%c", (v9[k] >> (8 * m)));
}
}
else
{
printf("fault!\nYou can go online and learn the tea algorithm!");
}

跟进 sub_140011339(v7),发现v7被重新赋值

原来的———————————————————>改后的

1
2
3
4
v7[0] = 1234;
v7[1] = 5678;
v7[2] = 9012;
v7[3] = 3456;
1
2
3
4
5
6
7
8
v6 = 2233;
v7 = 4455;
v8 = 6677;
v9 = 8899;
*a1 = 2233;
a1[1] = v7;
a1[2] = v8;
a1[3] = v9;

// v8备份到v9;

跟进sub_140011145(v8, v9);发现就是一个备份功能的函数

// v7为key,v8为输入的值,进行tea加密

sub_1400112B7(v8, v7);

进入 sub_140011B60 函数,得到加密后的数据,开始写脚本

cexp

经典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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <stdio.h>

int main() {
int key[] = {2233, 4455, 6677, 8899}; // 密钥数组
unsigned int value[10]; // 用于存储加密数据的数组

// 初始化加密数据
value[0] = 0x1A800BDA;
value[1] = 0xF7A6219B;
value[2] = 0x491811D8;
value[3] = 0xF2013328;
value[4] = 0x156C365B;
value[5] = 0x3C6EAAD8;
value[6] = 0x84D4BF28;
value[7] = 0xF11A7EE7;
value[8] = 0x3313B252;
value[9] = 0xDD9FE279;

int delta = 0xF462900; // 一个常量,用于加密算法
int i = 0;
int wheel; // 轮数
int sum = 0;

// 逆算法解密
for (i = 8; i >= 0; i--) {
wheel = 33; // 33轮加密
sum = delta * (i + wheel);
while (wheel--) {
sum -= delta;
value[i + 1] -= (sum + key[(sum >> 11) & 3]) ^ (value[i] + ((value[i] >> 5) ^ (16 * value[i])));
value[i] -= sum ^ (value[i + 1] + ((value[i + 1] >> 5) ^ (16 * value[i + 1]))) ^ (sum + key[sum & 3]);
}
}

// 将解密后的数据转换为字符并输出
for (i = 0; i <= 9; i++) {
printf("%c", (value[i] >> 24) & 0xFF); // 高8位
printf("%c", (value[i] >> 16) & 0xFF); // 次高8位
printf("%c", (value[i] >> 8) & 0xFF); // 次低8位
printf("%c", value[i] & 0xFF); // 低8位
}

return 0;
}

pyexp(会有乱码)

python代码可以会输出乱码,主要是溢出的问题,去掉乱码投机正确,还是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
28
29
30
31
def main():
key = [2233, 4455, 6677, 8899] # 密钥数组
value = [0x1A800BDA, 0xF7A6219B, 0x491811D8, 0xF2013328, 0x156C365B,
0x3C6EAAD8, 0x84D4BF28, 0xF11A7EE7, 0x3313B252, 0xDD9FE279] # 初始化加密数据

delta = 0x0F462900 # 一个常量,用于加密算法
sum = 0

# 逆算法解密
for i in range(8, -1, -1):
wheel = 33 # 33轮加密
sum = delta * (i + wheel)
while wheel > 0:
sum -= delta
sum &= 0xFFFFFFFF # 保持为32位
value[i + 1] -= ((sum + key[(sum >> 11) & 3]) ^ (value[i] + ((value[i] >> 5) ^ (16 * value[i]))))
value[i + 1] &= 0xFFFFFFFF # 保持为32位
value[i] -= (sum ^ (value[i + 1] + ((value[i + 1] >> 5) ^ (16 * value[i + 1]))) ^ (sum + key[sum & 3]))
value[i] &= 0xFFFFFFFF # 保持为32位
wheel -= 1

# 将解密后的数据转换为字符并输出
for val in value:
print(chr((val >> 24) & 0xFF), end='') # 高8位
print(chr((val >> 16) & 0xFF), end='') # 次高8位
print(chr((val >> 8) & 0xFF), end='') # 次低8位
print(chr(val & 0xFF), end='') # 低8位


if __name__ == "__main__":
main()

2、

代码分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
scanf("%s", v5);
v9 = v5;
// 将输入的值赋入 v4的后八位
for ( i = 0; i <= 5; ++i )
v4[i + 8] = *v9++;
// 两两进行XTea加密
for ( j = 0; j <= 2; ++j )
tea_encrypt(&v4[2 * j + 8], &key);
// 加密后的字符串要等于这些
v4[0] = -1054939302;
v4[1] = -1532163725;
v4[2] = -165900264;
v4[3] = 853769165;
v4[4] = 768352038;
v4[5] = 876839116;
for ( k = 0; k <= 5; ++k )
{
if ( v4[k] != v4[k + 8] )
{
printf("ERROR!");
exit(9);
}
}

按d,将key合成为4位、8字节的形式,再提取

tea加密函数

exp

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

int main()
{
unsigned int enc[6] = {0xC11EE75A, 0xA4AD0973, 0xF61C9018, 0x32E37BCD, 0x2DCC1F26, 0x344380CC};
unsigned int key[4] = {0x10203, 0x4050607, 0x8090A0B, 0x0C0D0E0F};
int i, j;
long sum = 0, delta = 0x61C88647;
// 解码
for(i=0;i < 6;i+=2){
sum = 0 - (32 * delta);
for(j = 0; j < 32; j++) {
enc[i+1] -= (((enc[i] >> 5) ^ (16 * enc[i])) + enc[i]) ^ (key[((sum >> 11) & 3)] + sum);
sum += delta;
enc[i] -= ((((enc[i+1] >> 5) ^ (16 * enc[i+1])) + enc[i+1]) ^ key[sum & 3] + sum);
}
}
// 打印
for (i = 0; i < 6; i++)
{
for (j = 0; j<=3; j++)
{
printf("%c", (enc[i] >> (j * 8)) & 0xFF);
}
}

return 0;
}

ezzzz

先每8位转化成一个数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def string_to_hex_with_prefix(input_string):
# 创建一个空的结果数组
hex_result = []

# 每 8 个字符一组
for i in range(0, len(input_string), 8):
chunk = input_string[i:i + 8]

# 将每组字符转为十六进制并加上 '0x' 前缀
hex_value = int(chunk.encode('utf-8').hex())

# 添加到数组中
hex_result.append(hex_value)

return hex_result


# 示例
input_string = "f1f186b25a96c782e6c63a0b70b61b5ced6bf84889700d6b09381b5ccb2f24fab1c79e796d822d9cdcc55f760f780e750d65c4afb89084a9e978c3827a8dd81091f28df3a84dbacab4d75f75f19af8e5b90f80fcfc10a5c3d20679fb2bc734c8ccb31c921ac52ad3e7f922b72e24d923fb4ce9f53548a9e571ebc25adf38862e10059186327509463dd4d54c905abc36c26d5312d2cd42c0772d99e50cd4c4665c3178d63a7ffe71ada251c070568d5a5798c2921ec0f7fc3ae9d8418460762930ca6a2dccef51d2a1a8085491b0f82d686ca34774c52d0f0f26449fc28d362c86f3311b8adc4fb1a4497e34e0f0915d" # 输入字符串
hex_output = string_to_hex_with_prefix(input_string)

# 输出结果
print("Hexadecimal array:", hex_output)

XTEA例题

1、

这里是典型的XTEA加密和异或加密,但是根据给定的key和算法,计算出来的是一个假flag:
fakeflag_plz_Try_more_hard_to_find_the_true_flag

RC4

详细了解RC4加密算法-CSDN博客

算法

密码学中,RC4(来自 Rivest Cipher 4 的缩写)是一种流加密算法,密钥长度可变。它加解密使用相同的密钥,因此也属于对称加密算法。RC4 是有线等效加密(WEP)中采用的加密算法,也曾经是 TLS 可采用的算法之一。

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) //初始化函数
{
int i =0, j = 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];
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];
}
}

其伪代码表示为:

初始化长度为 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

此算法保证每 256 次循环中 S 盒的每个元素至少被交换过一次

pyexp

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
def rc4_init(key):
s = list(range(256)) # 初始化 s 为 0 到 255 的列表
j = 0
k = bytearray(256) # 必须为无符号字节数组
key_len = len(key)

# 填充 k 并执行密钥调度算法(KSA)
for i in range(256):
k[i] = key[i % key_len]

for i in range(256):
j = (j + s[i] + k[i]) % 256
s[i], s[j] = s[j], s[i] # 交换 s[i] 和 s[j]

return s # 返回初始化后的状态数组 s


def rc4_crypt(s, data):
i = 0
j = 0
result = bytearray(len(data)) # 用于存储加密/解密结果

# 加解密过程
for k in range(len(data)):
i = (i + 1) % 256
j = (j + s[i]) % 256
s[i], s[j] = s[j], s[i] # 交换 s[i] 和 s[j]
t = (s[i] + s[j]) % 256
result[k] = data[k] ^ s[t] # 进行按位异或操作

return result # 返回加密/解密后的字节数组


# 示例用法
key = b"mysecretkey" # 秘钥
data = bytearray(b"Hello, RC4!") # 加密数据

# 初始化 RC4 状态
s = rc4_init(key)

# 加密或解密
encrypted_data = rc4_crypt(s.copy(), data) # 需要传递 s 的副本
print("加密后:", encrypted_data)

# 再次初始化 RC4 状态
s = rc4_init(key)

# 使用相同的状态解密
decrypted_data = rc4_crypt(s.copy(), encrypted_data)
print("解密后:", decrypted_data.decode('utf-8'))

例题

1、

2、

exp

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
import binascii

# 十六进制字符串
hex_data = "A71A68ECD82711CC8C9B16155CD2673E82ADCE75D4BC5756C28A52B86BD6CCF8A4BA722FE05715B92411"

# 将十六进制字符串转换为字节
ciphertext = binascii.unhexlify(hex_data)

# RC4 密钥(假设你知道密钥)
key = b'RC4_1s_4w3s0m3' # 替换为你的RC4密钥

# 创建 RC4 解密对象
cipher = ARC4.new(key)

# 解密数据
plaintext = cipher.decrypt(ciphertext)

# 输出解密后的内容
print(plaintext.decode('utf-8', errors='ignore'))

2024省赛初赛复现

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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
ezRe (Python 3.9)
[Code]
File Name: flag_checker.py
Object Name: <module>
Arg Count: 0
Pos Only Arg Count: 0
KW Only Arg Count: 0
Locals: 0
Stack Size: 7
Flags: 0x00000040 (CO_NOFREE)
[Names]
'base64'
'input'
'text'
'key'
'list'
'range'
's'
'j'
'i'
'len'
'data'
'_'
'append'
'result'
'zip'
'c'
'k'
'chr'
'ord'
'b64encode'
'encode'
'decode'
'enc'
'print'
[Var Names]
[Free Vars]
[Cell Vars]
[Constants]
0
None
'Flag: '
'7e021a7dd49e4bd0837e22129682551b'
[Code]
File Name: flag_checker.py
Object Name: <listcomp>
Arg Count: 1
Pos Only Arg Count: 0
KW Only Arg Count: 0
Locals: 2
Stack Size: 4
Flags: 0x00000043 (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)
[Names]
'ord'
[Var Names]
'.0'
'i'
[Free Vars]
[Cell Vars]
[Constants]
102
[Disassembly]
0 BUILD_LIST 0
2 LOAD_FAST 0: .0
4 FOR_ITER 16 (to 22)
6 STORE_FAST 1: i
8 LOAD_GLOBAL 0: ord
10 LOAD_FAST 1: i
12 CALL_FUNCTION 1
14 LOAD_CONST 0: 102
16 BINARY_XOR
18 LIST_APPEND 2
20 JUMP_ABSOLUTE 4
22 RETURN_VALUE
'<listcomp>'
256
50
1
''
51
'w53Cj3HDgzTCsSM5wrg6FMKcw58Qw7RZSFLCljRxwrxbwrVdw4AEwqMjw7/DkMKTw4/Cv8Onw4NGw7jDmSdcwq4GGg=='
'yes!'
'try again...'
[Disassembly]
0 LOAD_CONST 0: 0
2 LOAD_CONST 1: None
4 JUMP_FORWARD 0 (to 6)
6 JUMP_FORWARD 0 (to 8)
8 JUMP_FORWARD 0 (to 10)
10 IMPORT_NAME 0: base64
12 STORE_NAME 0: base64
14 LOAD_NAME 1: input
16 LOAD_CONST 2: 'Flag: '
18 CALL_FUNCTION 1
20 STORE_NAME 2: text
22 LOAD_CONST 3: '7e021a7dd49e4bd0837e22129682551b'
24 STORE_NAME 3: key
26 LOAD_CONST 4: <CODE> <listcomp>
28 LOAD_CONST 5: '<listcomp>'
30 MAKE_FUNCTION 0
32 LOAD_NAME 3: key
34 GET_ITER
36 CALL_FUNCTION 1
38 STORE_NAME 3: key
40 LOAD_NAME 4: list
42 LOAD_NAME 5: range
44 LOAD_CONST 6: 256
46 CALL_FUNCTION 1
48 CALL_FUNCTION 1
50 STORE_NAME 6: s
52 LOAD_CONST 0: 0
54 STORE_NAME 7: j
56 LOAD_NAME 5: range
58 LOAD_CONST 6: 256
60 CALL_FUNCTION 1
62 GET_ITER
64 FOR_ITER 62 (to 128)
66 STORE_NAME 8: i
68 LOAD_NAME 7: j
70 LOAD_NAME 6: s
72 LOAD_NAME 8: i
74 BINARY_SUBSCR
76 BINARY_ADD
78 LOAD_NAME 3: key
80 LOAD_NAME 8: i
82 LOAD_NAME 9: len
84 LOAD_NAME 3: key
86 CALL_FUNCTION 1
88 BINARY_MODULO
90 BINARY_SUBSCR
92 BINARY_ADD
94 LOAD_CONST 6: 256
96 BINARY_MODULO
98 STORE_NAME 7: j
100 LOAD_NAME 6: s
102 LOAD_NAME 7: j
104 BINARY_SUBSCR
106 LOAD_NAME 6: s
108 LOAD_NAME 8: i
110 BINARY_SUBSCR
112 ROT_TWO
114 LOAD_NAME 6: s
116 LOAD_NAME 8: i
118 STORE_SUBSCR
120 LOAD_NAME 6: s
122 LOAD_NAME 7: j
124 STORE_SUBSCR
126 JUMP_ABSOLUTE 64
128 LOAD_CONST 0: 0
130 DUP_TOP
132 STORE_NAME 8: i
134 STORE_NAME 7: j
136 BUILD_LIST 0
138 STORE_NAME 10: data
140 LOAD_NAME 5: range
142 LOAD_CONST 7: 50
144 CALL_FUNCTION 1
146 GET_ITER
148 FOR_ITER 88 (to 238)
150 STORE_NAME 11: _
152 LOAD_NAME 8: i
154 LOAD_CONST 8: 1
156 BINARY_ADD
158 LOAD_CONST 6: 256
160 BINARY_MODULO
162 STORE_NAME 8: i
164 LOAD_NAME 7: j
166 LOAD_NAME 6: s
168 LOAD_NAME 8: i
170 BINARY_SUBSCR
172 BINARY_ADD
174 LOAD_CONST 6: 256
176 BINARY_MODULO
178 STORE_NAME 7: j
180 LOAD_NAME 6: s
182 LOAD_NAME 7: j
184 BINARY_SUBSCR
186 LOAD_NAME 6: s
188 LOAD_NAME 8: i
190 BINARY_SUBSCR
192 ROT_TWO
194 LOAD_NAME 6: s
196 LOAD_NAME 8: i
198 STORE_SUBSCR
200 LOAD_NAME 6: s
202 LOAD_NAME 7: j
204 STORE_SUBSCR
206 LOAD_NAME 10: data
208 LOAD_METHOD 12: append
210 LOAD_NAME 6: s
212 LOAD_NAME 6: s
214 LOAD_NAME 8: i
216 BINARY_SUBSCR
218 LOAD_NAME 6: s
220 LOAD_NAME 7: j
222 BINARY_SUBSCR
224 BINARY_ADD
226 LOAD_CONST 6: 256
228 BINARY_MODULO
230 BINARY_SUBSCR
232 CALL_METHOD 1
234 POP_TOP
236 JUMP_ABSOLUTE 148
238 LOAD_CONST 9: ''
240 STORE_NAME 13: result
242 LOAD_NAME 14: zip
244 LOAD_NAME 2: text
246 LOAD_NAME 10: data
248 CALL_FUNCTION 2
250 GET_ITER
252 FOR_ITER 32 (to 286)
254 UNPACK_SEQUENCE 2
256 STORE_NAME 15: c
258 STORE_NAME 16: k
260 LOAD_NAME 13: result
262 LOAD_NAME 17: chr
264 LOAD_NAME 18: ord
266 LOAD_NAME 15: c
268 CALL_FUNCTION 1
270 LOAD_NAME 16: k
272 BINARY_XOR
274 LOAD_CONST 10: 51
276 BINARY_XOR
278 CALL_FUNCTION 1
280 INPLACE_ADD
282 STORE_NAME 13: result
284 JUMP_ABSOLUTE 252
286 LOAD_NAME 0: base64
288 LOAD_METHOD 19: b64encode
290 LOAD_NAME 13: result
292 LOAD_METHOD 20: encode
294 CALL_METHOD 0
296 CALL_METHOD 1
298 LOAD_METHOD 21: decode
300 CALL_METHOD 0
302 STORE_NAME 22: enc
304 LOAD_NAME 22: enc
306 LOAD_CONST 11: 'w53Cj3HDgzTCsSM5wrg6FMKcw58Qw7RZSFLCljRxwrxbwrVdw4AEwqMjw7/DkMKTw4/Cv8Onw4NGw7jDmSdcwq4GGg=='
308 COMPARE_OP 2 (==)
310 POP_JUMP_IF_FALSE 324
314 LOAD_NAME 23: print
316 LOAD_CONST 12: 'yes!'
318 CALL_FUNCTION 1
320 POP_TOP
322 JUMP_FORWARD 8 (to 332)
324 LOAD_NAME 23: print
326 LOAD_CONST 13: 'try again...'
328 CALL_FUNCTION 1
330 POP_TOP
332 LOAD_CONST 1: None
334 RETURN_VALUE
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
import base64

# 原始密钥和加密的目标输出
key = '7e021a7dd49e4bd0837e22129682551b'
encoded_target = 'w53Cj3HDgzTCsSM5wrg6FMKcw58Qw7RZSFLCljRxwrxbwrVdw4AEwqMjw7/DkMKTw4/Cv8Onw4NGw7jDmSdcwq4GGg=='

# 处理密钥
processed_key = [ord(i) ^ 102 for i in key]

# RC4 类似的流密码算法构建
s = list(range(256))
j = 0
for i in range(256):
j = (j + s[i] + processed_key[i % len(processed_key)]) % 256
s[i], s[j] = s[j], s[i]

# 生成数据流 `data`
i = j = 0
data = []
for _ in range(50): # 生成50个密钥流字节
i = (i + 1) % 256
j = (j + s[i]) % 256
s[i], s[j] = s[j], s[i]
data.append(s[(s[i] + s[j]) % 256])

# 解码 `encoded_target` 并转换为原始字符串
target_bytes = base64.b64decode(encoded_target).decode()
decoded_text = ''

# 使用 `data``target_bytes` 进行解码
for c, k in zip(target_bytes, data):
decoded_text += chr((ord(c) ^ k) ^ 51)

print("Decoded text (flag):", decoded_text)

Z3逆向

了解

https://www.freebuf.com/articles/web/232002.html

例题

1、login

先进行正常的py逆向,得到python文件

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
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.6

import sys
input1 = input('input something:')
if len(input1) != 14:
print('Wrong length!')
sys.exit()
code = []
for i in range(13):
code.append(ord(input1[i]) ^ ord(input1[i + 1]))

code.append(ord(input1[13]))
a1 = code[2]
a2 = code[1]
a3 = code[0]
a4 = code[3]
a5 = code[4]
a6 = code[5]
a7 = code[6]
a8 = code[7]
a9 = code[9]
a10 = code[8]
a11 = code[10]
a12 = code[11]
a13 = code[12]
a14 = code[13]
if ((((a1 * 88 + a2 * 67 + a3 * 65 - a4 * 5) + a5 * 43 + a6 * 89 + a7 * 25 + a8 * 13 - a9 * 36) + a10 * 15 + a11 * 11 + a12 * 47 - a13 * 60) + a14 * 29 == 22748) & ((((a1 * 89 + a2 * 7 + a3 * 12 - a4 * 25) + a5 * 41 + a6 * 23 + a7 * 20 - a8 * 66) + a9 * 31 + a10 * 8 + a11 * 2 - a12 * 41 - a13 * 39) + a14 * 17 == 7258) & ((((a1 * 28 + a2 * 35 + a3 * 16 - a4 * 65) + a5 * 53 + a6 * 39 + a7 * 27 + a8 * 15 - a9 * 33) + a10 * 13 + a11 * 101 + a12 * 90 - a13 * 34) + a14 * 23 == 26190) & ((((a1 * 23 + a2 * 34 + a3 * 35 - a4 * 59) + a5 * 49 + a6 * 81 + a7 * 25 + (a8 << 7) - a9 * 32) + a10 * 75 + a11 * 81 + a12 * 47 - a13 * 60) + a14 * 29 == 37136) & (((a1 * 38 + a2 * 97 + a3 * 35 - a4 * 52) + a5 * 42 + a6 * 79 + a7 * 90 + a8 * 23 - a9 * 36) + a10 * 57 + a11 * 81 + a12 * 42 - a13 * 62 - a14 * 11 == 27915) & ((((a1 * 22 + a2 * 27 + a3 * 35 - a4 * 45) + a5 * 47 + a6 * 49 + a7 * 29 + a8 * 18 - a9 * 26) + a10 * 35 + a11 * 41 + a12 * 40 - a13 * 61) + a14 * 28 == 17298) & ((((a1 * 12 + a2 * 45 + a3 * 35 - a4 * 9 - a5 * 42) + a6 * 86 + a7 * 23 + a8 * 85 - a9 * 47) + a10 * 34 + a11 * 76 + a12 * 43 - a13 * 44) + a14 * 65 == 19875) & (((a1 * 79 + a2 * 62 + a3 * 35 - a4 * 85) + a5 * 33 + a6 * 79 + a7 * 86 + a8 * 14 - a9 * 30) + a10 * 25 + a11 * 11 + a12 * 57 - a13 * 50 - a14 * 9 == 22784) & ((((a1 * 8 + a2 * 6 + a3 * 64 - a4 * 85) + a5 * 73 + a6 * 29 + a7 * 2 + a8 * 23 - a9 * 36) + a10 * 5 + a11 * 2 + a12 * 47 - a13 * 64) + a14 * 27 == 9710) & (((((a1 * 67 - a2 * 68) + a3 * 68 - a4 * 51 - a5 * 43) + a6 * 81 + a7 * 22 - a8 * 12 - a9 * 38) + a10 * 75 + a11 * 41 + a12 * 27 - a13 * 52) + a14 * 31 == 13376) & ((((a1 * 85 + a2 * 63 + a3 * 5 - a4 * 51) + a5 * 44 + a6 * 36 + a7 * 28 + a8 * 15 - a9 * 6) + a10 * 45 + a11 * 31 + a12 * 7 - a13 * 67) + a14 * 78 == 24065) & ((((a1 * 47 + a2 * 64 + a3 * 66 - a4 * 5) + a5 * 43 + a6 * 112 + a7 * 25 + a8 * 13 - a9 * 35) + a10 * 95 + a11 * 21 + a12 * 43 - a13 * 61) + a14 * 20 == 27687) & (((a1 * 89 + a2 * 67 + a3 * 85 - a4 * 25) + a5 * 49 + a6 * 89 + a7 * 23 + a8 * 56 - a9 * 92) + a10 * 14 + a11 * 89 + a12 * 47 - a13 * 61 - a14 * 29 == 29250) & (((a1 * 95 + a2 * 34 + a3 * 62 - a4 * 9 - a5 * 43) + a6 * 83 + a7 * 25 + a8 * 12 - a9 * 36) + a10 * 16 + a11 * 51 + a12 * 47 - a13 * 60 - a14 * 24 == 15317):
print('flag is GWHT{md5(your_input)}')
print('Congratulations and have fun!')
else:
print('Sorry,plz try again...')

注意

这里的(a8 << 7)要改成(a8 * 0x80),不然会报错

在Python中,使用左移操作符 << 可以将数值按位左移。然而,在Z3中,左移操作符 << 是不支持的。因此,需要将左移操作转换为等效的乘法操作。

左移7位相当于乘以 2的7次,也就是128。因此,a8 << 7 等价于 a8 * 128a8 * 0x80

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
from z3 import *

a1 = Int('a2')
a2 = Int('a1')
a3 = Int('a0')
a4 = Int('a3')
a5 = Int('a4')
a6 = Int('a5')
a7 = Int('a6')
a8 = Int('a7')
a9 = Int('a9')
a10 = Int('a8')
a11 = Int('a10')
a12 = Int('a11')
a13 = Int('a12')
a14 = Int('a13')

s = Solver()

s.add(a1 * 88 + a2 * 67 + a3 * 65 - a4 * 5 + a5 * 43 + a6 * 89 + a7 * 25 + a8 * 13 - a9 * 36 + a10 * 15 + a11 * 11 + a12 * 47 - a13 * 60 + a14 * 29 == 22748)
s.add(a1 * 89 + a2 * 7 + a3 * 12 - a4 * 25 + a5 * 41 + a6 * 23 + a7 * 20 - a8 * 66 + a9 * 31 + a10 * 8 + a11 * 2 - a12 * 41 - a13 * 39 + a14 * 17 == 7258)
s.add(a1 * 28 + a2 * 35 + a3 * 16 - a4 * 65 + a5 * 53 + a6 * 39 + a7 * 27 + a8 * 15 - a9 * 33 + a10 * 13 + a11 * 101 + a12 * 90 - a13 * 34 + a14 * 23 == 26190)
s.add(a1 * 23 + a2 * 34 + a3 * 35 - a4 * 59 + a5 * 49 + a6 * 81 + a7 * 25 + (a8 * 0x80) - a9 * 32 + a10 * 75 + a11 * 81 + a12 * 47 - a13 * 60 + a14 * 29 == 37136)
s.add(a1 * 38 + a2 * 97 + a3 * 35 - a4 * 52 + a5 * 42 + a6 * 79 + a7 * 90 + a8 * 23 - a9 * 36 + a10 * 57 + a11 * 81 + a12 * 42 - a13 * 62 - a14 * 11 == 27915)
s.add(a1 * 22 + a2 * 27 + a3 * 35 - a4 * 45 + a5 * 47 + a6 * 49 + a7 * 29 + a8 * 18 - a9 * 26 + a10 * 35 + a11 * 41 + a12 * 40 - a13 * 61 + a14 * 28 == 17298)
s.add(a1 * 12 + a2 * 45 + a3 * 35 - a4 * 9 - a5 * 42 + a6 * 86 + a7 * 23 + a8 * 85 - a9 * 47 + a10 * 34 + a11 * 76 + a12 * 43 - a13 * 44 + a14 * 65 == 19875)
s.add(a1 * 79 + a2 * 62 + a3 * 35 - a4 * 85 + a5 * 33 + a6 * 79 + a7 * 86 + a8 * 14 - a9 * 30 + a10 * 25 + a11 * 11 + a12 * 57 - a13 * 50 - a14 * 9 == 22784)
s.add(a1 * 8 + a2 * 6 + a3 * 64 - a4 * 85 + a5 * 73 + a6 * 29 + a7 * 2 + a8 * 23 - a9 * 36 + a10 * 5 + a11 * 2 + a12 * 47 - a13 * 64 + a14 * 27 == 9710)
s.add(a1 * 67 - a2 * 68 + a3 * 68 - a4 * 51 - a5 * 43 + a6 * 81 + a7 * 22 - a8 * 12 - a9 * 38 + a10 * 75 + a11 * 41 + a12 * 27 - a13 * 52 + a14 * 31 == 13376)
s.add(a1 * 85 + a2 * 63 + a3 * 5 - a4 * 51 + a5 * 44 + a6 * 36 + a7 * 28 + a8 * 15 - a9 * 6 + a10 * 45 + a11 * 31 + a12 * 7 - a13 * 67 + a14 * 78 == 24065)
s.add(a1 * 47 + a2 * 64 + a3 * 66 - a4 * 5 + a5 * 43 + a6 * 112 + a7 * 25 + a8 * 13 - a9 * 35 + a10 * 95 + a11 * 21 + a12 * 43 - a13 * 61 + a14 * 20 == 27687)
s.add(a1 * 89 + a2 * 67 + a3 * 85 - a4 * 25 + a5 * 49 + a6 * 89 + a7 * 23 + a8 * 56 - a9 * 92 + a10 * 14 + a11 * 89 + a12 * 47 - a13 * 61 - a14 * 29 == 29250)
s.add(a1 * 95 + a2 * 34 + a3 * 62 - a4 * 9 - a5 * 43 + a6 * 83 + a7 * 25 + a8 * 12 - a9 * 36 + a10 * 16 + a11 * 51 + a12 * 47 - a13 * 60 - a14 * 24 == 15317)

if 'un' not in str(s.check()):
print(s.model())

根据输出创建字典

exp

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
from z3 import *

a1 = Int('a2')
a2 = Int('a1')
a3 = Int('a0')
a4 = Int('a3')
a5 = Int('a4')
a6 = Int('a5')
a7 = Int('a6')
a8 = Int('a7')
a9 = Int('a9')
a10 = Int('a8')
a11 = Int('a10')
a12 = Int('a11')
a13 = Int('a12')
a14 = Int('a13')

s = Solver()

s.add(a1 * 88 + a2 * 67 + a3 * 65 - a4 * 5 + a5 * 43 + a6 * 89 + a7 * 25 + a8 * 13 - a9 * 36 + a10 * 15 + a11 * 11 + a12 * 47 - a13 * 60 + a14 * 29 == 22748)
s.add(a1 * 89 + a2 * 7 + a3 * 12 - a4 * 25 + a5 * 41 + a6 * 23 + a7 * 20 - a8 * 66 + a9 * 31 + a10 * 8 + a11 * 2 - a12 * 41 - a13 * 39 + a14 * 17 == 7258)
s.add(a1 * 28 + a2 * 35 + a3 * 16 - a4 * 65 + a5 * 53 + a6 * 39 + a7 * 27 + a8 * 15 - a9 * 33 + a10 * 13 + a11 * 101 + a12 * 90 - a13 * 34 + a14 * 23 == 26190)
s.add(a1 * 23 + a2 * 34 + a3 * 35 - a4 * 59 + a5 * 49 + a6 * 81 + a7 * 25 + (a8 * 0x80) - a9 * 32 + a10 * 75 + a11 * 81 + a12 * 47 - a13 * 60 + a14 * 29 == 37136)
s.add(a1 * 38 + a2 * 97 + a3 * 35 - a4 * 52 + a5 * 42 + a6 * 79 + a7 * 90 + a8 * 23 - a9 * 36 + a10 * 57 + a11 * 81 + a12 * 42 - a13 * 62 - a14 * 11 == 27915)
s.add(a1 * 22 + a2 * 27 + a3 * 35 - a4 * 45 + a5 * 47 + a6 * 49 + a7 * 29 + a8 * 18 - a9 * 26 + a10 * 35 + a11 * 41 + a12 * 40 - a13 * 61 + a14 * 28 == 17298)
s.add(a1 * 12 + a2 * 45 + a3 * 35 - a4 * 9 - a5 * 42 + a6 * 86 + a7 * 23 + a8 * 85 - a9 * 47 + a10 * 34 + a11 * 76 + a12 * 43 - a13 * 44 + a14 * 65 == 19875)
s.add(a1 * 79 + a2 * 62 + a3 * 35 - a4 * 85 + a5 * 33 + a6 * 79 + a7 * 86 + a8 * 14 - a9 * 30 + a10 * 25 + a11 * 11 + a12 * 57 - a13 * 50 - a14 * 9 == 22784)
s.add(a1 * 8 + a2 * 6 + a3 * 64 - a4 * 85 + a5 * 73 + a6 * 29 + a7 * 2 + a8 * 23 - a9 * 36 + a10 * 5 + a11 * 2 + a12 * 47 - a13 * 64 + a14 * 27 == 9710)
s.add(a1 * 67 - a2 * 68 + a3 * 68 - a4 * 51 - a5 * 43 + a6 * 81 + a7 * 22 - a8 * 12 - a9 * 38 + a10 * 75 + a11 * 41 + a12 * 27 - a13 * 52 + a14 * 31 == 13376)
s.add(a1 * 85 + a2 * 63 + a3 * 5 - a4 * 51 + a5 * 44 + a6 * 36 + a7 * 28 + a8 * 15 - a9 * 6 + a10 * 45 + a11 * 31 + a12 * 7 - a13 * 67 + a14 * 78 == 24065)
s.add(a1 * 47 + a2 * 64 + a3 * 66 - a4 * 5 + a5 * 43 + a6 * 112 + a7 * 25 + a8 * 13 - a9 * 35 + a10 * 95 + a11 * 21 + a12 * 43 - a13 * 61 + a14 * 20 == 27687)
s.add(a1 * 89 + a2 * 67 + a3 * 85 - a4 * 25 + a5 * 49 + a6 * 89 + a7 * 23 + a8 * 56 - a9 * 92 + a10 * 14 + a11 * 89 + a12 * 47 - a13 * 61 - a14 * 29 == 29250)
s.add(a1 * 95 + a2 * 34 + a3 * 62 - a4 * 9 - a5 * 43 + a6 * 83 + a7 * 25 + a8 * 12 - a9 * 36 + a10 * 16 + a11 * 51 + a12 * 47 - a13 * 60 - a14 * 24 == 15317)

if 'un' not in str(s.check()):
print(s.model())

direct={
13 : 33,
3 : 7,
4 : 104,
10 : 88,
12 : 88,
1 : 24,
7 : 91,
9 : 52,
6 : 28,
5 : 43,
0 : 10,
8 : 108,
2 : 119,
11 : 74
}
flag=[0 for i in range(15)]
for i in direct:
flag[i]=direct[i]

for i in range(13,-1,-1):
flag[i]^=flag[i+1]

for i in range(14):
print(chr(flag[i]),end='')

最后进行md5加密

58964088b637e50d3a22b9510c1d1ef8

2、babe-ze3(不会)

网站Hint最后一个if有问题,狗屁通说v4和 !(_DWORD)v4无法同时成立

之前Z3解密用的都是Ints类型,这次运算有变,变成BitVec()位向量

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
from libnum import n2s
from z3 import *
from Crypto.Util.number import *

# 定义变量
s = BitVec('s', 64)
v6 = BitVec('v6', 64)
v7 = BitVec('v7', 64)
v8 = BitVec('v8', 64)
solver = Solver()

# 添加条件
solver.add((v7 & s & v8 | (~(v6 | s) | v6 & v7) & v6 & s) == 0x2024243035302131)
solver.add((v6 ^ (v7 & (s + v7) | v8 & ~(v7 & s) | v6 & (v6 + v8) & ~s)) == 0x7071001344417B54)
solver.add(((v7 - v8) ^ (s - v6)) == 0x3FE01013130FFD3)
solver.add((s + v7 - v8 + v6) * (v8 + s + v6 - v7) == 0x1989A41A9049C5C9)
solver.add((v7 + v6 + s + v8) % 0x1BF52 == 21761)
solver.add(v8 * v7 * v6 * s % 0x1D4B42 == 827118)

# 检查是否有解
if solver.check() == sat:
model = solver.model()

# 输出变量的解
s_val = model[s].as_long()
v6_val = model[v6].as_long()
v7_val = model[v7].as_long()
v8_val = model[v8].as_long()

# 将解转换为字符串
print("s:", n2s(s_val))
print("v6:", n2s(v6_val))
print("v7:", n2s(v7_val))
print("v8:", n2s(v8_val))
else:
print("No solution found")

# 处理字符串翻转
s = 'cd5250c9dbc4fdab1760517947e35495'
s1 = ''
for i in range(0, 32, 8):
a = s[i:i+8]
a = a[::-1] # 翻转每个8字符的子串
s1 += a

print("Processed string:", s1)
# 结果应为: 9c0525dcba4fdfbd9715067159453e74

base变、tea、rc4
http://example.com/2024/03/13/算法逆向/
Author
chaye
Posted on
March 13, 2024
Licensed under