-
-
[原创]KCTF2021 第二题 write up
-
2021-5-12 01:05 4811
-
环境配置
系统 : win10 64bit \ Windows xp
程序 : pzcrackme.exe
要求 : 求flag
使用工具 :ida pro \ ollydbg \ 微步云沙箱
开始分析
这题有不少迷惑人的手段,所以需要尽可能把程序流程分析清楚,ida中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 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 | int __cdecl main( int argc, const char * * argv, const char * * envp) { char Tmp_ch_in_input; / / al int index_of_str; / / esi int INDEX_01234567; / / ecx int v7; / / edx int sum_index; / / eax unsigned int column; / / ecx int choice; / / eax signed int SIGNAL; / / edx int T2; / / eax char * a_pointer_of_matrix; / / eax char * MATRIX; / / eax int A_VALUE_SHOULD_BE_ZERO; / / edx char * v16; / / ecx int T1; / / eax int T4; / / eax int T3; / / eax int v20; / / [esp + 1Ch ] [ebp - 60h ] unsigned int row; / / [esp + 20h ] [ebp - 5Ch ] unsigned int v22; / / [esp + 24h ] [ebp - 58h ] char _0x30; / / [esp + 2Bh ] [ebp - 51h ] int NUM_0x24; / / [esp + 2Ch ] [ebp - 50h ] char STR [ 76 ]; / / [esp + 30h ] [ebp - 4Ch ] sub_40AD70(); sub_4AF840(&dword_4B8860, "Input your code: " ); sub_4B0AB0(&dword_4B8680, STR ); if ( strlen( STR ) < = 0x30 ) / / len ( str ) < = 0x30 { Tmp_ch_in_input = STR [ 0 ]; if ( STR [ 0 ] ) / / str [ 0 ] ! = null { index_of_str = 0 ; row = 0 ; v22 = 0 ; NUM_0x24 = dword_4B7020; / / 24 00 00 00 _0x30 = a0123456789abcd[ 0 ]; / / .data: 004B7040 30 31 32 33 34 35 + a0123456789abcd db '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' , 0 While_start: if ( NUM_0x24 > 0 ) { INDEX_01234567 = 0 ; if ( _0x30 = = Tmp_ch_in_input ) / / assert str [ 0 ] = = 0x30 { other_start: v7 = (index_of_str + INDEX_01234567 / 6 ) % 6 ; sum_index = INDEX_01234567 + index_of_str; column = v22; v20 = v7; choice = 5 - sum_index % 6 ; / / 5 - (sum_index % 6 ) SIGNAL = 0 ; while ( 1 ) { switch ( choice ) { case 1 : + + column; / / + + column break ; case 2 : T1 = (row + + & 1 ) = = 0 ; / / row + + column + = T1; / / column + = (row % 2 ? 0 : 1 ) break ; case 3 : T2 = (row + + & 1 ) ! = 0 ; / / row + + column - = T2; / / column - = (row % 2 ? 1 : 0 ) break ; case 4 : - - column; / / - - column break ; case 5 : T3 = (row - - & 1 ) ! = 0 ; / / row - - column - = T3; / / column - = (row % 2 ? 1 : 0 ) break ; default: T4 = (row - - & 1 ) = = 0 ; / / row - - column + = T4; / / column + = (row % 2 ? 0 : 1 ) break ; } if ( column > 9 ) / / ten columns break ; / / try again if ( row > 8 ) / / 9 rows break ; / / try again a_pointer_of_matrix = &matrix[ 10 * row + column]; if ( * a_pointer_of_matrix ) break ; / / try again * a_pointer_of_matrix = 1 ; if ( SIGNAL = = 1 ) / / skip this at frist time { + + index_of_str; v22 = column; Tmp_ch_in_input = STR [index_of_str]; if ( Tmp_ch_in_input ) goto While_start; / / back to start goto check; } SIGNAL = 1 ; choice = v20; } } else / / _0x30 ! = Tmp_ch_in_input { while ( NUM_0x24 ! = + + INDEX_01234567 ) { if ( a0123456789abcd[INDEX_01234567] = = Tmp_ch_in_input ) / / .data: 004B7040 30 31 32 33 34 35 + a0123456789abcd db '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' , 0 goto other_start; } } } } else { check: MATRIX = matrix; A_VALUE_SHOULD_BE_ZERO = 0 ; do / / check matrix { v16 = MATRIX + 10 ; do A_VALUE_SHOULD_BE_ZERO + = * MATRIX + + < 1u ; / / all element in matrix have not to set as zero while ( v16 ! = MATRIX ); } while ( &unk_4B70DA ! = v16 ); if ( !A_VALUE_SHOULD_BE_ZERO ) { printf_4ABF30(&dword_4B8860, "Good job!" , 9 ); afterprintf_4AD980(&dword_4B8860); return 0 ; } } } printf_4ABF30(&dword_4B8860, "Try again..." , 12 ); afterprintf_4AD980(&dword_4B8860); return 0 ; } |
将程序上传到云沙箱里看下,发现有tls_callback存在,可能是有反调试机制;不过先将程序运行起在等候输入的时候od附加就可以正常调试。
程序需要将一个matrix填满:
1 2 3 4 5 6 7 8 9 | 53 01 01 00 00 01 00 00 01 01 01 01 01 00 01 00 00 01 00 00 01 01 01 00 01 01 01 01 01 00 00 01 01 00 01 00 00 01 00 00 00 00 01 00 00 01 00 00 01 01 01 01 00 01 01 01 00 01 00 01 00 00 01 01 01 01 00 01 00 01 00 01 01 00 00 01 00 01 00 01 00 00 00 01 00 00 01 01 00 00 |
可以看到使用switch语句选择方向:
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 | while ( 1 ) { switch ( choice ) { case 1 : + + column; / / + + column break ; case 2 : T1 = (row + + & 1 ) = = 0 ; / / row + + column + = T1; / / column + = (row % 2 ? 0 : 1 ) break ; case 3 : T2 = (row + + & 1 ) ! = 0 ; / / row + + column - = T2; / / column - = (row % 2 ? 1 : 0 ) break ; case 4 : - - column; / / - - column break ; case 5 : T3 = (row - - & 1 ) ! = 0 ; / / row - - column - = T3; / / column - = (row % 2 ? 1 : 0 ) break ; default: T4 = (row - - & 1 ) = = 0 ; / / row - - column + = T4; / / column + = (row % 2 ? 0 : 1 ) break ; } |
手动填写一下:
1 2 3 4 5 6 7 8 9 | 53 FF 01 1F 20 01 23 24 01 01 01 01 02 1E 01 21 22 01 25 26 04 03 01 1D 01 01 01 01 01 27 05 01 01 1C 01 19 18 01 29 28 06 07 01 1B 1A 01 17 16 01 01 01 01 08 01 01 01 15 01 2B 01 0A 09 01 01 01 01 14 01 2C 01 0B 01 01 0F 10 01 13 01 2D 01 0C 0D 0E 01 11 12 01 01 2E 2F |
接下来构造相应的输入了,这里要注意的一个坑点是一个输入控制两次行动而非一次:
1 2 3 4 5 6 7 8 9 10 11 | if ( SIGNAL = = 1 ) / / skip this at frist time { + + index_of_str; v22 = column; Tmp_ch_in_input = STR [index_of_str]; if ( Tmp_ch_in_input ) goto While_start; / / back to start goto check; } SIGNAL = 1 ; / / jump to beginning of switch |
解
做py如下:
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 | matrix = [ 0x53 , 0xFF , 0x01 , 0x1E , 0x1F , 0x01 , 0x22 , 0x23 , 0x01 , 0x01 , 0x01 , 0x01 , 0x02 , 0x1D , 0x01 , 0x20 , 0x21 , 0x01 , 0x24 , 0x25 , 0x04 , 0x03 , 0x01 , 0x1C , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x26 , 0x05 , 0x01 , 0x01 , 0x1B , 0x01 , 0x18 , 0x17 , 0x01 , 0x28 , 0x27 , 0x06 , 0x07 , 0x01 , 0x1A , 0x19 , 0x01 , 0x16 , 0x29 , 0x01 , 0x01 , 0x01 , 0x01 , 0x08 , 0x01 , 0x01 , 0x01 , 0x15 , 0x01 , 0x2A , 0x01 , 0x0A , 0x09 , 0x01 , 0x01 , 0x01 , 0x01 , 0x14 , 0x01 , 0x2B , 0x01 , 0x0B , 0x01 , 0x01 , 0x0F , 0x10 , 0x01 , 0x13 , 0x01 , 0x2C , 0x01 , 0x0C , 0x0D , 0x0E , 0x01 , 0x11 , 0x12 , 0x01 , 0x01 , 0x2D , 0x2E ] ''' switch ( choice ) { case 1: ++column; // ++column break; case 2: T1 = (row++ & 1) == 0; // row++ column += T1; // >>> print((0&1)==0) break; case 3: T2 = (row++ & 1) != 0; // row++ column -= T2; // >>> print((0&1)!=0) break; case 4: --column; // --column break; case 5: T3 = (row-- & 1) != 0; // row-- column -= T3; // >>> print((0&1)!=0) break; default: T4 = (row-- & 1) == 0; // row-- column += T4; // >>> print((0&1)==0) break; } ''' def find_choice(Row,Column,Nrow,Ncolumn): choice = 0 for choice in range ( 0 , 6 ): row = Row column = Column if choice = = 0 : T4 = (row & 1 ) = = 0 column + = T4 row - = 1 if choice = = 1 : column + = 1 if choice = = 2 : T1 = (row & 1 ) = = 0 column + = T1 row + = 1 if choice = = 3 : T2 = (row & 1 ) ! = 0 ; column - = T2 row + = 1 if choice = = 4 : column - = 1 if choice = = 5 : T3 = (row & 1 ) ! = 0 column - = T3 row - = 1 if matrix[row * 10 + column] = = matrix[Nrow * 10 + Ncolumn]: return choice print ( 'error' ) exit( 0 ) def find_next(row,column): if matrix[row * 10 + column] = = 0x53 : return 0 , 1 if matrix[row * 10 + column] = = 0xFF : return 1 , 2 data = matrix[row * 10 + column] + 1 pos = matrix.index(data) return ( int (pos / 10 ),pos % 10 ) row = 0 column = 0 choices = [] while 1 : #print(row,column,end=",") #print('------->[%d]' % matrix[row*10+column]) if matrix[row * 10 + column] = = 0x2E : #print('Done') break Nrow,Ncolumn = find_next(row,column) choice = find_choice(row,column,Nrow,Ncolumn) #print(choice) choices.append(choice) row,column = Nrow,Ncolumn a123 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" first_time = True flag = "" ''' for index_0123 in range(0x24): if ( 5 - ((index_0123) % 6) == choices[0] ) and ( choices[1] == int(index_0123 / 6) % 6 ): flag += a123[index_0123] for index_0123 in range(0x24): if ( 5 - ((index_0123+1) % 6) == choices[2] ) and ( choices[3] == int(1+ index_0123 / 6) % 6 ): flag += a123[index_0123] for index_0123 in range(0x24): if ( 5 - ((index_0123+2) % 6) == choices[4] ) and ( choices[5] == int(2+ index_0123 / 6) % 6 ): flag += a123[index_0123] ''' for index in range ( 0 , len (choices), 2 ): Got = False for index_0123 in range ( 0x24 ): if Got = = False : if ( 5 - ((index_0123 + index / 2 ) % 6 ) = = choices[index] ) and ( choices[index + 1 ] = = int (index / 2 + index_0123 / 6 ) % 6 ): Got = True flag + = a123[index_0123] assert flag = = "GJ0V4LA4VKEVQZSVCNGJ00N" |
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法
赞赏
他的文章
[原创][安全运维向]模拟搭建小型企业内网
13139
看原图