pk8900 发表于 2017-12-17 10:44

[反汇编练习] 160个CrackMe之048(DueList.3.exe)算法分析及注册机编写

本帖最后由 pk8900 于 2017-12-17 11:44 编辑

      今天,继续研究 了【适合破解新手的160个crackme练手】,本文内容为第48个CrackMe: DueList.3.exe,论坛没有关于这个CrackMe的帖子,于是写了这篇帖子,分享一下我的分析过程及注册机编写方法,总体来说写注册机比分析过程更难一些(因为我的编程水平不咋的)。
【crackme简介】
       下载地址:http://pan.baidu.com/share/link?shareid=541269&uk=4146939145
       MASM32 / TASM32编写,无壳,是一个选择框式验证方式,打开有两排选择框,一排9个,共十八个,有Check按钮和Close按钮。
      分析工具:X64dbg,PE Explorer 注册机编写:VS2013
【crackme截图】

【算法分析过程】
       这个难度不太大,按星级估计算是1星的吧,点击Check按钮,有提示文字:"Your registration info is invalid... Please support shareware authors by buying software!",有字符串,从这里入手直接有效。通过搜索字符串,定位到程序关键代码位置:
00401127 | 0F BE 8E FE 20 40 00      | movsx ecx, byte ptr ds:    | 0x4020FE地址18个字节值为18个复选框对应的值
0040112E | 83 F9 4D                  | cmp ecx, 0x4D                            | 4D:'M' 最后一个复选框之后的值,用来检测结束
00401131 | 74 2F                     | je duelis.401162                         |
00401133 | 89 0D 5E 21 40 00         | mov dword ptr ds:, ecx         | 保存当前字节值
00401139 | 51                        | push ecx                                 | int nIDButton
0040113A | FF 75 08                  | push dword ptr ss:            | HANDLE hDlg
0040113D | E8 D0 01 00 00            | call <duelis.IsDlgButtonChecked>         | IsDlgButtonChecked    复选框状态
00401142 | 46                        | inc esi                                  |
00401143 | 83 F8 00                  | cmp eax, 0x0                           | 判断复选框状态
00401146 | 74 DF                     | je duelis.401127                         | 未选中 下一个
00401148 | A1 5E 21 40 00            | mov eax, dword ptr ds:         | EAX=当前复选框的值
0040114D | 0F BE 8E FE 20 40 00      | movsx ecx, byte ptr ds:    | ECX下一个复选框的值
00401154 | 0F AF C1                  | imul eax, ecx                            | EAX*ECX
00401157 | 0F AF C6                  | imul eax, esi                            | EAX*计数器N
0040115A | 01 05 62 21 40 00         | add dword ptr ds:, eax         | 结果累加至402162
00401160 | EB C5                     | jmp duelis.401127                        |
00401162 | A1 62 21 40 00            | mov eax, dword ptr ds:         |
00401167 | 6B C0 4D                  | imul eax, eax, 0x4D                      | 402162值*0x4D
0040116A | 3D 66 54 F3 00            | cmp eax, 0xF35466                        | 与:0xF35466比较,相同则成功
0040116F | 75 20                     | jne duelis.401191                        |
00401171 | 68 00 20 00 00            | push 0x2000                              |
00401176 | 68 01 20 40 00            | push duelis.402001                     | 402001:"Duelist's Crackme #3"
0040117B | 68 17 20 40 00            | push duelis.402017                     | 402017:"Congratulations! Please send a screenshot of your solution to duelist@beer.com!"
00401180 | 6A 00                     | push 0x0                                 |
00401182 | E8 55 01 00 00            | call <duelis.MessageBoxA>                |
00401187 | B8 01 00 00 00            | mov eax, 0x1                           |
0040118C | E9 69 FF FF FF            | jmp duelis.4010FA                        |
00401191 | 68 00 20 00 00            | push 0x2000                              |
00401196 | 68 01 20 40 00            | push duelis.402001                     | 402001:"Duelist's Crackme #3"
0040119B | 68 68 20 40 00            | push duelis.402068                     | 402068:"Your registration info is invalid... Please support shareware authors by buying software!"
004011A0 | 6A 00                     | push 0x0                                 |
004011A2 | E8 35 01 00 00            | call <duelis.MessageBoxA>                |
004011A7 | B8 00 00 00 00            | mov eax, 0x0                           |
004011AC | E9 49 FF FF FF            | jmp duelis.4010FA                        |
      代码很简短,经过跟踪分析,注册的算法为:
      程序的18个复选框,分别对应内存中18个连续的字节值(实际上是复选框的ID),后面还有一个为4D:'M',用来累加计算和判断循环结束,依次为:{
0x16, 0x49, 0x5E, 0x15, 0x27, 0x26, 0x21, 0x25, 0x1D, 0x59, 0x53, 0x37, 0x31, 0x48, 0x5D, 0x0C, 0x61, 0x52, 0x4D};,从第一个复选框开始, 保存当前字节值,若选中,则用当前字节值*下一个字节值再*当位位置,乘积累加至402162,若没选中,继续下一个。最后的累加值402162*0x4D后与0xF35466比较,相同则成功。
   程序右边标签提示:"You should use a resource editor!",意思是你需要一个资源修改器,我最开始没有明白为什么需要,在注册机写完以后,验证却没通过时,才明白,界面上的复选框并不和内存中那串复选框ID中相对应,确实需要一个工具来查看复选框的ID,我使用的是PE Explorer,查看过程看下图:

