-
-
[原创] 看雪 2024 KCTF 大赛 第七题 星际移民
-
发表于: 2024-8-28 23:50 536
-
IDA打开,函数不多,主要逻辑都在 sub_401120
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 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | int __cdecl sub_401120(unsigned __int8 **a1) { char *v1; // eax unsigned __int8 *global_buf_401120; // esi int i; // ecx char t; // cl int j; // eax char v6; // dl char v; // dl _BYTE *p_serial_; // eax int v9; // ecx char v10; // cl char xor1; // al char *k; // edx unsigned __int8 *global_buf_4010d0; // esi unsigned __int8 *p_serial; // edx int index; // eax unsigned int ii; // ebp unsigned __int8 *p_buf_4010d0; // edi int v18; // ecx unsigned int jj; // edi unsigned __int8 *v20; // ecx unsigned __int8 *v21; // edx int v22; // eax char *v23; // esi unsigned __int8 *global_buf_401120_; // esi _BYTE *p_final; // ebp int i_; // edi char v27; // bl char v28; // al unsigned int v29; // edx const char *finalcheck; // eax _BYTE *final; // ecx char *p_serial_index; // [esp+10h] [ebp-4Ch] _BYTE serial[68]; // [esp+14h] [ebp-48h] BYREF v1 = hexdecode(global_serial); qmemcpy(serial, v1, 67u); free (v1); global_buf_401120 = a1[1]; // 0x401120 for ( i = 0; i < 697; ++i ) serial[i % 67u] ^= global_buf_401120[i]; t = serial[0]; for ( j = 1; j < 66; t ^= serial[j - 2] ^ serial[j - 1] ^ serial[j - 3] ^ v6 ) { v6 = serial[j + 1] ^ serial[j]; j += 5; } v = t ^ serial[66]; serial[66] ^= t; p_serial_ = serial; v9 = 66; do { *p_serial_++ ^= v; --v9; } while ( v9 ); v10 = global_user[0]; xor1 = 0; for ( k = global_user; *k; v10 = *k ) { ++k; xor1 ^= v10; } global_buf_4010d0 = *a1; // 4010d0 p_serial = serial; p_serial_index = &serial[2 * (xor1 & 0xF)]; index = 2 * (xor1 & 0xF); if ( index >= 0 && p_serial_index != serial ) { ii = index; p_buf_4010d0 = global_buf_4010d0; if ( (unsigned int )index < 4 ) { LABEL_13: if ( !ii ) goto LABEL_22; } else { while ( *(_DWORD *)p_buf_4010d0 == *(_DWORD *)p_serial ) { ii -= 4; p_serial += 4; p_buf_4010d0 += 4; if ( ii < 4 ) goto LABEL_13; } } v18 = *p_buf_4010d0 - *p_serial; if ( !v18 ) { if ( ii <= 1 ) goto LABEL_22; v18 = p_buf_4010d0[1] - p_serial[1]; if ( !v18 ) { if ( ii <= 2 ) goto LABEL_22; v18 = p_buf_4010d0[2] - p_serial[2]; if ( !v18 ) { if ( ii <= 3 ) goto LABEL_22; v18 = p_buf_4010d0[3] - p_serial[3]; } } } if ( (v18 >> 31) | 1 ) return printf ( "fail.\n" ); } LABEL_22: jj = 44 - index; if ( 44 - index > 0 ) { v20 = &serial[index + 23]; v21 = &global_buf_4010d0[index + 23]; if ( jj < 4 ) { LABEL_26: if ( !jj ) goto LABEL_35; } else { while ( *(_DWORD *)v21 == *(_DWORD *)v20 ) { jj -= 4; v20 += 4; v21 += 4; if ( jj < 4 ) goto LABEL_26; } } v22 = *v21 - *v20; if ( v22 ) goto LABEL_34; if ( jj > 1 ) { v22 = v21[1] - v20[1]; if ( v22 ) goto LABEL_34; if ( jj > 2 ) { v22 = v21[2] - v20[2]; if ( v22 ) goto LABEL_34; if ( jj > 3 ) { v22 = v21[3] - v20[3]; LABEL_34: if ( (v22 >> 31) | 1 ) return printf ( "fail.\n" ); } } } } LABEL_35: qmemcpy(&global_final, p_serial_index, 20u); v23 = p_serial_index + 20; *((_WORD *)&global_final + 10) = *((_WORD *)p_serial_index + 10); *((_BYTE *)&global_final + 22) = v23[2]; global_buf_401120_ = a1[1]; p_final = &global_final; i_ = 23; do { v27 = *p_final >> (8 - (*global_buf_401120_ & 7)); v28 = *p_final++ << (*global_buf_401120_++ & 7); --i_; *(p_final - 1) = v28 | v27; } while ( i_ ); v29 = 23; finalcheck = "KCTF-2024-CRACK-SUCCESS" ; final = &global_final; while ( *(_DWORD *)final == *(_DWORD *)finalcheck ) { v29 -= 4; finalcheck += 4; final += 4; if ( v29 < 4 ) { if ( *finalcheck == *final && finalcheck[1] == final[1] && finalcheck[2] == final[2] ) return printf ( "***success***.\n" ); return printf ( "fail.\n" ); } } return printf ( "fail.\n" ); } |
对全局变量和一些局部变量做了重命名。该函数调用自_main,第一个参数是&off_403FD0,指向0x4010d0和0x401120两个值,也即_main函数和sub_401120函数的位置。
程序基于这两个函数代码所在内存做了大量运算,可能主要想坑软件断点调试(软件断点会修改断点处的字节为int3),不过此题逻辑非常简单,静态分析足够了。如果真的要调试,可以下硬件断点避免修改内存数据。
整理出来的检查逻辑和逆向的serial生成逻辑如下:
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 | with open ( "decode.exe" , "rb" ) as f: content = f.read() global_buf_401120 = content[ 0x520 : 0x520 + 697 ] global_buf_4010d0 = content[ 0x4d0 : 0x4d0 + 697 ] def name_to_index(u): xor1 = 0 for i in range ( len (u)): xor1 ^ = u[i] index = 2 * (xor1 & 0xf ) return index def change_bytes(b): r = bytearray(b) for i, c in enumerate (r): o = global_buf_401120[i] & 7 r[i] = (c >> ( 8 - o)) | ((c << o) & 0xff ) return r def rev_change_bytes(b): r = bytearray(b) for i, c in enumerate (r): o = global_buf_401120[i] & 7 r[i] = (c << ( 8 - o) & 0xff ) | ((c >> o) & 0xff ) return r def xor_all(s): r = 0 for c in s: r ^ = c return r def calc_final(name, serial): u = bytearray(name.encode()) s = bytearray(bytes.fromhex(serial)) for i in range ( 697 ): s[i % 67 ] ^ = global_buf_401120[i] t = s[ 0 ] for i in range ( 1 , 66 , 5 ): t ^ = s[i] ^ s[i + 1 ] ^ s[i + 2 ] ^ s[i + 3 ] ^ s[i + 4 ] v = t ^ s[ 66 ] v = xor_all(s) s[ 66 ] = v for i in range ( 66 ): s[i] ^ = v index = name_to_index(u) part1 = s[:index] part2 = s[index + 23 :] assert part1 = = global_buf_4010d0[:index], () assert part2 = = global_buf_4010d0[index + 23 : len (s)] b = bytearray(s[index:index + 23 ]) r = change_bytes(b) assert r = = b "KCTF-2024-CRACK-SUCCESS" def calc_serial(name): u = bytearray(name.encode()) index = name_to_index(u) s = bytearray(global_buf_4010d0[: 67 ]) s[index:index + 23 ] = rev_change_bytes(b 'KCTF-2024-CRACK-SUCCESS' ) v = s[ 66 ] for i in range ( 66 ): s[i] ^ = v s[ 66 ] ^ = xor_all(s[: 66 ]) for i in range ( 697 ): s[i % 67 ] ^ = global_buf_401120[i] return s. hex () # calc_final("39881BA5569BBADD", "d287e2bb87cbda561717c90e61e7a78ec1e8e1e904a2ccf5558045a3f792aeebba09dadcb1f7f19b4d110f2a4121e0d1fd330ed9c21474e364a4e4d6b02c4644b1b580") assert calc_serial( "39881BA5569BBADD" ) = = "d287e2bb87cbda561717c90e61e7a78ec1e8e1e904a2ccf5558045a3f792aeebba09dadcb1f7f19b4d110f2a4121e0d1fd330ed9c21474e364a4e4d6b02c4644b1b580" print (calc_serial( "KCTF" )) # d287e2bb87cbda561717c90e08eba2ad13cf09e4eb4428f36cf11cf83cea678dfa19e081bc5d66cdc17d1c2a4121e0d1fd330ed9c21474e364a4e4d6b02c4644b1b5cc |
最终答案:
name: KCTF
serial: d287e2bb87cbda561717c90e08eba2ad13cf09e4eb4428f36cf11cf83cea678dfa19e081bc5d66cdc17d1c2a4121e0d1fd330ed9c21474e364a4e4d6b02c4644b1b5cc
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
他的文章
看原图
赞赏
雪币:
留言: