前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >菜鸟 学注册机编写之 “MD5”

菜鸟 学注册机编写之 “MD5”

作者头像
我是小三
发布2018-08-08 10:28:25
4700
发布2018-08-08 10:28:25
举报
文章被收录于专栏:逆向与安全逆向与安全

测试环境  系统: xp sp3

 调试器 :od 1.10

sc_office_2003_pro 高手不要见笑,仅供小菜玩乐,有不对或不足的地方还请多多指教,不胜感激!   

一:定位关键CALL

1. 因为该软件是word插件,所以用OD载入word.exe,F9运行,运行后如下图:

2.  点击按钮”Save As PDF”出现如下界面

3. 点击”Register”随便输入用户名与注册码,如下图:

4.点击 “暂停”  点击 “K” ,来到如下图的地方

5.选择”MessageBoxExW” 右键 “显示调用”,然后在函数尾下好断点,F9运行,点”确定”,就会被断下

6.接下来就是一直F8单步走,来到如下图的地方

7.往上找就能找到关键跳与关键CALL,如下图

8.在关键CALL下好断点后重新载入OD, F9运行,随便输入用户名与注册码,接着就是分析算法了

二:算法分析

1.首先将注册码中含有小写字母转换成大写

代码语言:javascript
复制
1010EC3B           8BC6            mov eax,esi

1010EC3D           66:391E         cmp word ptr ds:[esi],bx                 ; ---将字母转换成大写

1010EC40           74 1B           je short doc2pdf.1010EC5D

1010EC42           0FB708          movzx ecx,word ptr ds:[eax]              ; 判断并取字符

1010EC45           83F9 61         cmp ecx,0x61                             ; ECX小于a 就跳

1010EC48           72 0B           jb short doc2pdf.1010EC55

1010EC4A           83F9 7A         cmp ecx,0x7A                             ; ECX大于z 就跳

1010EC4D           77 06           ja short doc2pdf.1010EC55

1010EC4F           83C1 E0         add ecx,-0x20                            ; 满足条件就将ECX and -0x20

1010EC52           66:8908         mov word ptr ds:[eax],cx                 ; 存放

1010EC55           83C0 02         add eax,0x2

1010EC58           66:3918         cmp word ptr ds:[eax],bx

1010EC5B         ^ 75 E5           jnz short doc2pdf.1010EC42               ; 判断是否完成

1010EC5D           33C0            xor eax,eax

1010EC5F           E9 E2000000     jmp doc2pdf.1010ED46

2.分析关键 call doc2pdf.100182D0 ,  F7跟进

代码语言:javascript
复制
10018376 E8 25F0FFFF     call <doc2pdf.strcat>    ;用户名与固定字符串拼接

 

1001741A E8 F1F3FEFF     call <doc2pdf.MtoB>     ; 将用户名中字母转换成大写

1010EC3D           66:391E         cmp word ptr ds:[esi],bx                 ; ---将字母转换成大写

1010EC40           74 1B           je short doc2pdf.1010EC5D

1010EC42           0FB708          movzx ecx,word ptr ds:[eax]              ; 判断并取字符

1010EC45           83F9 61         cmp ecx,0x61                             ; ECX小于a 就跳

1010EC48           72 0B           jb short doc2pdf.1010EC55

1010EC4A           83F9 7A         cmp ecx,0x7A                             ; ECX大于z 就跳

1010EC4D           77 06           ja short doc2pdf.1010EC55

1010EC4F           83C1 E0         add ecx,-0x20                            ; 满足条件就将ECX and -0x20

1010EC52           66:8908         mov word ptr ds:[eax],cx                 ; 存放

1010EC55           83C0 02         add eax,0x2

1010EC58           66:3918         cmp word ptr ds:[eax],bx

1010EC5B         ^ 75 E5           jnz short doc2pdf.1010EC42               ; 判断是否完成

1010EC5D           33C0            xor eax,eax

1010EC5F           E9 E2000000     jmp doc2pdf.1010ED46

 

 

1001744B           E8 A0280000     call <doc2pdf.WideCharToMultiByte>       ; 将用户名宽字符转换成单字符

 

1001745E           E8 FD280000     call <doc2pdf.Remove_digital>            ; 去掉用户输入用户名中包含的数字

10019D60 <doc2pd>  55              push ebp

10019D61           8BEC            mov ebp,esp

10019D63           56              push esi

10019D64           8B75 08         mov esi,dword ptr ss:[ebp+0x8]

10019D67           85F6            test esi,esi

10019D69           74 37           je short doc2pdf.10019DA2

10019D6B           8B55 0C         mov edx,dword ptr ss:[ebp+0xC]

10019D6E           85D2            test edx,edx

10019D70           74 30           je short doc2pdf.10019DA2

10019D72           8A0A            mov cl,byte ptr ds:[edx]

10019D74           8BC6            mov eax,esi

10019D76           84C9            test cl,cl

10019D78           74 25           je short doc2pdf.10019D9F

10019D7A           8D9B 00000000   lea ebx,dword ptr ds:[ebx]

10019D80           80F9 61         cmp cl,0x61                              ; 判断字符a

10019D83           7C 05           jl short doc2pdf.10019D8A

10019D85           80F9 7A         cmp cl,0x7A                              ; 判断字符z

10019D88           7E 0A           jle short doc2pdf.10019D94

10019D8A           80F9 41         cmp cl,0x41                              ; 字符A

10019D8D           7C 08           jl short doc2pdf.10019D97

10019D8F           80F9 5A         cmp cl,0x5A                              ; 字符Z

10019D92           7F 03           jg short doc2pdf.10019D97

10019D94           880E            mov byte ptr ds:[esi],cl

10019D96           46              inc esi

10019D97           8A4A 01         mov cl,byte ptr ds:[edx+0x1]

10019D9A           42              inc edx

10019D9B           84C9            test cl,cl

10019D9D         ^ 75 E1           jnz short doc2pdf.10019D80

10019D9F           5E              pop esi

10019DA0           5D              pop ebp

10019DA1           C3              retn

1001746D           E8 7E280000     call <doc2pdf.WideCharToMultiByte>       ; 将字串"f4hguNAg"转换成单字符

 

10017485           E8 5D8F0F00     call <doc2pdf.strcat>                    ; 用户名去掉数字与固定字符串连接

101103E7 <doc2pd>  8BFF            mov edi,edi

101103E9           55              push ebp

101103EA           8BEC            mov ebp,esp

101103EC           8B4D 08         mov ecx,dword ptr ss:[ebp+0x8]

101103EF           56              push esi

101103F0           57              push edi

101103F1           85C9            test ecx,ecx

101103F3           74 07           je short doc2pdf.101103FC

101103F5           8B7D 0C         mov edi,dword ptr ss:[ebp+0xC]

101103F8           85FF            test edi,edi

101103FA           75 13           jnz short doc2pdf.1011040F

101103FC           E8 B00F0000     call doc2pdf.101113B1

10110401           6A 16           push 0x16

10110403           5E              pop esi

10110404           8930            mov dword ptr ds:[eax],esi

10110406           E8 B4490000     call doc2pdf.10114DBF

1011040B           8BC6            mov eax,esi

1011040D           EB 41           jmp short doc2pdf.10110450

1011040F           8B55 10         mov edx,dword ptr ss:[ebp+0x10]

10110412           85D2            test edx,edx

10110414           75 05           jnz short doc2pdf.1011041B

10110416           C601 00         mov byte ptr ds:[ecx],0x0

10110419         ^ EB E1           jmp short doc2pdf.101103FC

1011041B           8BF1            mov esi,ecx

1011041D           803E 00         cmp byte ptr ds:[esi],0x0                ; 判断用户是否为0

10110420           74 04           je short doc2pdf.10110426

10110422           46              inc esi

10110423           4F              dec edi

10110424         ^ 75 F7           jnz short doc2pdf.1011041D

10110426           85FF            test edi,edi

10110428         ^ 74 EC           je short doc2pdf.10110416

1011042A           2BF2            sub esi,edx

1011042C           8A02            mov al,byte ptr ds:[edx]

1011042E           880416          mov byte ptr ds:[esi+edx],al             ; ----字符串f4hguNAg与用户名连接

10110431           42              inc edx

10110432           84C0            test al,al

10110434           74 03           je short doc2pdf.10110439

10110436           4F              dec edi

10110437         ^ 75 F3           jnz short doc2pdf.1011042C

10110439           85FF            test edi,edi

1011043B           75 11           jnz short doc2pdf.1011044E

1011043D           C601 00         mov byte ptr ds:[ecx],0x0

10110440           E8 6C0F0000     call doc2pdf.101113B1

10110445           6A 22           push 0x22

10110447           59              pop ecx

10110448           8908            mov dword ptr ds:[eax],ecx

1011044A           8BF1            mov esi,ecx

1011044C         ^ EB B8           jmp short doc2pdf.10110406

