低调的菜鸡 发表于 2019-3-23 16:42

新人第一次发一个简单的CM【注册码方式】

说明:
今天突发奇想想用纯win32 api做一个窗口程序,又突然想到了吾爱破解论坛上面的破解区,于是就写了个这个CrackMe。
小白第一次做CM,希望大家多多支持,大佬轻点喷。。
这是程序界面,目前账号只支持纯英文输入(本人水平有限,时间不够,才写的这样)



提示:字符串为明码,可通过od字符串查找查看。

欢迎大家踊跃尝试,有什么问题可以联系我讨论交流,当然,每日的1Cb免费的哦:lol(疯狂暗示)
附件:

monvvv 发表于 2019-3-24 13:04

稍微弄了一下,这个用的算是挺普遍的算法模式了。

代码:
验证流程:
```
def GetVerifictionForUsername(username):
    username = str.encode(username)
    for i in range(0, len(username)):
      byte = username
      if byte < 65:
            return 1
      if byte > 90:
            username = username[:i] + bytes() + username
    username_sum = 0
    for i in range(0, len(username)):
      username_sum += username
    username_verify = username_sum ^ 0x1357
    return username_verify


def GetVerifictionForReg(reg):
    reg_sum = 0
    for i in range(0, len(reg)):
      byte = ord(reg) - 48
      reg_sum = 10 * reg_sum + byte
    reg_verify = reg_sum ^ 0x2468
    return reg_verify


def CheckReg(username, reg):
    return GetVerifictionForUsername(username) == GetVerifictionForReg(reg)

```

根据上面逆推出的注册机:
```
def KeyGen(username):
    username_verifiction = GetVerifictionForUsername(username)

    reg_sum = username_verifiction ^ 0x2468

    results = []
    FindReg(results, reg_sum)

    #测试注册码
    for i in range(0, len(results)):
      reg = results
      assert CheckReg(username, reg)
    print("username_verifiction = " + str(username_verifiction))
    print("reg_verifiction = " + str(GetVerifictionForReg(results)))

    return results

#其实这段算是暴力枚举
def FindReg(result, reg_sum, n=-1, rs=[]):

    if reg_sum < 0:
      return
    if n != -1:
      #assert (reg_sum - n) % 10 == 0
      reg_sum = (reg_sum - n) // 10# 可以确定能整除
      rs.append(int(n + 48))
    if reg_sum == 0:
      rs.reverse()
      result.append(bytes(rs).decode())
      return

    singel_digits = reg_sum % 10# 确保减去最后一位后能被10整除

    # n belongs to
    min_digits = 0
    max_digits = 6 if singel_digits > 8 else 7
    for i in range(min_digits, max_digits + 1):
      new_rs = copy.deepcopy(rs)
      FindRegLoop(result, reg_sum, i * 10 + singel_digits, new_rs)
    return
```

迷雾 发表于 2019-7-4 13:01

本帖最后由 迷雾 于 2019-7-4 13:03 编辑

先上效果
本人渣渣一枚,大神们勿喷,lz的程序没加密我就直接ida f5了.
INT_PTR __stdcall DialogFunc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
char v5; // dl
void (__stdcall *v6)(UINT); // ebx
int v7; // ecx
char *v8; // ebx
char v9; // al
int v10; // esi
int v11; // eax
int v12; // esi
CHAR v13; // al
CHAR *v14; // edx
int v15; // ecx
CHAR v16; // al
HWND v17; // eax
HWND v18; // eax
HWND v19; // eax
HWND v20; // eax
HICON v21; // eax
signed int v22; //
CHAR String; //
char Dst; //
CHAR String2; //
__int16 v26; //
CHAR v27; //
int v28; //
__int16 v29; //
CHAR v30; //
__int16 v31; //
char v32; //

v26 = 33;
v28 = 565626318;
v29 = 33;
*(_OWORD *)String2 = xmmword_D52128;          // 对应的字符串为 "恭喜你,成功"
v31 = -24157;
*(_OWORD *)v27 = xmmword_D5213C;
v32 = 0;
*(_OWORD *)v30 = xmmword_D52154;
memset(Dst, 0, 0x64u);
memset(&String, 0, 0x64u);
if ( Msg == 0x10 )                            // WM_CLOSE
{
    DestroyWindow(hWnd);
    return 0;
}
if ( Msg == 272 )                           // WM_INITDIALOG
{
    v21 = LoadIconA(hInstance, (LPCSTR)0x69);
    SendMessageA(hWnd, 0x80u, 1u, (LPARAM)v21); // WM_SETICON
    SendDlgItemMessageA(hWnd, 1003, 0xC5u, 0x50u, 0);
    return 0;
}
if ( Msg != 273 )                           // WM_COMMAND
    return 0;
