新CrackMe160之135 - Szi - crackme

OD载入程序,搜索界面定位到成功关键词"now keygen it!"0040206F,往上看到GetDlgItemTextA,在它的下一行00401FD7处下好断点,开始分析算法
先用IDA分析源码:

if ( (_WORD)a4 == 101 )
{
  pv = 0;
  memset(&v20, 0, 0x26u);
  v12 = -1;
  GetDlgItemTextA(hWndParent, 100, (LPSTR)&pv, 42);
  v12 = 3;
  sub_40A164(&v23, &pv, &v24); //v23与v24有关
  LOBYTE(h) = 0;
  v12 = 1;
  sub_40A208(&v22, &v23); //v22与v23有关
  LOBYTE(h) = 1;
  if ( (unsigned __int8)sub_4017D0(&v22) ) //这个是关键算法,关键参数V22(系列号)
    LOBYTE(hdc) = byte_40E018 ^ 1;
  else
    LOBYTE(hdc) = 0;
  v12 = 2;
  sub_40A924(&v22); //猜这个是释放空间的方法
  if ( (_BYTE)hdc ) //=1就成功
  {
    v12 = 2;
    MessageBoxA(hWndParent, "now keygen it !", "gratz !!", 0);
  }
  v12 = 2;
  UpdateWindow(hWndParent);
  v12 = -1;
  sub_40A924(&v23); //猜这个是释放空间的方法
}

sub_4017D0()这个方法的源码:

char __cdecl sub_4017D0(int a1)
{
  int v1; // eax@1
  int v3; // edx@11
  int v4; // eax@16
  int v5; // edx@16
  int v6; // eax@19
  int v7; // ecx@19
  int v8; // eax@19
  int v9; // eax@22
  int v10; // edx@22
  int v11; // eax@25
  int v12; // ecx@25
  char v13; // al@26
  char v14; // al@27
  char v15; // al@28
  char v16; // al@29
  LPVOID v17; // [sp+0h] [bp-68h]@1
  int *v18; // [sp+4h] [bp-64h]@26
  char v19; // [sp+13h] [bp-55h]@16
  int v20; // [sp+14h] [bp-54h]@16
  unsigned int v21; // [sp+18h] [bp-50h]@2
  char v22; // [sp+1Ch] [bp-4Ch]@1
  int v23; // [sp+20h] [bp-48h]@5
  int (__cdecl *v24)(int, int, int, int, int, int); // [sp+34h] [bp-34h]@1
  __int16 *v25; // [sp+38h] [bp-30h]@1
  char *v26; // [sp+3Ch] [bp-2Ch]@1
  int (*v27)(); // [sp+40h] [bp-28h]@1
  LPVOID *v28; // [sp+44h] [bp-24h]@1
  char v29; // [sp+5Dh] [bp-Bh]@31
  char v30; // [sp+5Eh] [bp-Ah]@33
  char v31; // [sp+5Fh] [bp-9h]@35
  char v32; // [sp+60h] [bp-8h]@1

  v24 = sub_402618;
  v25 = &word_40B10E;
  v26 = &v32;
  v27 = sub_401C06;
  v28 = &v17;
  sub_406EA8(&v22);
  v1 = *(_DWORD *)a1;
  if ( *(_DWORD *)(*(_DWORD *)a1 - 12) != 11 ) //长度是否为11
    goto LABEL_38;
  if ( *(_DWORD *)(*(_DWORD *)a1 - 12 + 8) >= 0 )
  {
    v23 = -1;
    sub_4084A8(a1);
    v1 = *(_DWORD *)a1;
  }
  if ( *(_BYTE *)(v1 + 3) != 45 ) //第4位是否为-号
    goto LABEL_38;
  v23 = -1;
  sub_409854(a1);
  if ( *(_BYTE *)(*(_DWORD *)a1 + 7) != 45 ) //第8位是否为-号
    goto LABEL_38;
  if ( !byte_40E020 && sub_402D1C(&byte_40E020) )
  {
    v23 = 3;
    sub_40A164(&dword_40E040, "ibetthatyoucantcrackthis", &v31);
    sub_402E54(&byte_40E020);
    sub_401000(sub_401718);
  }
  if ( !byte_40E028 && sub_402D1C(&byte_40E028) )
  {
    v23 = 2;
    sub_40A164(&dword_40E03C, "1234567890", &v30);
    sub_402E54(&byte_40E028);
    sub_401000(sub_401660);
  }
  if ( !byte_40E030 && sub_402D1C(&byte_40E030) )
  {
    v23 = 1;
    dword_40E038 = sub_4084F0(0, 0, &v29);
    sub_402E54(&byte_40E030);
    sub_401000(sub_4015A8);
  }
  v3 = dword_40E040 - 12;
  if ( *(_DWORD *)(dword_40E040 - 12) )
  {
    v21 = 0;
    do                                      //OD跟踪可知,这个大循环是将上面两个固定串交叉组合在一起=> str = "i1b2e3..."
    {
      if ( *(_DWORD *)(v3 + 8) >= 0 )
      {
        v23 = -1;
        sub_4084A8(&dword_40E040);
      }
      v19 = *(_BYTE *)(dword_40E040 + v21);
      v4 = dword_40E038;
      v5 = *(_DWORD *)(dword_40E038 - 12);
      v20 = v5 + 1;
      if ( (unsigned int)(v5 + 1) > *(_DWORD *)(dword_40E038 - 12 + 4) || *(_DWORD *)(dword_40E038 - 12 + 8) > 0 )
      {
        v23 = -1;
        sub_409DF0(&dword_40E038, v20);
        v4 = dword_40E038;
        v5 = *(_DWORD *)(dword_40E038 - 12);
      }
      *(_BYTE *)(v4 + v5) = v19;
      v6 = dword_40E038 - 12;
      *(_DWORD *)(v6 + 8) = 0;
      v7 = v20;
      *(_DWORD *)v6 = v20;
      *(_BYTE *)(v6 + v7 + 12) = 0;
      v8 = dword_40E03C;
      if ( *(_DWORD *)(dword_40E03C - 12) > v21 )
      {
        if ( *(_DWORD *)(dword_40E03C - 12 + 8) >= 0 )
        {
          v23 = -1;
          sub_4084A8(&dword_40E03C);
          v8 = dword_40E03C;
        }
        v19 = *(_BYTE *)(v8 + v21);
        v9 = dword_40E038;
        v10 = *(_DWORD *)(dword_40E038 - 12);
        v20 = v10 + 1;
        if ( (unsigned int)(v10 + 1) > *(_DWORD *)(dword_40E038 - 12 + 4) || *(_DWORD *)(dword_40E038 - 12 + 8) > 0 )
        {
          v23 = -1;
          sub_409DF0(&dword_40E038, v20);
          v9 = dword_40E038;
          v10 = *(_DWORD *)(dword_40E038 - 12);
        }
        *(_BYTE *)(v9 + v10) = v19;
        v11 = dword_40E038 - 12;
        *(_DWORD *)(v11 + 8) = 0;
        v12 = v20;
        *(_DWORD *)v11 = v20;
        *(_BYTE *)(v11 + v12 + 12) = 0;
      }
      ++v21;
      v3 = dword_40E040 - 12;
    }
    while ( v21 < *(_DWORD *)(dword_40E040 - 12) );
  }
  v23 = -1;
  sub_409854(a1);
  LOBYTE(v21) = **(_BYTE **)a1;
  sub_409854(a1);
  v18 = &dword_40E038;
  v17 = (LPVOID)(*(_BYTE *)(*(_DWORD *)a1 + 1) + 4919); // code[1] + 0x1337
  v13 = sub_40154C(v17, &dword_40E038);   //由code[1]算出code[0], 由OD分析可得算法为: code[0] = str[(code[1] + 0x1337) % len(str)]
  if ( (_BYTE)v21 != v13
    || (sub_409854(a1),
        LOBYTE(v21) = *(_BYTE *)(*(_DWORD *)a1 + 2), //code[2]
        sub_409854(a1),
        v18 = &dword_40E038,
        v17 = (LPVOID)(*(_BYTE *)(*(_DWORD *)a1 + 4) - 4919), // code[4] - 0x1337
        v14 = sub_40154C(v17, &dword_40E038),   //由code[4]算出code[2], 由OD分析可得算法为: code[2] = str[(code[4] - 0x1337) % len(str)]
        (_BYTE)v21 != v14)
    || (sub_409854(a1),
        LOBYTE(v21) = *(_BYTE *)(*(_DWORD *)a1 + 5), //code[5]
        sub_409854(a1),
        v18 = &dword_40E038,
        v17 = (LPVOID)(4919 * *(_BYTE *)(*(_DWORD *)a1 + 6)), //code[6]
        v15 = sub_40154C(v17, &dword_40E038),   //由code[6]算出code[5], 由OD分析可得算法为: code[5] = str[(code[6] * 41 * 15 * 7) % len(str)]
        (_BYTE)v21 != v15) )
  {
LABEL_38:
    LOBYTE(v21) = 0;
  }
  else
  {
    sub_409854(a1);
    LOBYTE(v21) = *(_BYTE *)(*(_DWORD *)a1 + 8); //code[8]
    sub_409854(a1);
    v18 = &dword_40E038;
    v17 = (LPVOID)*(_BYTE *)(*(_DWORD *)a1 + 9); //code[9]
    v16 = sub_40154C(v17, &dword_40E038);   //由code[9]算出code[8]
    LOBYTE(v21) = (_BYTE)v21 == v16;
  }
  sub_406E54(&v22);
  return v21;
}

由上面算法分析可得:
code[1] => code[0]
code[4] => code[2]
'-' => code[3]
code[6] => code[5]
'-' => code[7]
code[9] => code[8]
code[A] => 无
左侧必须为已知数(所有随机生成), 右侧为算法得到, 由此注册机如下:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

int main() {
	srand((unsigned int)time(NULL));
	char *str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
	char *rlt = "i1b2e3t4t5h6a7t8y9o0ucantcrackthis";
	int len1 = strlen(str), len2 = strlen(rlt);
	char code[12] = {0};
	code[3] = '-';
	code[7] = '-';
	code[1] = str[rand() % len1];
	code[4] = str[rand() % len1];
	code[6] = str[rand() % len1];
	code[9] = str[rand() % len1];
	code[10]= str[rand() % len1];
	code[0] = rlt[(code[1] + 0x1337) % len2]; 
	code[2] = rlt[((unsigned int)(code[4] - 0x1337)) % len2];
	code[5] = rlt[(code[6] * 41 * 15 * 8 - code[6]) % len2];
	code[8] = rlt[code[9] % len2];
	printf("系列号: %s\n", code);
	
	getchar();getchar();
	return 0;
}

运行示例:
系列号: hY2-LcK-tlh

 
 
本节高手录制的视频,点击前往查看

 
 
 
使用的工具连接(工具有点多有点大,可以先下OD,其它的后面慢慢下) 点击前往下载

下面是我的OD的界面布局,我觉得这4个是最常用的界面,其它的我基本上没用到~
OD界面布局

posted @ 2024-12-30 14:34  hankerstudio  阅读(23)  评论(0)    收藏  举报