2024_XGCTF_西瓜杯_Ctypto

【改变的确很难,但结果值得冒险】

本文主要是对Crypto方向解答:

目录

奇怪的条形码

思路

简单密码

思路

代码

factor

思路一

思路二

思路一代码

 给你d又怎样

思路

代码

 混合密码体系

思路

 代码


奇怪的条形码

题目

思路

通过手机充电口查看图片的内容,然后base64解码即可

简单密码

题目

647669776d757e83817372816e707479707c888789757c92788d84838b878d9d

思路

先尝试cyberchef和随波逐流,发现解不开

观察编码,貌似就是单纯的十六进制

与此同时我们发现ctfshow对应的十六进制就是63 74 66 73 68 68 6f 77

 发现就是将每两位十六进制逐次减去i(i初始为一,每次加一)

代码

hex = '647669776d757e83817372816e707479707c888789757c92788d84838b878d9d'

#将hex数组内容两位一组形成一个新数组
a = [hex[i:i+2] for i in range(0, len(hex), 2)]
# chr()参数必须是10进制,或者是0x+16进制,如果只写十六进制不加0x,会被认为str
for i in range(0,len(a)):
    m=int(a[i],16)-(i+1)
    print(chr(m),end='')

ctfshow{xiguabei_just_ez_signin}

factor

题目

from Crypto.Util.number import *
import gmpy2
import os
from enc import flag

hint = os.urandom(36)
tmp = bytes_to_long(hint)
m = bytes_to_long(flag)
p = getPrime(512)
q = getPrime(512)
d = getPrime(400)
phi = (p-1)*(q-1)
e = gmpy2.invert(d,phi)
n = p*q
c = pow(m,e,n)
leak1 = p^tmp
leak2 = q^tmp
print(f"n = {n}")
print(f"e = {e}")
print(f"c = {c}")
print(f"leak1 = {leak1}")
print(f"leak2 = {leak2}")
'''
n = 145462084881728813723574366340552281785604069047381248513937024180816353963950721541845665931261230969450819680771925091152670386983240444354412170994932196142227905635227116456476835756039585419001941477905953429642459464112871080459522266599791339252614674500304621383776590313803782107531212756620796159703
e = 10463348796391625387419351013660920157452350067191419373870543363741187885528042168135531161031114295856009050029737547684735896660393845515549071092389128688718675573348847489182651631515852744312955427364280891600765444324519789452014742590962030936762237037273839906251320666705879080373711858513235704113
c = 60700608730139668338977678601901211800978306010063875269252006068222163102100346920465298044880066999492746508990629867396189713753873657197546664480233269806308415874191048149900822050054539774370134460339681949131037133783273410066318511508768512778132786573893529705068680583697574367357381635982316477364
leak1 = 13342820281239625174817085182586822673810894195223942279061039858850534510679297962596800315875604798047264337469828123370586584840078728059729121435462780
leak2 = 10901899434728393473569359914062349292412269512201554924835672710780580634465799069211035290729536290605761024818770843901501694556825737462457471235151530
'''

思路一

异或的思路:

自己与自己异或,结果为0

m与0异或,结果为m

m与1异或,结果是m二进制每位的相反数

这里leak1^leak2=p^q

但我们不知道p和q,只能从p和q二进制的最低位到高位逐渐累加(递归)

从而找到真正符合的p和q

 这里的p和q的最低位如何确定?

print((leak1^leak2)%2)  //结果是0

说明p和q的最低位相同,1,1或0,0,

1,1说明都是奇数

0,0说明都是偶数

奇数*奇数=奇数

偶数*偶数=偶数

这里由n是奇数可知:

n = 145462084881728813723574366340552281785604069047381248513937024180816353963950721541845665931261230969450819680771925091152670386983240444354412170994932196142227905635227116456476835756039585419001941477905953429642459464112871080459522266599791339252614674500304621383776590313803782107531212756620796159703

p和q一定是奇数,所以得出p和q的最低位都是1

后面就是不断的递归查找高位了

find_pq('1' + bin_p, '1' + bin_q)
find_pq('1' + bin_p, '0' + bin_q)
find_pq('0' + bin_p, '1' + bin_q)
find_pq('0' + bin_p, '0' + bin_q)

思路二

发现这里的n是可以通过工具分解的

 有了p和q就是常规的RSA了

在线分解工具网站factordb.com

思路一代码

from Crypto.Util.number import *
import gmpy2


