CTF之crpto练习三
DES弱加密之easy_BlockCipher
分析题目,题目中给出了加密时的代码。
des-ofb.py:
from Crypto.Cipher import DES
f = open('key.txt', 'r')
key_hex = f.readline()[:-1] # discard newline
f.close()
KEY = key_hex.decode("hex")
IV = '13245678'
a = DES.new(KEY, DES.MODE_OFB, IV)
f = open('plaintext', 'r')
plaintext = f.read()
f.close()
ciphertext = a.encrypt(plaintext)
f = open('ciphertext', 'w')
f.write(ciphertext)
f.close()
可知加密时采用了DES算法,并且在OFB模式下对明文进行加密。
因此在已知 IV = ‘12345678’ 的情况下,只需要知道Key,即可对密文进行破解。
根据已知信息,仅有IV以及未知的Key,所以想到DES加密种存在弱密钥。在 DES 的计算中,56bit 的密钥最终会被处理为 16 个轮密钥,每一个轮密钥用于 16 轮计算中的一轮,DES 弱密钥会使这 16 个轮密钥完全一致,所以称为弱密钥。
其中四个弱密钥为:
0x0000000000000000
0xFFFFFFFFFFFFFFFF
0xE1E1E1E1F0F0F0F0
0x1E1E1E1E0F0F0F0F
利用四组若密钥尝试对密文进行破解。
from Crypto.Cipher import DES
f = open('ciphertext', 'r')
ciphertext = f.read()
f.close()
IV = '13245678'
KEY=b'\x00\x00\x00\x00\x00\x00\x00\x00'
a = DES.new(KEY, DES.MODE_OFB, IV)
plaintext = a.decrypt(ciphertext)
print plaintext
KEY=b'\x1E\x1E\x1E\x1E\x0F\x0F\x0F\x0F'
a = DES.new(KEY, DES.MODE_OFB, IV)
plaintext = a.decrypt(ciphertext)
print plaintext
KEY="\xE1\xE1\xE1\xE1\xF0\xF0\xF0\xF0"
a = DES.new(KEY, DES.MODE_OFB, IV)
plaintext = a.decrypt(ciphertext)
print plaintext
KEY="\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
a = DES.new(KEY, DES.MODE_OFB, IV)
plaintext = a.decrypt(ciphertext)
print plaintext
从得到的结果中得到明文为莎士比亚的一首诗。
#coding:utf-8
from Crypto.Cipher import DES
import libnum
ct=open('ciphertext','rb').read()
KEY=libnum.n2s(0xe0e0e0e0f1f1f1f1)
IV='13245678'
a=DES.new(KEY,DES.MODE_OFB,IV)
print a.decrypt(ct)
最终得到flag:flag{_poor_single_dog_has_found_an_echo_from_it}RSA算法之special-rsa
题目描述:在学习RSA算法时,我发现了一种和RSA具有同等安全性的算法。 对msg.txt加密得到了msg.enc。 $ python special_rsa.py enc msg.txt msg.enc 你能从flag.enc中恢复flag.txt么?下载附件,里面包含了4个文件,如下:
https://adworld.xctf.org.cn/media/task/attachments/7a407f44a073442c91fd395b20594f01.zip
flag.enc special_rsa.py msg.enc msg.txt
题目的思路是用隐藏的key解密flag.enc文件,阅读special_rsa.py文件加密和解密过程后,我做了简单的公式来找到隐藏的key。
伪代码如下:flag.sage:
N = 23927411014020695772934916764953661641310148480977056645255098192491740356525240675906285700516357578929940114553700976167969964364149615226568689224228028461686617293534115788779955597877965044570493457567420874741357186596425753667455266870402154552439899664446413632716747644854897551940777512522044907132864905644212655387223302410896871080751768224091760934209917984213585513510597619708797688705876805464880105797829380326559399723048092175492203894468752718008631464599810632513162129223356467602508095356584405555329096159917957389834381018137378015593755767450675441331998683799788355179363368220408879117131L c1 = 14548997380897265239778884825381301109965518989661808090688952232381091726761464959572943383024428028270717629953894592890859128818839328499002950828491521254480795364789013196240119403187073307558598496713832435709741997056117831860370227155633169019665564392649528306986826960829410120348913586592199732730933259880469229724149887380005627321752843489564984358708013300524640545437703771424168108213045567568595093421366224818609501318783680497763353618110184078118456368631056649526433730408976988014678391205055298782061128568056163894010397245301425676232126267874656710256838457728944370612289985071385621160886 c2 = 12793942795110038319724531875568693507469327176085954164034728727511164833335101755153514030256152878364664079056565385331901196541015393609751624971554016671160730478932343949538202167508319292084519621768851878526657022981883304260886841513342396524869530063372782511380879783246034751883691295368172069170967975561364277514063320691930900258017293871754252209727301719207692321798229276732198521711602080244950295889575423383308099786298184477668302842952215665734671829249323604032320696267130330613134368640401070775927197554082071807605399448960911234829590548855031180158567578928333030631307816223152118126597 m1 = 8246074182642091125578311828374843698994233243811347691229334829218700728624047916518503687366611595562099039411430662968666847086659721231623198995017758424796091810259884653332576136128144958751327844746991264667007359518181363522934430676655236880489550093852524801304612322373542296281962196795304499711006801211783005857297362930338978872451934860435597545642219213551685973208209873623909629278321181485010964460652298690058747090298312365230671723790850998541956664376820820570709272500330966205578898690396706695024001970727864091436518202414166919020415892764617055978488996164642229582717493375419993187360 m2 = 15575051453858521753108462063723750986386093067763948316612157946190835527332641201837062951012227815568418309166473080588354562426066694924364886916408150576082667797274000661726279871971377438362829402529682825471299861814829463510659258586020732228351258291527965822977048954720558973840956731377322516168809373640494227129998871167089589689796024458501705704779109152762373660542684880052489213039920383757930855300338529058000330103359636123251274293258 r1 = 12900676191620430360427117641859547516838813596331616166760756921115466932766990479475373384324634210232168544745677888398849094363202992662466063289599443 r2 = 7718975159402389617924543100113967512280131630286624078102368166185443466262861344357647019797762407935675150925250503475336639811981984126529557679881059 _, a, b = xgcd(r1, r2) k = pow((c1/m1 % N), a, N) * pow((c2/m2 % N), b, N) print (k)
得到key:
175971776542095822590595405274258668271271366360140578776612582276966567082080372980811310146217399585938214712928761559525614866113821551467842221588432676885027725038849513527080849158072296957428701767142294778752742980766436072183367444762212399986777124093501619273513421803177347181063254421492621011961
得到key,解密flag.enc,得到答案:
port msgpack
def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
def modinv(a, m):
g, x, y = egcd(a, m)
assert g == 1
return x % m
def pad_even(x):
return ('', '0')[len(x)%2] + x
def decrypt(c, k):
out = ''
for r_s, c_s in msgpack.unpackb(c):
r = int(r_s.encode('hex'), 16)
c = int(c_s.encode('hex'), 16)
k_inv = modinv(k, N)
out += pad_even(format(pow(k_inv, r, N) * c % N, 'x')).decode('hex')
return out
N = 23927411014020695772934916764953661641310148480977056645255098192491740356525240675906285700516357578929940114553700976167969964364149615226568689224228028461686617293534115788779955597877965044570493457567420874741357186596425753667455266870402154552439899664446413632716747644854897551940777512522044907132864905644212655387223302410896871080751768224091760934209917984213585513510597619708797688705876805464880105797829380326559399723048092175492203894468752718008631464599810632513162129223356467602508095356584405555329096159917957389834381018137378015593755767450675441331998683799788355179363368220408879117131
k = 175971776542095822590595405274258668271271366360140578776612582276966567082080372980811310146217399585938214712928761559525614866113821551467842221588432676885027725038849513527080849158072296957428701767142294778752742980766436072183367444762212399986777124093501619273513421803177347181063254421492621011961
print decrypt(open("flag.enc").read(), k)最终得到flag:Flag: BCTF{q0000000000b3333333333-ju57-w0n-pwn20wn!!!!!!!!!!!!}题目描述:It seems easy, right?Tip: openssl rsautl -encrypt -in FLAG -inkey public.pem -pubin -out flag.enc
题目给了一个flag.enc,还有一个public.pem,附件下载地址:
https://adworld.xctf.org.cn/media/task/attachments/9244cc370caa43f491636f8c4670fe7d.zip
安装openssl可以读取到n和e,因为n不大,可以在yafu或者factordb.com上分解得到n = p * q * r
根据flag.enc,可以得到密文m
根据中国剩余定理,我们要求得m在p,q,r下的余数,不妨设为pmod,qmod,rmod
然后根据模三次剩余,即:proot ^ 3 ≡ pmod ( mod p),求得:proot,同理求得qroot,rroot
利用网页工具可以直接计算得到:
我们从openssl命令行得到一个似乎是通过RSA加密的密文。我们还可以访问公钥,因此我们像使用标准RSA密码一样,通过恢复参数来执行以下操作:
e = 3
n = 23292710978670380403641273270002884747060006568046290011918413375473934024039715180540887338067
使用YAFU,我们将模量分为:
p = 26440615366395242196516853423447
q = 27038194053540661979045656526063
r = 32581479300404876772405716877547
我们得到三个质数。这仍然是好的,这可能只是多质RSA。这一点也不奇怪,总的来说很简单(p-1)(q-1)(r-1),其余的计算照常进行。但它不存在,因为我们发现模乘逆不存在。原因很明显:gcd(e,to客户端)=3,应该是1。这不是我们第一次遇到类似的情况(如https://github.com/p4-team/ctf/tree/master/2015-10-18-hitcon/crypto 314-u rsabin-35;eng版本),所以我们对如何处理这个问题有了一些想法。
在应用RSA解码之前,我们需要去掉这3个。这意味着加密是:
ciphertext = plaintext^e mod n = (plaintext^e')^3 mod n
所以如果我们能形成方程两边的模三次根(mod n),我们就可以用e'=e/3进行RSA译码。因为e=3,所以e'=e/3=1,所以这里并不容易,这意味着我们的加密是简单的:
ciphertext = plaintext^3 mod n
所以整个解密过程需要密文中的模立方根(mod n)。
一些关于模根的阅读使我们得出结论,这是可能的,但只有在有限的领域。所以它不能对n做,这是一个复合数,我们知道它是,因为它是pqr。
这个问题让我们想起了中文提醒定理( https://en.wikipedia.org/wiki/Chinese_remainder_theorem ),我们考虑了一会儿,我们想到了一个想法,如果我们能从密文(mod prime)中计算出3个素数的三次模根,我们就能计算出合并根。我们可以用高斯算法(http://www.di-mgt.com.au/crt.html#gaussalg)来实现这一点。
所以我们继续计算:
pt^3 mod p = ciperhtext mod p = 20827907988103030784078915883129
pt^3 mod q = ciperhtext mod q = 19342563376936634263836075415482
pt^3 mod r = ciperhtext mod r = 10525283947807760227880406671000
然后我们花了一段时间来解决pt的这个方程,最后我们发现wolframalpha实现了这个功能,例如:
http://www.wolframalpha.com/input/?i=x^3+%3D+20827907988103030784078915883129+%28mod+26440615366395242196516853423447%29
这给了我们一套可能的解决方案:
roots0 = [5686385026105901867473638678946, 7379361747422713811654086477766, 13374868592866626517389128266735]
roots1 = [19616973567618515464515107624812]
roots2 = [6149264605288583791069539134541, 13028011585706956936052628027629, 13404203109409336045283549715377]
我们对这些根应用高斯算法:
# -*- coding:utf-8 -*-
# 0CTF 2016: RSA? (Crypto 2pt)
'''
# openssl rsa -in public.pem -pubin -text -modulus
Public-Key: (314 bit)
Modulus:
02:ca:a9:c0:9d:c1:06:1e:50:7e:5b:7f:39:dd:e3:
45:5f:cf:e1:27:a2:c6:9b:62:1c:83:fd:9d:3d:3e:
aa:3a:ac:42:14:7c:d7:18:8c:53
Exponent: 3 (0x3)
Modulus=2CAA9C09DC1061E507E5B7F39DDE3455FCFE127A2C69B621C83FD9D3D3EAA3AAC42147CD7188C53
writing RSA key
-----BEGIN PUBLIC KEY-----
MEEwDQYJKoZIhvcNAQEBBQADMAAwLQIoAsqpwJ3BBh5Qflt/Od3jRV/P4Seixpti
HIP9nT0+qjqsQhR81xiMUwIBAw==
-----END PUBLIC KEY-----
'''
# Chinese Remainder Theorem
def chinese_remainder(n, a):
sum = 0
prod = reduce(lambda a, b: a*b, n)
for n_i, a_i in zip(n, a):
p = prod / n_i
sum += a_i * mul_inv(p, n_i) * p
return sum % prod
def mul_inv(a, b):
b0 = b
x0, x1 = 0, 1
if b == 1: return 1
while a > 1:
q = a / b
a, b = b, a%b
x0, x1 = x1 - q * x0, x0
if x1 < 0: x1 += b0
return x1
e = 3
n = 0x2CAA9C09DC1061E507E5B7F39DDE3455FCFE127A2C69B621C83FD9D3D3EAA3AAC42147CD7188C53
# Factorize n using factordb.com
p = 26440615366395242196516853423447
q = 27038194053540661979045656526063
r = 32581479300404876772405716877547
assert p * q * r == n
ct = int(open("flag.enc", "rb").read().encode("hex"), 16)
# ct = 2485360255306619684345131431867350432205477625621366642887752720125176463993839766742234027524
# pt^3 mod p = ct mod p = 20827907988103030784078915883129
# pt^3 mod q = ct mod q = 19342563376936634263836075415482
# pt^3 mod r = ct mod r = 10525283947807760227880406671000
# Calculate possible cube-root
# using wolflam alpha (or using modified Tonelli-Shanks algorithm)
# like this: "x^3 = 20827907988103030784078915883129 (mod 26440615366395242196516853423447)"
p_root = [5686385026105901867473638678946, 7379361747422713811654086477766, 13374868592866626517389128266735]
q_root = [19616973567618515464515107624812]
r_root = [6149264605288583791069539134541, 13028011585706956936052628027629, 13404203109409336045283549715377]
# For every compination of roots, mix them using Chinese Remainder Theorem
for x in p_root:
for y in q_root:
for z in r_root:
m = chinese_remainder([p, q, r], [x, y, z])
pt = hex(m)[2:-1]
if len(pt) % 2 != 0:
pt = "0"+pt
pt = pt.decode("hex")
if pt.find("0ctf{") >= 0:
# Get the flag
print pt.strip()
break最终flag:0ctf{HahA!Thi5_1s_n0T_rSa~}RSA解密之babyRSA1
1.下载附件,发现有3个文件:
https://adworld.xctf.org.cn/media/task/attachments/5a456b6a66c04c02bf754d540e5b531d.zip
在挑战中,我们获得代码,公钥和结果。
加密相当简单:
R.<a> = GF(2^2049)
def encrypt(m):
global n
assert len(m) <= 256
m_int = Integer(m.encode('hex'), 16)
m_poly = P(R.fetch_int(m_int))
c_poly = pow(m_poly, e, n)
c_int = R(c_poly).integer_representation()
c = format(c_int, '0256x').decode('hex')
return c
看来n这是GF(2)上的PolynomialRing的多项式。加密基本上将消息更改为GF(2 ^ 2049)的元素,然后将其表示为环P的元素,然后将该消息的多项式表示形式提高为emod多项式的幂n。
所以,它真的可以归结为经典的RSA,与小搓那m和n现在是多项式,一切都在PolynomialRing在GF(2)calcualted。
我们发现了一篇很好的论文,描述了这个想法:www.diva-portal.se/smash/get/diva2:823505/FULLTEXT01.pdf(Izabela Beatrice Gafitoiu的理学学士学位论文)。
如果遵循此论点,我们会发现在这种情况下,d解密指数可以计算为emod的模乘逆s。特殊值s是等效的phi,从经典RSA,并且基本上是(2^p_d-1)(2^q_d-1)其中p_d和q_d正度多项式的p和q,使得p*q == n。
所以这个想法很简单:
1、因子多项式n成p和q 2、计算 s 3、计算 d 4、解密标志
def decrypt(m, d):
m_int = Integer(m.encode('hex'), 16)
m_poly = P(R.fetch_int(m_int))
c_poly = pow(m_poly, d, n)
c_int = R(c_poly).integer_representation()
c = format(c_int, '0256x').decode('hex')
return c
if __name__ == '__main__':
p,q = n.factor()
p,q = p[0],q[0]
s = (2^p.degree()-1)*(2^q.degree()-1)
d = inverse_mod(e,s)
with open('flag.enc', 'rb') as f:
ctext = f.read()
print(decrypt(ctext,d))
最终得到flag:flag{P1ea5e_k33p_N_as_A_inTegeR~~~~~~}
AES解密之in-plain-sight
题目描述:这次的挑战并不难:你只需要对隐藏的密文进行解密。为了让解密更加简单,我会给你除了HiddenCiphertext以外你需要的所有东西,你要做的就是自己将密文找出来! 你需要: 算法:AES-256-CBC 密钥:c086e08ad8ee0ebe7c2320099cfec9eea9a346a108570a4f6494cfe7c2a30ee1 IV:0a0e176722a95a623f47fa17f02cc16a
通过网站,https://morsecode.world/international/decoder/audio-decoder-adaptive.html(音频解密器)得到C1和C2的值
C1:4314251881242803343641258350847424240197348270934376293792054938860756265727535163218661012756264314717591117355736219880127534927494986120542485721347351
C2:485162209351525800948941613977942416744737316759516157292410960531475083863663017229882430859161458909478412418639172249660818299099618143918080867132349
利用openssl对两个公钥进行解密,得到n1n2和e1e2:
import gmpy2
import libnum
n1 = gmpy2.mpz(10285341668836655607404515118077620322010982612318568968318582049362470680277495816958090140659605052252686941748392508264340665515203620965012407552377979)
n2 = gmpy2.mpz(8559553750267902714590519131072264773684562647813990967245740601834411107597211544789303614222336972768348959206728010238189976768204432286391096419456339)
e1 = 41221
e2 = 41221
p = gmpy2.gcd(n1,n2)
q1 = n1 / p
q2 = n2 / p
c1 = 4314251881242803343641258350847424240197348270934376293792054938860756265727535163218661012756264314717591117355736219880127534927494986120542485721347351
c2 = 485162209351525800948941613977942416744737316759516157292410960531475083863663017229882430859161458909478412418639172249660818299099618143918080867132349
phin1 = (p - 1)*(q1 - 1)
phin2 = (p - 1)*(q2 - 1)
d1 = gmpy2.invert(e1,phin1)
d2 = gmpy2.invert(e2,phin2)
print(libnum.n2s(pow(c1,d1,n1))+libnum.n2s(pow(c2,d2,n2)))最终得到flag:UNCTF{ac01dff95336aa470e3b55d3fe43e9f6}题目描述:安全分析人员截获间谍发出的秘密邮件,该邮件只有一个mp3文件,安全人员怀疑间谍通过某种private的方式将信息传递出去,尝试分析该文件,获取藏在文件中的数据。 flag形式为 flag{}
题目附件连接:https://adworld.xctf.org.cn/media/task/attachments/206c0533300340b19c3a18d82d806a98.mp3
解题步骤:题目提示文件使用了private加密信息,在010Editor中打开mp3文件,发现存在private bit,因此,只需要提取每一个mf组中的该字节,组合起来,就是答案。可以从图中看到 ms 开始位为1 C1B8H,即第115128字节,如图所示:,如图所示:
uint32 frame_sync : 12 uint32 mpeg_id : 1 uint32 layer_id : 2 uint32 protection_bit : 1 uint32 bitrate_index : 4 uint32 frequency_index : 2 uint32 padding_bit : 1 uint32 private_bit : 1 uint32 channel_mode : 2 uint32 mode_extension : 2 uint32 copyright : 1 uint32 original : 1 uint32 emphasis : 212+1+2+1+4+2+1+1+2+2+1+1+2=32,即总共4字节,private_bit 为24,所在的字节为第3个字节因此要从前一个,即第二个字节开始提取内容,该字节对应的地址为 115130观察每一个mf组,大小都为414h,即1044字节,因此可以得到以下脚本:
# coding:utf-8 import re import binascii n = 115130 result = '' fina = '' file = open('flag-woody.mp3','rb') while n < 2222222 : file.seek(n,0) n += 1044 file_read_result = file.read(1) read_content = bin(ord(file_read_result))[-1] result = result + read_content textArr = re.findall('.{'+str(8)+'}', result) textArr.append(result[(len(textArr)*8):]) for i in textArr: fina = fina + hex(int(i,2))[2:].strip('\n') fina = fina#.decode('hex') print (fina)将得到的字符串
464c41477b707231763474335f6269377d25a1cedc3e69888894dac4dd3a87c5e1c5276fa6d626832148d39288a0c596c95abaac3f09f9f524647595ae4894f9b82b3f4c1b47537c365d8d69d84a353c1a93ae436761d430e666e4111752d479746d1828f9c07c27ab1c3eaf1948f8a9e839b280a4342f321e89eb73b237a2b55d5310b77811c0975cfc1365e146f6c9212e244751398f73c17ee1a6664b4fd712d4b0a297275fa471fb65e440bc7bdc12fb0a39d81a1d374f2d55b8faabf9bf2c342f1046fbab7e66ac7896ffac672d277b89f8606759a8ac21a58fbb4b9b51d45f126a7f67c1a297e1fcb638356ec739b89555568816
转换对应的ASCII码,得到Flag:最终 flag:flag{pr1v4t3_bi7}