新160个crackme - 012-ACG-crcme1

运行分析

在这里插入图片描述

  • 需要破解Name和Serial

PE分析

在这里插入图片描述

  • 32位,未知程序,未知是否有壳

静态、动态分析

在这里插入图片描述

  • ida发现关键字符串Yeah You Did It!!!
  • 发现有个ACG.key,可能是注册文件,进入函数看看

注册

void __noreturn start()
{
  HANDLE FileA; // eax

  FileA = CreateFileA(FileName, 0x80000000, 0, 0, 3u, 0x80u, 0);// 读取ACG.key
  if ( FileA != (HANDLE)-1 )
  {
    hFile = FileA;
    if ( GetFileSize(FileA, 0) == 12 )          // ACG.key长度为12
    {
      lpBuffer = GlobalAlloc(0, 0xCu);          // 定义lpBuffer
      ReadFile(hFile, lpBuffer, 0xCu, &NumberOfBytesRead, 0);// LpBuffer = ACG.key内容
      if ( __ROL4__(*(_BYTE *)lpBuffer ^ 0x1B, 2) == 360// 执行计算,result = ((byte[lpBuffer] ^ 0x1b) * 4) ^ 0x160
        && __ROL4__(*((_BYTE *)lpBuffer + 1) ^ 0x1B, 2) == 0x160
        && __ROL4__(*((_BYTE *)lpBuffer + 2) ^ 0x1B, 2) == 0x170
        && __ROL4__(*((_BYTE *)lpBuffer + 3) ^ 0x1B, 2) == 0xEC
        && __ROL4__(*((_BYTE *)lpBuffer + 4) ^ 0x1B, 2) == 0x13C
        && __ROL4__(*((_BYTE *)lpBuffer + 5) ^ 0x1B, 2) == 0x1CC
        && __ROL4__(*((_BYTE *)lpBuffer + 6) ^ 0x1B, 2) == 0x1F8
        && __ROL4__(*((_BYTE *)lpBuffer + 7) ^ 0x1B, 2) == 0xEC
        && __ROL4__(*((_BYTE *)lpBuffer + 8) ^ 0x1B, 2) == 0x164
        && __ROL4__(*((_BYTE *)lpBuffer + 9) ^ 0x1B, 2) == 0x1F8
        && __ROL4__(*((_BYTE *)lpBuffer + 10) ^ 0x1B, 2) == 0x1A0
        && __ROL4__(*((_BYTE *)lpBuffer + 11) ^ 0x1B, 2) == 0x1BC )
      {
        MessageBoxA(0, Text, Caption, 0);       // 找不到ACG.key,则弹窗错误
      }
    }
  }
  hInstance = GetModuleHandleA(0);
  DialogBoxParamA(hInstance, TemplateName, 0, DialogFunc, 0);// 进入Name和Serial判定函数
  ExitProcess(0);
}
  • 先读取同目录下ACG.key文件,长度必须为12
  • ACG.key内容中每一位字符做运算,相等进入下一级段

CODE:00401068 ; 12:       if ( __ROL4__(*(_BYTE *)lpBuffer ^ 0x1B, 2) == 360// 执行亦或计算
CODE:00401068 ; 13:         && __ROL4__(*((_BYTE *)lpBuffer + 1) ^ 0x1B, 2) == 0x160
CODE:00401068 ; 14:         && __ROL4__(*((_BYTE *)lpBuffer + 2) ^ 0x1B, 2) == 0x170
CODE:00401068 ; 15:         && __ROL4__(*((_BYTE *)lpBuffer + 3) ^ 0x1B, 2) == 0xEC
CODE:00401068 ; 16:         && __ROL4__(*((_BYTE *)lpBuffer + 4) ^ 0x1B, 2) == 0x13C
CODE:00401068 ; 17:         && __ROL4__(*((_BYTE *)lpBuffer + 5) ^ 0x1B, 2) == 0x1CC
CODE:00401068 ; 18:         && __ROL4__(*((_BYTE *)lpBuffer + 6) ^ 0x1B, 2) == 0x1F8
CODE:00401068 ; 19:         && __ROL4__(*((_BYTE *)lpBuffer + 7) ^ 0x1B, 2) == 0xEC
CODE:00401068 ; 20:         && __ROL4__(*((_BYTE *)lpBuffer + 8) ^ 0x1B, 2) == 0x164
CODE:00401068 ; 21:         && __ROL4__(*((_BYTE *)lpBuffer + 9) ^ 0x1B, 2) == 0x1F8
CODE:00401068 ; 22:         && __ROL4__(*((_BYTE *)lpBuffer + 10) ^ 0x1B, 2) == 0x1A0
CODE:00401068 ; 23:         && __ROL4__(*((_BYTE *)lpBuffer + 11) ^ 0x1B, 2) == 0x1BC )
CODE:00401068                 mov     edi, ds:lpBuffer ; [edi] = lpBuffer,即读取ACG.key
CODE:0040106E                 xor     ebx, ebx        ; ebx = 0
CODE:00401070                 mov     bl, [edi]       ; bl = edi单个字符
CODE:00401072                 xor     bl, 1Bh         ; bl = bl ^ 0x1b
CODE:00401075                 rol     ebx, 2          ; 循环左移,ebx = ebx * 4,低位补0
CODE:00401078                 xor     ebx, 168h       ; ebx = ebx ^ 0x168
CODE:0040107E                 test    ebx, ebx
CODE:00401080                 jnz     loc_40117E
CODE:00401086                 inc     edi             ; edi = edi + 1
CODE:00401087                 mov     bl, [edi]       ; 以下为重复计算步骤
CODE:00401089                 xor     bl, 1Bh
CODE:0040108C                 rol     ebx, 2
CODE:0040108F                 xor     ebx, 160h
CODE:00401095                 test    ebx, ebx
CODE:00401097                 jnz     loc_40117E
  • 分析汇编代码,得出关键计算步骤为ebx = ((ebx ^ 0x1b) * 4) = 0x160
  • 逆向运算后,ebx = ( 0x160 / 4) ^ 0x1b
res = [0x168,0x160,0x170,0xEC,0x13C,0x1CC,0x1F8,0xEC,0x164,0x1F8,0x1A0,0x1BC]
key = ''

for i in range(len(res)):
    key += chr((res[i] // 4) ^ 0x1b)

print(key)

在这里插入图片描述

  • 写出逆向算法,得出ACG.key的值为ACG The Best

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 创建ACG.key后再运行exe文件,发现弹出已破解

继续破解Name和Serial

在这里插入图片描述

  • ida找到字符串Yeah You Did It!!!,进入函数
INT_PTR __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4)
{
  INT_PTR result; // eax
  HMODULE ModuleHandleA; // eax
  CHAR *Name_; // edi
  int Name_byte; // ebx
  int Name_byte_plus; // eax
  int Serial_byte; // ebx
  int v10; // edi
  CHAR *i; // esi
  HWND DesktopWindow; // eax
  int v13; // [esp-24h] [ebp-24h]

  result = a2;
  if ( (_WORD)a2 == 2 || (_WORD)a2 == 16 )
    goto LABEL_6;
  if ( (_WORD)a2 != 273 )
  {
    if ( (_WORD)a2 != 272 )
      return 0;
    dword_402012 = (int)LoadIconA(hInstance, (LPCSTR)0x69);
    SendMessageA(hDlg, 0x80u, 0, dword_402012);
    GetWindowRect(hDlg, &Rect);
    DesktopWindow = GetDesktopWindow();
    GetWindowRect(DesktopWindow, &stru_4020F6);
    dword_4020F2 = Rect.bottom - Rect.top;
    dword_4020EE = Rect.right - Rect.left;
    return MoveWindow(
             hDlg,
             (unsigned int)(stru_4020F6.right - (Rect.right - Rect.left)) >> 1,
             (unsigned int)(stru_4020F6.bottom - (Rect.bottom - Rect.top)) >> 1,
             Rect.right - Rect.left,
             Rect.bottom - Rect.top,
             0);
  }
  if ( a3 != 1003 )
  {
    if ( a3 != 1005 )
    {
      if ( a3 == 1004 )
        return MessageBoxA(hDlg, aHiToJeTrailCra, Caption, 0);
      return result;
    }
LABEL_6:
    if ( ++dword_40231C == 1 )
      sub_40141F();
    return EndDialog(hDlg, 0);
  }
  if ( *(&loc_401246 + 1) != 0x84 )
  {
    MessageBoxA(hDlg, aGdzieMiGrzebie, Caption, 0);
    goto LABEL_6;
  }
  ModuleHandleA = GetModuleHandleA(ModuleName);
  if ( *(_BYTE *)GetProcAddress(ModuleHandleA, ProcName) == 0xCC )
  {
    MessageBoxA(hDlg, aNoBpxAllowedIO, Caption, 0);
  }
  else if ( GetDlgItemTextA(hDlg, 1001, Name, 40) >= 5 )// 获取Name,长度要>= 5
  {
    GetDlgItemTextA(hDlg, 1002, Serial, 40);    // 获取Serial
    Name_ = Name;
    Name_byte = 0;
    Name_byte_plus = 0;
    while ( (unsigned __int8)*Name_ >= 32u )    // name的ascii值需要大于32
    {
      LOBYTE(Name_byte) = *Name_;               // Name_byte = Name单个字符的值
      Name_byte_plus += Name_byte;              // Name_byte_plus为所有Name的值相加
      if ( !*++Name_ )                          // 当Name到达最后一位时执行
      {
        v13 = __ROL4__(Name_byte_plus, 3) ^ 0x515A5;// v13 = (Name_byte_plus * 8) ^ 0x515a5
        Serial_byte = 0;
        v10 = 0;
        for ( i = Serial; ; ++i )               // i = Serial地址
        {
          LOBYTE(Serial_byte) = *i;             // Serial_byte = Serial单个字符的值
          if ( !Serial_byte )
            break;
          if ( (unsigned __int8)Serial_byte < 48u || (char)Serial_byte > 57 )// 不能执行此跳转,Serial_byte的ascii值要在48~57之间,即数字0-9
            goto LABEL_25;
          Serial_byte -= 48;
          v10 = Serial_byte + 10 * v10;
        }
        if ( (v10 ^ 0x87CA) + v13 == 0x797E7 )
        {
          MessageBoxA(hDlg, aYeahYouDidItCz, Caption, 0);// 破解成功弹窗
          return v13;
        }
        break;
      }
    }
  }
LABEL_25:
  MessageBoxA(hDlg, aNicZTego, Caption, 0x10u);
  SetDlgItemTextA(hDlg, 1002, &byte_4020DD);
  return v13;
}
  • 分析函数,前面的不重要,从获取Name和Serial处开始分析
  • Name每个字符ascii相加,在通过运算得到v13 =(Name_byte_plus * 8) ^ 0x515a5
  • Serial每个字符ascii通过运算v10 += Serial_byte + 10 * v10
  • 验算(v10 ^ 0x87CA) + v13 == 0x797E7,相等则注册成功

算法分析

Name = 'concealbear'
Serial = ''

# 计算v13
Name_byte_plus = 0
for i in range(len(Name)):
    Name_byte_plus += ord(Name[i])
v13 = (Name_byte_plus * 8) ^ 0x515A5

# 计算v10
v10 = (0x797E7 - v13) ^ 0x87CA

# 爆破Serial,暂定长度为1-7
for Serial_byte1 in range(0,10):
    for Serial_byte2 in range(0, 10):
        for Serial_byte3 in range(0, 10):
            for Serial_byte4 in range(0, 10):
                for Serial_byte5 in range(0, 10):
                    for Serial_byte6 in range(0, 10):
                        for Serial_byte7 in range(0, 10):
                            v10 = (((((((((Serial_byte1 * 10) + Serial_byte2) * 10) +Serial_byte3) *10) + Serial_byte4) * 10) + Serial_byte5) * 10 + Serial_byte6) * 10 + Serial_byte7
                            # print(v10)
                            if (v10 ^ 0x87CA) + v13 == 0x797E7:
                                Serial = str(Serial_byte1) + str(Serial_byte2) + str(Serial_byte3) + str(Serial_byte4) + str(Serial_byte5) + str(Serial_byte6)+ str(Serial_byte7)
                                print(Name + "的Serial为:\n"+Serial)
                                exit()

  • 首先确定Name,暂定Serial为7位,再通过爆破的方式得出Serial

在这里插入图片描述
在这里插入图片描述

  • 输入任意Name,执行算法得到Serial,验证成功
  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值