-
-
[原创]第八题 AI核心地带
-
发表于: 2023-9-18 11:07 3453
-
1 2 | 这是一道简单题,文件大小才 8K 。所以ida打开后主流程基本一览无余。在看完ida的数据流程后,基本可以肯定这个程序就是对输入的每个字节进行顺序判断,所以可以对每个字节进行遍历求取以判断当前字节是否正确。 将主函数稍微修改一下,让判断失败时返回 0 ,判断成功时输出ans,需要进行下一位比较时返回 2 。得到如下Check函数。 |
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 | int Check(char * Input ) { char FakeFlag[ 48 ]; strcpy_s(FakeFlag, 48 , "flag{BzcZDnfNIqmQCtkTGlwLyDYeiHIjxSXwkRKzpFPv}" ); _BYTE Data[ 27 ]; strcpy_s((char * )Data, 27 , "Can you crack me?^olo^" ); int StrLength = strlen( Input ); int bFail1 = 0 , bFail2 = 0 , MayFail = 0 ; int v9, v20 = 0 ; int Last = 0 ; int v11; int v26; DWORD Index = 0 ; char v7 = FakeFlag[ 42 ]; bool v8 = StrLength > 0 ; do { if (v8) { int v19 = Input [Index]; if (v19 - (unsigned int ) '0' > 9 ) / / 大于‘ 9 ’失败? { return 0 ; bFail1 = 1 ; MayFail = 1 ; goto LABEL_32; } v9 = (v19 + ( 0xFFFEC610 >> (Index % 0x1F ))) % 0xA ; if ((Index & 1 ) ! = v9 < 1 ) { return 0 ; MayFail = 1 ; } } else { v9 = v20; Last = 1 ; } v11 = v9; v26 = * (_DWORD * )&Data[ 16 ] ^ * (_DWORD * )&Data[ 12 ] ^ * (_DWORD * )&Data[ 8 ] ^ * (_DWORD * )&Data[ 4 ] ^ * (_DWORD * )Data; if (Last || 1 ) { if ((((unsigned __int8)v26 ^ (unsigned __int8)(Data[ 18 ] ^ Data[ 14 ] ^ Data[ 10 ] ^ Data[ 6 ] ^ Data[ 2 ])) & 0x1F ) ! = 0 || ((HIBYTE(v26) ^ BYTE1(v26)) & 0x1F ) ! = 0 ) { / / v11 = - 1 ; / / if (Last) / / return 0 ; } else { printf( "ans: %s" , Input ); getchar(); return 1 ; } / / goto LABEL_26; } if (v9 > = 1 ) { BYTE v12, v13, v14; v12 = BYTE2(v26); if (v9 > = 6 ) { if ((((unsigned __int8)v26 ^ BYTE2(v26)) & 0x1F ) ! = 0 ) { LABEL_25: return 0 ; v11 = 9 ; goto LABEL_26; } v12 = HIBYTE(v26); v13 = 13 - v9; v14 = BYTE1(v26); } else { v13 = 8 - v9; v14 = v26; } if ((((v14 << v13) + 0x80 )& 0xff ) = = ((v12 << v13)& 0xff )) { if (Index = = StrLength - 1 ) return 2 ; goto LABEL_26; } goto LABEL_25; } LABEL_26: v20 = v11; if (Last) { bool v15 = v11 < 0 ; bFail1 = MayFail; if (v15) bFail2 = 1 ; } else { int v16 = * (_DWORD * )&FakeFlag[ 4 * v11 + 5 ]; * (_DWORD * )Data ^ = v16; * (_DWORD * )&Data[ 4 ] ^ = v16; * (_DWORD * )&Data[ 8 ] ^ = v16; * (_DWORD * )&Data[ 12 ] ^ = v16; v8 = v11 < = 8 ; bFail1 = MayFail; * (_DWORD * )&Data[ 16 ] ^ = v16; if (!v8 && (v7 & 0x10000000 ) = = 0 ) { v7 = ~v7 & 0x7F ; FakeFlag[ 42 ] = v7; } } LABEL_32: v8 = ( int ) + + Index < StrLength; } while (( int )Index < = StrLength); if (bFail1 || bFail2) return 0 ; return 2 ; } |
1 | 继续构造主函数对每一字节进行遍历,一开始 Input 字节数没给够,导致遍历不出来,后面看到题目给了 1000 的缓存,修改后才得到答案。主程序如下: |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | int main() { char Input [ 1024 ] = "0" ; memset(& Input [ 0 ], 0 , 1000 ); int Cur = 0 ; while (Cur < 1000 ) { for ( int Index = 0 ; Index < 10 ; Index + + ) { Input [Cur] = 0x30 + Index; int res = Check( Input ); if (res = = 2 ) { Cur + + ; break ; } } } } |
1 2 | 因为题目限制了输入必须是字母 0 - 9 ,所以这个答案基本上是秒出。得到flag为: 582606981190746395118531851185249089744027265368693769576937697816165851808443150195011501950410798490871663488927792799277958360668112074539521851185318514909974002766535869476937695769681626582180144305010501950115040079949037162348792789277927995826067811907483951185218511853490897410272653986937694769376988161658318084433501950105019504207984904716634829277927892779584606681100745395418511852185149009740027365358697769376947696816365821809443050125019501050400790490371673487927 。 ps:注意到 if ( !v8 && (v7 & 0x10000000 ) = = 0 )这一段,有可能出题人的意思是让v11大于 8 时修改FakeFlag[ 42 ]的值,从而限制错误的输入,但是由于可以多次修改FakeFlag[ 42 ],导致该值不可预期,从而可以产生其他预期外的解。 |
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
他的文章
- [原创]第十二题 深入内核 4064
- [原创]第十一题 步步逼近 4524
- [原创]第八题 AI核心地带 3454
- [原创] 第七题 智能联盟计划 3623
- 第六题 至暗时刻 10387
看原图
赞赏
雪币:
留言: