1.warmup
阅读源码,我们发现整个加密流程如下—对明文长度使用pad()填充至长度为16的倍数,然后将msg分成长度为16 的n段,将n段明文做异或得到一段长度为16的明文,然后使用aes_cbc模式加密得到密文。在题目中已经给出了明文'see you at three o\'clock tomorrow'和它的密文,题目要求我们输入“please send me your flag”使用pad()填充后的明文和密文。在该算法中存在一个极大的漏洞就是unpad()函数。通常的unpad会检查填充的长度不能超过一组密文的长度0x10和填充的内容是否为填充长度。而题目中的函数unpad()直接删除长度为尾部字节大小的长度。所以我们尝试在“please send me your flag”之后填充字符使得其分段异或的结果和'see you at three o\'clock tomorrow'填充异或的结果相同,这时两个明文有着相同的密文。我们将修改后的明文和密文输入,即可得到结果,具体代码如下
from Crypto.Util.strxor import strxor
msg="please send me your flag"+"\x00"*7+"\x64"+"3b1c5a0d0f0658502b612436656a3818".decode("hex")
res1="24054d4c1a0f19444e0f4016080f1805".decode("hex")
res = chr(0)*16
res = strxor(msg[0:16], res)
res = strxor(msg[16:32], res)
res = strxor(msg[32:48], res)
assert res==res1
print msg.encode("hex")
根据上面的代码能得到我们需要输入的明文,然后将题目给我们的密文作为输入明文的密文,最后我们就可以获得flag
2.babygame
阅读源码,我们发现这里面隐藏着3关,第一关要求对明文使用RSA加密,再解密后和原明文不相同,我们知道再RSA中明文要小于n。当明文大于n的时候,解出的值为明文模n的值,与原明文不同。而题中的,所以我们选取填入即可
第二关是对一个message进行加密,加密流程为,且给出了三组,并且将a,b.n和密文c给出,所以这里应该是使用RSA的低幂指数广播攻击。但这里不能直接使用中国剩余定理求解广播攻击里的一系列方程,由于在明文处使用了一次方程,导致方程明文处每次都不相同。所以我们需要构造求解方程式。我们首先求解,,。使用中国剩余定理求解T1,然后代入方程组,那么该方程组可以除。体同理我们可以找到另外两个方程,代入求解即可
cArray=[0x3ec0dac47c45bcb89edda91a302ee32b7202a93fac6056176cd6bd8f7a94b5f2c43fa10c5e4dae5e2bef32f13141889ea7ac09bae39966821e1c3b516eb7ddc41de8d9db2fed5f012614a1ee4fc8515fb18cfed81834be3f869dfb6d38279a1f670ccfa56ef1f1377651e11c2e9dd917701f1eac41653138e1777006d41b3f6b,
0x2a50058d6bac5ecc1d20e60e6dd3b74b372e761b49be0826f2c803fe7dff502b64202905fad1f336650313825b1e3d5e5bfb739f135e3bc69052394a20d1cfe6498d9e78730b3cab49b78e64b6388d0e7cb3a4ad9458ec4cc6415bc509af080d20dc6f95056f7619c525bc482389afea0e8c5693b6e46f06e28dac8867ee987a,
0x20ac4dd17cfd459112dbd86d024a4a44d841bf7eaec3167cc0a430bf6854c6552dde5aad514fdff23fa9ee9f416000450b772406e9ba545076787ce6e9dedf38d70601dcdc3a7cc46fa60c1877ec680081dd324de5235d40526c55d0f975f65e4e6734871e0338503b7256f7e9ad16cbe4d1329675d7fd7c97778a5c32ca1127]
nArray=[0x8de0792c98a93c950ea12c65d62fdbbfd46d6aab145bc39ecebb371acd6774ee9fba24db94437485b5938249bdedf32d2aa2e8799b6aa6db63bbb2ddd5b458f1f437769a7710eee95069b3650e96253e4b0c5e2a22389673f74b0b01bd0956669a519aec556383f9b8d76f04b2a00a491625649bc6af4a1fa4e10aefc8c33cb5,
0x948279bc2d86bee933357246711e64b5dff9f924e97559d0527aaa265e441a5ca259538161d5fe3efcbdc85b72b46b96d50afa3bf5d4bab7b850bcfa604fa74ef525b710e11d7f2c26b6df595cb9ea2b9a81fc81f0a721fbd9b0fef341bd471457c64efad02df1a2e93ada374627f55c33a178890904adb982e3d5df4fe78433,
0xa98e47d25554632b5c2a2b6d292f2caf088050eb1ffbc556c062bebdb10f65fcbb942b9f0fdafa724ca90ea85ab17c1c2cd15eb4a59bf672909fbf0ef0fb88ac2569e571741162805c495b60dd8ea0eee9e5afb2ddcd5435d5fcfbd1c49f496eaef37ecde17b6a64a69cb869425d77d13f487632504b851f309ff36c826570cb]
aArray=[0x8f2b591edb38649f6637abc8cd63f2e9f50e024d7230151b1f888190a821d10213587f34633dd2a7b40f4d37c338c420acdc2df19f88e958a250cd691922c781,
0xae3e922d88e35e986e5dd4e8dedab00a1ab7f9f5f3fd658eade9371d1247ef7ada800ca381ff3f9c69a30dbf3c61c9f9539863fdb2d2c8af23d4cb87a9e5857f,
0xe4550619a6029ac6158f188a969741cdd2cc37d1ff2c9dd1f24a7f6b12357196a15852912cb61e64e4ccb2ff6dae5a5f654fbe20623f04c6d8428d72ad5e02ef]
bArray=[0xc955b34abfce3a409449bebc24163397795a163d337b7fb1320900aaffc21576d785b115f7d3dca7ada072f1c6608dfeb49c6c6264e5f691cf9bb96548222581,
0xcb50868d5d12d5f166b2e57ef4789f8ebaacc1137a055118d1650e4557bcf05f3858a9124783c8be9be947667b45cdf1a4e2604e544210e8acc665e1c1c0d2ef,
0x97a4d4c4b3e5ed99a5539ac17cde2a32890a0601be7f7bb6026cfe4a9ffe93633be15c4345268fec2bc69030353db729ccacfeaa3aa0952df418220db0266b4f]
"""
Performs Hastads attack on raw RSA with no padding.
cArray = Ciphertext Array
nArray = Modulus Array
e = public exponent
"""
def hastads(cArray,nArray,e=3):
if(len(cArray)==len(nArray)==e):
for i in range(e):
cArray[i] = Integer(cArray[i])
nArray[i] = Integer(nArray[i])
M = crt(cArray,nArray)
return(Integer(M).nth_root(e,truncate_mode=1))
else:
print("CiphertextArray, ModulusArray, need to be of the same length, and the same size as the public exponent")
"""
Performs Hastads attack on raw RSA with no padding.
This is for RSA encryptions of the form: cArray[i] = pow(aArray[i]*msg + bArray[i],e,nArray[i])
Where they are all encryptions of the same message.
cArray = Ciphertext Array
nArray = Modulus Array
aArray = Array of 'slopes' for the linear padding
bArray = Array of 'y-intercepts' for the linear padding
e = public exponent
"""
def linearPaddingHastads(cArray,nArray,aArray,bArray,e=3,eps=1/8):
if(len(cArray) == len(nArray) == len(aArray) == len(bArray) == e):
for i in range(e):
cArray[i] = Integer(cArray[i])
nArray[i] = Integer(nArray[i])
aArray[i] = Integer(aArray[i])
bArray[i] = Integer(bArray[i])
TArray = [-1]*e
for i in range(e):
arrayToCRT = [0]*e
arrayToCRT[i] = 1
print arrayToCRT
TArray[i] = crt(arrayToCRT,nArray)
print TArray
P. = PolynomialRing(Zmod(prod(nArray)))
gArray = [-1]*e
for i in range(e):
gArray[i] = TArray[i]*(pow(aArray[i]*x + bArray[i],e) - cArray[i])
print gArray
g = sum(gArray)
g = g.monic()
# Use Sage's inbuilt coppersmith method
roots = g.small_roots(epsilon=eps)
if(len(roots)== 0):
print("No Solutions found")
return -1
return roots[0]
else:
print("CiphertextArray, ModulusArray, and the linear padding arrays need to be of the same length," + "and the same size as the public exponent")
print(hastads(cArray,nArray))
print(linearPaddingHastads(cArray,nArray,aArray,bArray))
这样我们就拿到了message。
第三关是使用AES_OFB模式进行加密。我们已经有了一对明密文,而ofb加密模式就是使用iv用key加密后的流密码与明文异或。我们可以根据已有的明密文求解出流密码,然后将题目所要求的明文进行加密,将密文放入即可过第三关
from Crypto.Util.strxor import strxor
miwen="deddcc81681767b13c39c78f33d665f55f8f19830f3ecedecdda7df68698e82d3d05122a53bc994499b8b6b40795448d".decode("hex")
s="I will send you the ticket tomorrow afternoon"+"\x03"*3
s1="I will send you the ticket tomorrow morning"+"\x05"*5
miwen1=strxor(miwen,s)
miwen1=strxor(miwen1,s1)
print miwen1.encode("hex")