241029 网鼎杯青龙组 Crypto2

原题

import gmpy2
import random
import binascii
from hashlib import sha256
from sympy import nextprime
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from Crypto.Util.number import long_to_bytes
from FLAG import flag
#flag = 'wdflag{123}'def victory_encrypt(plaintext, key):key = key.upper()key_length = len(key)plaintext = plaintext.upper()ciphertext = ''for i, char in enumerate(plaintext):if char.isalpha():shift = ord(key[i % key_length]) - ord('A')encrypted_char = chr((ord(char) - ord('A') + shift) % 26 + ord('A'))ciphertext += encrypted_charelse:ciphertext += charreturn ciphertextvictory_key = "WANGDINGCUP"
victory_encrypted_flag = victory_encrypt(flag, victory_key)p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f
a = 0
b = 7
xG = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
yG = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
G = (xG, yG)
n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
h = 1
zero = (0,0)dA = nextprime(random.randint(0, n))if dA > n:print("warning!!")def addition(t1, t2):if t1 == zero:return t2if t2 == zero:return t2(m1, n1) = t1(m2, n2) = t2if m1 == m2:if n1 == 0 or n1 != n2:return zeroelse:k = (3 * m1 * m1 + a) % p * gmpy2.invert(2 * n1 , p) % pelse:k = (n2 - n1 + p) % p * gmpy2.invert((m2 - m1 + p) % p, p) % pm3 = (k * k % p - m1 - m2 + p * 2) % pn3 = (k * (m1 - m3) % p - n1 + p) % preturn (int(m3),int(n3))def multiplication(x, k):ans = zerot = 1while(t <= k):if (k &t )>0:ans = addition(ans, x)x = addition(x, x)t <<= 1return ansdef getrs(z, k):(xp, yp) = Pr = xps = (z + r * dA % n) % n * gmpy2.invert(k, n) % nreturn r,sz1 = random.randint(0, p)
z2 = random.randint(0, p)
k = random.randint(0, n)
P = multiplication(G, k)
hA = multiplication(G, dA)
r1, s1 = getrs(z1, k)
r2, s2 = getrs(z2, k)print("r1 = {}".format(r1))
print("r2 = {}".format(r2))
print("s1 = {}".format(s1))
print("s2 = {}".format(s2))
print("z1 = {}".format(z1))
print("z2 = {}".format(z2))key = sha256(long_to_bytes(dA)).digest()
cipher = AES.new(key, AES.MODE_CBC)
iv = cipher.iv
encrypted_flag = cipher.encrypt(pad(victory_encrypted_flag.encode(), AES.block_size))
encrypted_flag_hex = binascii.hexlify(iv + encrypted_flag).decode('utf-8')print("Encrypted flag (AES in CBC mode, hex):", encrypted_flag_hex)# output
# r1 = 86806104739558095745988469033305523200538774705708894815836887970976487278764
# r2 = 86806104739558095745988469033305523200538774705708894815836887970976487278764
# s1 = 93400851884262731807098055393482657423555590196362184363643455285862566867372
# s2 = 58741027521216057788923508334695668250013849866589902683641825341545919891746
# z1 = 47591695289461307212638536234394543297527537576682980326526736956079807805586
# z2 = 97911075901954715147720917205165523174582665086645698292621371632896283314804
# ('Encrypted flag (AES in CBC mode, hex):', u'86cd24e2914c0c4d9b87bea34005a98bd8587d14cae71909b917679d3328304e7915e6ba4cad1096faa4a85bc52f8056d3f21ef09516be8a5160f1b338a6b936')

步骤一:安装缺失运行库

# 创建虚拟环境,防止污染本机环境
python3 -m venv venv
source ./venv/bin/activate
# pip安装运行库
pip install gmpy2 sympy pycryptodome

步骤二:分析加密代码实现

key = sha256(long_to_bytes(dA)).digest()
cipher = AES.new(key, AES.MODE_CBC)
iv = cipher.iv
encrypted_flag = cipher.encrypt(pad(victory_encrypted_flag.encode(), AES.block_size))
encrypted_flag_hex = binascii.hexlify(iv + encrypted_flag).decode('utf-8')

题目提供给我们的是encrypted_flag_hex,我们要获取flag,需要先得到encrypted_flag.

encrypted_flag_hex = u'86cd24e2914c0c4d9b87bea34005a98bd8587d14cae71909b917679d3328304e7915e6ba4cad1096faa4a85bc52f8056d3f21ef09516be8a5160f1b338a6b936'
encrypted_flag_bytes = binascii.unhexlify(encrypted_flag_hex)
iv = encrypted_flag_bytes[:AES.block_size]
encrypted_flag = encrypted_flag_bytes[AES.block_size:]

我们需要获得victory_encrypted_flag的值,也就需要:

key = sha256(long_to_bytes(dA)).digest()
cipher = AES.new(key, AES.MODE_CBC, iv)victory_encrypted_flag = unpad(cipher.decrypt(encrypted_flag), AES.block_size).decode('utf-8')

这里需要dA的值,而dA在这里定义:

dA = nextprime(random.randint(0, n))

首先生成一个在 0n 之间的随机整数,然后找到大于这个随机整数的下一个质数,并将其赋值给变量dA. 如果要求得dA,就要求得k的值。

步骤三:计算得到k

先看看原函数如何包装k值:

首先,生成范围为(0, n)的随机整数k.

n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
k = random.randint(0, n)

然后生成范围为(0, p)的随机整数z1, z2.

p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f
z1 = random.randint(0, p)
z2 = random.randint(0, p)

z1, z2均已给出输出值。

然后将k, z1, z2分别传入getrs()函数。并输出r1, s1, r2, s2.

r1, s1 = getrs(z1, k)
r2, s2 = getrs(z2, k)

现在已经明白了k是如何被一步步包装成六个变量的,可以根据代码逐步的逆向运算得到k值。

首先,r1, s1, r2, s2指向了一个getrs()函数,我们可以分析一下这个函数。

def getrs(z, k):(xp, yp) = Pr = xps = (z + r * dA % n) % n * gmpy2.invert(k, n) % nreturn r,s

此函数的(xp, yp) = P指向了P = multiplication(G, k).我们可以分析一下multiplication()函数。

def multiplication(x, k):ans = zerot = 1while(t <= k):if (k &t )>0:ans = addition(ans, x)x = addition(x, x)t <<= 1return ans

这个函数的某些变量指向了addition()函数,我们继续看一下这段函数。

def addition(t1, t2):if t1 == zero:return t2if t2 == zero:return t2(m1, n1) = t1(m2, n2) = t2if m1 == m2:if n1 == 0 or n1 != n2:return zeroelse:k = (3 * m1 * m1 + a) % p * gmpy2.invert(2 * n1 , p) % pelse:k = (n2 - n1 + p) % p * gmpy2.invert((m2 - m1 + p) % p, p) % pm3 = (k * k % p - m1 - m2 + p * 2) % pn3 = (k * (m1 - m3) % p - n1 + p) % preturn (int(m3),int(n3))

通过这几段有关椭圆函数的运算可以推断出k是使用椭圆曲线数字签名算法(ECDSA)加密的。可参考一文看懂椭圆曲线签名算法 - 知乎进行求解k值。

k = (z1 - z2) * gmpy2.invert(s1 - s2, n) % n

步骤四:计算得到dA

根据之前的分析,可以逆向得到dA.

dA = (s1 * k - z1) * gmpy2.invert(r1, n) % n

步骤五:反推函数得到victory_encrypted_flag

阅读“步骤二”可得victory_encrypted_flag的逆向代码。

key = sha256(long_to_bytes(dA)).digest()
cipher = AES.new(key, AES.MODE_CBC, iv)victory_encrypted_flag = unpad(cipher.decrypt(encrypted_flag), AES.block_size).decode('utf-8')

运行后得到输出值为SDSRDO{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx},这并不是正确flag格式。

步骤六:得到正确flag

仔细阅读代码,可以发现victory_encrypted_flagvictory_encrypt()函数得到。

def victory_encrypt(plaintext, key):key = key.upper()key_length = len(key)plaintext = plaintext.upper()ciphertext = ''for i, char in enumerate(plaintext):if char.isalpha():shift = ord(key[i % key_length]) - ord('A')encrypted_char = chr((ord(char) - ord('A') + shift) % 26 + ord('A'))ciphertext += encrypted_charelse:ciphertext += charreturn ciphertextvictory_key = "WANGDINGCUP"
victory_encrypted_flag = victory_encrypt(flag, victory_key)

我们反推victory_encrypt()得到victory_decrypt()

def victory_decrypt(ciphertext, key):key = key. upper()key_length = len(key)ciphertext = ciphertext. upper()plaintext = ''for i, char in enumerate(ciphertext):if char.isalpha():shift = ord(key[i % key_length]) - ord('A')decrypted_char = chr((ord(char) - ord('A') - shift +26)% 26 + ord('A'))plaintext += decrypted_charelse:plaintext += charreturn plaintext

通过victory_decrypt()可以得到大写的FLAG,将其转换成小写flag即可。

完整实现源码

import binascii
from hashlib import sha256
from Crypto.Cipher import AES
from Crypto.Util.number import long_to_bytes
from Crypto.Util.Padding import unpad
import gmpy2n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
r1 = 86806104739558095745988469033305523200538774705708894815836887970976487278764
r2 = 86806104739558095745988469033305523200538774705708894815836887970976487278764
s1 = 93400851884262731807098055393482657423555590196362184363643455285862566867372
s2 = 58741027521216057788923508334695668250013849866589902683641825341545919891746
z1 = 47591695289461307212638536234394543297527537576682980326526736956079807805586
z2 = 97911075901954715147720917205165523174582665086645698292621371632896283314804
k = (z1 - z2) * gmpy2.invert(s1 - s2, n) % n
dA = (s1 * k - z1) * gmpy2.invert(r1, n) % nencrypted_flag_hex = u'86cd24e2914c0c4d9b87bea34005a98bd8587d14cae71909b917679d3328304e7915e6ba4cad1096faa4a85bc52f8056d3f21ef09516be8a5160f1b338a6b936'
encrypted_flag_bytes = binascii.unhexlify(encrypted_flag_hex)
iv = encrypted_flag_bytes[:AES.block_size]
encrypted_flag = encrypted_flag_bytes[AES.block_size:]key = sha256(long_to_bytes(dA)).digest()
cipher = AES.new(key, AES.MODE_CBC, iv)victory_encrypted_flag = unpad(cipher.decrypt(encrypted_flag), AES.block_size).decode('utf-8')def victory_decrypt(ciphertext, key):key = key. upper()key_length = len(key)ciphertext = ciphertext. upper()plaintext = ''for i, char in enumerate(ciphertext):if char.isalpha():shift = ord(key[i % key_length]) - ord('A')decrypted_char = chr((ord(char) - ord('A') - shift +26)% 26 + ord('A'))plaintext += decrypted_charelse:plaintext += charreturn plaintextvictory_key = "WANGDINGCUP"
flag = victory_decrypt(victory_encrypted_flag, victory_key)print(flag)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/463383.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【操作系统】每日 3 题(六)

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?typeblog &#x1f4e3;专栏地址&#xff1a;https://blog.csdn.net/newin2020/category_12820365.html &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享操作系统面试中常见的面试题给大家~ ❤️…

研究了100个小绿书十万加之后,我们发现2024小绿书独家秘籍就是:在于“先抄后超,持续出摊,量大管饱”!

小绿书作为今年最大的红利&#xff0c;很多人已经吃到了螃蟹。看——&#xff1a; 今天我们总结了100个10万爆款&#xff0c;我们发现要在这个平台上脱颖而出&#xff0c;找到属于自己的方法尤为重要。在这里分享一个主题——小绿书的秘诀就是“先抄后超&#xff0c;持续出摊”…

Python | Leetcode Python题解之第526题优美的排列

题目&#xff1a; 题解&#xff1a; class Solution:def countArrangement(self, n: int) -> int:f [0] * (1 << n)f[0] 1for mask in range(1, 1 << n):num bin(mask).count("1")for i in range(n):if mask & (1 << i) and (num % (i …

服务器数据恢复—RAID5阵列中部分成员盘重组RAID5阵列后如何恢复原raid5阵列数据?

服务器数据恢复环境&#xff1a; 一台服务器挂接一台存储&#xff0c;该存储中有一组由5块硬盘组建的RAID5阵列。 服务器故障&#xff1a; 存储raid5阵列中有一块硬盘掉线。由于RAID5的特性&#xff0c;阵列并没有出现问题。工作一段时间后&#xff0c;服务器出现故障&#xff…

每日OJ题_牛客_消减整数_贪心+数学_C++_Java

目录 牛客_消减整数_贪心数学 题目解析 C代码 Java代码 牛客_消减整数_贪心数学 消减整数 (nowcoder.com) 描述&#xff1a; 给出一个正整数H&#xff0c;从1开始减&#xff0c;第一次必须减1&#xff0c;每次减的数字都必须和上一次相同或者是上一次的两倍&…

iOS 18.2 可让欧盟用户删除App Store、Safari、信息、相机和照片应用

升级到 iOS 18.2 之后&#xff0c;欧盟的 iPhone 用户可以完全删除一些核心应用程序&#xff0c;包括 App Store、Safari、信息、相机和 Photos 。苹果在 8 月份表示&#xff0c;计划对其在欧盟的数字市场法案合规性进行更多修改&#xff0c;其中一项更新包括欧盟用户删除系统应…

Cisco Packet Tracer 8.0 路由器静态路由配置

文章目录 静态路由简介一、定义与特点二、配置与命令三、优点与缺点四、应用场景 一&#xff0c;搭建拓扑图二&#xff0c;配置pc IP地址三&#xff0c;pc0 ping pc1 timeout四&#xff0c;配置路由器Router0五&#xff0c;配置路由器Router1六&#xff0c;测试 静态路由简介 …

单片机原理及应用笔记:C51的数组与项目实践

作者简介 马博文&#xff0c;男&#xff0c;银川科技学院计算机与人工智能学院&#xff0c;2022级计算机科学与技术9班本科生&#xff0c;单片机原理及应用课程第9组。 指导老师&#xff1a;王兴泽 电子邮件&#xff1a;1834746988qq.com 本篇文章是参考《单片机原理及应用&…

Kubernetes实战——部署微服务项目(一)

目录 一、搭建Redis集群 1、安装redis 2、测试连接 二、搭建RocketMq 1、下载资源 2、安装 3、查看dashboard 三、搭建Elasticseach 1、es-service.yaml 2、es-statefulset.yaml 3、创建资源 四、搭建mongodb 1、mongodb.yaml 2、创建资源 五、搭建Mysql集群 1…

【React 轮子】文本溢出后显示展开/收起按钮

/** hooks* 用于文本展示时判断是否展示 展开/收起按钮 &#xff08;包含监听 文本变化/页面尺寸变换&#xff09;* param { string } text 需要展示的文本* param { number } maxLength 文本最大展示行数* param { number } lineHeight 文本行高 (单位 px) */ import React, …

【AD】2-1 元件符号的绘制创建实例-电阻容/CHIP类器件

1.新建工程后&#xff0c;双击原理图库&#xff0c;点击Panels后&#xff0c;选择SCH Library&#xff0c;双击元器件可在右侧进行更改名称 2.点击视图&#xff0c;栅格&#xff0c;设置捕捉栅格为100mil 3.点击放置管脚&#xff0c;可按空格键进行旋转&#xff0c;按TAB键可以…

