第一届OpenHarmonyCTF
第一届OpenHarmony CTF专题赛 Crypto题解
赛题不是很难, 但是套了层鸿蒙,还挺有意思的。
Weak_random
seed的范围很小,可以直接爆,iv不影响CBC第一块密文之后的解密结果,所以不用管iv
1 | from Crypto.Util.number import * |
Ea5y_RSA
两个关键文件是,entry/src/main/ets/util
路径下的RsaUtil.ets和entry/src/main/ets/page
下的Index.ets
RsaUtil.ets
1 | import { cryptoFramework } from '@kit.CryptoArchitectureKit'; |
Index.ets
1 | check(){ |
从RsaUtil.ets中的rsaEncryptBySegment
函数可以知道,hint是RSA私钥文件的第7-284字节,恢复一下
1 | hint = [48,13,6,9,42,134,72,134,247,13,1,1,1,5,0,4,130,2,97,48,130,2,93,2,1,0,2,129,129,0,219,91,76,137,49,174,41,189,193,240,64,187,23,143,171,74,107,120,166,142,186,244,90,56,6,54,147,63,158,119,222,110,46,245,223,167,190,173,76,7,36,210,188,249,83,151,200,24,88,11,247,108,112,208,109,173,32,143,133,158,62,83,232,150,60,120,232,201,90,239,207,77,200,36,2,107,62,204,214,35,28,190,48,150,242,52,247,4,11,255,164,13,122,170,42,223,66,36,114,134,183,30,99,21,31,224,194,169,223,86,12,216,139,0,255,220,115,223,83,90,71,25,221,180,160,8,212,41,2,3,1,0,1,2,129,128,82,97,158,131,227,241,153,225,151,69,136,185,251,38,76,217,93,53,105,176,47,12,120,25,148,83,200,199,90,215,127,228,247,164,5,196,52,251,86,147,84,68,5,14,202,83,53,165,214,227,95,160,13,90,105,230,92,85,42,132,124,185,252,158,69,85,122,160,246,99,167,168,183,89,173,57,73,126,186,253,22,111,92,152,14,5,95,175,46,189,186,93,207,30,207,8,231,173,143,91,128,18,58,6,25,209,64,207,123,224,255,177] |
得到
1 | 300d06092a864886f70d0101010500048202613082025d02010002818100db5b4c8931ae29bdc1f040bb178fab4a6b78a68ebaf45a380636933f9e77de6e2ef5dfa7bead4c0724d2bcf95397c818580bf76c70d06dad208f859e3e53e8963c78e8c95aefcf4dc824026b3eccd6231cbe3096f234f7040bffa40d7aaa2adf42247286b71e63151fe0c2a9df560cd88b00ffdc73df535a4719ddb4a008d429020301000102818052619e83e3f199e1974588b9fb264cd95d3569b02f0c78199453c8c75ad77fe4f7a405c434fb56935444050eca5335a5d6e35fa00d5a69e65c552a847cb9fc9e45557aa0f663a7a8b759ad39497ebafd166f5c980e055faf2ebdba5dcf1ecf08e7ad8f5b80123a0619d140cf7be0ffb1 |
按pem文件格式稍微区分一下
1 | 300d06092a864886f70d0101010500048202613082025d |
从中提取出n
,e
,以及d
的高位(895bit),那大概率是低位128未知。
我的思路是用
$$
k’ = \frac{e\times d_h}{n} + 1
$$
来近似正确的k
,实际上这就是正确的k
然后令
$$
S = N + 1 - \frac{(e\times d_h)}{k}
$$
$$
D = \sqrt{S^2 - 4n}
$$
然后计算
$$
p_h = \frac{S + D}{2}
$$
得到的$p_h$和正确的$p$差了低128bit左右,一元copper得解
思路来源:Small Public Exponent Brings More: Improved Partial Key Exposure Attacks against RSA
1 | from Crypto.Util.number import * |
Small Message For (SM4) Encryption
猜测secret_message
很短,直接爆破
1 | from gmssl import sm4 |
得到
1 | key = b'sMsMsMsMsMsMsMsM' |
Simple LLL
定位到关键函数runMixer
1 | public Object #~@0>#runMixer(Object functionObject, Object newTarget, Index this) { |
先把flag按3字节拆分,然后生成3个素数,加密逻辑是encrypted_i = k_i * getPrime + (getPrime2 ^ flag_i,getPrime3) * ord(s_i) % P
,s是上面那串很长的字符串
把后面模P部分看作y_i
,就是ACD。拿正交格打出后面DLP部分,然后解DLP
1 | from Crypto.Util.number import * |
得到
1 | f8abee3f93898fdbe1168d414e4f0e3614bfdd629b0f1f8abee3f93898fdbe1168d414e4f0e3614bfdd629b0f1f8abee3f93898fdbe1168d414e4f0e3614bfdd629b0f1f8abee3f93898fd |
有重复部分
flag{f8abee3f93898fdbe1168d414e4f0e3614bfdd629b0f1}