-
-
[原创]第六题 追凶者也_pw
-
2018-12-12 00:05 2262
-
运行效果。
IDA加载
快速定位错误位置。
int __cdecl W_CHECKsub_401040(HWND hDlg) { void *v1; // ST08_4 signed int i; // [esp+Ch] [ebp-24h] signed int v4; // [esp+10h] [ebp-20h] CHAR String; // [esp+18h] [ebp-18h] int v6; // [esp+19h] [ebp-17h] int v7; // [esp+1Dh] [ebp-13h] int v8; // [esp+21h] [ebp-Fh] int v9; // [esp+25h] [ebp-Bh] __int16 v10; // [esp+29h] [ebp-7h] char v11; // [esp+2Bh] [ebp-5h] strcpy(aTryAgain_0, "try again!"); strcpy(aFail_0, "fail"); String = 0; v6 = 0; v7 = 0; v8 = 0; v9 = 0; v10 = 0; v11 = 0; GetDlgItemTextA(hDlg, 1001, &String, 20); v4 = 0; for ( i = 0; i < 20; ++i ) v4 += *(&String + i); if ( v4 > 0 && v4 < 4132 ) { v1 = malloc(v4); sub_401020(); j___free_base(v1); } return MessageBoxA(0, aTryAgain_0, aFail_0, 0); }
无奈之际发现存在另外的线程。
void __stdcall StartAddress(LPVOID lpThreadParameter) { while ( 1 ) { EnterCriticalSection(&CriticalSection); if ( dword_4147FC == 1 ) { sub_401C10(); dword_4147FC = 0; } LeaveCriticalSection(&CriticalSection); } }
是不是很熟悉,修改内存,跳转到指定位置401A10。
int __cdecl sub_401C10() { void *v0; // edx signed int j; // [esp+0h] [ebp-Ch] signed int i; // [esp+8h] [ebp-4h] sub_4018D0(0xCCCCCCCC, 0xCCCCCCCC, 0xCCCCCCCC); lpAddress = v0; // // getdlgitemtexta // sub_4019B0(v0); // protect for ( i = 0; i < 5; ++i ) byte_4147DC[i] = *((_BYTE *)lpAddress + i + 32); *(_DWORD *)&byte_414028[1] = (char *)W_chek___sub_401A10 - (char *)((_BYTE *)lpAddress + 32) - 5; for ( j = 0; j < 5; ++j ) *((_BYTE *)lpAddress + j + 32) = byte_414028[j]; return sub_4019E0(lpAddress); }
进入跳转的函数,发现别有洞天。4147F0 开始计算是否正确。计算成功后对对话框的提示字符串进行异或计算,生成正确的字符串。
Int __usercall W_chek___sub_401A10@<eax>(int a1@<ecx>, int a2@<ebp>, int a3@<esi>) { unsigned int v3; // et0 int v4; // eax _BYTE *v5; // ecx unsigned int v7; // [esp-24h] [ebp-24h] int v8; // [esp-18h] [ebp-18h] v8 = a1; v3 = __readeflags(); v7 = v3; dword_414800 = a3; len_20_dword_4147EC = *(_DWORD *)(a2 + 20); pIn_dword_4147F0 = malloc(len_20_dword_4147EC); dword_4147F4 = a2 + 16; memmove(pIn_dword_4147F0, *(const void **)(a2 + 16), len_20_dword_4147EC); *(_DWORD *)(a2 - 0x10) = pIn_dword_4147F0; *(_DWORD *)(a2 - 0x14) = *(_DWORD *)(a2 - 0x10) + 1; do *(_BYTE *)(a2 - 0x15) = *(_BYTE *)(*(_DWORD *)(a2 - 0x10))++; while ( *(_BYTE *)(a2 - 0x15) ); *(_DWORD *)(a2 - 28) = *(_DWORD *)(a2 - 16) - *(_DWORD *)(a2 - 20);// 求长度 if ( sub_401290((int)pIn_dword_4147F0, *(_DWORD *)(a2 - 28)) )// 检测开始 { v4 = sub_401870(pIn_dword_4147F0); if ( sub_4017B0((int)pIn_dword_4147F0, v4) == 0x5634D252 ) { v5 = off_414030; *(_WORD *)off_414030 = 0; v5[2] = 0; for ( *(_WORD *)(a2 - 4) = 0; *(signed __int16 *)(a2 - 4) < 8; ++*(_WORD *)(a2 - 4) ) *((char *)off_414030 - *(signed __int16 *)(a2 - 4)) = (0x27 - *(unsigned __int16 *)(a2 - 4)) ^ byte_41401C[7 - *(signed __int16 *)(a2 - 4)]; *(_WORD *)off_414034 = 0; for ( *(_WORD *)(a2 - 8) = 0; *(signed __int16 *)(a2 - 8) < 3; ++*(_WORD *)(a2 - 8) ) *((char *)off_414034 - *(signed __int16 *)(a2 - 8)) = (34 - *(unsigned __int16 *)(a2 - 8)) ^ byte_414024[2 - *(signed __int16 *)(a2 - 8)]; } } j___free_base(pIn_dword_4147F0); dword_4147F8 = (int (__thiscall *)(_DWORD))((char *)lpAddress + 32); sub_4019B0(lpAddress); for ( *(_DWORD *)(a2 - 12) = 0; *(_DWORD *)(a2 - 12) < 5; ++*(_DWORD *)(a2 - 12) ) *((_BYTE *)lpAddress + *(_DWORD *)(a2 - 12) + 32) = byte_4147DC[*(_DWORD *)(a2 - 12)]; sub_4019E0(lpAddress); dword_4147FC = 1; __writeeflags(v7); return dword_4147F8(v8); }
输入参数为字符串指针和长度。下列函数中初始化9字节的内存(3*3)
Bool __cdecl sub_401290(int a1, int a2) { byte_4147D0[0] = 4; byte_4147D0[1] = 1; byte_4147D0[2] = 3; byte_4147D0[3] = 7; byte_4147D0[4] = 2; byte_4147D0[5] = 5; byte_4147D0[6] = 8; byte_4147D0[7] = 6; byte_4147D0[8] = 0; return sub_4015B0(a1, a2); }
检查输入个数是否为偶数,按照2个字节一组对4147D0进行操作。操作函数401380。
输入: 413725860
输出: 123456780
Bool __cdecl sub_4015B0(int a1, int a2) { int I; // [esp+0h] [ebp-Ch] int v4; // [esp+8h] [ebp-4h] v4 = 0xCCCCCCCC; if ( a2 % 2 ) return 0; for ( I = 0; I < a2; I += 2 ) { if ( *(_BYTE *)(I + a1) == ‘w’ ) v4 = 0; if ( *(_BYTE *)(I + a1) == ‘d’ ) v4 = 1; if ( *(_BYTE *)(I + a1) == ‘s’ ) v4 = 2; if ( *(_BYTE *)(I + a1) == ‘a’ ) v4 = 3; if ( !sub_401380(v4, *(char *)(I + a1 + 1) – ‘0’) ) return 0; } return byte_4147D0[0] == 1 && byte_4147D0[1] == 2 && byte_4147D0[2] == 3 && byte_4147D0[3] == 4 && byte_4147D0[4] == 5 && byte_4147D0[5] == 6 && byte_4147D0[6] == 7 && byte_4147D0[7] == 8 && !byte_4147D0[8]; }
进一步分析401380. A1 取值 wdsa. A2取值1234567890. A1想不想打游戏的前后左右操作。A2的值在4147D0中计算索引位置。该位置分解为横纵俩个坐标(3*3)。分析法发现 w 将当前 位置值向上移动, s 是向下移动,d向右移动, a向左移动。
Char __cdecl sub_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; }
结果就是完成七巧板控制。0可以与周围任意交换。
4 | 1 | 3 |
7 | 2 | 5 |
8 | 6 | 0 |
1 | 2 | 3 |
4 | 5 | 6 |
7 | 8 | 0 |
所以结论是:d6d8s7s4a1w2a5w6
七巧板应该还有其他的解,程序中已经限定20个字符,10个操作。这可能也就是唯一解了。当然应该也可以爆破。
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法
最后于 2018-12-12 00:06
被scpczc编辑
,原因:
赞赏
他的文章
[原创]2019CTFQ2T6
2075
[原创]CTF2019Q2T1 破文
1705
看原图