-
-
[原创]KCTF2023 第五题 争分夺秒
-
2023-9-12 14:39 2744
-
- 程序多解吧?
两个0x4a数组,len位,程序里是双字节,实际录入4字节
input base64_decode后的数据结构如下:
1 2 3 4 5 6 7 8 9 10 11 | 2a 62 53 31 / / 4 字节,第四层的M 4a 00 / / arr1长度 37 38 / / ??? arr1 / / 第七层,大数arr1 f550c4d11be88545a17edf49a600d30212a17760f814f054f252f5fac9e3c915b1195d9f2d52f3bbd2cb5690982c85dfbca0c4102132cff25e4740f3c9c71174802c59a7faf98daebc52 9d a4 72 43 / / 4 字节,第四层的N 4a 00 / / arr2长度 33 34 / / ??? arr2 / / 第七层,大数arr2 54449bc8e9713a6f2de69acceadb2bb55f550294d7f4d887d561c858c12d74aa218e45766d0799391a8c617f5e3fb00fd4995e9e5077100721858261a223fb4773736ce6027275e7a9ec 0B 73 5F 7A / / crc32 7A5F730B |
程序中充满着大量恶心的垃圾代码,直接挑选参数的传递函数去分析
先看弹窗逻辑
1 2 3 4 5 6 7 8 9 10 11 12 | int __usercall sub_4EB910@<eax>( int ebx0@<ebx>, int edi0@<edi>, int a3@<esi>, int a1, int a2) { if ( a1 = = 2 ) { lstrlenA( * (LPCSTR * )(a2 + 4 )); if ( sub_47B430(ebx0, edi0, a3, * (_DWORD * )(a2 + 4 )) = = 1 ) MessageBoxA( 0 , "OK!" , 0 , 0 ); else MessageBoxA( 0 , "Error!" , 0 , 0 ); } return 0 ; } |
- 进入下一层,发现有5层校验
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 | signed int __usercall sub_47B430@<eax>( int ebx0@<ebx>, int a2@<edi>, int a3@<esi>, int a1) { if ( sub_40A580(ebx0, a2, a3, a1, (char * * )& input , &input_len) ) √ / / 3339 解base64,刚解密出来是正常的 { if ( sub_455F80(( int ) input , input_len) ) ( "4234567890" , 10 ) Crc32( "前len-4位" ) = = 后 4 位 √ { if ( sub_458D90(ebx0, a2, input , input_len - 4 , ( int )&v2357, ( int )&v2356) ) / / 字符串中有 2 个长度标记位,校验通过,√ { if ( sub_474170( * v2357, * v2356) ) / / 对 2 个dword进行除法校验,满足的情况总共有 2 * 4 = 8 种 { v1378 = v2357 + 8 ; / / 5153 .text: 004870AC 这里就要篡改一次数据 for ( i169 = 0 ; i169 < v1379; + + i169 ) { v5 = 16 ; * (_BYTE * )(i169 + v1378) ^ = * (&v1593 + i169 % 0x10u ); } sub_4E1620( * (_DWORD * )v2357, v2357 + 8 , * (unsigned __int16 * )(v2357 + 4 )); / / 5298 将 + 8 数组进行xor操作 sub_4E1620( * (_DWORD * )v2356, v2356 + 8 , * (unsigned __int16 * )(v2356 + 4 )); / / 5453 v1360 = v2357 + 8 ; / / 5602 for ( i214 = 0 ; i214 < v1361; + + i214 ) { v5 = 16 ; * (_BYTE * )(i214 + v1360) ^ = * (&v1577 + i214 % 0x10u ); / / arr1比arr2多 2 次xor } if ( sub_45F640( ( int )(v2357 + 2 ), * ((unsigned __int16 * )v2357 + 2 ), ( int )(v2356 + 2 ), * ((unsigned __int16 * )v2356 + 2 )) ) { sub_4E81E0(ebx0, a2, v5, v2359); result = 1 ; } else result = 0 ; } else result = 0 ; } else result = 0 ; } else result = 0 ; } else result = 0 ; } |
- 第一层,sub_40A580,base64解密
1 2 3 4 5 | if ( BASE64_table_4FBD18[kk] = = a1 ) break ; v347 = 119 ; v232 = - 1 ; v274 = 104 ; |
- 第二层,sub_455F80,crc校验,结果存放在最后4字节
1 2 3 | v207 = sub_453B90(v2, v3, v4, (char * ) input , input_len - 4 ); if ( v207 = = * (_DWORD * )(input_len + input - 4 ) ) result = 1 ; |
- 第三层,sub_458D90,对字符串长度校验,并取出2个魔法数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | if ( (unsigned int )input_len_jian4 > = 0x10 ) / / len - 4 > = 16 { * (_DWORD * )a5 = input ; / / 1406 if ( (signed int ) * (unsigned __int16 * )( * (_DWORD * )a5 + 4 ) > 0 / / 1547 45B83C && * (unsigned __int16 * )( * (_DWORD * )a5 + 4 ) < = (unsigned int )(input_len_jian4 - 16 ) ) { * (_DWORD * )a6 = input + * (unsigned __int16 * )( * (_DWORD * )a5 + 4 ) + 8 ; / / 1655 if ( (signed int ) * (unsigned __int16 * )( * (_DWORD * )a6 + 4 ) > 0 / / 1831 45d381 && * (unsigned __int16 * )( * (_DWORD * )a6 + 4 ) < = input_len_jian4 - 16 - (unsigned int ) * (unsigned __int16 * )( * (_DWORD * )a5 + 4 ) ) { result = 1 ; } } } |
- 第四层,sub_474170,对2个魔法书校验
1 2 3 4 5 6 | M = i * 0x7D45 ; M % 0x346F8717 = = 1 M = 3153622A 65C2E941 65C2E941 CEA1F76F N = j * 0xD711 ; N % 0x346F8717 = = 1 N = 4372A49D B60C0E9C |
- 第五层,对数组4次xor
1 2 3 4 | xor(arr1); sub_4E1620( * (_DWORD * )v2357, v2357 + 8 , * (unsigned __int16 * )(v2357 + 4 )); / / arr1 sub_4E1620( * (_DWORD * )v2356, v2356 + 8 , * (unsigned __int16 * )(v2356 + 4 )); / / arr2 xor(arr1); |
- 第六层,sub_45F640,大数校验
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 能跑出数据结果 n = 0x8395475F m = 0xb5b441af57592c12ec5c722d5b377bfc3d5fecb8ba3daf5b7812ef8fd1255e50913d2e7a6cb48837833074e78dcfec0689d4219c8b98a1c617596a6dfba28c973bebf711efb09844b305 i = 0 while i < 0x99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 : if ((m * i + 1 ) % n = = 0 ): print ( hex (i)) i + = 1 n = 0x8395475F m = 0xb5b441af57592c12ec5c722d5b377bfc3d5fecb8ba3daf5b7812ef8fd1255e50913d2e7a6cb48837833074e78dcfec0689d4219c8b98a1c617596a6dfba28c973bebf711efb09844b305 i = 0 while i < 0x99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 : if ((m * i + 1 ) % n = = 0 ): print ( hex (i)) i + = 1 |
- 然后再根据结果反推重新计算crc32校验,验证失败!
OD运行是success,命令行运行是失败,说明有反调试。
1 2 3 4 5 6 7 8 9 10 11 12 13 | if ( sb001() = = 1 ) { if ( * (_BYTE * ) input & 1 ) { a3 = 0 ; * (_BYTE * ) input + = (signed int )sb002() % 3 + 1 ; } else { a3 = 0 ; * (_BYTE * ) input + = (signed int )sb002() % 4 + 4 ; } } |
- 然后又重新调整数值,得到flag
KmJTMUoAAAD1UMTRG+iFRaF+30mmANMCEqF3YPgU8FTyUvX6yePJFbEZXZ8tUvO70stWkJgshd+8oMQQITLP8l5HQPPJxxF0gCxZp/r5ja68Up2kckNKAAAAVESbyOlxOm8t5prM6tsrtV9VApTX9NiH1WHIWMEtdKohjkV2bQeZORqMYX9eP7AP1JlenlB3EAchhYJhoiP7R3NzbOYCcnXnqewe7SYM
[培训]科锐逆向工程师培训 48期预科班将于 2023年10月13日 正式开班
赞赏
他的文章
[原创]看雪2023 第三题 秘密计划
3463