XCTF 4th-WHCTF-2017-CRACKME

查壳

在这里插入图片描述

分析

  • 看图标就猜得出是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}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值