crackme.chm之CKme

    首先使用dede查看有多少用户自定函数

    由于FormCreate函数是最先被调用的,所以我们在IDA中找到对应函数,并使用F5分析

int __fastcall TForm1_FormCreate(int a1)
{
  int v1; // ebx@1
  int v2; // edx@1
  int v3; // edx@1

  v1 = a1;
  unknown_libname_28(a1 + 784, &str_____Sun_Bird[1]);
  unknown_libname_28(v1 + 788, &str_dseloffc_012_OK[1]);
  LOBYTE(v2) = 1;
  Controls::TControl::SetVisible(*(_DWORD *)(v1 + 740), v2);
  LOBYTE(v3) = 1;
  return Controls::TControl::SetVisible(*(_DWORD *)(v1 + 752), v3);
}
    上面的函数比较简单也比较直观,就是初始化两个字符串指针成员变量,并且显示两个控件,我们这边记住下两个成员变量的地址分别是784、788,对应的字符串分别为“黑头Sun Bird”、“dseloffc-012-OK”

    接下来让我们看下第二个自定义函数KeyUp

int __fastcall TForm1_KeyUp(int a1, int a2, int a3, int a4)
{
  int v4; // ebx@1
  int v5; // eax@1
  int result; // eax@1

  v4 = a1;
  v5 = Controls::TControl::GetTextLen(*(_DWORD *)(a1 + 724));
  *(_DWORD *)(v4 + 760) = v5;
  result = abs(v5);
  *(_DWORD *)(v4 + 760) = result;
  return result;
}
    上面的函数也比较简单,主要是获取输入的字符串的长度并且保存到一个成员变量中,这边我们记下成员变量的地址760,至于是记录什么控件的文本长度,我们看下dede中KeyUp是哪个控件上的函数即可

    可以看到是TEdit1就是用户名,所以this->760保存的是用户名的长度,接下来看下第三个自定义函数Panel1Click

int __fastcall TForm1_Panel1Click(int a1)
{
  int v1; // esi@1
  int v2; // ebx@1
  int v3; // eax@2
  int v4; // ST04_4@2
  int v5; // ecx@2
  int v6; // ebx@4
  int v7; // eax@5
  int v8; // ST04_4@5
  int v9; // ecx@5
  unsigned int v11; // [sp-Ch] [bp-38h]@1
  int (*v12)(); // [sp-8h] [bp-34h]@1
  int (*v13)(); // [sp-4h] [bp-30h]@1
  int v14; // [sp+8h] [bp-24h]@5
  int v15; // [sp+Ch] [bp-20h]@5
  int v16; // [sp+10h] [bp-1Ch]@5
  int v17; // [sp+14h] [bp-18h]@5
  int v18; // [sp+18h] [bp-14h]@2
  int v19; // [sp+1Ch] [bp-10h]@2
  int v20; // [sp+20h] [bp-Ch]@2
  int v21; // [sp+24h] [bp-8h]@2
  char v22; // [sp+28h] [bp-4h]@2
  int v23; // [sp+2Ch] [bp+0h]@1

  v1 = a1;
  v13 = (int (*)())&v23;
  v12 = loc_4580FD;
  v11 = __readfsdword(0);
  __writefsdword(0, (unsigned int)&v11);
  v2 = 0;
  do
  {
    TControl::GetText(*(_DWORD *)(v1 + 724), &v20);
    v3 = sub_403B7C(v20);
    Sysutils::IntToStr(v3 + 30, &v21);
    TControl::GetText(*(_DWORD *)(v1 + 724), &v19);
    v4 = v19;
    Sysutils::IntToStr(v2, &v18);
    System::__linkproc___LStrCatN(&v22, 3, v5, v4, v18);
    ++v2;
  }
  while ( v2 != 19 );
  if ( *(_DWORD *)(v1 + 780) == 133 )
  {
    v6 = 0;
    do
    {
      TControl::GetText(*(_DWORD *)(v1 + 724), &v16);
      v7 = sub_403B7C(v16);
      Sysutils::IntToStr(v7 + 3, &v17);
      TControl::GetText(*(_DWORD *)(v1 + 724), &v15);
      v8 = v15;
      Sysutils::IntToStr(v6, &v14);
      System::__linkproc___LStrCatN(&v22, 3, v9, v8, v14);
      ++v6;
    }
    while ( v6 != 19 );
    Controls::TControl::SetVisible(*(_DWORD *)(v1 + 752), 0);
    unknown_libname_28(dword_45B820 + 112, &str________________[1]);
  }
  __writefsdword(0, v11);
  v13 = loc_458104;
  unknown_libname_26(&v14);
  unknown_libname_27(&v15, 2);
  unknown_libname_27(&v17, 2);
  unknown_libname_27(&v19, 2);
  return unknown_libname_27(&v21, 2);
}
    简单的分析上面函数,可得到如下代码

