-
-
[原创]KCTF Q3 第八题:人妒英才 WP
-
发表于: 2019-9-23 00:17 3103
-
用IDA载入CM,找到main函数
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 | int __usercall sub_41B870@<eax>( int a1@<xmm0>) { ... //省略掉初始化 dword_428300 = 11; dword_428304 = 4; v85 = sub_4115F5(&dword_428300, dword_428000); v86 = v1; dword_428308 = v85; dword_42830C = v1; sub_4113B6(byte_4252C2); v90 = 0; v2 = sub_411802(std::cout, "Ep = y^2 = x^3 + 125*x " ); v3 = std::basic_ostream< char ,std::char_traits< char >>::operator<<(v2, sub_411159); sub_411361(v4, &v19 == &v19, v3, a1); v5 = sub_411802(std::cout, "Prime field p=127,base point G(11,4),publicK(120,41) please find private key k" ); v6 = std::basic_ostream< char ,std::char_traits< char >>::operator<<(v5, sub_411159); sub_411361(v7, &v19 == &v19, v6, a1); v8 = sub_411802(std::cout, "input your flag:" ); v9 = std::basic_ostream< char ,std::char_traits< char >>::operator<<(v8, sub_411159); sub_411361(v10, &v19 == &v19, v9, a1); sub_411212(std::cin, &str1); v84 = &v16; v22 = sub_411447(( int )&v16, a1, ( int )&str1); v21 = strencrypt(( int )&v83, v16); // 加密输入的字符串 v20 = v21; strmove(( int )&str1, a1, v21); free (a1, ( int )&v83); flag = 94; ... //初始化变量,太长,省略掉 v18 = sub_4113D4(( int )&v82); v11 = sub_4112C1(&v81, ( int )&flag, ( int )&v79); newstr(*v11, v11[1], v18); // start,end if ( check(&str1, a1, ( int )&str2) ) // memcmp,把所有字符串加密后的结果dump一份就行了 print( "try again" , v19); else print( "Congratulations~~" , v19); v12 = system ( "pause" ); sub_411361(v13, &v19 == &v19, v12, a1); v80 = 0; free (a1, ( int )&str2); v90 = -1; free (a1, ( int )&str1); v18 = v14; sub_411677(( int )&savedregs, ( int )&dword_41BC54, v80); return sub_411361((unsigned int )&savedregs ^ v89, 1, v17, a1); } |
CM整体逻辑比较简单,加密输入字符串后比较加密后的结果。
用OD载入CM,输入1111111111。

可以看到结果都差不多,用一个DWORD表示一个字符,前两个BYTE 5E26是特征字符,第三个应该是表示字符index,可以不看,最后一个是字符加密的结果。
再往下单步几次就能看到flag加密后的样子了。

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 | int __usercall sub_41B870@<eax>( int a1@<xmm0>) { ... //省略掉初始化 dword_428300 = 11; dword_428304 = 4; v85 = sub_4115F5(&dword_428300, dword_428000); v86 = v1; dword_428308 = v85; dword_42830C = v1; sub_4113B6(byte_4252C2); v90 = 0; v2 = sub_411802(std::cout, "Ep = y^2 = x^3 + 125*x " ); v3 = std::basic_ostream< char ,std::char_traits< char >>::operator<<(v2, sub_411159); sub_411361(v4, &v19 == &v19, v3, a1); v5 = sub_411802(std::cout, "Prime field p=127,base point G(11,4),publicK(120,41) please find private key k" ); v6 = std::basic_ostream< char ,std::char_traits< char >>::operator<<(v5, sub_411159); sub_411361(v7, &v19 == &v19, v6, a1); v8 = sub_411802(std::cout, "input your flag:" ); v9 = std::basic_ostream< char ,std::char_traits< char >>::operator<<(v8, sub_411159); sub_411361(v10, &v19 == &v19, v9, a1); sub_411212(std::cin, &str1); v84 = &v16; v22 = sub_411447(( int )&v16, a1, ( int )&str1); v21 = strencrypt(( int )&v83, v16); // 加密输入的字符串 v20 = v21; strmove(( int )&str1, a1, v21); free (a1, ( int )&v83); flag = 94; ... //初始化变量,太长,省略掉 v18 = sub_4113D4(( int )&v82); v11 = sub_4112C1(&v81, ( int )&flag, ( int )&v79); newstr(*v11, v11[1], v18); // start,end if ( check(&str1, a1, ( int )&str2) ) // memcmp,把所有字符串加密后的结果dump一份就行了 print( "try again" , v19); else print( "Congratulations~~" , v19); v12 = system ( "pause" ); sub_411361(v13, &v19 == &v19, v12, a1); v80 = 0; free (a1, ( int )&str2); v90 = -1; free (a1, ( int )&str1); v18 = v14; sub_411677(( int )&savedregs, ( int )&dword_41BC54, v80); return sub_411361((unsigned int )&savedregs ^ v89, 1, v17, a1); } |
CM整体逻辑比较简单,加密输入字符串后比较加密后的结果。
用OD载入CM,输入1111111111。

可以看到结果都差不多,用一个DWORD表示一个字符,前两个BYTE 5E26是特征字符,第三个应该是表示字符index,可以不看,最后一个是字符加密的结果。
再往下单步几次就能看到flag加密后的样子了。

我直接收集0-9 a-z加密后的结果。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
他的文章
赞赏
雪币:
留言: