-
-
[原创]KCTF2021 春季赛 第四题 英雄救美 WP
-
2021-5-15 01:23 5564
-
main函数伪代码如下:
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 | int __cdecl main( int argc, const char * * argv, const char * * envp) { int len ; / / 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 solve[ 128 ]; / / [esp + 68h ] [ebp - 270h ] BYREF __int128 v11; / / [esp + 268h ] [ebp - 70h ] BYREF char serial[ 92 ]; / / [esp + 278h ] [ebp - 60h ] BYREF printf( "\t\t\t看雪CTF大赛\r\n" ); printf( "\t\t祝愿看雪CTF大赛越办越好\r\n" ); printf( "Serial: " ); scanf_s( "%s" , serial); len = strlen(serial); / / 先检查序列号是否合法,检测合法则转换成数独的解,然后开始填数独 if ( len < = 64 && serial2solve( len , serial, solve) = = 1 && sudoku(( int )solve, len - 9 ) = = 1 ) { v11 = 0i64 ; memset(v9, 0 , sizeof(v9)); v9[ 5 ] = 0 ; v9[ 4 ] = 0 ; v9[ 0 ] = 0x67452301 ; v9[ 1 ] = 0xEFCDAB89 ; v9[ 2 ] = 0x98BADCFE ; v9[ 3 ] = 0x10325476 ; sub_4014E0(( int )serial, ( int )v9, len ); / / 计算serial的 hash ,解密shellcode sub_4015B0(( int )&v11, ( int )v9); sub_401ED0(v4, (unsigned __int8 * )&v11); v8 = (void ( * )(void))VirtualAlloc( 0 , 0x620u , 0x1000u , 0x40u ); v5 = (char * )v8; v6 = 98 ; do { * (__m128i * )v5 = _mm_loadu_si128((const __m128i * )&v5[&unk_4181A0 - (_UNKNOWN * )v8]); sub_4028B0(( int )solve, v5); v5 + = 16 ; - - v6; } while ( v6 ); v8(); } return 0 ; } |
从sudoku函数内可以提取到数独
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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 / / 懒得解(不会解)数独,直接求助度娘解出来 5 , 4 , 6 , 7 , 1 , 9 , 2 , 3 , 8 9 , 2 , 1 , 8 , 3 , 4 , 6 , 5 , 7 8 , 3 , 7 , 6 , 2 , 5 , 4 , 1 , 9 7 , 1 , 8 , 4 , 6 , 3 , 9 , 2 , 5 4 , 5 , 3 , 2 , 9 , 1 , 7 , 8 , 6 6 , 9 , 2 , 5 , 8 , 7 , 1 , 4 , 3 2 , 8 , 4 , 9 , 5 , 6 , 3 , 7 , 1 3 , 6 , 5 , 1 , 7 , 2 , 8 , 9 , 4 1 , 7 , 9 , 3 , 4 , 8 , 5 , 6 , 2 |
sudoku函数只在数值为0处填充解,所以把0处的解提取出来
[(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)]
再看serial2solve函数
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 | int __usercall serial2solve@<eax>( int len @<edx>, char * serial@<ecx>, int * solve) { int decnum; / / ebx int v4; / / esi unsigned int y; / / edi char chr ; / / al signed int v7; / / ecx int v9; / / ecx char * v10; / / [esp + 0h ] [ebp - 64h ] int v11; / / [esp + 4h ] [ebp - 60h ] __int128 strtable[ 5 ]; / / [esp + Ch] [ebp - 58h ] char v14; / / [esp + 5Ch ] [ebp - 8h ] strtable[ 0 ] = (__int128)_mm_load_si128((const __m128i * )&xmmword_416280); decnum = 0 ; strtable[ 1 ] = (__int128)_mm_load_si128((const __m128i * )&xmmword_4162A0); v4 = 0 ; v11 = len ; v10 = serial; v14 = 113 ; strtable[ 2 ] = (__int128)_mm_load_si128((const __m128i * )&xmmword_416270); strtable[ 3 ] = (__int128)_mm_load_si128((const __m128i * )&xmmword_416290); strtable[ 4 ] = (__int128)_mm_load_si128((const __m128i * )&xmmword_416260); if ( len < = 0 ) return 1 ; y = 0 ; while ( 1 ) { chr = serial[v4]; if ( chr > '0' && chr < = '9' ) break ; v7 = y; / / 可以当成strtable的纵坐标 if ( y > = 81 ) return 0 ; while ( chr ! = * ((_BYTE * )strtable + v7) ) { if ( (unsigned int ) + + v7 > = 81 ) return 0 ; } v9 = v7 % 9 + 1 ; / / 将strtable的横坐标 + 1 ,写到数独的解 if ( v9 = = - 1 ) return 0 ; * solve = v9; serial = v10; + + decnum; + + solve; len = v11; LABEL_13: if ( + + v4 > = len ) return 1 ; } if ( decnum + chr = = '9' ) / / 猜测serial每填满一行数独后就跟一位数字表示没填到的数独的个数 { decnum = 0 ; y + = 9 ; goto LABEL_13; } return - 1 ; } |
清楚序列号转数独解的过程后,撸一份python解出flag即可
1 2 3 4 5 6 7 8 9 | resultarr = [( 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 )] table = """$BPV:ubfYp}]DtN>aT^MGmJQ#*Hr`O'wjic0!hdy{oZz-@n+?&%s_/g<e[W)XUxRFSLRA;.l=CEkvK-(q""" flag = '' for i in range ( len (resultarr)): for j in range ( len (resultarr[i])): flag + = table[ 9 * i + resultarr[i][j] - 1 ] if len (resultarr[i]) - 1 = = j: flag + = chr ( 0x39 - j - 1 ) print (flag) |
运行得到flag(下面整行都是)
:u$YBPf2pa]Dt4#QM^H4ic'j0`w2y{d-Zzo2%/n_s@+2<UW)e4AR;F.4=-qEkvC2
吐槽:目前的flag都不是KCTF{}格式
[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。
赞赏
他的文章
看原图