if ( (unsigned __int16)wParam == 1007 )
{
    v22 = GetDlgItemTextA(hWnd, 1003, Dst, 101);// UserName
    GetDlgItemTextA(hWnd, 1004, &String, 101);// PassWord
    v5 = Dst;
    v6 = (void (__stdcall *)(UINT))MessageBeep;
    if ( Dst && v22 >= 5 )                   // if userName!=0 && length(userName)>=5
    {
      v7 = 0;
      v8 = Dst;                                 // userName
      if ( v22 <= 0 )                           // length(userName)
      {
LABEL_15:
      v10 = 0;
      if ( v5 )                               // v5=首字符
      {
          do
          {
            v11 = v5;                           // 移到下一个字符,v5=下一字符
            v5 = *++v8;
            v10 += v11;
          }
          while ( *v8 );
      }
      v12 = v10 ^ 0x1357;                     // v10=所有字符ascii码之和
      }
      else                                    // if userName==0 || length(userName)<5
      {
      while ( 1 )
      {
          v9 = Dst;                         // 如果用户名是数字,跳出循环
          if ( v9 < 65 )
            break;                              // 如果ASCI大于90(判断小写字母?)
          if ( v9 > 90 )                        // 转为大写字母
            Dst = v9 - 32;
          if ( ++v7 >= v22 )                  // 索引下移,这里应该是v7++吧?,先移动下一再判断是否到达结尾
          {
            v5 = Dst;                        // v5=首字符
            goto LABEL_15;
          }
      }                                       // 如果有数字跳出循环设置这个标记
      v12 = 1;
      }
      v13 = String;                           // PassWord
      v14 = &String;                            // Pointer to PassWord
      v15 = 0;
      if ( String )                           // 将每一个密码字符-48('0')转为数字 然后放到缓冲区v14中,v15为每一次转换出的数字加上上一次的转换的数字*10
      {
      do
      {
          v16 = v13 - 48;
          *v14++ = v16;
          v15 = v16 + 10 * v15;
          v13 = *v14;                           // 这个v13好像没什么卵用
      }
      while ( *v14 );
      }
      if ( v12 == (v15 ^ 0x2468) )            // 如果用户名有数字的话这里v12==1
      {
      lstrcpyA(Text, String2);                // 密码正确 "恭喜你,成功"
      v17 = GetDlgItem(hWnd, 1003);
      EnableWindow(v17, 0);
      v18 = GetDlgItem(hWnd, 1004);
      EnableWindow(v18, 0);
      }
      else
      {
      lstrcpyA(Text, v27);                  // 密码错误
      }
      v19 = GetDlgItem(hWnd, 1004);
      SetFocus(v19);
      v6 = (void (__stdcall *)(UINT))MessageBeep;
    }
    else
    {
      lstrcpyA(Text, v30);                      // 长度不对
      v20 = GetDlgItem(hWnd, 1003);
      SetFocus(v20);
      MessageBeep(0);
    }
    v6(0);
    MessageBoxA(hWnd, Text, "CrackMe", 0);
}
else if ( (unsigned __int16)wParam == 1008 )
{
    SendMessageA(hWnd, 0x10u, 0, 0);
    return 1;
}
return 1;
}

//根据这个枚举出5位数字下的一个正确密码
#include <iostream>
using namespace std;
int func(char *p)
{
      int a=0, b=0, c=0;
      char buf = { 0 };
      int i = 0;
      do
      {
                a = *p - '0';
                buf = a;
                c = a + 10 * c;
                p++;

      } while (*p);
      return c;
}
int main()
{
      char a, b, c, d, e;
      char buf = { 0 };
      for (a = '0'; a <= '9'; a++)
                for (b = '0'; b <= '9'; b++)
                        for (c = '0'; c <= '9'; c++)
                              for (d = '0'; d <= '9'; d++)
                                        for (e = '0'; e <= '9'; e++)
                                        {
                                                buf = a;
                                                buf = b;
                                                buf = c;
                                                buf = d;
                                                buf = e;

                                                int ret = func(buf);
                                                if ((ret^0x2468) == 1)
                                                {
                                                      cout << "find" << endl;
                                                      cout << a << b << c << d << e << "ret:" << ret << endl;
                                                }
                                                
                                        }
      return 0;
}


find
09321ret:9321

低调的菜鸡 发表于 2019-3-23 22:11

hbwwt 发表于 2019-3-23 22:05
不明白有啥用哦

大佬。。。你都注册这么久了。我实在很难跟你解释这个有啥用。。。:rggrg

跌宕起伏 发表于 2019-3-24 02:55



直接下了MessageBox断点

低调的菜鸡 发表于 2019-3-24 09:20

跌宕起伏 发表于 2019-3-24 02:55
直接下了MessageBox断点

哈哈,还能这么玩的么,阔以

低调的菜鸡 发表于 2019-3-24 09:22

天阶 发表于 2019-3-23 23:05
感谢楼主辛苦分享!也请楼主给我这样的新人普及下该程序的作用及使用方法!谢谢!

这个东西就是拿着练习逆向技术的。。如何分析程序保护,以及如何破解程序的注册机制,当然,由于编写者都不怎么专业,比起市面上的辅助这些少了很多检测技术,所以适合练手。

低调的菜鸡 发表于 2019-3-24 09:25

跌宕起伏 发表于 2019-3-24 02:55
直接下了MessageBox断点

考虑不周了,当时想用个对话框来提示信息的,哈哈,为了省事儿直接用的messagebox,没想到这么容易就被爆破了

l1679668663 发表于 2019-3-24 10:14

不明白有什么用的   看帖子上面的蓝字   那不是有介绍吗

byh3025 发表于 2019-3-24 12:42

那么多的坑让我这样的小白去跳,有意思吗

低调的菜鸡 发表于 2019-3-24 14:56

monvvv 发表于 2019-3-24 13:04
稍微弄了一下,这个用的算是挺普遍的算法模式了。

代码:


很强啊,老哥,哈哈哈,基本上和我写的注册机一样了:lol
页: [1] 2 3
查看完整版本: 新人第一次发一个简单的CM【注册码方式】