【注册机编写过程】
      算法过程很简单,但注册机不太好写,这应该算是一个组合的问题,反推最终比较结果:0xF35466除0x4D=0x328FE,接下来分别计算每个复选框对应的累加值即check*check*n,接下来的组合情况,我用了递归方法来穷举可能的组合。
C++代码如下:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include <vector>
using namespace std;
void print(vector<int> &tmp)          //打印验证成功的结果
{
      int y = 0;
      for (vector<int>::iterator x = tmp.begin(); x < tmp.end(); x++)
      {
                if (y == 9)
                {
                        cout << endl;
                        y = 0;
                }
                y++;
                cout << *x << "   ";
      }
      cout<< endl << "-------------------------------------------------------" << endl;
}
void calc(const vector<int> v, vector<int> base, int x_begin, int x_end, long src_value)
{
      vector<int> tmp(base);
      long end_v = src_value;
      for (int x = x_begin; x < x_end; x++)
      {   
                for (int y = 0; y <= 1; y++)
                {
                        tmp = y;
                        if (y==1)
                        end_v = end_v - v;
                              if (end_v == 0)
                        {
                              print(tmp);          //打印成功结果
                              break;
                        }
                              if (end_v < 0)
                              break;
                              if (end_v > 0 && x+1<x_end)
                                        calc(v, tmp, x + 1, x_end, end_v);   //进行递归循环
                }
      }
}

int main()
{
      //代码运行中的控件值顺序
      int Check_value[] = {0x16, 0x49, 0x5E, 0x15, 0x27, 0x26, 0x21, 0x25, 0x1D, 0x59, 0x53, 0x37, 0x31, 0x48, 0x5D, 0x0C,0x61, 0x52, 0x4D};
      //代码运行中的控件值顺序
      int value_D[] = {0x16, 0x49, 0x5E, 0x15, 0x27, 0x26, 0x21, 0x25, 0x1D, 0x59, 0x53, 0x37, 0x31, 0x48, 0x5D, 0x0C,0x61, 0x52, 0x4D};               
      //界面上的控件位置
      int value_J[] = {97,73,94,22,37,38,33,89,83,21,55,49,72,93,12,82,39,29,      0x4D };
      vector<int> check(18,0);
      long end_value = 0x328FE;    //最终比较值
      for (int x = 0; x < 18; x++)
      {                         //计算出每个复选框对应的值
                Check_value *= Check_value;
                Check_value *= (x + 1);
      }
      vector <int> v_value(18,0);
      for (int x = 0; x < 18; x++)   //按实际位置 重新排序控件值
                for (int y = 0; y < 18; y++)
                {
                        if (value_J == value_D)
                              v_value = Check_value;
                }
      calc(v_value, check, 0, 18, end_value);
      cout << "calc is over!" << endl;
      system("pause");
}
最后附上成功通过的截图:



          欢迎大家回贴交流。

wenwen520 发表于 2019-4-20 07:55

本帖最后由 wenwen520 于 2019-4-20 07:59 编辑

这个算法 我研究下了,你这里的0x328FE写的不是很详细,我觉得你应该告诉大家这个是是用0xF35466除以0x4D的结果

pk8900 发表于 2020-8-24 06:55

simdabo 发表于 2020-8-23 12:52
链接没有了。。
到这个帖子里下载
https://www.52pojie.cn/thread-709699-1-1.html

rendercc 发表于 2017-12-17 10:57

谢谢@Thanks!

shmilyshirley 发表于 2017-12-17 14:43

厉害了!

zbnysjwsnd8 发表于 2017-12-17 17:30

学习了。。。
支持楼主!

rake_yin 发表于 2017-12-17 17:42

支持楼主!@Thanks!

zakang 发表于 2017-12-17 23:14

rake_yin 发表于 2017-12-17 17:42
支持楼主!@Thanks!

兄弟,咱俩头像有点像:lol

ABB327 发表于 2017-12-18 14:04

非常感谢!

malong213 发表于 2017-12-18 18:38

谢谢分享!

cy666 发表于 2017-12-18 22:14


谢谢分享!

ziye 发表于 2017-12-20 16:13

厉害了大神。。。。。
页: [1] 2
查看完整版本: [反汇编练习] 160个CrackMe之048(DueList.3.exe)算法分析及注册机编写