-
-
[原创]kctf 2021 第四题
-
2021-5-15 01:30 5536
-
大概算法:
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 | int __cdecl main( int argc, const char * * argv, const char * * envp) { int v3; / / kr00_4 int v4; / / ecx char * v5; / / esi int v6; / / edi void ( * v8)(void); / / [esp + Ch] [ebp - 2CCh ] int v9[ 22 ]; / / [esp + 10h ] [ebp - 2C8h ] BYREF int v10[ 128 ]; / / [esp + 68h ] [ebp - 270h ] BYREF __int128 v11; / / [esp + 268h ] [ebp - 70h ] BYREF char flag[ 92 ]; / / [esp + 278h ] [ebp - 60h ] BYREF printf( "\t\t\t看雪CTF大赛\r\n" ); printf( "\t\t祝愿看雪CTF大赛越办越好\r\n" ); printf( "Serial: " ); scanf_s( "%s" , flag); v3 = strlen(flag); if ( v3 < = 64 && trans_input(v3, flag, v10) = = 1 && check_sudoku(( int )v10, v3 - 9 ) = = 1 ) / / 数独 { v11 = 0i64 ; memset(v9, 0 , sizeof(v9)); v9[ 5 ] = 0 ; v9[ 4 ] = 0 ; v9[ 0 ] = 0x67452301 ; / / md5_init v9[ 1 ] = 0xEFCDAB89 ; v9[ 2 ] = 0x98BADCFE ; v9[ 3 ] = 0x10325476 ; mde_update(( int )flag, ( int )v9, v3); md5_final(( int )&v11, ( int )v9); aes_init(v4, (unsigned __int8 * )&v11); v8 = (void ( * )(void))VirtualAlloc( 0 , 0x620u , 0x1000u , 0x40u ); v5 = (char * )v8; v6 = 'b' ; do { * (__m128i * )v5 = _mm_loadu_si128((const __m128i * )&v5[&byte_4181A0 - (_UNKNOWN * )v8]); aes_dec(( int )v10, v5); v5 + = 16 ; - - v6; } while ( v6 ); v8(); } return 0 ; } |
trans_input把输入转换为数字,然后验证数独,数独比较简单,直接就能解出来:
但是前面那个转换输入的函数我疑惑了好久,首先转换的规则是将输入查一个81大小的table,然后把查到的索引%9+1作为填入数独的数字,但是这样一来一个数字对应的输入就有9种可能,那56个数字就有9^56种可能,最后还会多9个字符,那可能性可就太多了,感觉有限时间内爆破不完。
知道后来,我又仔细审了一下tran_input函数,发现末尾有点奇怪的逻辑:
当输入是数字时会有一个判断,而每次判断就会把查表的起始索引+9,我突然想到会不会是每一行数字填完之后要输入一个数字把索引+9,而对于的输入就只在起始索引+9的范围内查找,而多的9个数字又正好把多的9个输入覆盖了。试了一下,果然如此:
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 | s_table = [[ 5 , 6 , 1 , 9 , 2 , 3 , 8 ], [ 1 , 8 , 3 , 4 , 5 ], [ 7 , 6 , 2 , 1 , 9 ], [ 7 , 8 , 4 , 6 , 9 , 2 , 5 ], [ 4 , 5 , 3 , 9 , 7 , 8 , 6 ], [ 6 , 9 , 2 , 8 , 7 , 1 , 3 ], [ 2 , 8 , 5 , 6 , 3 ], [ 6 , 1 , 7 , 2 , 8 ], [ 1 , 7 , 9 , 3 , 4 , 5 , 2 ]] #+ [1] * 9 index_table = [ 0x24 , 0x42 , 0x50 , 0x56 , 0x3A , 0x75 , 0x62 , 0x66 , 0x59 , 0x70 , 0x7D , 0x5D , 0x44 , 0x74 , 0x4E , 0x3E , 0x61 , 0x54 , 0x5E , 0x4D , 0x47 , 0x6D , 0x4A , 0x51 , 0x23 , 0x2A , 0x48 , 0x72 , 0x60 , 0x4F , 0x27 , 0x77 , 0x6A , 0x69 , 0x63 , 0x30 , 0x21 , 0x68 , 0x64 , 0x79 , 0x7B , 0x6F , 0x5A , 0x7A , 0x2D , 0x40 , 0x6E , 0x2B , 0x3F , 0x26 , 0x25 , 0x73 , 0x5F , 0x2F , 0x67 , 0x3C , 0x65 , 0x5B , 0x57 , 0x29 , 0x58 , 0x55 , 0x78 , 0x52 , 0x46 , 0x53 , 0x4C , 0x52 , 0x41 , 0x3B , 0x2E , 0x6C , 0x3D , 0x43 , 0x45 , 0x6B , 0x76 , 0x4B , 0x2D , 0x28 , 0x71 ] res = '' f = 0 for fi in s_table: for i in fi: res + = chr (index_table[i - 1 + f * 9 ]) res + = str ( 9 - len (fi)) f + = 1 print ( len (res),res) |
一开始还以为是爆破题,没想到最后是脑洞题,学到了很多,谢谢出题人。
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法
赞赏
看原图