-
-
[原创]KCTF2020秋季赛 第七题 鱼目混珠
-
2020-12-5 00:36 5019
-
程序有很多花指令,不过都有特征,写个OD脚本去掉就行。
去掉以后dump下来丢给IDA F5,配合下动态调试分析
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 | int __cdecl main( int argc, const char * * argv, const char * * envp) { char * v3; / / edx int v4; / / ecx unsigned int v5; / / eax char * v6; / / edx int v7; / / ecx unsigned int v8; / / eax char * v9; / / kr00_4 int v10; / / esi int v11; / / ecx int v12; / / edi int v13; / / ebx int v14; / / esi int v16; / / edx unsigned int v17; / / eax int v18; / / edx unsigned int v19; / / eax int v20; / / edx unsigned int v21; / / eax unsigned int v22; / / eax int v23; / / [esp + 1Ch ] [ebp - A0h] unsigned int v24; / / [esp + 20h ] [ebp - 9Ch ] int v25; / / [esp + 24h ] [ebp - 98h ] int v26; / / [esp + 28h ] [ebp - 94h ] char v27; / / [esp + 2Ch ] [ebp - 90h ] _DWORD antidebug[ 9 ]; / / [esp + 3Ch ] [ebp - 80h ] int ( * v29)(void); / / [esp + 60h ] [ebp - 5Ch ] int ( * v30)(void); / / [esp + 64h ] [ebp - 58h ] _DWORD v31[ 2 ]; / / [esp + 68h ] [ebp - 54h ] BYREF char v32[ 76 ]; / / [esp + 70h ] [ebp - 4Ch ] BYREF sub_40CA20(); antidebug[ 0 ] = sub_401700; / / 一大堆反调试 antidebug[ 1 ] = sub_401740; antidebug[ 2 ] = sub_4017B0; antidebug[ 3 ] = sub_401890; antidebug[ 4 ] = sub_4018F0; antidebug[ 5 ] = sub_401570; dword_4C5028 = 0 ; antidebug[ 6 ] = sub_401820; antidebug[ 7 ] = sub_401950; antidebug[ 8 ] = sub_401AB0; v29 = sub_402F20; v30 = sub_402F90; dword_4C5024 = 0 ; v31[ 0 ] = sub_401620; v3 = a104010010e4b4c; do { v4 = * (_DWORD * )v3; v3 + = 4 ; v5 = ~v4 & (v4 - 16843009 ) & 0x80808080 ; } while ( !v5 ); if ( (~v4 & (v4 - 16843009 ) & 0x8080 ) = = 0 ) v5 >> = 16 ; if ( (~v4 & (v4 - 16843009 ) & 0x8080 ) = = 0 ) v3 + = 2 ; hexdecode(( int * )&result, ( int )a104010010e4b4c, ( int )&v3[ - __CFADD__((_BYTE)v5, (_BYTE)v5) - 0x4B9083 ]); / / 解码两个大数 每字节的高位和低位互换 v6 = a1e9705f8d92146; do { v7 = * (_DWORD * )v6; v6 + = 4 ; v8 = ~v7 & (v7 - 16843009 ) & 0x80808080 ; } while ( !v8 ); if ( (~v7 & (v7 - 16843009 ) & 0x8080 ) = = 0 ) v8 >> = 16 ; if ( (~v7 & (v7 - 16843009 ) & 0x8080 ) = = 0 ) v6 + = 2 ; hexdecode(( int * )&big_c2, ( int )a1e9705f8d92146, ( int )&v6[ - __CFADD__((_BYTE)v8, (_BYTE)v8) - 4952147 ]); v23 = * (_DWORD * )&result.buf[ 8 ]; v24 = * (_DWORD * )&result.buf[ 4 ]; print ( * (_DWORD * )&result.buf[ 12 ]); memset(v32, 0 , 0x40u ); scan(( int )&dword_4BA660, v32); v9 = &v32[strlen(v32)]; if ( (unsigned int )(v9 - v32 - 13 ) > 0x32 ) goto LABEL_22; v10 = sub_4030E0(v32, 7 ); v12 = sub_4030E0((_BYTE * )v31 + v9 - v32 + 1 , 7 ); v13 = 0 ; v26 = 0 ; v25 = 0 ; do { v27 = 15 - v13; if ( (v13 & 1 ) = = (( int (__fastcall * )( int ))antidebug[v13])(v11) ) / / 执行反调试 { + + v25; v10 = v29() ^ __ROR4__(v10, v13); / / 两个crc防patch v12 = v30() ^ __ROR4__(v12, v27); } else { + + v26; v10 = v30() ^ __ROR4__(v10, v27); v12 = (( int (__fastcall * )( int ))v29)(v13) ^ __ROR4__(v12, v13); } + + v13; } while ( v13 ! = 9 ); if ( !v25 ) goto LABEL_22; if ( !v26 ) goto LABEL_22; v14 = dword_4B904C ^ v10; if ( v14 ! = v23 || (v12 ^ dword_4B9048) ! = v24 || hexdecode(( int * )& input , ( int )v32, strlen(v32)) < 0 ) / / 比较crc是否与预设值一样 动态调试时patch掉 goto LABEL_22; big_r.buf[ 4 ] = 0 ; * (_DWORD * )big_r.buf = * (_DWORD * )result.buf; v16 = 4 ; while ( 1 ) { v17 = v16 - 1 ; if ( big_r.buf[v16 - 1 ] ) break ; - - v16; if ( !v17 ) goto LABEL_29; } v17 = v16; LABEL_29: big_r. len = v17; big_mul(&big_n, & input , &big_r); input .buf[ 4 ] = 0 ; * (_DWORD * ) input .buf = 0xE053D0F ; v18 = 4 ; while ( 1 ) { v19 = v18 - 1 ; if ( input .buf[v18 - 1 ] ) break ; - - v18; if ( !v19 ) goto LABEL_32; } v19 = v18; input . len = v19; big_div(&big_n, &big_n, & input ); / / * 0xE053D0F big_add(&big_n, &big_n, &result); big_add(&big_n, &big_n, &big_c2); / / + 0xfea1bd9e6964129d8f5079e1 big_mul(&big_c, &result, &big_c2); big_sub(&big_r, &big_n, &big_c); / / - 0x3f58d70f55459ad75491a4c3ea858c4961226c27f5a1f8a95b18fde1 if ( ( int )big_r. len > 16 ) goto LABEL_22; LABEL_32: big_mul(&big_n, &big_n, & input ); / / * 0xE053D0F input .buf[ 4 ] = 0 ; * (_DWORD * ) input .buf = 37 ; v20 = 4 ; while ( 1 ) { v21 = v20 - 1 ; if ( input .buf[v20 - 1 ] ) break ; - - v20; if ( !v21 ) goto LABEL_36; } v21 = v20; LABEL_36: input . len = v21; big_mul(&big_c, &big_n, & input ); / / * 37 big_add(&big_c, &big_c, &big_c); / / 此处溢出,最高位为 1 ,刚好覆盖了result的长度 v22 = big_r. len ; if ( big_r. len = = result. len ) { while ( ( - - v22 & 0x80000000 ) = = 0 ) { if ( big_r.buf[v22] ! = result.buf[v22] ) / / 表面上跟 0x3faffa2b01b6ba9744c4b4e010010401 比较 实际上是 1 goto LABEL_22; } print (v14); / / GOOD } else { LABEL_22: print (v24); / / ERROR } return 0 ; } |
逻辑很清晰,除了最后那个溢出覆盖len比较坑了点
解开方程,再把结果按hexdecode的方法转回字符串就可以了
1 2 | x * 0x10010401 / 0xE053D0F + 0x3faffa2b01b6ba9744c4b4e010010401 + 0xfea1bd9e6964129d8f5079e1 - 0x3f58d70f55459ad75491a4c3ea858c4961226c27f5a1f8a95b18fde1 = = 1 x = 0x377EF3DC43F112E46ACF040E9077C8D23C530FB3654C9B33803F7C01 |
按hexdecode的方法转回字符串得到flag
10C7F30833B9C4563BF035C32D8C7709E040FCA64E211F34CD3FE773
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
他的文章
看原图