-
-
[原创]看雪CTF.TSRC 2018 团队赛 第六题 追凶者也 解题过程
-
2018-12-11 14:04 1428
-
1.下断点GetDlgItemTextA ,随手输入注册码,点确定断下:






发现有一处hook,跟进401a10 发现这个是验证函数。

主要函数就红圈中两个。
Check函数:


调试了几次发现是个拼图游戏

这个比win7自带的还简单点,是个3*3的:
初始状态:
4 1 3
7 2 5
8 6 0
0是空块,最终要还原成:
1 2 3
4 5 6
7 8 0
char __cdecl move_401380(int a1, int a2) { char result; // al signed int i; // [esp+8h] [ebp-8h] signed int v4; // [esp+Ch] [ebp-4h] if ( !a2 ) return 0; v4 = 0; LABEL_4: if ( v4 >= 3 ) return 0; for ( i = 0; ; ++i ) { if ( i >= 3 ) { ++v4; goto LABEL_4; } if ( byte_4147D0[3 * v4 + i] == a2 ) break; LABEL_6: ; } switch ( a1 ) { case 0: if ( v4 ) { if ( byte_4147D0[3 * (v4 - 1) + i] ) { result = 0; } else { byte_4147D0[3 * (v4 - 1) + i] = byte_4147D0[3 * v4 + i]; byte_4147D0[3 * v4 + i] = 0; result = 1; } } else { result = 0; } break; case 1: if ( i == 2 ) { result = 0; } else if ( byte_4147D1[3 * v4 + i] ) { result = 0; } else { byte_4147D1[3 * v4 + i] = byte_4147D0[3 * v4 + i]; byte_4147D0[3 * v4 + i] = 0; result = 1; } break; case 2: if ( v4 == 2 ) { result = 0; } else if ( byte_4147D0[3 * (v4 + 1) + i] ) { result = 0; } else { byte_4147D0[3 * (v4 + 1) + i] = byte_4147D0[3 * v4 + i]; byte_4147D0[3 * v4 + i] = 0; result = 1; } break; case 3: if ( i ) { if ( byte_4147CF[3 * v4 + i] ) { result = 0; } else { byte_4147CF[3 * v4 + i] = byte_4147D0[3 * v4 + i]; byte_4147D0[3 * v4 + i] = 0; result = 1; } } else { result = 0; } break; default: goto LABEL_6; } return result; }
move 函数有两个参数:
参数1:操作,主要是wdsa(上下左右)
参数2:本次要操作的数字
3*3 拼图比较难还原的是 3,4,7 这几个,而这个拼图,3在原位,4,7,下移一步就到了:
拼图游戏 0 为空块 操作方法 :[操作(上下左右(wsad))][操作的数字对应的块] 起始: 4 1 3 7 2 5 8 6 0 操作 d 6 -->数字6 对应的块右移 4 1 3 7 2 5 8 0 6 操作 d 8 -->数字8 对应的块右移 4 1 3 7 2 5 0 8 6 操作 s 7 -->数字7 对应的块下移 4 1 3 0 2 5 7 8 6 操作 s 4 -->数字4 对应的块下移 0 1 3 4 2 5 7 8 6 操作 a 1 -->数字1 对应的块左移 1 0 3 4 2 5 7 8 6 操作 w 2 -->数字2 对应的块上移 1 2 3 4 0 5 7 8 6 操作 a 5 -->数字5 对应的块左移 1 2 3 4 5 0 7 8 6 操作 w 6 -->数字6 对应的块上移 1 2 3 4 5 6 7 8 0
将以上步骤组合起来为:d6d8s7s4a1w2a5w6 验证成功。

拼图游戏,每一步都有两个数字可以移动,作者加了一个验证函数:
int __stdcall hash_4017B0(int a1, int a2) { int i; // [esp+0h] [ebp-8h] int v4; // [esp+4h] [ebp-4h] v4 = a2; for ( i = 0; i < a2; ++i ) v4 = *(char *)(i + a1) ^ (v4 >> 28) ^ 16 * v4; return v4; }
这个是为了防治多解的吧。
赞赏
他的文章