2024第八届御网杯信息安全网络大赛线上WP详解(misc+cryoto)(详解-思路-脚 ...

宁睿  论坛元老 | 2024-9-29 04:32:22 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1084|帖子 1084|积分 3262

芜湖~
首届御网杯线上和ISCC分开举行 但照旧用的ISCC的页面差评 嘻嘻
又是玄乎的一天
以下是我本身的一些思路息争析 有什么问题大概建议随时都可以接洽我
目录
附件
# Misc
##Notice
##编码转换
Brainfuck编码 
jsfuck编码
Ook! 编码
 ##bluetooth
导出压缩包
第一种
第二种
第三种
注意
举行异或
整合脚本解析
##coding
#Crypto
##不警惕
原题目脚本解释
##Justmath
原脚本解释
第一部分:使用SageMath解方程规复部分flag
第二部分:使用RSA和Coppersmith的小根数攻击规复剩余的flag
##BASE
总结套娃层
##easy_crypto1
求解E1
求解E2: 中国剩余定理 
求P以及flag
完整解题代码

加油各位( •̀ ω •́ )y 期待与君再相逢


附件

   通过网盘分享的文件:2024第八届御网杯线上题目附件
链接: https://pan.baidu.com/s/1Jq7anXVdjH5AfxQ_CujY3w 提取码: lulu 
--来自百度网盘超级会员v5的分享

  # Misc

##Notice

一年一道签到题 开启“玄幻”的一天

签到题不会太难 所以别多想直接打开
直接目视 哈哈哈

有隐藏字符(先考虑是否字体颜色隐藏,再想文档隐写其他的)

改颜色 出 好下一道
flag{HNCTF9090AS9nbg87600hn77hn88}
##编码转换

Brainfuck编码 jsfuck编码 OoK! 编码 这个几个编码是深受御网主办方喜爱
无论线上线下出现在大众视野已经不止一两次了 (不会无需惆怅,这东西纯靠积累)

在线网址
http://www.hiencode.com/jsfuck.html
https://www.splitbrain.org/services/ook
  1. Brainfuck编码
复制代码
  Brainfuck编码 

  语言只有八种符号,全部的操作都由这八种符号 **(> < + - . , [ ])** 的组合来完成
  

  1. jsfuck编码
复制代码
  jsfuck编码

  jother是javascript语言中使用少量字符构造精简的匿名函数方法对于字符串举行的编码方式。此中少量字符包罗:"!"、"+"、"("、")"、"["、"]"、"{"、"}"。只用这些字符就能完成对任意字符串的编码。
  
​、

  1. Ook! 编码
复制代码
  Ook! 编码

  由Ook ! . ? 组成
  

组合得到
flag{ab71cda1b495e13b3f21f6fd50221978}
 ##bluetooth

流量分析的题
看见流量分析的题若没有显着特性 需要去观察协议分级
 
 

发现没有HTTP  TCP之类显着的协议
直接举行关键字符搜索
 
 

发现有显着的压缩包 以及flag.txt文档
 
 

还有个key的密钥
 
 

将压缩包导出(文件时间够老的 嘻嘻)

导出压缩包

这里有人不知道怎样把这两个文件导出  我简单说一下
第一种

将流量包文件改成zip之类的压缩包格式 举行解压分离提取
第二种

直接将流量包文件用相干下令举行分离
第三种

打开流量包找到存在关键字的原始数据 复制导入16进制文件 需改文头尾 得到压缩包
注意

这里有很多人得到压缩包 发现文件受损 打不开  这里你换一个解压软件就可以

得到密文和密钥
  1. flag.txt
  2. 10004583275926070044326083910251708233320797779355779208703097816305188140191914132269450797
  3. Key
  4. 5216294695211820293806247029887026154798297270637676463374801674229881314620340407569315152
复制代码
  将10进制转16进制
  
  在举行异或即可
  
10进制转16进制(这里可以使用在线,但线下就没有办法联网,所以要熟悉把握脚本编写使用)
这个脚本大学python基础课的水平 
  1. def dec_to_hex(number):
  2.     # 使用内置函数hex进行转换,但hex会返回以'0x'开头的字符串
  3.     # 使用切片操作去除'0x'
  4.     hex_str = hex(number)[2:]
  5.     # 如果转换后的字符串长度是1(即小于16),为了符合常规表示习惯,我们在前面添加一个'0'
  6.     if len(hex_str) == 1:
  7.         hex_str = '0' + hex_str
  8.     return hex_str
  9. # 示例
  10. if __name__ == "__main__":
  11.     # 从用户获取输入
  12.     number = int(input("请输入一个非负整数: "))
  13.     # 转换并输出结果
  14.     hex_representation = dec_to_hex(number)
  15.     print(f"{number}的16进制表示为: {hex_representation}")
复制代码
密文转          
  

密钥转
 
 

  1. 密文
  2. 4e94dcdb6de87e65d263419ec45aec93e8a2e1d386b31fb804e0f02366df44dbe86a8a7c462d
  3. 密钥 
  4. 28f8bdbc16de4850e05579acf33c8aa08ac3d9e6e3822b8c3081c04700eb25b88a08eb457550
复制代码
举行异或

  1. # 定义加密后的密文和密钥的十六进制字符串  
  2. txt = "4e94dcdb6de87e65d263419ec45aec93e8a2e1d386b31fb804e0f02366df44dbe86a8a7c462d"
  3. key = "28f8bdbc16de4850e05579acf33c8aa08ac3d9e6e3822b8c3081c04700eb25b88a08eb457550"
  4. # 将十六进制字符串转换为字节对象
  5. ciphertext_bytes = bytes.fromhex(txt)
  6. key_bytes = bytes.fromhex(key)
  7. # 使用逐字节异或进行解密
  8. # 注意:这里假设密钥和密文长度相同,否则zip会截断到较短的长度
  9. decrypted_bytes = bytes([c ^ k for c, k in zip(ciphertext_bytes, key_bytes)])
  10. # 尝试将解密后的字节对象解码为字符串,忽略无法解码的字节
  11. # 这里假设解密后的字节能够大部分解码为有效的UTF-8字符
  12. print(decrypted_bytes.decode(errors="ignore"))
  13. # 打印解密后的字符串(这行代码其实和上面的print是重复的,但保留以展示意图)
  14. # print(decrypted_bytes.decode(errors="ignore"))
复制代码
得到flag
flag{66526827ff3ba85e1444a0df4acbba93}

固然基础比较好的可以直接把脚本整合(如下 仅供参考)
整合脚本解析

  1. # 定义两个非常大的整数,flag 和 key  
  2. flag = 10004583275926070044326083910251708233320797779355779208703097816305188140191914132269450797  
  3. key = 5216294695211820293806247029887026154798297270637676463374801674229881314620340407569315152  
  4.   
  5. # 将 flag 和 key 转换为十六进制字符串,并去掉前缀 '0x'  
  6. flag_hex = hex(flag)[2:]  
  7. key_hex = hex(key)[2:]  
  8.   
  9. # 确定 flag_hex 和 key_hex 中较长者的长度,以便进行零填充  
  10. max_length = max(len(flag_hex), len(key_hex))  
  11.   
  12. # 使用零填充较短的十六进制字符串,使其与较长的字符串长度相同  
  13. flag_hex = flag_hex.zfill(max_length)  
  14. key_hex = key_hex.zfill(max_length)  
  15.   
  16. # 将填充后的十六进制字符串转换为字节对象  
  17. flag_bytes = bytes.fromhex(flag_hex)  
  18. key_bytes = bytes.fromhex(key_hex)  
  19.   
  20. # 对 flag_bytes 和 key_bytes 进行逐字节的异或操作  
  21. # 使用列表推导式和 zip 函数来遍历两个字节对象的对应位置,并对它们进行异或操作  
  22. flag_xor = bytes([f ^ k for f, k in zip(flag_bytes, key_bytes)])  
  23.   
  24. # 打印异或操作的结果  
  25. # 注意:这个结果是一个字节对象,可能无法直接作为可读文本打印(除非它仅包含可打印字符)  
  26. # 你可以将其再次转换为十六进制字符串来查看  
  27. print(flag_xor.hex())  
  28.   
  29. # 如果你想要查看原始的字节表示(作为十六进制字符串,但带有空格分隔),可以这样做:  
  30. print(' '.join(f'{byte:02x}' for byte in flag_xor))
复制代码
##coding

  1. &#x39;&#x33;&#x36;&#x35;&#x34;&#x34;&#x61;&#x35;&#x35;&#x33;&#x31;&#x34;&#x61;&#x37;&#x65;&#x34;&#x33;&#x33;&#x39;&#x35;&#x34;&#x35;&#x66;&#x34;&#x37;&#x37;&#x37;&#x36;&#x61;&#x36;&#x65;&#x34;&#x31;&#x33;&#x31;&#x35;&#x61;&#x37;&#x64;&#x34;&#x31;&#x33;&#x32;&#x35;&#x37;&#x34;&#x33;&#x35;&#x37;&#x35;&#x36;&#x35;&#x35;&#x34;&#x35;&#x35;&#x62;&#x34;&#x34;&#x37;&#x38;&#x35;&#x31;&#x36;&#x61;&#x36;&#x35;&#x33;&#x37;&#x34;&#x31;&#x36;
  2. 谜底就是flag,希望大家享受解码的过程。
复制代码

一看题目就知道是经典套娃
直接cyberchef搜哈了(以后离线成熟,那还得了)
(经典工具照旧可靠,打CTF不知道这个工具就犹如西方不知道耶路撒冷)

得到flag
flag{HNCTFbs789024301143b9}
#Crypto

##不警惕

题目
  1. # coding:utf-8
  2. # python 3.6
  3. from flag import flag
  4. import re
  5. s = "fst3Sem8Wgnobcd9+++++uv2JKpUViFGHz0QRMyjkA7NaBC14wXYxh5OP/DEqrZIl6LT"
  6.   
  7. assert re.match(r'^DASCTF\{[a-f0-9]+\}$',flag) != None
  8. def encode(inputs):
  9.     bin_str = []
  10.     for i in inputs:
  11.         x = str(bin(ord(i))).replace('0b', '')
  12.         bin_str.append('{:0>8}'.format(x))
  13.     outputs = ""
  14.     nums = 0
  15.     while bin_str:
  16.         temp_list = bin_str[:3]
  17.         if (len(temp_list) != 3):
  18.             nums = 3 - len(temp_list)
  19.             while len(temp_list) < 3:
  20.                 temp_list += ['0' * 8]
  21.         temp_str = "".join(temp_list)
  22.         temp_str_list = []
  23.         for i in range(0, 4):
  24.             temp_str_list.append(int(temp_str[i * 6:(i + 1) * 6], 2))
  25.         if nums:
  26.             temp_str_list = temp_str_list[0:4 - nums]
  27.         for i in temp_str_list:
  28.             outputs += s[i]
  29.         bin_str = bin_str[3:]
  30.     outputs += nums * '='
  31.     return outputs
  32.    
  33. c = encode(flag)
  34. print(c)
  35. # +Se++h+mF5u0d++Oc++RbQJYbyuMb++0cYuQc+SwdmK0d+fwcYRYG+==
复制代码
原题目脚本解释

这里我们来分析一下 题目脚本(我直接在脚本中给出解释)
  1. # 编码设置和导入必要的库  
  2. # coding:utf-8  # 指定文件编码为utf-8  
  3. # python 3.6  # 注释说明该脚本应在Python 3.6环境下运行,但实际上这行对Python解释器没有实际作用  
  4. from flag import flag  # 从flag模块中导入flag变量,假设flag模块中定义了flag变量,存储了CTF比赛的flag  
  5. import re  # 导入正则表达式库  
  6. # 给定的字符串,用于编码过程中的映射  
  7. s = "fst3Sem8Wgnobcd9+++++uv2JKpUViFGHz0QRMyjkA7NaBC14wXYxh5OP/DEqrZIl6LT"
  8. # 使用正则表达式断言flag的格式,确保flag以DASCTF{开头,后跟一串十六进制数字,以}结尾  
  9. assert re.match(r'^DASCTF\{[a-f0-9]+\}$', flag) != None
  10. def encode(inputs):
  11.     """  
  12.     将输入的字符串(假设为flag)进行编码。  
  13.     编码过程:  
  14.     1. 将每个字符转换为二进制字符串,并填充至8位。  
  15.     2. 每3个二进制字符串(共24位)合并,然后每6位一组转换为十进制数。  
  16.     3. 使用s字符串中对应位置的字符替换这些十进制数。  
  17.     4. 如果最后不足3个二进制字符串,则补零至3个,并相应地减少输出的字符数(用'='表示)。  
  18.     """
  19.     bin_str = []  # 存储每个字符的二进制表示(填充至8位)  
  20.     for i in inputs:
  21.         x = str(bin(ord(i))).replace('0b', '')  # 将字符转换为二进制字符串,并去除前缀'0b'  
  22.         bin_str.append('{:0>8}'.format(x))  # 填充至8位  
  23.     outputs = ""  # 存储编码后的字符串  
  24.     nums = 0  # 记录需要补零的二进制字符串数量  
  25.     while bin_str:
  26.         temp_list = bin_str[:3]  # 每次取3个二进制字符串  
  27.         if len(temp_list) != 3:  # 如果不足3个,则记录需要补零的数量  
  28.             nums = 3 - len(temp_list)
  29.             # 注意:这里的补零逻辑实际上在后续处理中被忽略了,因为temp_list直接用于处理  
  30.             # 理论上应该在这里补零,但代码中没有实现,可能是个遗漏  
  31.         temp_str = "".join(temp_list)  # 合并3个二进制字符串  
  32.         temp_str_list = []  # 存储每6位二进制转换成的十进制数  
  33.         for i in range(0, 4):  # 每6位一组进行转换(因为24位/6位=4组)  
  34.             temp_str_list.append(int(temp_str[i * 6:(i + 1) * 6], 2))  # 转换为十进制  
  35.         if nums:  # 如果需要补零,则减少输出的字符数  
  36.             temp_str_list = temp_str_list[0:4 - nums]
  37.         for i in temp_str_list:  # 使用s字符串中的字符替换这些十进制数  
  38.             outputs += s[i]
  39.         bin_str = bin_str[3:]  # 处理下一个3个二进制字符串  
  40.     outputs += nums * '='  # 使用'='表示补零的数量(但这里的实现可能不完全准确,因为补零逻辑未完全实现)  
  41.     return outputs
  42. # 对flag进行编码并打印结果
  43. c = encode(flag)
  44. print(c)  # 输出编码后的字符串  
  45. # +Se++h+mF5u0d++Oc++RbQJYbyuMb++0cYuQc+SwdmK0d+fwcYRYG+==
复制代码
“+”有多个,就需要爆破一下
   着实这里一个小漏洞
  我们看他本身给的脚本中有DASCTF的字样 这足以证实这道题是之前的原题(这里分析主办方有点懒呀 无意得罪 哈哈哈) (是2022河北银行CTF的原题 )
  

所以脚本直接照搬加以修改也可以(解释)
  1. # coding:utf-8
  2. # Python 3.6
  3. # 自定义编码函数,将输入字符串转换为基于特定字符串 s 的编码
  4. def encode(inputs):
  5.     bin_str = []
  6.     for i in inputs:
  7.         # 将字符转换为二进制字符串,并去掉前缀 '0b',然后填充至8位
  8.         x = '{:08b}'.format(ord(i))
  9.         bin_str.append(x)
  10.     outputs = ""
  11.     nums = 0
  12.     while bin_str:
  13.         # 每组处理3个二进制字符串(不足时用'0'填充至8位后的全0字符串代替)
  14.         temp_list = bin_str[:3]
  15.         if len(temp_list) != 3:
  16.             nums = 3 - len(temp_list)
  17.             while len(temp_list) < 3:
  18.                 temp_list.append('0' * 8)  # 直接添加8个0的字符串,而不是列表
  19.         temp_str = "".join(temp_list)
  20.         # 从每24位二进制中提取4个6位的部分,转换为十进制索引
  21.         temp_str_list = [int(temp_str[i * 6:(i + 1) * 6], 2) for i in range(4)]
  22.         if nums:
  23.             temp_str_list = temp_str_list[:4 - nums]  # 如果不足3个二进制字符串,则截取前面的部分
  24.         # 使用索引从字符串 s 中选择字符,并构建输出
  25.         for i in temp_str_list:
  26.             outputs += "fst3Sem8Wgnobcd9+++++uv2JKpUViFGHz0QRMyjkA7NaBC14wXYxh5OP/DEqrZIl6LT"[i]
  27.         bin_str = bin_str[3:]
  28.         # 如果不是3的倍数,则添加 '=' 填充
  29.     outputs += '=' * nums
  30.     return outputs
  31. # 模拟解码 Base64 的过程(实际上并未直接使用 Base64 解码,而是利用了自定义的 s 字符串)
  32. s = "fst3Sem8Wgnobcd9+++++uv2JKpUViFGHz0QRMyjkA7NaBC14wXYxh5OP/DEqrZIl6LT"
  33. h = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
  34. c = '+Se++h+mF5u0d++Oc++RbQJYbyuMb++0cYuQc+SwdmK0d+fwcYRYG+'
  35. m = ''
  36. for i in c:
  37.     # 通过查找 c 中每个字符在 s 中的索引,用该索引从 Base64 字符集 h 中选择字符
  38.     m += h[s.index(i)]
  39. print("模拟解码结果:", m)
  40. # 递归函数,用于解密特定的 Base64 字符串
  41. from base64 import b64decode
  42. import string
  43. ss = b'0123456789abcdef-_{}'
  44. def aaa(idx, mm):
  45.     if idx >= 4:
  46.         try:
  47.             # 尝试 Base64 解码
  48.             t = b64decode(mm)
  49.         except:
  50.             return
  51.             # 检查解码后的每个字节是否在允许的字符集 ss 中
  52.         if all(v in ss for v in t):
  53.             print("解码成功:", t.decode())  # 解码后可能需要转为字符串输出
  54.         return
  55.     if mm[idx] == 'Q':
  56.         # 替换 'Q' 为 'QRSTU' 中的一个字符,并递归处理
  57.         for v in "QRSTU":
  58.             aaa(idx + 1, mm[:idx] + v + mm[idx + 1:])
  59.     else:
  60.         # 继续递归处理下一个字符
  61.         aaa(idx + 1, mm)
  62.     # 解密过程
  63. m = 'QEFQQ1QGezc4YWQhMQEzZQcwOWZkZjEyYQVhYQQhYQVkZDYyZQMzfQ=='
  64. m = m[8:]  # 去掉前缀 'QEFQQ1Q',可能是为了减少搜索空间或符合特定条件
  65. # 分块处理 Base64 字符串
  66. for v in range(0, len(m), 4):
  67.     print('---------', v, m[v:v + 4])
  68.     aaa(0, m[v:v + 4])
  69. # 预期输出: DASCTF{78ada113e709fdf12a5aa4aa5dd62e33}
  70. # 注意:这个输出是预期值,实际输出取决于 m 的内容和递归函数的实现
复制代码
得到FLAG

DASCTF{78ada113e709fdf12a5aa4aa5dd62e33}
##Justmath

题目一个函数图像 一个脚本

原脚本解释

  1. # 导入必要的库  
  2. from gmpy2 import *  # 导入GMPY2库,用于高精度算术  
  3. from Crypto.Util.number import *  # 导入Crypto库的实用程序,用于数字加密和数学函数  
  4. from secret import FLAG,x,y  # 假设这是一个包含FLAG(待解密的消息)、x和y(可能是某个函数的变量和表达式)的模块  
  5. import sympy  # 导入SymPy库,用于符号数学  
  6. import pylab  # 导入pylab,通常用于绘图,但在这个上下文中可能不太必要  
  7.   
  8. # 定义calc函数,可能用于演示或测试符号求导和绘图  
  9. def calc():  
  10.     y1 = sympy.diff(y,x)  # 对y关于x求一阶导数  
  11.     y2 = sympy.diff(y1,x)  # 对y1(即y的一阶导数)关于x求二阶导数  
  12.     v1,v2,v3 = [],[],[]  # 初始化三个列表,用于存储计算结果  
  13.     for i in FLAG:  # 遍历FLAG中的每个字符(这里假设FLAG被转换为数字列表)  
  14.         v1.append(y.subs('x',i))  # 将y中的x替换为FLAG中的当前数字,并将结果添加到v1  
  15.     print('v1 =',v1[:34])  # 打印v1的前34个元素  
  16.     for i in v1:  
  17.         v2.append(y1.subs('x',i))  # 将y1中的x替换为v1中的当前值,并将结果添加到v2  
  18.     print('v2 =',v2[:2])  # 打印v2的前两个元素  
  19.     for i in v2:  
  20.         v3.append(y2.subs('x',i))  # 将y2中的x替换为v2中的当前值,并将结果添加到v3  
  21.     print('v3 =',v3[:2])  # 打印v3的前两个元素  
  22.     pylab.plot(v2,v3)  # 使用pylab绘制v2和v3的图形  
  23.     pylab.show()  # 显示图形  
  24.   
  25. # 定义rsam函数,生成RSA密钥对并加密FLAG  
  26. def rsam():  
  27.     m = bytes_to_long(FLAG)  # 将FLAG(假设为字节串)转换为长整型数字  
  28.     while True:  
  29.         try:  
  30.             p = getPrime(768)  # 生成一个768位的质数p  
  31.             q = getPrime(768)  # 生成另一个768位的质数q  
  32.             n = p*q  # 计算n = p*q,用于RSA模  
  33.             e = 3  # 使用小整数e=3作为公钥的一部分(在实际应用中,e应选择与phi(n)互质的大整数)  
  34.             phi = (p-1)*(q-1)  # 计算欧拉函数phi(n)  
  35.             d = invert(e,phi)  # 计算e关于phi的模逆d,用于私钥  
  36.             c = pow(m,e,n)  # 使用公钥(e,n)加密m  
  37.             print('n =',n)  # 打印公钥和密文的一部分  
  38.             print('e =',e)  
  39.             print('c =',c)  
  40.             break  # 跳出循环  
  41.         except:  
  42.             pass  # 如果生成质数或计算过程中发生错误,则忽略并继续尝试  
  43.   
  44. # 定义main函数,按顺序调用rsam和calc  
  45. def main():  
  46.     rsam()  # 调用rsam函数以生成RSA密钥对并加密FLAG  
  47.     calc()  # 调用calc函数以进行符号求导和绘图(与RSA加密无关)  
  48.   
  49. if __name__ == '__main__':  
  50.     main()  # 如果此脚本作为主程序运行,则调用main函数  
  51.   
  52. # 给出的RSA参数和计算结果  
  53. # ...(这里列出了n, e, c, v1, v2, v3的值,这些值用于验证或进一步分析)
  54. n = 2260375559104345425590426977960386256287009777233277062625487017885931446911942921201492850167115455071935831283269948569220356763988762825230315520633702443866690239945242948370781975714325308306543337600783340792458991506685843729962897796956171467876531084194426101796617903015810156717396227079274786269217370618477266867389155551378798713259843750289765858717627925689021561352438080039804957145513478767641674644346609224034274906228784593435462413278410143
  55. e = 3
  56. c = 1683427726786225271109289808778075351906457081282891335272956455076290407290946927840180672315908981114229434899424882579823897506730018911375238394076293908946844135295984336122170362703361647325169444373502665686779049846717305377396296752361918921007897449738856962248716579014267597667341690453460130215215256776249910808564677407383996700090361822122676428069577517468851642648993930679875398568383201032360229083338487146673018350740571719960730053254352184
  57. v1 = [3149069, 2271689, 2337632, 3068562, 67697, 2337632, 3068562, 67697, 2143547, 2543093, 1844472, 2206998, 67697, 1844472, 2686547, 2020317, 67697, 3149069, 2271689, 2081324, 67697, 2143547, 2543093, 1844472, 2206998, 67697, 2337632, 3068562, 67697, 2143547, 2543093, 1844472, 2206998, 3752378]
  58. v2 = [59499825996845, 30963434563085]
  59. v3 = [713997911962144, 371561214757024]
复制代码
编写脚本
第一部分:使用SageMath解方程规复部分flag

  1. # 引入SageMath的solve函数用于解方程  
  2. from sage.symbolic.relation import solve
  3. # 定义变量x  
  4. x = var('x')
  5. # y_value列表包含了通过某种方式(可能是符号函数在特定x值下的结果)得到的值  
  6. y_value = [3149069, 2271689, 2337632, 3068562, 67697, 2337632, 3068562, 67697, 2143547, 2543093, 1844472, 2206998, 67697, 1844472, 2686547, 2020317, 67697, 3149069, 2271689, 2081324, 67697, 2143547, 2543093, 1844472, 2206998, 67697, 2337632, 3068562, 67697, 2143547, 2543093, 1844472, 2206998, 3752378]  # 省略了中间的值以节省空间
  7. # 初始化flag字符串  
  8. flag = ""
  9. # 遍历y_value列表中的每个值  
  10. for i in y_value:
  11.     # 构造一个三次方程,使其等于y_value中的当前值  
  12.     equation = 2 * x ^ 3 + 2 * x ^ 2 + 3 * x + 17 == i
  13.     # 解这个方程  
  14.     solutions = solve(equation, x)
  15.     # 假设方程有三个解,取第三个解(注意:这里假设了解的顺序和存在性)  
  16.     # 并将该解转换为字符后添加到flag字符串中  
  17.     flag += chr(solutions[2].rhs())
  18. # 打印恢复的flag部分  
  19. print(flag)
复制代码
第二部分:使用RSA和Coppersmith的小根数攻击规复剩余的flag

  1. # 引入Crypto.Util.number中的函数
  2. from Crypto.Util.number import *
  3. # 已知flag的一部分(前缀)
  4. flag = b"this is flag and the flag is flag{"
  5. # RSA的公钥参数:模n和指数e
  6. n = 2260375559104345425590426977960386256287009777233277062625487017885931446911942921201492850167115455071935831283269948569220356763988762825230315520633702443866690239945242948370781975714325308306543337600783340792458991506685843729962897796956171467876531084194426101796617903015810156717396227079274786269217370618477266867389155551378798713259843750289765858717627925689021561352438080039804957145513478767641674644346609224034274906228784593435462413278410143  # 省略了具体的大数值以节省空间
  7. e = 3
  8. c = 1683427726786225271109289808778075351906457081282891335272956455076290407290946927840180672315908981114229434899424882579823897506730018911375238394076293908946844135295984336122170362703361647325169444373502665686779049846717305377396296752361918921007897449738856962248716579014267597667341690453460130215215256776249910808564677407383996700090361822122676428069577517468851642648993930679875398568383201032360229083338487146673018350740571719960730053254352184  # 省略了具体的密文大数值以节省空间
  9. # 定义模n的多项式环
  10. R. < x > = PolynomialRing(Zmod(n))
  11. # 尝试使用Coppersmith的小根数攻击来找到m(原始消息)
  12. # 由于我们知道flag的一部分,我们可以尝试通过不断添加'\x00'(即0字节)来扩展这个前缀
  13. # 然后我们尝试找到满足(m + x)^e - c = 0的小x值
  14. for i in range(40):  # 尝试不同的扩展长度
  15.     mhigh = bytes_to_long(flag + b"\x00" * 32 + b"}")  # 构造一个可能的高位m值
  16.     f = (mhigh + x) ^ e - c  # 构造多项式
  17.     # 使用small_roots方法尝试找到多项式的小根
  18.     # 参数X指定了搜索的界限,beta和epsilon影响搜索的精度和性能
  19.     res = f.small_roots(X=256 ^ i, beta=0.4, epsilon=0.05)
  20.     if res != []:  # 如果找到了根
  21.         # 将找到的小根值加到mhigh上,得到可能的m值
  22.         m = mhigh + int(res[0])
  23.         # 将m值转换回字节串并打印
  24.         print(long_to_bytes(m))
复制代码
得到flag
flag{0f5a1806d07f030767e113352727ea2d}
##BASE

题目

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

宁睿

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表