1011044E           33C0            xor eax,eax

10110450           5F              pop edi

10110451           5E              pop esi

10110452           5D              pop ebp

10110453           C3              retn

拼接完成后得到字符串 “TESTf4hguNAg”

将拼接完成后的字符传入函数进行计算, F7跟进,观察函数发下如下图所示特征

貌似MD5计算,我们直接让该函数走完,看它会出什么结果,发现函数执行完后与我们用工具直接对字符串” TESTf4hguNAg”进行MD5的结果是一样的。如下图

然后将计算得到的MD5值转换成字符,并且将小写字母转换成大写,如下图

3.查找并替换MD5中的字符

代码语言:javascript
复制
100183E2           6A 5A           push 0x5A                                 ; Z

100183E4           6A 31           push 0x31                                 ; 1

100183E6           8D8D 44FEFFFF   lea ecx,dword ptr ss:[ebp-0x1BC]

100183EC           E8 6FE3FEFF     call <doc2pdf.Find_and_Replace>           ; 查找第1个参数,找到则用第2个替换

1替换成Z

2替换成W

0替换成K

3替换成T

8替换成P

7替换成S

代码语言:javascript
复制
10006760 <doc2pd>  55              push ebp

10006761           8BEC            mov ebp,esp

10006763           83EC 08         sub esp,0x8

10006766           66:8B45 08      mov ax,word ptr ss:[ebp+0x8]

1000676A           53              push ebx

1000676B           57              push edi

1000676C           33FF            xor edi,edi

1000676E           8BD9            mov ebx,ecx

10006770           897D F8         mov dword ptr ss:[ebp-0x8],edi

10006773           66:3B45 0C      cmp ax,word ptr ss:[ebp+0xC]

10006777           74 72           je short doc2pdf.100067EB

10006779           8B03            mov eax,dword ptr ds:[ebx]

1000677B           56              push esi

1000677C           8B70 F4         mov esi,dword ptr ds:[eax-0xC]

1000677F           32C9            xor cl,cl

10006781           3BF7            cmp esi,edi

10006783           7E 65           jle short doc2pdf.100067EA

10006785           66:8B55 08      mov dx,word ptr ss:[ebp+0x8]

10006789           66:391478       cmp word ptr ds:[eax+edi*2],dx            ; 比较MD5值中是否有传进的第1个参数

1000678D           75 37           jnz short doc2pdf.100067C6

1000678F           84C9            test cl,cl

10006791           75 28           jnz short doc2pdf.100067BB

10006793           C645 FF 01      mov byte ptr ss:[ebp-0x1],0x1

10006797           85F6            test esi,esi

10006799           78 5B           js short doc2pdf.100067F6

1000679B           8B03            mov eax,dword ptr ds:[ebx]                ; ----MD5值地址

1000679D           8B50 F8         mov edx,dword ptr ds:[eax-0x8]

100067A0           B9 01000000     mov ecx,0x1

100067A5           2B48 FC         sub ecx,dword ptr ds:[eax-0x4]

100067A8           2BD6            sub edx,esi

100067AA           0BCA            or ecx,edx                                ; 0xA

100067AC           7D 08           jge short doc2pdf.100067B6

100067AE           56              push esi

100067AF           8BCB            mov ecx,ebx

100067B1           E8 BAEDFFFF     call doc2pdf.10005570

100067B6           8B03            mov eax,dword ptr ds:[ebx]                ; ---MD5值地址

100067B8           8A4D FF         mov cl,byte ptr ss:[ebp-0x1]

100067BB           66:8B55 0C      mov dx,word ptr ss:[ebp+0xC]              ; ---函数传进来的第2个参数

100067BF           FF45 F8         inc dword ptr ss:[ebp-0x8]

100067C2           66:891478       mov word ptr ds:[eax+edi*2],dx            ; 将传进的第2个参数替换掉MD5中查到的值

100067C6           8D7C3F 02       lea edi,dword ptr ds:[edi+edi+0x2]

100067CA           D1FF            sar edi,1

100067CC           3BFE            cmp edi,esi                               ; 判断是否查找结束

100067CE         ^ 7C B5           jl short doc2pdf.10006785

100067D0           84C9            test cl,cl

100067D2           74 16           je short doc2pdf.100067EA

100067D4           85F6            test esi,esi

100067D6           78 1E           js short doc2pdf.100067F6

100067D8           8B03            mov eax,dword ptr ds:[ebx]

100067DA           3B70 F8         cmp esi,dword ptr ds:[eax-0x8]

100067DD           7F 17           jg short doc2pdf.100067F6

100067DF           8970 F4         mov dword ptr ds:[eax-0xC],esi

100067E2           8B03            mov eax,dword ptr ds:[ebx]

100067E4           33C9            xor ecx,ecx

100067E6           66:890C70       mov word ptr ds:[eax+esi*2],cx

100067EA           5E              pop esi

100067EB           8B45 F8         mov eax,dword ptr ss:[ebp-0x8]

100067EE           5F              pop edi

100067EF           5B              pop ebx

100067F0           8BE5            mov esp,ebp

100067F2           5D              pop ebp

100067F3           C2 0800         retn 0x8

 

 

//--获得注册码

1001844B           E8 90D9FEFF     call <doc2pdf.Get12Char>                  ; --获取MD5替换后前12字节

10018450           6A 0C           push 0xC

10018452           8D8D 38FEFFFF   lea ecx,dword ptr ss:[ebp-0x1C8]

10018458           51              push ecx

10018459           8BCB            mov ecx,ebx

1001845B           C645 FC 02      mov byte ptr ss:[ebp-0x4],0x2

1001845F           E8 7CD9FEFF     call <doc2pdf.Get12Char>                  ; --获取用户输入注册码12字节

10018464           8B00            mov eax,dword ptr ds:[eax]

4.比较注册码,如下图

代码语言:javascript
复制
1010EB5D           8BFF            mov edi,edi
1010EB5F           55              push ebp
1010EB60           8BEC            mov ebp,esp
1010EB62           833D 78EA1810 0>cmp dword ptr ds:[0x1018EA78],0x0
1010EB69           56              push esi
1010EB6A           75 69           jnz short doc2pdf.1010EBD5
1010EB6C           8B75 08         mov esi,dword ptr ss:[ebp+0x8]
1010EB6F           85F6            test esi,esi
1010EB71           75 17           jnz short doc2pdf.1010EB8A
1010EB73           E8 39280000     call doc2pdf.101113B1
1010EB78           C700 16000000   mov dword ptr ds:[eax],0x16
1010EB7E           E8 3C620000     call doc2pdf.10114DBF
1010EB83           B8 FFFFFF7F     mov eax,0x7FFFFFFF
1010EB88           EB 5B           jmp short doc2pdf.1010EBE5
1010EB8A           8B4D 0C         mov ecx,dword ptr ss:[ebp+0xC]
1010EB8D           85C9            test ecx,ecx
1010EB8F         ^ 74 E2           je short doc2pdf.1010EB73
1010EB91           2BF1            sub esi,ecx
1010EB93           0FB7040E        movzx eax,word ptr ds:[esi+ecx]           ; 取MD5后生成的注册码
1010EB97           83F8 41         cmp eax,0x41                              ; A
1010EB9A           72 0D           jb short doc2pdf.1010EBA9
1010EB9C           83F8 5A         cmp eax,0x5A                              ; Z
1010EB9F           77 08           ja short doc2pdf.1010EBA9
1010EBA1           83C0 20         add eax,0x20                              ; 转换成小写
1010EBA4           0FB7D0          movzx edx,ax                              ; 给值dx
1010EBA7           EB 02           jmp short doc2pdf.1010EBAB
1010EBA9           8BD0            mov edx,eax
1010EBAB           0FB701          movzx eax,word ptr ds:[ecx]               ; 取用户输入的注册码
1010EBAE           83F8 41         cmp eax,0x41                              ; A
1010EBB1           72 0B           jb short doc2pdf.1010EBBE
1010EBB3           83F8 5A         cmp eax,0x5A                              ; Z
1010EBB6           77 06           ja short doc2pdf.1010EBBE
1010EBB8           83C0 20         add eax,0x20                              ; 转换成小写
1010EBBB           0FB7C0          movzx eax,ax
1010EBBE           83C1 02         add ecx,0x2
1010EBC1           66:85D2         test dx,dx                                ; 判断是否为零
1010EBC4           74 05           je short doc2pdf.1010EBCB
1010EBC6           66:3BD0         cmp dx,ax                                 ; 比较注册码
1010EBC9         ^ 74 C8           je short doc2pdf.1010EB93
1010EBCB           0FB7C8          movzx ecx,ax
1010EBCE           0FB7C2          movzx eax,dx
1010EBD1           2BC1            sub eax,ecx
1010EBD3           EB 10           jmp short doc2pdf.1010EBE5
1010EBD5           6A 00           push 0x0
1010EBD7           FF75 0C         push dword ptr ss:[ebp+0xC]
1010EBDA           FF75 08         push dword ptr ss:[ebp+0x8]
1010EBDD           E8 78FEFFFF     call doc2pdf.1010EA5A
1010EBE2           83C4 0C         add esp,0xC
1010EBE5           5E              pop esi
1010EBE6           5D              pop ebp
1010EBE7           C3              retn

总结

1.  将用户输入的注册码中小写字母转换成大写

2.  将用户名中数字去掉并将字母转换成大写

3.  将用户名与固定字符拼接

4.  将拼接后的字符进行MD5计算并且将值转换成字符

5.  查找替换MD5字符

6.  取MD5前12字节做注册码

注册机编写

代码语言:javascript
复制
#include <stdio.h>
#include <windows.h>
#include <string.h>
#include "md5.h"


/**************************************************************************** 
函数名称: hex_to_str 
函数功能: 十六进制转字符串 
输入参数: ptr 字符串 buf 十六进制 len 十六进制字符串的长度。 
输出参数: 无 
*****************************************************************************/  

void hex_to_str(char *ptr,unsigned char *buf,int len)  
{  
    int i=0;
    for(i = 0; i < len; i++)  
    {  
        sprintf(ptr, "%02x",buf[i]);  
        ptr += 2;  
    }  
} 


/*
MD5:    转换成大写的MD5值
Val:    要查找到值
RpVal:  要替换的值    
*/
void FindVal_Replace(char* MD5, char Val, char RpVal)
{

    int i = 0;

    if (NULL == MD5 || 0 == Val || 0 == RpVal)
    {
        return;
    }


    for (i=0; i<strlen(MD5); i++)
    {
        if ( Val == MD5[i] )
        {
            MD5[i] = RpVal;
        }
    }
}

int main(int argc, char* argv[])
{
    char UserName[256] = {0};
    char License[256] = {0};
    char BigStrName[256] = {0};
    char MD5[256] = {0};

    //与用户名拼凑
    char *ConstString = "f4hguNAg";

    MD5_CTX context;
    long dtLength;
    char szHash[256] = {0};
    TCHAR szBuffer[256] = {0};
    int i = 0;
    int n = 0;
    char j = 0;
    printf("---------doc2pdf2 V5.0注册机-------\n\n");

    printf("请输入用户名: ");
    scanf("%s",UserName);
    if ( strlen(UserName) >= 240 )
    {
        printf("用户名不能超过240位\n");
        return -1;
    }


    for (i=0; i<strlen(UserName); i++)
    {
        //--是数字
        if (isdigit(UserName[i]) != 0)
        {
            continue;
        }
        else
        {
            //--是字母
            if ( isalpha(UserName[i])!=0)
            {
                //--判断是大小写并转换成大写
                if(UserName[i]>='a'&& UserName[i]<='z') 
                {
                        BigStrName[i] = UserName[i] - 32;
                        continue;
                }
            }

        }
    }
    

    //--用户名与固定字符拼凑并计算MD5值
    strcat(BigStrName,ConstString);
//    strncpy(BigStrName+strlen(BigStrName), ConstString, strlen(ConstString));

    //计算MD5值
    MD5Init(&context);
    MD5Update(&context, BigStrName, strlen(BigStrName));
    MD5Final(szHash, &context);


    //--将MD5值转换成字符
    hex_to_str(MD5, szHash, strlen(szHash));


    //--将MD5字符串转换成大写
    for (n=0; n<strlen(MD5); n++)
    {
        //--判断是大小写并转换成大写
        if(MD5[n]>='a'&& MD5[n]<='z') 
        {
            MD5[n] -= 32;
            continue;
        }
    }

    //--查找并替换掉MD5字符
    FindVal_Replace(MD5, '1', 'Z');//1替换成Z

    FindVal_Replace(MD5, '2', 'W');//2替换成W

    FindVal_Replace(MD5, '0', 'K');//0替换成K

    FindVal_Replace(MD5, '3', 'T');//3替换成T

    FindVal_Replace(MD5, '8', 'P');//8替换成P

    FindVal_Replace(MD5, '7', 'S');//7替换成S

    //-拷贝注册码
    strncpy(License, MD5, 12);

    printf("注册码:%s\n",License);
    system("pause");

    return 0;
}

测试注册机

输入用户名 test 生成注册码

注册成功

样本及注册机源码下载

http://yunpan.cn/cAFbdqsBEYEyr (提取码:2967)

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2014-11-17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档