int __fastcall TForm1_Panel1Click(int this)
{
  int this; // esi@1
  int i; // ebx@1
  int iNLen; // eax@2
  int v4; // ST04_4@2
  int v5; // ecx@2
  int j; // ebx@4
  int iNLen; // eax@5
  int pszName; // [sp+1Ch] [bp-10h]@2
  int pszName; // [sp+20h] [bp-Ch]@2

  i = 0;
  do
  {
    TControl::GetText(*(_DWORD *)(this + 724), &pszName);
    iNLen = strlen(pszName);
    Sysutils::IntToStr(iNLen + 30, &v21);
    TControl::GetText(*(_DWORD *)(this + 724), &pszName);
    System::__linkproc___LStrCatN(&v22, 3, pszName, i);
    ++i;
  }
  while ( i != 19 );
  if ( *(_DWORD *)(this + 780) == 133 )
  {
    j = 0;
    do
    {
      TControl::GetText(*(_DWORD *)(this + 724), &pszName);
      iNLen = strlen(pszName);
      Sysutils::IntToStr(iNLen + 3, &v17);
      TControl::GetText(*(_DWORD *)(this + 724), &pszName);
      System::__linkproc___LStrCatN(&v22, 3, pszName, j);
      ++j;
    }
    while ( j != 19 );
    Controls::TControl::SetVisible(*(_DWORD *)(this + 752), 0);
    unknown_libname_28(dword_45B820 + 112, "恭喜恭喜!注册成功");
  }
}

    可以看到两个do-while循环都是迷惑性的,根本不影响最后“注册成功”的提示,真正的判断点在于if ( *(_DWORD *)(this + 780) == 133 ),但是我们发现在当前函数即之前函数都没有发觉对this+780有赋值,所以我们需要看下下一个函数Panel1DbClick

