查壳
分析
-
看图标就猜得出是MFC框架的,不过这次的MFC和之前遇到的不一样。主要是在载入主窗口的方式不一样,导致分析的难度也就不一样。
-
通过字符串索引,来到载入主窗口那个地方
-
这是以非模态的方式载入对话框。不管是模态还是非模态,这样的方式都表示着所有的消息处理函数均在类中。而MFC是个大类,所以得需要一些线索才能够找到大海里的那根针。
-
这个线索正是注册码错误时弹出的信息框,并且在IDA最左侧一栏就有这个函数。通过对其进行交叉引用,我们找到两处位置,并且结构都是相似的。就看其中的一处吧:
text:004016E0 ; int __thiscall sub_4016E0(CWnd *this) .text:004016E0 sub_4016E0 proc near ; CODE XREF: sub_4015F1+26↑p .text:004016E0 .text:004016E0 var_24 = byte ptr -24h .text:004016E0 .text:004016E0 sub esp, 24h .text:004016E3 lea eax, [esp+24h+var_24] .text:004016E7 push ebx .text:004016E8 push esi .text:004016E9 mov ebx, ecx .text:004016EB push edi .text:004016EC mov ecx, 8 .text:004016F1 mov esi, offset dword_40326C .text:004016F6 lea edi, [esp+30h+var_24] .text:004016FA push eax .text:004016FB rep movsd .text:004016FD push 14h .text:004016FF movsw .text:00401701 call sub_4016A0 .text:00401706 add esp, 8 .text:00401709 lea ecx, [esp+30h+var_24] .text:0040170D push 0 ; unsigned int .text:0040170F push 0 ; char * .text:00401711 push ecx ; char * .text:00401712 mov ecx, ebx ; this .text:00401714 call ?MessageBoxA@CWnd@@QAEHPBD0I@Z ; CWnd::MessageBoxA(char const *,char const *,uint) .text:00401719 pop edi .text:0040171A pop esi .text:0040171B pop ebx .text:0040171C add esp, 24h .text:0040171F retn .text:0040171F sub_4016E0 endp
-
动态调试可知,call sub_4016A0 是对提示信息进行解码。再次对sub_4016E0这个函数进行交叉引用,来到真正检测输入的地方:
text:004015F1 sub_4015F1 proc near .text:004015F1 .text:004015F1 arg_0 = dword ptr 4 .text:004015F1 .text:004015F1 lea eax, [esi+294h] .text:004015F7 cmp dword ptr [ecx-8], 21h ; 输入的长度等于33 .text:004015FB jnz short loc_40161F .text:004015FD push ecx .text:004015FE mov ecx, esp ; this .text:00401600 mov [esp+4+arg_0], esp .text:00401604 push eax ; struct CString * .text:00401605 call ??0CString@@QAE@ABV0@@Z ; CString::CString(CString const &) .text:0040160A mov ecx, esi .text:0040160C call sub_401630 .text:00401611 test al, al .text:00401613 jz short loc_40161F .text:00401615 mov ecx, esi ; this .text:00401617 call sub_4016E0 .text:0040161C pop esi .text:0040161D pop ecx .text:0040161E retn.
-
动态 调试可知这个检测的过程。首先是检查长度是否等于33,然后进入sub_401630这个函数中进一步转换。
char __thiscall sub_401630(_BYTE *this, int a2) { int v2; // edi _BYTE *v3; // ebp int v4; // edx signed int v5; // esi char v7; // [esp+13h] [ebp-1h] v2 = 0; v3 = this; v7 = 1; v4 = 10; v5 = 0; do { srand(v4); v4 = rand() % 10; if ( *(_BYTE *)(v2 + a2) != v3[v5 + 96 + v4] ) v7 = 0; v5 += 10; ++v2; } while ( v5 < 330 ); CString::~CString((CString *)&a2); return v7; }
-
这个函数也不复杂,就是检测输入的数据要与v3中对应位置相等。将v3的数据dump出来。
脚本
#include<iostream>
#include<stdlib.h>
#include<string.h>
using namespace std;
int main(){
char data[]={
0x68,0x24,0x40,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x58,0x40,0x51,0x0,
0xa8,0xa,0x46,0x0,0x0,0x0,0x0,0x0,0x18,0x0,0x0,0x0,0x48,0x14,0xde,
0x77,0xff,0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x66,0x0,0x0,0x0,0x66,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3b,
0x66,0x31,0x4b,0x33,0x7b,0x63,0x35,0x3a,0x65,0x66,0x6c,0x32,0x31,0x74,
0x34,0x3b,0x31,0x74,0x31,0x7a,0x61,0x78,0x70,0x69,0x6d,0x39,0x7d,0x35,
0x2b,0x3f,0x67,0x74,0x75,0x78,0x3b,0x3d,0x76,0x63,0x39,0x76,0x7b,0x76,
0x37,0x2b,0x62,0x75,0x68,0x55,0x7b,0x62,0x54,0x3d,0x2d,0x61,0x6d,0x32,
0x71,0x7d,0x3d,0x66,0x68,0x5b,0x78,0x6b,0x7b,0x79,0x3f,0x78,0x72,0x71,
0x65,0x7b,0x3f,0x7d,0x6c,0x35,0x2d,0x73,0x64,0x32,0x2d,0x4d,0x6f,0x2b,
0x3a,0x6a,0x7b,0x39,0x3d,0x73,0x59,0x5b,0x64,0x61,0x6c,0x76,0x70,0x78,
0x3f,0x7a,0x33,0x7b,0x3f,0x6e,0x6f,0x7b,0x5b,0x6b,0x35,0x6c,0x6c,0x7b,
0x7a,0x6a,0x73,0x75,0x35,0x5b,0x6b,0x66,0x6c,0x61,0x2b,0x72,0x36,0x5a,
0x67,0x37,0x32,0x6f,0x30,0x73,0x6b,0x71,0x36,0x63,0x47,0x6c,0x35,0x63,
0x77,0x5b,0x3d,0x64,0x3f,0x33,0x76,0x39,0x71,0x35,0x2d,0x76,0x6b,0x6a,
0x53,0x76,0x7b,0x34,0x73,0x71,0x74,0x67,0x3d,0x66,0x30,0x63,0x7a,0x7b,
0x2b,0x6a,0x75,0x72,0x6a,0x66,0x6c,0x5b,0x74,0x62,0x5d,0x6c,0x72,0x66,
0x46,0x31,0x3b,0x32,0x7d,0x75,0x64,0x68,0x62,0x3f,0x30,0x67,0x38,0x7b,
0x6f,0x6d,0x3a,0x54,0x34,0x64,0x68,0x3b,0x7a,0x3a,0x6f,0x7a,0x2d,0x44,
0x6e,0x3d,0x6d,0x3d,0x75,0x78,0x3b,0x6f,0x5b,0x67,0x73,0x39,0x7b,0x2b,
0x7a,0x71,0x78,0x2b,0x73,0x71,0x2d,0x64,0x73,0x78,0x63,0x74,0x63,0x76,
0x79,0x6b,0x55,0x73,0x32,0x6f,0x64,0x64,0x72,0x74,0x34,0x33,0x70,0x77,
0x76,0x3a,0x66,0x30,0x3b,0x6e,0x6a,0x6b,0x72,0x62,0x39,0x6c,0x6f,0x73,
0x36,0x67,0x30,0x7b,0x69,0x68,0x3f,0x72,0x71,0x61,0x6e,0x74,0x66,0x78,
0x24,0x73,0x73,0x6c,0x71,0x64,0x3a,0x72,0x76,0x71,0x69,0x78,0x72,0x3b,
0x6a,0x7b,0x3f,0x6f,0x3a,0x73,0x6e,0x2b,0x5b,0x69,0x5b,0x79,0x41,0x31,
0x31,0x3b,0x67,0x73,0x6d,0x72,0x38,0x6c,0x6d,0x30,0x3f,0x33,0x7d,0x3b,
0x2b,0x69,0x76,0x2b,0x54,0x66,0x3a,0x34,0x47,0x74,0x76,0x32,0x3a,0x2d,
0x32,0x30,0x75,0x70,0x69,0x30,0x5d,0x37,0x3f,0x37,0x37,0x3d,0x3b,0x71,
0x7a,0x78,0x7b,0x6d,0x2d,0x57,0x3b,0x30,0x76,0x74,0x75,0x65,0x68,0x5d,
0x6b,0x6f,0x38,0x64,0x3f,0x3d,0x77,0x3a,0x66,0x62,0x68,0x64,0x7b,0x45,
0x3a,0x3b,0x31,0x39,0x3f,0x70,0x3d,0x6b,0x3a,0x62,0x2b,0x7d,0x64,0x6f,
0x68,0x74,0x36,0x77,0x70,0x45,0x71,0x2d,0x7a,0x5d,0x32,0x71,0x62,0x56,
0x31,0x7d,0x64,0x68,0x34,0x31,0x36,0x71,0x77,0x39,0x3a,0x78,0x6d,0x5b,
0x3b,0x65,0x64,0x3b,0x3a,0x65,0x63,0x62,0x2d,0x30,0x3a,0x6e,0x69,0x2d,
0x73,0x34,0x75,0x32,0x6b,0x66,0x36,0x5d,0x32,0x77,0x6e,0x34,0x35,0x61,
0x6d,0x7a,0x6a,0x72,0x75,0x6e,0x3d,0x6f,0x66,0x6b,0x78,0x2d,0x3d,0x68,
0x6d,0x67,0x6f,0x2d,0x6c,0x7a,0x3b,0x6a,0x39,0x30,0x39,0x3d,0x72,0x6d,
0x6f,0x37,0x78,0x63,0x6a,0x34,0x6c,0x65,0x30,0x68,0x78,0x73,0x5b,0x69,
0x5d,0x2d,0x76,0x6a,0x6c,0x5b,0x3f,0x6f,0x31,0x32,0x3a,0x73,0x76
};
int i;
int v4=10;
for(i=0;i<330;i+=10){
srand(v4);
v4=rand()%10;
cout<<(data[96+i+v4]);
}
return 0;
}
flag{The-Y3ll0w-turb4ns-Upri$ing}