def find_pq(bin_p, bin_q):
    l = len(bin_p)
    if l == 512:
        p = int(bin_p, 2)
        if n % p == 0:
            q = n//p
            phi = (p-1)*(q-1)
            d = gmpy2.invert(e,phi)
            m = pow(c,d,n)
            flag = long_to_bytes(m)
            print(flag)
    else:
        p = int(bin_p, 2)
        q = int(bin_q, 2)
        if (p ^ q) % (2 ** l) == p_xor_q % (2 ** l) and p * q % (2 ** l) == n % (2 ** l):
            find_pq('1' + bin_p, '1' + bin_q)
            find_pq('1' + bin_p, '0' + bin_q)
            find_pq('0' + bin_p, '1' + bin_q)
            find_pq('0' + bin_p, '0' + bin_q)

n = 145462084881728813723574366340552281785604069047381248513937024180816353963950721541845665931261230969450819680771925091152670386983240444354412170994932196142227905635227116456476835756039585419001941477905953429642459464112871080459522266599791339252614674500304621383776590313803782107531212756620796159703
e = 10463348796391625387419351013660920157452350067191419373870543363741187885528042168135531161031114295856009050029737547684735896660393845515549071092389128688718675573348847489182651631515852744312955427364280891600765444324519789452014742590962030936762237037273839906251320666705879080373711858513235704113
c = 60700608730139668338977678601901211800978306010063875269252006068222163102100346920465298044880066999492746508990629867396189713753873657197546664480233269806308415874191048149900822050054539774370134460339681949131037133783273410066318511508768512778132786573893529705068680583697574367357381635982316477364
leak1 = 13342820281239625174817085182586822673810894195223942279061039858850534510679297962596800315875604798047264337469828123370586584840078728059729121435462780
leak2 = 10901899434728393473569359914062349292412269512201554924835672710780580634465799069211035290729536290605761024818770843901501694556825737462457471235151530
p_xor_q = leak1^leak2
find_pq('1', '1')

 cftshow{do_you_know_what_is_xor_and_prune!!!}

 这里我还想尝试下先利用高位都是1,去找低位,发现行不通

 给你d又怎样

题目

from Crypto.Util.number import *
from gmpy2 import *

flag="ctfshow{***}"
m=bytes_to_long(flag.encode())
e=65537
p=getPrime(128)
q=getPrime(128)
n=p*q
phin=(p-1)*(q-1)
d=invert(e,phin)
c=pow(m,e,n)
print("c=",c)
print("hint=",pow(n,e,c))
print("e=",e)
print("d=",d)
"""
c= 48794779998818255539069127767619606491113391594501378173579539128476862598083
hint= 7680157534215495795423318554486996424970862185001934572714615456147511225105
e= 65537
d= 45673813678816865674850575264609274229013439838298838024467777157494920800897
"""

思路

进行了两次加密

第一步:

hint=pow(n,e,c)  //第二步加密

这里的c可以在线工具分解,求出phi_c,从而得到n

第二步:

c=pow(m,e,n)  //第一步加密

由第一步解密我们知道求出的n一定是小于c的

但在第一步的加密中c是小于n的

所以第一步求出的n=n+kc

我们只需要遍历k即可

判断的条件就是n.bit_length==512

m=pow(c,d,n+c)

代码

from Crypto.Util.number import *
from gmpy2 import *

c= 48794779998818255539069127767619606491113391594501378173579539128476862598083
hint= 7680157534215495795423318554486996424970862185001934572714615456147511225105
e= 65537
d= 45673813678816865674850575264609274229013439838298838024467777157494920800897


phic=(6091-1)*(8010963716765433514869336359812774009376685535134030237002058632158407913-1)

print(gmpy2.gcd(e,phic))

dc=gmpy2.invert(e,phic)

n=pow(hint,dc,c)

n=n+c

print(long_to_bytes(int(pow(c,d,n))))

ctfshow{Oh_u_knOw_4uler}

 混合密码体系

题目

# 库
from Crypto.Util.number import bytes_to_long,getPrime
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad

# 对称加密
flag = b'ctfshow{***}'      # 密文,隐藏
key = b'flag{***}'      # 会话密钥,隐藏
iv = b'flag{1fake_flag}'       # AES偏移向量,已知
# 对明文进行填充,使其长度符合AES加密的要求
padded_plaintext = pad(flag, AES.block_size)

# 创建AES加密对象
cipher = AES.new(key, AES.MODE_CBC, iv)

# 加密
ciphertext = cipher.encrypt(padded_plaintext)

# 加密后的文本通常是字节串,转成整数便于进行会话密钥的RSA加密
c1 = bytes_to_long(ciphertext)

print(f'c1 = {c1}')

# 非对称加密
m = bytes_to_long(key)
e = 0x10001
p = getPrime(1024)
q = getPrime(1024)
n = p * q
c = pow(m,e,n)
print(f'p = {p}')
print(f'q = {q}')
print(f'n = {n}')
print(f'c2 = {c}')
# print("hint:key需要转成字节流也就是b''")

'''
c1 = 10274623386006297478525964130173470046355982953419353351509177330015001060887455252482567718546651504491658563014875
p = 126682770761631193509957156425049279522830651950325320826580754739365086374362604934854454428815835196844469535588686149210573266628767888593088817059600076401582225549728184309047483547810100015820325082976781284679340880386138390518973395696206374336712856387090369022746536868747455939074262253452873845903
q = 99825079362327808334563489684167271427241139432727401182808888165552821217781929397837262324242177528386988701584385208395369790542025175917752058047649096340776854252623173162664426065810683048016574420043010318337693586527652970534982946701493024718805916479479658257730226388868060010370893747360166996939
n = 12646117645119414744807511144503229609414192869007113075368323921021672404219693075011763838210400633721060798765473421092201704833591315689681668160927426685183273670665030724394172000165517517884654100267567861284096827407481978978840602383267875832034344793848710383473014512122260278131503985961857107838296047172582364612603344429943715046318283653354068887129071531081918798285138812386418361474496678248683513378861801570673376726388110813411011818940310547686977359605296489433805717348250520973842927175837164120905300831792358190183785344002217291207378744610039145999012939983693891188308725179098958690917
c2 = 5211902378262010726785508340196935051860438587769647187076059600864676774592415052428465708887047312982844957691943180258845015420187239772414768121857728821510440178906193308448250067671679439841031484589864038401572589752057423667532898133171822921282769652197139455317095891357335645435094243006629469245881345449943250189771998449015275390517315432969774421721243965028796050948747282387052634211032729131656214346307483397410725129682422969273915759947596313513270946529649661334582775282060624547405060499311618257517792321792697831000977711752728887999320311631022598717946355057272761740061999974856808147244
'''

思路

先AES,后RSA加密,基础的加密,常规解密即可

 代码

from Crypto.Util.number import *
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import gmpy2


c1 = 10274623386006297478525964130173470046355982953419353351509177330015001060887455252482567718546651504491658563014875
p = 126682770761631193509957156425049279522830651950325320826580754739365086374362604934854454428815835196844469535588686149210573266628767888593088817059600076401582225549728184309047483547810100015820325082976781284679340880386138390518973395696206374336712856387090369022746536868747455939074262253452873845903
q = 99825079362327808334563489684167271427241139432727401182808888165552821217781929397837262324242177528386988701584385208395369790542025175917752058047649096340776854252623173162664426065810683048016574420043010318337693586527652970534982946701493024718805916479479658257730226388868060010370893747360166996939
n = 12646117645119414744807511144503229609414192869007113075368323921021672404219693075011763838210400633721060798765473421092201704833591315689681668160927426685183273670665030724394172000165517517884654100267567861284096827407481978978840602383267875832034344793848710383473014512122260278131503985961857107838296047172582364612603344429943715046318283653354068887129071531081918798285138812386418361474496678248683513378861801570673376726388110813411011818940310547686977359605296489433805717348250520973842927175837164120905300831792358190183785344002217291207378744610039145999012939983693891188308725179098958690917
c2 = 5211902378262010726785508340196935051860438587769647187076059600864676774592415052428465708887047312982844957691943180258845015420187239772414768121857728821510440178906193308448250067671679439841031484589864038401572589752057423667532898133171822921282769652197139455317095891357335645435094243006629469245881345449943250189771998449015275390517315432969774421721243965028796050948747282387052634211032729131656214346307483397410725129682422969273915759947596313513270946529649661334582775282060624547405060499311618257517792321792697831000977711752728887999320311631022598717946355057272761740061999974856808147244
e=0x10001

phi=(p-1)*(q-1)
print(gmpy2.gcd(e,phi))
#确认互素,可以求逆元

#逆元求解
d=gmpy2.invert(e,phi)

#反求密钥key
m=pow(c2,d,n)
key=long_to_bytes(m)

#将长整型转换成AES加密后的字节串
ciphertext=long_to_bytes(c1)

#创建解密对象
iv = b'flag{1fake_flag}'
cipher=AES.new(key,AES.MODE_CBC,iv)

#AES解密,含填充padding部分
padded_plaintext=cipher.decrypt(ciphertext)

#字节类型,需要utf-8解密输出
print(padded_plaintext.decode())

#或者去掉填充,再输出
flag = unpad(padded_plaintext, AES.block_size)
print(flag.decode())

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值