[DiceCTF 2023] rRabin

news/2024/4/24 10:48:49/文章来源:https://blog.csdn.net/weixin_52640415/article/details/128960324

一点点学习别人的WP,这回看到一个大姥(r3kapig)的帖子,DiceCTF第二名,不过有好多东西一时还理解不了,得慢慢来。

题目

这个题有3个功能:

  1. rsa加密功能,p,q,N未知,e=17低加密指数

  1. 解密,不过解密方法比较特别,分别对p,q求nth_root不过未给出nth_root函数,所以不能直接使用。

  1. 对flag加密,用PKCS1_OAEP填充。多数情况下低加密指数如果明文比较小会导致加密后比N小或者仅比N大一点,可以通过开根号爆破。但填充后长度基本与N长度一致,爆破无效。

import asyncio
import traceback
from Crypto.Util.number import getPrime, bytes_to_long
from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSAfrom nth_root import nth_root, chinese_remainder # not providedclass Server:def __init__(self):e = 17nbits = 512p = getPrime(nbits)q = getPrime(nbits)N = p * qself.p = pself.q = qself.N = Nself.e = edef encrypt(self, m):assert 0 <= m < self.Nc = pow(m, self.e, self.N)return int(c)def decrypt(self, c):assert 0 <= c < self.Nmp = int(nth_root(c, self.p, self.e))mq = int(nth_root(c, self.q, self.e))m = chinese_remainder([mp, mq], [self.p, self.q])return int(m)def encrypt_flag(self):with open("flag.txt", "rb") as f:flag = f.read()key = RSA.construct((self.N, self.e))cipher = PKCS1_OAEP.new(key)c = cipher.encrypt(flag)c = bytes_to_long(c)return casync def handle(a):S = Server()while True:cmd = (await a.input("Enter your option (EDF) > ")).strip()if cmd == "E":m = int(await a.input("Enter your integer to encrypt > "))c = S.encrypt(m)await a.print(str(c) + '\n')elif cmd == "D":c = int(await a.input("Enter your integer to decrypt > "))m = S.decrypt(c)await a.print(str(m) + '\n')elif cmd == "F":c = S.encrypt_flag()await a.print(str(c) + '\n')returnclass Handler:def __init__(self, reader, writer):self.reader = readerself.writer = writerasync def print(self, data):self.writer.write(str(data).encode())await self.writer.drain()async def input(self, prompt):await self.print(prompt)return (await self.reader.readline()).decode()async def __aenter__(self):return selfasync def __aexit__(self, exc_t, exc_v, exc_tb):self.writer.close()await self.writer.wait_closed()if exc_v is not None and not isinstance(exc_v, asyncio.TimeoutError):traceback.print_exception(exc_v)return Trueasync def main():async def callback(*args):async with Handler(*args) as a:await asyncio.wait_for(handle(a), 20)server = await asyncio.start_server(callback, '0.0.0.0', 5000)print('listening')async with server:await server.serve_forever()if __name__ == "__main__":asyncio.run(main())

思路:

求N

首先要求N,我本来是想弄几个17次幂后比N略大的值求gcd,看到大姥的解法眼前一亮。

先随机取m,然后求enc(m),enc(m^2),enc(m^4)然后分别用没有模过N的原值求差m^e,(m^2)^e,(m^4)^e减,再求gcd这个更方便。

函数头部

from pwn import *
import random 
from Crypto.Util.number import GCD,long_to_bytes,bytes_to_long 
from gmpy2 import iroot context.log_level = 'debug'def enc(m):io.sendlineafter(b"Enter your option (EDF) > ", b'E')io.sendlineafter(b"Enter your integer to encrypt > ", str(m).encode())return int(io.recvline())def dec(c):io.sendlineafter(b"Enter your option (EDF) > ", b'D')io.sendlineafter(b"Enter your integer to encrypt > ", str(c).encode())return int(io.recvline())def get_flag():io.sendlineafter(b"Enter your option (EDF) > ", b'F')return int(io.recvline())def decrypt(c, N, p, q):assert 0 <= c < Nmp = int(c.nth_root(e))mq = int(c.nth_root(e))m = chinese_remainder([mp, mq], [p, q])return int(m)

求N

m = random.randrange(0,2**155)
m2 = m**2
m4 = m**4
c1 = enc(m)
c2 = enc(m2)
c4 = enc(m4)
N = GCD(GCD(c1**2 - c2, c2**2 - c4), c1**4 - c4)

分解N

这个方法头一回见。

先取一个略小于的值,使p<m<q(大概率),求c = m^e %N

由于e=17所以gcd(e,(p-1)*(q-1))有1/17的概率不为1,p,q两个出现1个的概率略大于1/9,对于爆破来说这个概率并不小。

当不互素时 decrypt(c)-m = kp 与N求gcd就能得到p

这时候获取enc(flag),(远端会在获取后结束,对flag无法交互)

    tmpn = iroot(N,2)[0] - 1000c = enc(tmpn)ret = dec(c)if ret == tmpn:io.close()continue else:iflag = get_flag()print('N = ',N)print('tmpn = ', tmpn)print('c = ',c)print('ret = ', ret)print('iflag = ',iflag)#e=17 gcd(e,p-1) != 1 的概率是1/17 io.interactive()

经过x 次交互得到如下数据

e = 17
N = 145929886027830605678430202427323053628064442310464018856395565973995064472578943595719088909803787366850912624656960966772751178490892976055180188367608145038609558294202567019869852120311834412433602187079592510589435977725095316257649141862850904221294264419961365596274045500230679371213475300930406042261
tmpn = 12080144288369680134663865822252253203358727058793479854567933546272937742973360100460050936204099841676294371963062308235668122560773478644865802421986920
ret = 38626509565846846198929657581252980560445889902524802003755764516997686363556486348466834915881637092111849253058180514729213545303952798006800009337375370781676698957130798722071959097949405886433880476180556708960839753606831748033044468904639617141322699562124769255797179947555095545345666523628726328021
iflag = 94785540286244324280900673502395494485593520218609389745579915172323211491609524359277466592150462516952301308455222973538441633205212054875400879171885042191555256518152907528122607881031719899722188867464126986611318409258138548887258038636675128271840693263847776054879375943419688129202875859618405032469

这时候就能得到p,q

p = GCD(ret-tmpn, N)
q = N//p 
'''
p = 12489852031586615822311701100326231241806260275896449364532516898411555577529972957144893166576911381503372838312839610202975336506868820457393001178785531
q = 11683876290830066998757443847623160481197019426815171259465107520260429703525441378146027740470276103931704547758704704292062887913193269825188377531686831
'''

修改PKCS1_OAEP.py增加unpad函数

pycryptodome库在PKCS1_OAEP.py提供了OAEP的解密功能,在RSA解密后进行了unpad但是没有独立的unpad函数。而由于gcd(e,phi)!=1所以也就不能直接用decrypt函数。

修改的方法是将decrypt函数复制一下,改为unpad然后将第2a,2b步的解密删掉改为从参数直接获取明文

unpad后

    def unpad(self, ct_int):"""Decrypt a message with PKCS#1 OAEP.:param ciphertext: The encrypted message.:type ciphertext: bytes/bytearray/memoryview:returns: The original message (plaintext).:rtype: bytes:raises ValueError:if the ciphertext has the wrong length, or if decryptionfails the integrity check (in which case, the decryptionkey is probably wrong).:raises TypeError:if the RSA key has no private half (i.e. you are tryingto decrypt using a public key)."""# See 7.1.2 in RFC3447modBits = Crypto.Util.number.size(self._key.n)k = ceil_div(modBits,8) # Convert from bits to byteshLen = self._hashObj.digest_size#patch--------------------------------------------# Step 1b and 1c#if len(ciphertext) != k or k<hLen+2:#    raise ValueError("Ciphertext with incorrect length.")# Step 2a (O2SIP)#ct_int = bytes_to_long(ciphertext)# Step 2b (RSADP)#m_int = self._key._decrypt(ct_int)m_int = ct_int    #与decrypt基本相同,只是用ct_int跳过解密#------------------------------------------------------# Complete step 2c (I2OSP)em = long_to_bytes(m_int, k)# Step 3alHash = self._hashObj.new(self._label).digest()# Step 3by = em[0]# y must be 0, but we MUST NOT check it here in order not to# allow attacks like Manger's (http://dl.acm.org/citation.cfm?id=704143)maskedSeed = em[1:hLen+1]maskedDB = em[hLen+1:]# Step 3cseedMask = self._mgf(maskedDB, hLen)# Step 3dseed = strxor(maskedSeed, seedMask)# Step 3edbMask = self._mgf(seed, k-hLen-1)# Step 3fdb = strxor(maskedDB, dbMask)# Step 3gone_pos = hLen + db[hLen:].find(b'\x01')lHash1 = db[:hLen]invalid = bord(y) | int(one_pos < hLen)hash_compare = strxor(lHash1, lHash)for x in hash_compare:invalid |= bord(x)for x in db[hLen:one_pos]:invalid |= bord(x)if invalid != 0:raise ValueError("Incorrect decryption.")# Step 4return db[one_pos + 1:]

文件位置一般在这

"C:\Users\AAAA\AppData\Local\Programs\Python\Python310\Lib\site-packages\Crypto\Cipher\PKCS1_OAEP.py"

求明文

由于e与phi不互素,所以这里要对p,q分别求根

from Crypto.Util.number import isPrime,long_to_bytes,bytes_to_long 
from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA
import time def rthroot(c, r, q):c %= qassert(isPrime(r) and (q - 1) % r == 0 and (q - 1) % (r**2) != 0)l = ((q - 1) % (r**2)) // ralpha = (-inverse(l, r)) % rroot = pow(c, ((1 + alpha * (q - 1) // r) // r), q)return rootdef allroot(r, q, root):all_root = set()all_root.add(root)while len(all_root) < r:new_root = rootunity = pow(getRandomRange(2, q), (q - 1) // r, q)for i in range(r - 1):new_root = (new_root * unity) % qall_root.add(new_root)return all_rootdef decrypt(proot, qroot, p, q):count = 0total = len(proot) * len(qroot)t1 = inverse(q, p)t2 = inverse(p, q)for i in proot:for j in qroot:count += 1m = (i * t1 * q + j * t2 * p) % (p * q)assert (pow(m,e,N) == c)try:print( cipher.unpad((m)))print(m)except:continuekey = RSA.construct((N, e))
cipher = PKCS1_OAEP.new(key)  #rthroot要求 (q-1)%e == 0 所以必要时是p,q交换,使(q-1)%e == 0
p,q = q,p proot = rthroot(c, e, p)
qroot = pow(c,inverse(e,q-1),q)
print('[+] Calculating all e-th roots...')all_proot = allroot(e, p, proot)
all_qroot = [qroot]# 3 allroot(e, q, qroot)
print('[+] CRT cracking...')decrypt(all_proot, all_qroot, p, q)

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

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

相关文章

Reflections反射包在springboot jar环境下扫描不到class排查过程

需求&#xff1a; 要实现指定pkg&#xff08;如com.qiqitrue.test.pojo&#xff09;扫描包下所有class类信息&#xff1a;使用代码如下 使用的版本&#xff1a;0.10.2&#xff08;截至目前是最新版&#xff09;发现只能在idea编译期间可以获取得到&#xff08;也就是在开发阶段…

解读YOLO v7的代码(三)损失函数

在前两篇博客中我分析了YOLO v7的模型结构以及训练数据的准备。这里将对损失函数的代码进行分析。在train.py中&#xff0c;我们可以看到以下的代码是进行损失值计算的if loss_ota not in hyp or hyp[loss_ota] 1:loss, loss_items compute_loss_ota(pred, targets.to(device…

图解项目延期的原因及解决应对方案大全

项目管理中经常出现项目延期的情况&#xff0c;面对项目延期的风险如何应对是考验每个项目经理管理水平的时候&#xff0c;很多人纵然是工作多年也没有对延期的种种情况进行总结思考。咱们社区的小竹对大家常见的项目延期情况及处理方案进行了详细全面的总结&#xff0c;供大家…

【数据结构-JAVA】排序

排序在现实生活中的应用可谓相当广泛&#xff0c;比如电商平台中&#xff0c;选购商品时&#xff0c;使用价格排序或是综合排序、高考填报志愿的时候&#xff0c;会参考全国大学排名的情况。下面介绍一些计算机中与排序相关的概念&#xff1a;排序&#xff1a;所谓排序&#xf…

python自学之《21天学通Python》(10)——正则表达式

第13章 正则表达式 最初的正则表达式出现于理论计算机科学的自动控制理论和形式化语言理论中。在这些领域中有对计算&#xff08;自动控制&#xff09;的模型和对形式化语言描述与分类的研究。 程序员所用的正则表达式是指用某种模式去匹配一类具有共同特征的字符串。正则表达…

机器学习调参

机器学习调参常用调参方法举例K邻近算法&#xff08;最常规版本&#xff09;加入交叉验证加上网格搜索GridSearchCV函数介绍GridSearchCVcross_val_score常用调参方法举例 sklearn使得我们在很多编写代码的时候更多的工作倾向于调参数而不是去写算法本身&#xff0c;本篇文章整…

卸载Node.js

0 写在前面 无论您是因为什么原因要卸载Node.js都必须要卸载干净。 请阅读&#xff1a; 1 卸载步骤 1.1通过控制面板卸载node.js winR—>control.exe—>卸载程序—>卸载Node.js 等待—>卸载成功 1.2 删除安装时的nodejs文件夹 通过记忆或者Everthing搜索找…

「自控元件及线路」14 电子电力技术与功率放大器概述

本节介绍电子电力技术的基本概念 本节介绍PD、SCR、GTR、MOSFET、IGBT等电子电力器件 本节介绍功率放大器的基本概念和线性功率放大器 文章目录电力电子技术概述电能变换电子电力器件功率二极管PD晶闸管SCR功率晶体管GTR功率场效应晶体管PowerMOSFET绝缘栅双极晶体管IGBT功率放…

使用 ThreeJS 实现第一个三维场景(详)

