加密脚本分析—evil.py

加密脚本分析—evil.py

1.题目

源文件

一共两个文件

enc_flag.txt

evil.py(原文件无注释)

 1 # coding: utf-8
 2 
 3 import base64
 4 import string
 5 import random
 6 import hashlib
 7 
 8 #第二调用
 9 def random_str(length=4, chars=string.ascii_lowercase):
10     words = ''
11     chars_len = len(chars) - 1
12     for i in range(length):
13         words += chars[random.randint(0, chars_len)]#随机获取小写英文字符
14     return words
15 
16 #第三调用,使用key的md5值对加密过后的flag进行第二次异或加密
17 def key_crypt(data, key):
18     md5 = hashlib.md5()
19     md5.update(key.encode())
20     key_md5 = md5.hexdigest()
21     key_index = 0
22     cipher_data = ''
23     for i in range(len(data)):
24         key_index = 0 if key_index == 32 else key_index#无用,key_index第一次被赋值为0后就没有任何改变了
25         cipher_data += chr(ord(data[i]) ^ ord(key_md5[key_index]))
26     return cipher_data
27 
28 #第一调用
29 def encrypt(plain_data, key):#('flag{fake_flag}', 'SK1llS_KeY')
30     rnd = random_str(32)#调用第二函数,获取随机的32位字符串
31     plain_data_len = len(plain_data)
32     rnd_index = 0
33     cipher_data = ''
34     for i in range(plain_data_len):#使用第二函数返回的32位字符串加密flag
35         rnd_index = 0 if rnd_index == 32 else rnd_index#无用,rnd_index第一次被赋值为0后就没有任何改变
36         cipher_data += rnd[rnd_index] + chr(ord(plain_data[i]) ^ ord(rnd[rnd_index]))
37     return base64.b64encode(key_crypt(cipher_data, key).encode()).decode()#调用第三函数二次加密flag并将二次加密后的flag转base64
38 
39 #主函数
40 cipher = encrypt('flag{fake_flag}', 'SK1llS_KeY')
41 with open('enc_flag.txt', 'w') as f:
42     f.write(cipher)

2.解题过程

很明显encrypt的第一个参数就是要加密的flag,代码中的flag是假的但是我们可以使用ta来进行实验!

首先大体的观看代码并写下注释以便后续逆向

想要获得原来的flag需要知道三个必要条件“flag的长度”、“key”和“rnd”

key就直接写在代码上了“SK1llS_KeY”

直接cv key_crypt函数即可,因为key_crypt是使用key的md5值与第一次加密后的flag进行异或的,所以我们使用base64解码后的flag在次加密一次就可以获得第一次加密后的flag了

 1 import base64
 2 import hashlib
 3 
 4 flag = "HHoccBx9HHscZxwuHC0cKBwvHCwcKhwpHC4cLRwvHHgceRwuHHgcKhwvHCQcKhx5HCUcKBwrHC8cehwkHHoceBwlHH4cfhwpHHgcYQ=="
 5 key = "SK1llS_KeY"
 6 
 7 def key_crypt(data, key):
 8   md5 = hashlib.md5()
 9   md5.update(key.encode())
10   key_md5 = md5.hexdigest()
11   key_index = 0
12   cipher_data = ''
13   for i in range(len(data)):
14     key_index = 0 if key_index == 32 else key_index
15     cipher_data += chr(ord(data[i]) ^ ord(key_md5[key_index]))
16   return cipher_data
17 print(key_crypt(base64.b64decode(flag).decode(),key).encode())

输出

可以发现这串字符里有很多的y,在联想到第一函数的异或加密

1 def encrypt(plain_data, key):#('flag{fake_flag}', 'SK1llS_KeY')
2     rnd = random_str(32)#调用第二函数,获取随机的32位字符串
3     plain_data_len = len(plain_data)
4     rnd_index = 0
5     cipher_data = ''
6     for i in range(plain_data_len):#使用第二函数返回的32位字符串加密flag
7         rnd_index = 0 if rnd_index == 32 else rnd_index#无用,rnd_index第一次被赋值为0后就没有任何改变
8         cipher_data += rnd[rnd_index] + chr(ord(plain_data[i]) ^ ord(rnd[rnd_index]))
9     return base64.b64encode(key_crypt(cipher_data, key).encode()).decode()#调用第三函数二次加密flag并将二次加密后的flag转base64

 

  • cipher_data += rnd[rnd_index] + chr(ord(plain_data[i]) ^ ord(rnd[rnd_index]))

每次循环都在异或后的flag前面加上一个字符,所以确定当时加密这一段flag时随机生成的32位字符串的第0位为“y”

论证:

通过flag的头是“flag{”并稍微修改一下代码

 1 def encrypt(plain_data, key):
 2   for o in string.ascii_lowercase:
 3     rnd = [o]
 4     plain_data_len = len(plain_data)
 5     rnd_index = 0
 6     cipher_data = ''
 7     for i in range(plain_data_len):
 8       rnd_index = 0 if rnd_index == 32 else rnd_index
 9       cipher_data += rnd[rnd_index] + chr(ord(plain_data[i]) ^ ord(rnd[rnd_index]))
10     print(o+':'+base64.b64encode(key_crypt(cipher_data, key).encode()).decode())
11 cipher = encrypt('flag{fake_flag}', 'SK1llS_KeY')

 

可以发现rnd为“y”的加密flag头几个字符与最终的flag头几个字符一模一样,所以可以确定rnd就是“y”

将解密的flag按照y为头排成多列,有14列,所以确定循环异或了14遍

将分成的多列转成数组再用修改后的第一函数异或即可

 1 def encrypt():
 2   rnd = ['y']
 3   rnd_index = 0
 4   cipher_data = ''
 5   for i in list:
 6     rnd_index = 0 if rnd_index == 32 else rnd_index
 7     cipher_data += chr(ord(i) ^ ord(rnd[rnd_index]))
 8   print(cipher_data)
 9 list = ['\x1f','\x15','\x18','\x1e','\x02','K','H','M','J','I','O','L','K','H','J','\x1d','\x1c','K','\x1d','O','J','A','O','\x1c','@','M','N','J','\x1f','A','\x1f','\x1d','@','\x1b','\x1b','L','\x1d','\x04']
10 encrypt()

获得flag

posted @ 2023-03-02 16:04  懒床的星间  阅读(77)  评论(2)    收藏  举报