int __fastcall TForm1_Panel1DblClick(int a1)
{
  int v1; // esi@1
  int v2; // ebx@1
  int v3; // eax@2
  int v4; // ST04_4@2
  int v5; // ecx@2
  int v6; // ebx@5
  int v7; // eax@6
  int v8; // ST04_4@6
  int v9; // ecx@6
  unsigned int v11; // [sp-Ch] [bp-38h]@1
  int (*v12)(); // [sp-8h] [bp-34h]@1
  int (*v13)(); // [sp-4h] [bp-30h]@1
  int v14; // [sp+8h] [bp-24h]@6
  int v15; // [sp+Ch] [bp-20h]@6
  int v16; // [sp+10h] [bp-1Ch]@6
  int v17; // [sp+14h] [bp-18h]@6
  int v18; // [sp+18h] [bp-14h]@2
  int v19; // [sp+1Ch] [bp-10h]@2
  int v20; // [sp+20h] [bp-Ch]@2
  int v21; // [sp+24h] [bp-8h]@2
  char v22; // [sp+28h] [bp-4h]@2
  int v23; // [sp+2Ch] [bp+0h]@1

  v1 = a1;
  v13 = (int (*)())&v23;
  v12 = loc_457FA9;
  v11 = __readfsdword(0);
  __writefsdword(0, (unsigned int)&v11);
  v2 = 0;
  do
  {
    TControl::GetText(*(_DWORD *)(v1 + 724), &v20);
    v3 = sub_403B7C(v20);
    Sysutils::IntToStr(v3 + 9, &v21);
    TControl::GetText(*(_DWORD *)(v1 + 724), &v19);
    v4 = v19;
    Sysutils::IntToStr(v2, &v18);
    System::__linkproc___LStrCatN(&v22, 3, v5, v4, v18);
    ++v2;
  }
  while ( v2 != 19 );
  if ( *(_DWORD *)(v1 + 780) == 62 )
    *(_DWORD *)(v1 + 780) = 133;
  v6 = 0;
  do
  {
    TControl::GetText(*(_DWORD *)(v1 + 724), &v16);
    v7 = sub_403B7C(v16);
    Sysutils::IntToStr(v7 + 21, &v17);
    TControl::GetText(*(_DWORD *)(v1 + 724), &v15);
    v8 = v15;
    Sysutils::IntToStr(v6, &v14);
    System::__linkproc___LStrCatN(&v22, 3, v9, v8, v14);
    ++v6;
  }
  while ( v6 != 19 );
  __writefsdword(0, v11);
  v13 = loc_457FB0;
  unknown_libname_26(&v14);
  unknown_libname_27(&v15, 2);
  unknown_libname_27(&v17, 2);
  unknown_libname_27(&v19, 2);
  return unknown_libname_27(&v21, 2);
}
    可以看到中间有个赋值动作

if ( *(_DWORD *)(v1 + 780) == 62 )
    *(_DWORD *)(v1 + 780) = 133;
    所以本函数将影响前一个函数,这边也会发现两个do-while也是迷惑性的,根本不会影响上面的赋值表达式,而问题又转移到什么时候*(_DWORD *)(v1 + 780) == 62表达式会成立呢?来看最后一个自定义函数ChkCode
