-
-
[原创]KCTF2022春季赛第二题 解题过程
-
2022-5-15 22:37 6735
-
算法分析题,有众多的printf打印信息,整个流程比较清晰,有正确的提示。从输入开始进行流程分析。
step1:输入ID,最多41个字符,第42个会设为0。
1 2 3 4 5 | printf_40100C( Format , (char)byte_4055C0); scanf_40103A( "%s" , (char) ID ); printf_40100C(asc_403160, v33); ID [ 41 ] = 0 ; iLenOfID = strlen( ID ); |
step2:计算CRC8(ID)
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 | v5 = 0 ; t_ = iLenOfID; v6 = iLenOfID; ID_CRC8 = 0 ; if ( iLenOfID ) { v7 = ID ; do { v5 ^ = * v7; - - v6; + + v7; v8 = 8 ; do { v9 = 2 * v5; v10 = v9 ^ 7 ; if ( v9 > = 0 ) v10 = v9; v5 = v10; - - v8; } while ( v8 ); } while ( v6 ); iLenOfID = t_; ID_CRC8 = v10; } |
step3:计算CRC32(ID),不过这里要注意,正常CRC32计算的时候定义为unsigned int类型,这里识别的是int类型,在进行移位的时候如果是负数,则高位添加0xff。
1 2 3 4 5 6 7 | CRC32_Init_40106C(); ID_CRC32 = 0xFFFFFFFF ; for ( i = 0 ; i < iLenOfID; + + i ) ID_CRC32 = dword_405B20[(unsigned __int8)(ID_CRC32 ^ ID [i])] ^ (ID_CRC32 >> 8 ); ID_CRC32_R = ~ID_CRC32; |
step4:将输入的ASCII码类型字符串,转换为int类型。Ascii2Raw_4010B7((int)ID, iLenOfID);
step5:直接搜索3*n+1是什么数列,得知为Callztz数列,无论初始输入为多少,最终的结果就是变为1、4、2的循环,猜测经过200次变换,最后3个值为(1 4 2)、(4 2 1)或(2 1 4)的一种。
第一次校验:输入的前3个数的异或值为7。ID[2] ^ ID[1] ^ ID[0] == 7
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 | v13 = ID_CRC8; imod = 1 ; v68 = ID_CRC8 + 1 ; v14 = v68; do { v15 = v13; for ( j = 1 ; j < 200 ; + + j ) / / Callatz { if ( (v15 & 1 ) ! = 0 ) v15 = 3 * v15 + 1 ; else v15 >> = 1 ; CallatzTable[j] = v15; } + + v13; } while ( v13 < v14 ); value_7 = CallatzTable[ 198 ] | CallatzTable[ 197 ] | CallatzTable[ 196 ]; v18 = t_; if ( value_7 ! = ( ID [ 2 ] ^ ID [ 1 ] ^ ID [ 0 ]) ) / / b0111 的组合 { printf_40100C( "\n%s" , (char)&unk_405594); printf_40100C( "\n%s\n%s" , (char)&unk_405678); printf_40100C( "\n%s" , (char)&unk_405118); printf_40100C( "\n%s" , (char)&unk_4053A4); goto LABEL_57; } |
step6:判断ID[3:7]是否为KCTF。(下图略掉printf)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | if ( ID [ 3 ] ! = 20 ) / / K { / / goto LABEL_57; } / / if ( ID [ 4 ] ! = 12 ) / / C { / / goto LABEL_57; } / / if ( ID [ 5 ] ! = 29 ) / / T { / / goto LABEL_57; } / / if ( ID [ 6 ] ! = 15 ) / / F { / / goto LABEL_57; } |
step7:mod测试:
ID[7]%1 == 0
(ID[7]*10 + ID[8]) %2 == 0
(ID[7]*100 + ID[8]*10 + ID[9] ) %3 == 0
...
(ID[7]*100000000 + ID[8]*10000000 + ... + ID[15]) % 9 == 0
随后对ID[7:16]共9个数字进行冒泡排序,排序后为123456789,说明ID[7:16]为123456789的组合。
编程求解得解为:ID[7:16] == 381654729
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 | if ( value_9 > 0 ) { istart = 1 ; do { v23 = ID [istart + 6 ] + 10 * before; before_ = v23 - 926365495 ; / / junkcode if ( v23 < = 1262703685 ) before_ = v23; before = before_; if ( before_ % imod ) / / mod 1 2 3 4 5 6 7 8 9 中间必须是 5 goto LABEL_50; t = t_ + 1 ; istart = imod + 1 ; t_ = t; + + imod; } while ( t < value_9 ); } value_8 = value_9 - 1 ; if ( value_9 - 1 > 0 ) { value_8_ = value_9 - 1 ; do { i_ = 0 ; if ( value_8 > 0 ) { do { v28 = ID [i_ + 7 ]; / / 冒泡排序 从小到大 排序后为 123456789 v29 = ID [i_ + 8 ]; if ( v28 > v29 ) { ID [i_ + 7 ] = v29; ID [i_ + 8 ] = v28; } + + i_; } while ( i_ < value_8 ); v3 = 0 ; } - - value_8; - - value_8_; } while ( value_8_ ); } Ascii2Raw_4010B7(( int )a1234567890Abcd, value_9); / / 123456789 i__ = 0 ; if ( value_9 > 0 ) { while ( a1234567890Abcd[i__] = = ID [i__ + 7 ] ) { if ( + + i__ > = value_9 ) goto LABEL_41; } goto LABEL_49; } |
step8:如果输入字符长度超过16,则对后续的字符判断是否为8字节的倍数,进行变换sub_4010E1,不过简单分析感觉并不可逆。如果长度正好为16则校验ID_CRC32_R == 0xF52E0765。
假设输入ID正好为16字符,综合以上分析,只需CRC32(XYZKCTF381654219) = ~0xF52E0765,且X^Y^Z==7。直接编程进行穷尽即可,注意这里的CRC32计算时为int类型。最后得421KCTF381654219。
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 | ID_16 = & ID [value_9 + 7 ]; sub_4010E1(( int )ID_16, iLenOfID_sub_16); if ( iLenOfID_sub_16 < = 0 ) { LABEL_45: printf_40100C(asc_403C08, v60); if ( ID_CRC32_R = = 0xF52E0765 ) { printf_40100C(asc_403C50, v61); printf_40100C( "\n" "十年后,你终于干掉了赤月恶魔,肃清了赤月邪教,获得了 赤月套装 .\n" "恭喜你,少年,你成功了\n" "恭喜你,少年,你成功了\n" "恭喜你,少年,你成功了\n" "恭喜你,少年,你成功了\n" "恭喜你,少年,你成功了\n" "恭喜你,少年,你成功了\n" "恭喜你,少年,你成功了\n" "恭喜你,少年,你成功了." , v62); } else { printf_40100C( "\n%s" , (char)&unk_4051BC); printf_40100C( "\n%s" , (char)&unk_40524C); } } else { while ( ((unsigned __int8)byte_4055C0[v3] ^ (unsigned __int8)ID_16[v3]) = = byte_403DC8[v3] ) { if ( + + v3 > = iLenOfID_sub_16 ) goto LABEL_45; } printf_40100C(asc_403B50, v60); printf_40100C(asc_403BC0, v63); } |
[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界