标题有点拗口,看问题需求就理解了------
一,问题需求
有一个字符串s1,其中包含a1、a2、a3到a14这些子串,我需要将s1中出现的这些子串全部对应替换成v[0],v[1],v[2]到v[13]等等,应该怎么编写程序
例如:
s1='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'
替换后:
s1='v[0] * 88 + v[1] * 67 + v[2] * 65 - v[3] * 5 + v[4] * 43 + v[5] * 89 + v[6] * 25 + v[7] * 13 - v[8] * 36 + v[9] * 15 + v[10] * 11 + v[11] * 47 - v[12] * 60 + v[13] * 29 == 22748'
二,应用场景
博主在刷ctf的re方向题目时遇到求解多(14)元方程问题,之前其实已经写过一篇z3求解器的相关文章->z3求解器脚本(CTF-reverse必备)_ctf z3-CSDN博客
该脚本用到了列表,默认方程的未知数都是列表中的元素,可以用类似v[index]的形式存储或访问,但是题目中出现的方程一般是以a1、a2或x1、x2等序列形式来表示未知数的,手搓当然可以一个个全部替换,但显然太不优雅了!
因此可以用此脚本对方程中出现的未知数序列统一替换成v[0]、v[1]等序列形式,以便于我们直接套用z3求解器的脚本!
三,完整脚本
只要脚本省时间的可以不看后面的解释了(博主一向这么直白,还望留赞o(* ̄▽ ̄*)ブ)
因为约束方程一般未知数较多故字符串较长,因此一个一个方程进行处理会比较方便,每替换一次你需要自己更改s1的内容直到完成题目所给出的所有方程的处理
python
import re
def replace_func(match):
index = int(match.group(1)) - 1 #match.group(1)是第一个括号匹配部分,在此处即a后的数字1到14
return str(f'v[{index}]') #返回字符串'v[a后数字-1]',用其替换匹配到的an
if __name__=='__main__':
s1 = "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" #定义包含an的字符串
s1 = re.sub(r'a(1[0-4]|[1-9])', replace_func, s1)
#sub函数参数, pattern、repl、string分别表示:正则表达式匹配规则、替换后结果(可以是函数也可以是常量)、要被查找替换的原始字符串
print(s1)
四,脚本详解
该脚本的主要难点在于re(正则表达式)模块的相关API的使用
s1是原始字符串,我们希望将其中的a1、a2...a14等序列替换为对应的v[0]、v[1]...v[13],以便于直接复制该脚本替换后的字符串作为z3求解器脚本的约束方程组
你需要了解sub()函数的机理------Python 正则表达式 | 菜鸟教程 (runoob.com)
省流解释------re.sub(pattern, repl, string)
sub函数参数, pattern、repl、string分别表示:正则表达式匹配规则、替换后结果(可以是函数也可以是常量)、要被查找替换的原始字符串
此处pattern参数为r'a(1[0-4]|[1-9])',意味匹配a后带整数10到14或1到9的子串,请注意,1[0-4]必须写于[1-9]之前,否则会出现a10中的a1被错误匹配成v[0]的情况导致替换结果为v[0]0
pythons1 = re.sub(r'a(1[0-4]|[1-9])', replace_func, s1)
替换结果函数
当参数repl是固定值时被匹配的子串都会替换成固定值,但是我们希望实现的是
a1->v[0]、a2->v[1]的映射,因此使用函数可以实现复杂替换
此处的match.group(1)是第一个括号匹配部分,在此处即a后的数字1到14
如果是match.group(0)则是整个匹配到的子串,即a0、a1...a14
获取到a后的数字,根据替换的映射关系减一作为新的序列编号,返回格式为v[index]的新序列,这些序列中的v[0]、v[1]...v[13]将对应替换匹配到的a1、a2...a14
最后直接输出替换后的结果即可
pythondef replace_func(match): index = int(match.group(1)) - 1 #match.group(1)是第一个括号匹配部分,在此处即a后的数字1到14 return str(f'v[{index}]') #返回字符串'v[a后数字-1]',用其替换匹配到的an
五,例题放送
[羊城杯 2020]login
题目链接->NSSCTF | 在线CTF平台
python
import sys
input1 = input("input something:")
if len(input1) != 14:
print("Wrong length!")
sys.exit()
else:
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...")
wp:
本题考察多元方程求解,可以使用z3求解器->z3求解器脚本(CTF-reverse必备)_ctf z3-CSDN博客
但是约束方程没法直接套用,有两点原因,其一为所有方程都作为if的条件用&连接,导致复制的过程很繁琐,其二为方程未知数是a1、a2...a14,但套用到z3求解器中的方程未知数需要是v[index]的列表访问形式(当然可以修改z3求解脚本,但那样会更加繁琐且通用性较差)
我们可以先编写一段脚本来处理方程,以&作为分隔符分隔所有方程并输出
python
s = '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'
lst = s.split('&')
for i in lst:
print(i) #默认输出换行隔开各个方程方便复制
"""下面是输出结果
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
"""
此时再复制单个方程就方便多了,分别将它们代入替换脚本中的s1变量,以第一个方程为例子
python
#coding=gbk
import re
def replace_func(match):
index = int(match.group(1)) - 1 #match.group(1)是第一个括号匹配部分,在此处即a后的数字0到14
return str(f'v[{index}]') #返回字符串'v[a后数字-1]',用其替换匹配到的an
if __name__=='__main__':
s1 = "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" #定义包含an的字符串
s1 = re.sub(r'a(1[0-5]|[1-9])', replace_func, s1)
#sub函数参数, pattern、repl、string分别表示:正则表达式匹配规则、替换后结果(可以是函数也可以是常量)、要被查找替换的原始字符串
print(s1)
#输出结果
#v[0] * 88 + v[1] * 67 + v[2] * 65 - v[3] * 5 + v[4] * 43 + v[5] * 89 + v[6] * 25 + v[7] * 13 - v[8] * 36 + v[9] * 15 + v[10] * 11 + v[11] * 47 - v[12] * 60 + v[13] * 29 == 22748
其余方程如法炮制,得到替换未知数名称的方程后,同时将其放入z3求解器的脚本中
注意,第4个方程中出现了<<7,z3求解不支持位移操作,将其替换为等价的*128即可
解出方程后不要太激动,仔细审题,还有一部异或操作,要异或回去才是正确答案,所以先把方程解存在列表里
最后输出的结果根据题目是要md5值,说明不是具体的字符串,那就直接打印整数,然后用hashlib模块中的API进行md5加密
python
# coding=gbk
from z3 import *
import hashlib # 题目最后得到的字符串要md5加密
# 创建未知数变量
v = [Int(f'v{i}') for i in range(0, 14)] # 14个未知数
# 创建解释器对象
solver = Solver() # 创建一个求解器对象
# 添加约束方程
# 不要漏也不要多,题目是14个
solver.add(v[0] * 88 + v[1] * 67 + v[2] * 65 - v[3] * 5 + v[4] * 43 + v[5] * 89 + v[6] * 25 +
v[7] * 13 - v[8] * 36 + v[9] * 15 + v[10] * 11 + v[11] * 47 - v[12] * 60 + v[13] * 29 == 22748)
solver.add(v[0] * 89 + v[1] * 7 + v[2] * 12 - v[3] * 25 + v[4] * 41 + v[5] * 23 + v[6] * 20 -
v[7] * 66 + v[8] * 31 + v[9] * 8 + v[10] * 2 - v[11] * 41 - v[12] * 39 + v[13] * 17 == 7258)
solver.add(v[0] * 28 + v[1] * 35 + v[2] * 16 - v[3] * 65 + v[4] * 53 + v[5] * 39 + v[6] * 27 +
v[7] * 15 - v[8] * 33 + v[9] * 13 + v[10] * 101 + v[11] * 90 - v[12] * 34 + v[13] * 23 == 26190)
solver.add(v[0] * 23 + v[1] * 34 + v[2] * 35 - v[3] * 59 + v[4] * 49 + v[5] * 81 + v[6] * 25 +
(v[7] * 128) - v[8] * 32 + v[9] * 75 + v[10] * 81 + v[11] * 47 - v[12] * 60 + v[13] * 29 == 37136)
solver.add(v[0] * 38 + v[1] * 97 + v[2] * 35 - v[3] * 52 + v[4] * 42 + v[5] * 79 + v[6] * 90 +
v[7] * 23 - v[8] * 36 + v[9] * 57 + v[10] * 81 + v[11] * 42 - v[12] * 62 - v[13] * 11 == 27915)
solver.add(v[0] * 22 + v[1] * 27 + v[2] * 35 - v[3] * 45 + v[4] * 47 + v[5] * 49 + v[6] * 29 +
v[7] * 18 - v[8] * 26 + v[9] * 35 + v[10] * 41 + v[11] * 40 - v[12] * 61 + v[13] * 28 == 17298)
solver.add(v[0] * 12 + v[1] * 45 + v[2] * 35 - v[3] * 9 - v[4] * 42 + v[5] * 86 + v[6] * 23 +
v[7] * 85 - v[8] * 47 + v[9] * 34 + v[10] * 76 + v[11] * 43 - v[12] * 44 + v[13] * 65 == 19875)
solver.add(v[0] * 79 + v[1] * 62 + v[2] * 35 - v[3] * 85 + v[4] * 33 + v[5] * 79 + v[6] * 86 +
v[7] * 14 - v[8] * 30 + v[9] * 25 + v[10] * 11 + v[11] * 57 - v[12] * 50 - v[13] * 9 == 22784)
solver.add(v[0] * 8 + v[1] * 6 + v[2] * 64 - v[3] * 85 + v[4] * 73 + v[5] * 29 + v[6] * 2 +
v[7] * 23 - v[8] * 36 + v[9] * 5 + v[10] * 2 + v[11] * 47 - v[12] * 64 + v[13] * 27 == 9710)
solver.add(v[0] * 67 - v[1] * 68 + v[2] * 68 - v[3] * 51 - v[4] * 43 + v[5] * 81 + v[6] * 22 -
v[7] * 12 - v[8] * 38 + v[9] * 75 + v[10] * 41 + v[11] * 27 - v[12] * 52 + v[13] * 31 == 13376)
solver.add(v[0] * 85 + v[1] * 63 + v[2] * 5 - v[3] * 51 + v[4] * 44 + v[5] * 36 + v[6] * 28 +
v[7] * 15 - v[8] * 6 + v[9] * 45 + v[10] * 31 + v[11] * 7 - v[12] * 67 + v[13] * 78 == 24065)
solver.add(v[0] * 47 + v[1] * 64 + v[2] * 66 - v[3] * 5 + v[4] * 43 + v[5] * 112 + v[6] * 25 +
v[7] * 13 - v[8] * 35 + v[9] * 95 + v[10] * 21 + v[11] * 43 - v[12] * 61 + v[13] * 20 == 27687)
solver.add(v[0] * 89 + v[1] * 67 + v[2] * 85 - v[3] * 25 + v[4] * 49 + v[5] * 89 + v[6] * 23 +
v[7] * 56 - v[8] * 92 + v[9] * 14 + v[10] * 89 + v[11] * 47 - v[12] * 61 - v[13] * 29 == 29250)
solver.add(v[0] * 95 + v[1] * 34 + v[2] * 62 - v[3] * 9 - v[4] * 43 + v[5] * 83 + v[6] * 25 +
v[7] * 12 - v[8] * 36 + v[9] * 16 + v[10] * 51 + v[11] * 47 - v[12] * 60 - v[13] * 24 == 15317)
solution = []
# 求解并转化为字符输出,得到flag
if solver.check() == sat: # check()方法用来判断是否有解,sat(即satisify)表示满足有解
ans = solver.model() # model()方法得到解
for i in v:
solution.append(ans[i].as_long()) # 将解保存在solution列表中
# solution=[119, 24, 10, 7, 104, 43, 28, 91, 52, 108, 88, 74, 88, 33]
# 一般不会无解,如果无解八成是未知数变量的类型不符合,或约束方程添加错误
else:
print("no ans!")
print(solution)
# 分析题目得知,解和输入的字符顺序不是一一对应的,需要按输入字符串code的索引顺序重新排列解的顺序
index = [2, 1, 0, 3, 4, 5, 6, 7, 9, 8, 10, 11, 12, 13]
data = []
for i in range(len(index)):
# 按index的顺序重排solution元素,新元素存入data[]中,注意不能直接放回solution[],细想一下就明白了
data.append(solution[index[i]])
for i in range(12, -1, -1):
# code.append(ord(input1[i]) ^ ord(input1[i + 1])) 异或解密
data[i] ^= data[i + 1]
flag = ''
for i in data:
flag += chr(i) # 结果:U_G07_th3_k3y!,题目说用md5加密才是flag
# 下面来进行md5加密
md5 = hashlib.md5() # 创建md5对象
md5.update(flag.encode()) # 更新md5对象的信息,必须传入bytes类型的数据(b'xxx'格式)
print(md5.hexdigest()) # 获取加密后的内容:58964088b637e50d3a22b9510c1d1ef8