-
-
[原创]KCTF2021 第四题 英雄救美 writeup
-
2021-5-14 21:06 5138
-
KCTF2021 第四题 英雄救美 writeup
IDA
main
1 2 3 4 5 6 7 8 9 10 11 | main(){ / / ... printf( "Serial: " ); scanf_s( "%s" , v12); v3 = strlen(v12); if ( v3 < = 64 && sub_691240(v3, ( int )v12, v10) = = 1 && sub_691000(v10, v3 - 9 ) = = 1 ) { / / ... } / / ... } |
sub_691240
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 | int __usercall sub_691240@<eax>( int a1@<edx>, int a2@<ecx>, int * a3) { / / ... __int128 v13[ 5 ]; / / [esp + Ch] [ebp - 58h ] 9 * 9 初始化表 char v14; / / [esp + 5Ch ] [ebp - 8h ] v13[ 0 ] = (__int128)_mm_load_si128(&stru_6A6280); v3 = 0 ; v13[ 1 ] = (__int128)_mm_load_si128(stru_6A62A0); v4 = 0 ; v11 = a1; v10 = a2; v14 = 'q' ; v13[ 2 ] = (__int128)_mm_load_si128(&stru_6A6270); v13[ 3 ] = (__int128)_mm_load_si128(&stru_6A6290); v13[ 4 ] = (__int128)_mm_load_si128(&stru_6A6260); if ( a1 < = 0 ) return 1 ; v5 = 0 ; while ( 1 ) { v6 = * (_BYTE * )(v4 + a2); if ( v6 > '0' && v6 < = '9' ) break ; v7 = v5; if ( v5 > = 81 ) / / 数字不可以超过 9 个 return 0 ; while ( v6 ! = * ((_BYTE * )v13 + v7) ) / / 从数字的个数 * 9 的位置开始检索 就是第n行开始 { if ( (unsigned int ) + + v7 > = 81 ) return 0 ; } v9 = v7 % 9 + 1 ; if ( v9 = = - 1 ) return 0 ; * a3 = v9; / / 属于第几列的 记录下来 a2 = v10; + + v3; + + a3; a1 = v11; LABEL_13: if ( + + v4 > = a1 ) return 1 ; } if ( v3 + v6 = = '9' ) / / 数字在字符串后为( 9 - 字符长度) { v3 = 0 ; v5 + = 9 ; goto LABEL_13; } return - 1 ; } |
sub_691240
通过输入的字符串生成一个数组仅包含数字1-9。
在9*9的初始化表中匹配字符,每出现数字就从下一行开始匹配,将匹配到的第几列存下来。按数字分割字符串,数字=9-数字前字符串的长度。
通过main中sub_691000(v10, v3 - 9)
的调用可以知道数字会出现9次。
导出初始化表
1 | "$BPV:ubfYp}]DtN>aT^MGmJQ#*Hr`O'wjic0!hdy{oZz-@n+?&%s_/g<e[W)XUxRFSLRA;.l=CEkvK-(q" |
sub_691000
sub_691000(arr, arr_len)
是个数独的判断。
首先将arr
顺序填充到006A87C0非零的值上,9行9列,其中0值有55个,则要输入64(55+9)个字符。
接下来就是判断每行每列每个9宫格不能有重复数字。
导出数独初始值
1 2 3 4 5 6 7 8 9 | 0 4 0 7 0 0 0 0 0 9 2 0 0 0 0 6 0 7 8 3 0 0 0 5 4 0 0 0 1 0 0 0 3 0 0 0 0 0 0 2 0 1 0 0 0 0 0 0 5 0 0 0 4 0 0 0 4 9 0 0 0 7 1 3 0 5 0 0 0 0 9 4 0 0 0 0 0 8 0 6 0 |
求出数独
得到arr值5619238183457621978469254539786692871328563617281793452
然而并不知道如何分割为9份。
感谢出题人手下留情,按照数独分行即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #include <iostream> #include <string> using namespace std; int main() { string ar[] = { "5619238" , "18345" , "76219" , "7846925" , "4539786" , "6928713" , "28563" , "61728" , "1793452" }; string key = "$BPV:ubfYp}]DtN>aT^MGmJQ#*Hr`O'wjic0!hdy{oZz-@n+?&%s_/g<e[W)XUxRFSLRA;.l=CEkvK-(q" ; for ( int i = 0 ; i < 9 ; i + + ) { string s = ar[i]; for (char c : s) { int d = c - '1' ; printf( "%c" , key[i * 9 + d]); } printf( "%d" , 9 - s.length()); } return 0 ; } |
:u$YBPf2pa]Dt4#QM^H4ic'j0`w2y{d-Zzo2%/n_s@+2<UW)e4AR;F.4=-qEkvC2
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法
最后于 2021-5-14 21:17
被Wblank编辑
,原因:
赞赏
他的文章
看原图