文章目录参考描述index.html三维场景的基本实现导入 ThreeJS准备工作场景摄像机视锥体正交摄像机透视摄像机渲染器后续处理将摄像机添加至场景中移动摄像机设置画布尺寸将渲染器创建的画布添加到 HTML 元素中渲染物体结构材质合成将物体添加至场景中代码总汇执行效果动画reques…

你的自动化框架如何设计的?为什么感觉面试官总是不满意,到底问题出在哪?

前言去面试自动化测试岗位&#xff0c;尤其是接口自动化岗位&#xff0c;面试官总会问&#xff1a;说下你的自动化框架如何设计的&#xff1f;为什么回答后&#xff0c;面试官对你的框架设计总是感觉不满意&#xff1f;自动化测试实现的几种方式对于不同的公司来说&#xff0c;…

2023年地方两会政府工作报告汇总(各省市23年重点工作)

新年伊始&#xff0c;全国各地两会密集召开&#xff0c;各省、市、自治区2023年政府工作报告相继出炉&#xff0c;各地经济增长预期目标均已明确。相较于2022年&#xff0c;多地经济增长目标放缓&#xff0c;经济不断向“高质量”发展优化转型。今年是二十大后的开局之年&#…

【参加CUDA线上训练营】零基础cuda,一文认识cuda基本概念

【参加CUDA线上训练营】零基础cuda,一文认识cuda基本概念1.术语2.线程层次2.1 Block、Warp与Thread之间的关系2.2 Thread index1.术语 \\%序号名称描述1HostCPU和内存&#xff08;host memory&#xff09;2DeviceGPU和显存&#xff08;device memory&#xff09;3SMStreaming M…

101-并发编程详解(上篇)

并发编程详解在学习之前&#xff0c;如果多线程的理解足够&#xff0c;可以往下学习&#xff0c;否则的话&#xff0c;建议先看看26章博客&#xff08;只是建议&#xff09;&#xff0c;注意&#xff1a;可能有些字的字体不对&#xff0c;那么一般是复制粘贴来的&#xff0c;但…

开关电源-一种方便快捷计算开关电源环路参数的方法及实例

一种方便快捷计算开关电源环路参数的方法及实例 接上文《技术实例 | 开关电源环路测量时&#xff0c;注入信号的幅值对测量结果的影响》&#xff0c;得到电流环功率级的开环传递函数后&#xff0c;我们通过matlab的sisotool工具箱自动计算出了电流环路补偿器的传递函数C&#…

三层交换机【实验】

目录 1、要求&#xff1a; 2、拓扑&#xff1a; 3、创建vlan和端口定义并划入vlan&#xff1a; 4、创建以太网中继Eth-Trunk使sw1和sw2的相互冗余并且不浪费链路&#xff1a; 5、使用mstp定义组和对应的根&#xff1a; 6、配置网关冗余&#xff1a; 7、核心层的路由的IP配…

云仓仓储的运行模式是什么?

仓库能够简单地定义为一个规划空间&#xff0c;通常是一个用于处置和贮存货物的大型商业建筑。因而&#xff0c;仓储是指在这样一个规划空间中存储和处置货物所触及的一切过程。仓库中常见的货物包括&#xff1a;;机械零配件、建筑资料、废品农产品、家具和电子产品。仓库中的一…

Fluid-数据缓存亲和性调度原理解析

前言在Fluid中&#xff0c;Dataset资源对象中所定义的远程文件是可被调度的&#xff0c;这意味着你能够像管理你的Pod一样管理远程文件缓存在Kubernetes集群上的存放位置。另外&#xff0c;Fluid同样支持对于应用的数据缓存亲和性调度&#xff0c;这种调度方式将应用(e.g. 数据…

二进制部署K8S集群

目录 一、架构图 二、部署步骤 1、实验环境 2、操作系统初始化配置 3、部署 docker引擎 4、部署 etcd 集群 5、部署 Master 组件 一、架构图 二、部署步骤 1、实验环境 服务器类型IP地址master192.168.80.5node01192.168.80.8node02192.168.80.9 2、操作系统初始化配置…

SpringBoot整合Mybatis的核心原理

0. 前言&#xff1a;1. 自动配置类MybatisAutoConfiguration&#xff1a;1.1. SqlSessionFactory的生成&#xff1a;1.2. Mapper的扫描和代理生成&#xff1a;1.2.1. MapperScannerConfigurer1.2.2. MapperFactoryBean1.2.3. getMapper生成代理对象2. 小结&#xff1a;0. 前言&…

3D模型深度生成网络【ShapeAssembly】

推荐&#xff1a;使用 NSDT场景设计器 快速搭建 3D场景。 我们提出了一个深度生成模型&#xff0c;该模型学习在ShapeAssembly中编写新颖的程序&#xff0c;ShapeAssembly是一种用于建模3D形状结构的特定领域语言。 执行 ShapeAssembly 程序会生成一个由部件代理长方体的分层连…