-
-
[比赛]看雪.WiFi万能钥匙 CTF 2017第十三题 点评及解题思路
-
发表于: 2017-6-27 18:16 2680
-
看雪CTF 2017 比赛进行至第十三题
截止至今天中午12点,第十三题破解人数为 2 人!
防守方 hsadkhk 依然位居首位~
此题过后,风间仁依然处于第一位~,kkHAIKE升至第二位。
比赛进入尾声,仅剩 2 题。
对于比赛前几名的争夺战,将在前十名之间展开。
期待ing......
接下来我们来回顾一下第十三题
看看 看雪评委和出题者是怎么说的ヾ(๑╹◡╹)ノ"。
看雪评委 netwind 点评
此题考查攻方选手对算法的分析能力。该题算法模型是:考虑一条有限域椭圆曲线上的已知点 G1, G2, 以及给定的系数 h1,h2,h3,求点S(x,y) 满足方程:h1( S + h3*G1) = h2(S + h3*G2) mod n,判断正确的key等价于判断方程两边运算的点的x坐标: 两个大数相等。如果对算法模型不熟悉,做起来可能会有一定难度。
作者简介
看雪 CTF 2017 第十二题设计思路
根据规则,crackme 内部name固定。 SN唯一。
本题sn为:
7A7102F36F3B344D666132A6FF7EF4BA05B99640BB815C9E712A72C64B6ABC582C2
正确提示:
"Oh Yes! You got it.",
设计思路:
(1)考虑一条有限域椭圆曲线上的已知点 G1, G2, 以及给定的系数 h1,h2,h3,求点S(x,y) 满足方程, 以下大写字母表示有限域椭圆曲线上的点, 小写字母表示数值:
h1( S + h3*G1) = h2(S + h3*G2) mod n
那么, 判断正确的key, 等价于判断方程两边运算的点的x坐标: 两个大数相等。
因此, 比较key,不会出现明文比较。这里S是可以计算的,并没有用到ECDLP(椭圆曲线离散对数)。
那么,如何求出S(x,y):
=> (h1 - h2) S = h2*h3*G2 - h1*h3*G1
S(x,y) = (h2*h3/(h1 - h2)) * G2- (h1*h3/(h1 - h2)) * G1 mod n
sn = S(x,y) , x,y is the point on the cuver ECC2K-130
椭圆曲线选取公开的ECC2K-130:
(参数取自如下pdf文档)
http://www.ecc-challenge.info/anon.pdf
========
ECC2K-130 GF(2^m)
========
E: y^2 + xy = x^3 + a*x^2 + b
m = 131
f = x^131 + x^13 + x^2 + x + 1
a = 0
b = 1
E 即: y^2 + xy = x^3 + 1 , over GF(2^131)
point P (G1):
X= 51C99BFA6F18DE467C80C23B98C7994AA
Y= 42EA2D112ECEC71FCF7E000D7EFC978BD
Point Q (G2):
X= 6C997F3E7F2C66A4A5D2FDA13756A37B1
Y= 4A38D11829D32D347BD0C0F584D546E9A
np (number of points) = 80000000000000001353F755C0E8FC9A4
n (prime order) = 200000000000000004D4FDD5703A3F269
(2) 补充细节的考虑 之一 关于hash。
为了使得h1, h2, h3 线性无关,并且与name, 和相关字符 关联起来, 这里取md5 hash作为系数。
h1 = hash1(0x1 name - pediy);
h2 = hash2(0x2 0x2 name - 2017);
h3 = hash3(0x3 0x3 0x3 name - crackme);
hash 采用md5
例如: name = readyu
readyu-pediy
hexstring= 017265616479752D7065646979
hash1=
51c75f1f444baa97ed18dd6c340835d7
readyu-2017
hexstring= 02027265616479752D32303137
hash2=
0e5cf7f068d6efa16f42f935ec424a75
readyu-crackme
hexstring= 0303037265616479752D637261636B6D65
hash3=
a4cd1d64486abde1be441944460cd41d
(3)
补充细节的考虑 之二 关于sn 编码。
采用一个素数P269, 把S(x,y) 用d加密编码。 结果就是sn。用到了费马小定理。
sn = S^d mod P
P269(prime)= 10000000000000000000000000000000000000000000000000000000000000000079
e=0x5
d= CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCD2D
这里有:
m^(P-1) = 1 (mod P) (m为自然数, P为素数, 1 <= m < P) 费马小定理
e*d = 1 ( mod (P-1) ) , 素数P的欧拉函数是P-1
=〉
(m^d)^e = m ( mod P)
(4) 答案:
计算hash:
readyu-pediy
017265616479752D7065646979
hash1 = 51c75f1f444baa97ed18dd6c340835d7
readyu-2017
02027265616479752D32303137
hash2 = 0e5cf7f068d6efa16f42f935ec424a75
readyu-crackme
0303037265616479752D637261636B6D65
hash3 = a4cd1d64486abde1be441944460cd41d
计算S(x,y):
h1=51C75F1F444BAA97ED18DD6C340835D7
h2=0E5CF7F068D6EFA16F42F935EC424A75
h3=A4CD1D64486ABDE1BE441944460CD41D
G1(x,y)=(51C99BFA6F18DE467C80C23B98C7994AA , 42EA2D112ECEC71FCF7E000D7EFC978BD)
G2(x,y)=(6C997F3E7F2C66A4A5D2FDA13756A37B1 , 4A38D11829D32D347BD0C0F584D546E9A)
S(x,y) = (h2*h3/(h1 - h2)) * G2 - (h1*h3/(h1 - h2)) * G1 mod Order
Order = 200000000000000004D4FDD5703A3F269
h1 - h2 = 436A672EDB74BAF67DD5E43
下面选取攻击者 风间仁 的破解分析
1. 处理逻辑
name是内置的: readyu
code是输入的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | int __cdecl sub_40AEF0( HWND hDlg) { ... GetDlgItemTextA(hDlg, 1000, name, 64); v1 = GetDlgItemTextA(hDlg, 1001, code, 256); v2 = v1; if ( v1 >= 0x21 ) { if ( code[0] != 0x30 ) { v3 = 0; if ( v1 <= 0 ) { LABEL_9: memset (byte_41BC84, 0, sizeof (byte_41BC84)); v5 = off_418078[check(code, name)]; MessageBoxA(hDlg, v5, v5, 0); return 0; } while ( 1 ) { v4 = code[v3]; if ( ! isxdigit (v4) || islower (v4) ) break ; if ( ++v3 >= v2 ) goto LABEL_9; } } ... } |
z = 10000000000000000000000000000000000000000000000000000000000000000079
r = code ^ 5 mod z
r有34字节, 前17字节作为x, 后17字节作为y
epInput = (x,y)
根据name计算3个md5值:
md0=md5("\x01readyu-pediy")=51C75F1F444BAA97ED18DD6C340835D7
md1=md5("\x02\x02readyu-2017")=0E5CF7F068D6EFA16F42F935EC424A75
md2=md5("\x03\x03\x03readyu-crackme")=A4CD1D64486ABDE1BE441944460CD41D
椭圆曲线: m=131, a=13, b=2, c=1, a2=0, a6=1
前面的epInput是这个曲线上的点
ep1 = ( 51C99BFA6F18DE467C80C23B98C7994AA, 42EA2D112ECEC71FCF7E000D7EFC978BD )
ep2 = ( 6C997F3E7F2C66A4A5D2FDA13756A37B1, 4A38D11829D32D347BD0C0F584D546E9A )
n = 200000000000000004D4FDD5703A3F269
校验 (md2 * ep1 + epInput) * md0 mod n == (md2 *ep2 + epInput) * md1 mod n
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | signed int __cdecl check( char *code, const char *a2) { ... get_mip(); v29[0] = 0; memset (&v29[1], 0, 0x20u); *(_WORD *)&v29[33] = 0; v29[35] = 0; ptr[0] = 0x10; ptr[1] = 0; ptr[2] = 0; ptr[3] = 0; ptr[4] = 0; ptr[5] = 0; ptr[6] = 0; ptr[7] = 0; ptr[8] = 0; ptr[9] = 0; ptr[10] = 0; ptr[11] = 0; ptr[12] = 0; ptr[13] = 0; ptr[14] = 0; ptr[15] = 0; ptr[16] = 0; ptr[17] = 0; ptr[18] = 0; ptr[19] = 0; ptr[20] = 0; ptr[21] = 0; ptr[22] = 0; ptr[23] = 0; ptr[24] = 0; ptr[25] = 0; ptr[26] = 0; ptr[27] = 0; ptr[28] = 0; ptr[29] = 0; ptr[30] = 0; ptr[31] = 0; ptr[32] = 0; ptr[33] = 0x79; mirsys_init(); v2 = z; a2_1 = ::a2; v4 = ::x; y = dword_41BC68; x = dword_41BC64; a6 = dword_41BC70; w = dword_41BC74; bytes_to_big(34, ptr, z); cinstr(v4, code); if ( mr_compare(v4, v2) <= 0 ) { power(v4, 5, v2, w); memset (v29, 0, sizeof (v29)); if ( big_to_bytes(34, w, v29, 1) == 34 ) { bytes_to_big(17, v29, x); bytes_to_big(17, &v29[17], y); convert(0, a2_1); convert(1, a6); v17 = 1; if ( ecurve2_init(131, 13, 2, 1, a2_1, a6, 0, 0) ) { qmemcpy(v46, "51C99BFA6F18DE467C80C23B98C7994AA" , sizeof (v46)); qmemcpy(v47, "42EA2D112ECEC71FCF7E000D7EFC978BD" , sizeof (v47)); qmemcpy(v44, "6C997F3E7F2C66A4A5D2FDA13756A37B1" , sizeof (v44)); qmemcpy(v43, "4A38D11829D32D347BD0C0F584D546E9A" , sizeof (v43)); qmemcpy(v45, "200000000000000004D4FDD5703A3F269" , sizeof (v45)); v30 = dword_418118; v31 = word_41811C; memset (v32, 0, sizeof (v32)); v33 = 0; v34 = dword_4180E4; v35 = byte_4180E8; memset (v36, 0, sizeof (v36)); v37 = 0; v38 = 0; v40 = dword_4180F0; v39 = dword_4180EC; memset (v41, 0, sizeof (v41)); a1 = 0; memset (v49, 0, sizeof (v49)); v50 = 0; v51 = 0; i = 0; v6 = &a1; a3 = ( char *)mds; lpMem = (flash)&v30; do { strcpy (v6, a2); strcat (v6, "-" ); strcat (v6, ( const char *)lpMem); xmd5(v6, strlen (v6), a3, i + 1); v6 += 256; ++i; lpMem += 4; a3 += 16; } while ( i < 3 ); md0 = mirvar(0); md1 = mirvar(0); md2 = mirvar(0); x1 = mirvar(0); a3a = mirvar(0); x2 = mirvar(0); lpMema = mirvar(0); v9 = mirvar(0); ep1 = epoint_init(); ep2 = epoint_init(); p1 = epoint_init(); p2 = epoint_init(); epInput = epoint_init(); if ( epoint2_set(x, y, 0, epInput) ) { cinstr(x1, v46); cinstr(a3a, v47); epoint2_set(x1, a3a, 0, ep1); cinstr(x2, v44); cinstr(lpMema, v43); epoint2_set(x2, lpMema, 0, ep2); bytes_to_big(16, (_BYTE *)mds, md0); bytes_to_big(16, mds[1], md1); bytes_to_big(16, mds[2], md2); ecurve2_mult(md2, ep1, p1); ecurve2_mult(md2, ep2, p2); ecurve2_add(epInput, p1); ecurve2_add(epInput, p2); ecurve2_mult(md0, p1, p1); ecurve2_mult(md1, p2, p2); epoint2_get(p1, x1, a3a); epoint2_get(p2, x2, lpMema); cinstr(v9, v45); divide(x1, v9, v9); divide(x2, v9, v9); v17 = 3; if ( !mr_compare(x1, x2) ) v17 = 0; } else { v17 = 2; } mirkill(md0); mirkill(md1); mirkill(md2); mirkill(x1); mirkill(x2); mirkill(a3a); mirkill(lpMema); mirkill(v9); epoint_free(ep1); epoint_free(ep2); epoint_free(p1); epoint_free(p2); epoint_free(epInput); } mirexit(); result = v17; } else { mirexit(); result = 1; } } else { mirexit(); result = 1; } return result; } |
2. 计算
(md2 * ep1 + epInput) * md0 mod n == (md2 *ep2 + epInput) * md1 mod n
=>
epInput = (md2 * md1 * ep2 - md2 * md0 * ep1) * (((md0 - md1) ^-1) mod n)
得到 ( 02D23461BA71B50AF182DC76E5A7C726F5, 07BE013AF19BD185BCD20BB341EA31298B )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | void test2() { big a2 = mirvar(0); big a6 = mirvar(1); if (ecurve2_init(131, 13, 2, 1, a2, a6, 0, 0)) { epoint *epInput = epoint_init(); big x = mirvar(0); big y = mirvar(0); big md0 = mirvar(0); big md1 = mirvar(0); big md2 = mirvar(0); cinstr(md0, "51C75F1F444BAA97ED18DD6C340835D7" ); cinstr(md1, "0E5CF7F068D6EFA16F42F935EC424A75" ); cinstr(md2, "A4CD1D64486ABDE1BE441944460CD41D" ); epoint *p1 = epoint_init(); big x1 = mirvar(0); big y1 = mirvar(0); cinstr(x1, "51C99BFA6F18DE467C80C23B98C7994AA" ); cinstr(y1, "42EA2D112ECEC71FCF7E000D7EFC978BD" ); epoint2_set(x1, y1, 0, p1); epoint *p2 = epoint_init(); big x2 = mirvar(0); big y2 = mirvar(0); cinstr(x2, "6C997F3E7F2C66A4A5D2FDA13756A37B1" ); cinstr(y2, "4A38D11829D32D347BD0C0F584D546E9A" ); epoint2_set(x2, y2, 0, p2); big n = mirvar(0); cinstr(n, "200000000000000004D4FDD5703A3F269" ); ecurve2_mult(md2, p2, p2); ecurve2_mult(md1, p2, p2); ecurve2_mult(md2, p1, p1); ecurve2_mult(md0, p1, p1); ecurve2_sub(p1, p2); big r = mirvar(0); big rd = mirvar(0); big nd = mirvar(0); big z = mirvar(0); subtract(md0, md1, r); xgcd(r, n, rd, nd, z); ecurve2_mult(rd, p2, epInput); epoint2_get(epInput, x, y); char sx[256]; char sy[256]; cotstr(x, sx); cotstr(y, sy); printf ( "%s\n" , sx); printf ( "%s\n" , sy); } } |
用RDLP计算得到code
>>> 7A7102F36F3B344D666132A6FF7EF4BA05B99640BB815C9E712A72C64B6ABC582C2
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
赞赏
- [话题] 9月10日 教师节到了,说说你记忆深刻的老师 4519
- [原创] 我和程序猿男朋友的爱恨情仇【结帖】 8666
- [推荐]看雪杯AFSRC造洞节,最棒的福利送给看雪的你! 6463
- [注意]某白帽未授权渗透测试政府网站被抓 8526
- [分享] 本周 安全类会议 大汇总 4688