int __fastcall TForm1_chkcode(int a1, int a2, signed __int32 a3, int a4)
{
  int v4; // ebx@1
  int v5; // ST04_4@1
  int v6; // ecx@1
  int v7; // esi@1
  int v8; // eax@2
  int v9; // ST08_4@2
  int v10; // ecx@2
  char v11; // zf@3
  int v12; // eax@5
  int v13; // esi@5
  int v14; // eax@6
  int v15; // ST08_4@6
  int v16; // ecx@6
  int v17; // eax@7
  unsigned int v19; // [sp-Ch] [bp-44h]@1
  int (__stdcall *v20)(int); // [sp-8h] [bp-40h]@1
  int (__stdcall *v21)(int); // [sp-4h] [bp-3Ch]@1
  int v22; // [sp+8h] [bp-30h]@6
  int v23; // [sp+Ch] [bp-2Ch]@6
  int v24; // [sp+10h] [bp-28h]@6
  int v25; // [sp+14h] [bp-24h]@6
  int v26; // [sp+18h] [bp-20h]@3
  int v27; // [sp+1Ch] [bp-1Ch]@2
  int v28; // [sp+20h] [bp-18h]@2
  int v29; // [sp+24h] [bp-14h]@2
  int v30; // [sp+28h] [bp-10h]@2
  int v31; // [sp+2Ch] [bp-Ch]@1
  int v32; // [sp+30h] [bp-8h]@1
  int v33; // [sp+34h] [bp-4h]@1
  int v34; // [sp+38h] [bp+0h]@1

  _InterlockedExchange((signed __int32 *)&v33, a3);
  v4 = a1;
  v21 = (int (__stdcall *)(int))&v34;
  v20 = loc_457E3D;
  v19 = __readfsdword(0);
  __writefsdword(0, (unsigned int)&v19);
  Sysutils::IntToStr(*(_DWORD *)(a1 + 760) + 5, &v32);
  v5 = *(_DWORD *)(v4 + 788);
  TControl::GetText(*(_DWORD *)(v4 + 724), &v31);
  System::__linkproc___LStrCatN(v4 + 792, 4, v6, v5, v31);
  Controls::TControl::SetVisible(*(_DWORD *)(v4 + 756), 0);
  Controls::TControl::SetText(*(_DWORD *)(v4 + 756), *(_DWORD *)(v4 + 792));
  v7 = 0;
  do
  {
    TControl::GetText(*(_DWORD *)(v4 + 724), &v29);
    v8 = sub_403B7C(v29);
    Sysutils::IntToStr(v8 + 3, &v30);
    TControl::GetText(*(_DWORD *)(v4 + 724), &v28);
    v9 = v28;
    Sysutils::IntToStr(v7, &v27);
    System::__linkproc___LStrCatN(&v33, 3, v10, v9, v27);
    ++v7;
  }
  while ( v7 != 19 );
  TControl::GetText(*(_DWORD *)(v4 + 728), &v26);
  System::__linkproc___LStrCmp(v26, *(_DWORD *)(v4 + 792));
  if ( v11 )
    *(_DWORD *)(v4 + 780) = 62;
  v12 = *(_DWORD *)(v4 + 780) + 16;
  *(_DWORD *)(v4 + 764) = v12;
  *(_DWORD *)(v4 + 768) = v12 + 35;
  v13 = 0;
  do
  {
    TControl::GetText(*(_DWORD *)(v4 + 724), &v24);
    v14 = sub_403B7C(v24);
    Sysutils::IntToStr(v14 + 3, &v25);
    TControl::GetText(*(_DWORD *)(v4 + 724), &v23);
    v15 = v23;
    Sysutils::IntToStr(v13, &v22);
    System::__linkproc___LStrCatN(&v33, 3, v16, v15, v22);
    ++v13;
  }
  while ( v13 != 19 );
  v17 = *(_DWORD *)(v4 + 768) + *(_DWORD *)(v4 + 764);
  *(_DWORD *)(v4 + 772) = v17;
  *(_DWORD *)(v4 + 776) = v17 + *(_DWORD *)(v4 + 764) + 9;
  __writefsdword(0, v19);
  v21 = loc_457E44;
  unknown_libname_26(&v22);
  unknown_libname_27(&v23, 2);
  unknown_libname_26(&v25);
  unknown_libname_26(&v26);
  unknown_libname_26(&v27);
  unknown_libname_27(&v28, 2);
  unknown_libname_26(&v30);
  unknown_libname_26(&v31);
  return unknown_libname_27(&v32, 2);
}
    简单的分析上面的函数,去掉无关代码结果如下:(注意this+784/788我们在第一个自定义函数中已经知道是两个常量字符串,IDA的StrCat漏掉了下面两个参数,分别是this->784以及用户名长度this->760+5)

int __fastcall TForm1_chkcode(int this, int a2, signed __int32 a3, int a4)
{
  TControl::GetText(*(_DWORD *)(v4 + 724), &pszName);
  System::__linkproc___LStrCatN(v4 + 792, *(_DWORD *)(v4 + 784), *(_DWORD *)(v4 + 760)+5 ,*(_DWORD *)(v4 + 788), pszName);
  TControl::GetText(*(_DWORD *)(v4 + 728), &pszSerial);
  if (!System::__linkproc___LStrCmp(pszSerial, *(_DWORD *)(v4 + 792)))
    *(_DWORD *)(v4 + 780) = 62;
}
    根据上面的函数可以推导出注册算法为

void main()
{
	char szMagicA[] = "黑头Sun Bird";
	char szMagicB[] = "dseloffc-012-OK";
	char szName[] = "@@@@";
	cout<<"The Serial:"<<szMagicA<<strlen(szName)+5<<szMagicB<<szName<<endl;
}
    输入用户名和序列号后,双击画布再单击画布即可完成破解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值