javascript-Web APLs (三)

事件流 指的是事件完整执行过程中的流动路 说明&#xff1a;假设页面里有个div&#xff0c;当触发事件时&#xff0c;会经历两个阶段&#xff0c;分别是捕获阶段、冒泡阶段 简单来说&#xff1a;捕获阶段是 从父到子 冒泡阶段是从子到父 实际工作都是使用事件冒泡为主 事件…

恋爱脑学Rust之Box与RC的对比

在遥远的某个小镇&#xff0c;住着一对年轻的恋人&#xff1a;阿丽和小明。他们的爱情故事就像 Rust 中的 Rc 和 Box 智能指针那样&#xff0c;有着各自不同的「所有权」和「共享」的理解。 故事背景 阿丽和小明准备共同养一株非常珍贵的花&#xff08;我们称之为“心之花”&…

【uni-app】创建自定义模板

1. 步骤 打开自定义模板文件夹 在此文件夹下创建模板文件&#xff08;注意后缀名&#xff09; 重新点击“新建页面” 即可看到新建的模板 2. 注意事项 创建的模板必须文件类型对应&#xff08;vue模板就创建*.vue文件, uvue模板就创建*.uvue文件&#xff09;

推荐一款功能强大的数据库开发管理工具:SQLite Expert Pro

SQLite Expert Professional是一个功能强大的工具&#xff0c;旨在简化SQLite3数据库的开发。 它是SQLite的一个功能丰富的管理和开发工具&#xff0c;旨在满足所有用户从编写简单SQL查询到开发复杂数据库的需求。 图形界面支持所有SQLite功能。 它包括一个可视化查询构建器&a…

【制造业&仓库】流水线能源设备检测系统源码&数据集全套:改进yolo11-DCNV2-Dynamic

改进yolo11-CAA-HSFPN等200全套创新点大全&#xff1a;流水线能源设备检测系统源码&#xff06;数据集全套 1.图片效果展示 项目来源 人工智能促进会 2024.11.01 注意&#xff1a;由于项目一直在更新迭代&#xff0c;上面“1.图片效果展示”和“2.视频效果展示”展示的系统图…

FreeRTOS学习9——补充 API函数详解(创建、删除任务函数 和 挂起、恢复任务函数,空闲任务函数)

API函数详解(创建任务函数 和 删除任务函数) 创建函数 xTaskCreate() 作用&#xff1a;创建任务 ​ 函数 xTaskCreate()在 task.c 文件中有定义&#xff0c;具体的代码如下所示&#xff1a; BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,const char * const pcName,…

Vue2.0 通过vue-pdf-signature@4.2.7和pdfjs-dist@2.5.207实现PDF预览

1.安装依赖 npm install pdfjs-dist2.5.207 --savenpm install vue-pdf-signature4.2.7 --save2.在.vue文件中 script 部分引入 <script> import * as PDFJS from pdfjs-dist PDFJS.GlobalWorkerOptions.workerSrc require(pdfjs-dist/build/pdf.worker.js);//解决pdf…

kafka-console-ui的简介及安装使用

kafka-console-ui的简介及安装使用 一、kafka-console-ui的简介二、安装kafka-console-ui2.1 源码安装2.2 docker安装 三、kafka-console-ui功能使用3.1、功能特性3.2、 功能介绍3.2.1 集群3.2.2 topic3.2.3 消费组3.2.4 Acl3.2.5 运维 一、kafka-console-ui的简介 kafka-cons…

MySQL(上)

一、SQL优化 1、如何定位及优化SQL语句的性能问题&#xff1f;创建的索引有没有被使用到?或者说怎么才可以知道这条语句运行很慢的原因&#xff1f; 对于性能比较低的sql语句定位&#xff0c;最重要的也是最有效的方法其实还是看sql的执行计划&#xff0c;而对于mysql来说&a…