-
-
[原创]第八题 AI核心地带
-
发表于: 2023-9-18 11:07 3868
-
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],导致该值不可预期,从而可以产生其他预期外的解。 |
[培训]传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!
赞赏
他的文章
- [原创]第十二题 深入内核 4536
- [原创]第十一题 步步逼近 4990
- [原创]第八题 AI核心地带 3869
- [原创] 第七题 智能联盟计划 4051
- 第六题 至暗时刻 14418
赞赏
雪币:
留言: