发新话题
打印

[转载]Photo Screensaver Maker V5.0.0 注册算法分析

[转载]Photo Screensaver Maker V5.0.0 注册算法分析

信息来源:看雪学院


【软件名称】Photo Screensaver Maker V5.0.0
【破文作者】forever[RCT]
【编程语言】VC
【保护方式】RSA256
【使用工具】ida4.6,ollydbg1.1
【软件简介】一款幻灯屏幕保护程序制作软件,你可以用它来制作带照片、音乐和文本的屏保。支持的图片格式:jpg,gif,bmp,png,tif,tga,pcx。支持音频格式:mp3,midi和wav。可以为图片添加文本,并为图片设置各种转场过渡效果
【下载地址】http://www3.skycn.com/soft/22288.html
【破文正文】这个软件不错,使用简单,做出的屏保有很多特效。
        破解的基本步骤如下:
        1。用peid检测一下编程语言,并且顺便用插件查看一下使用算法。编程语言是VC++,检测到的算法是CRC。不过软件实际使用的算
          法却不是CRC。
        2。运行程序,看看注册过程能提供给我们什么信息。注册需要注册名和注册码,没有和硬件绑定。填入注册名,随便填一个注册码:
          12345678,弹出一个出错的对话框,给出提示信息:Invalid user name or register code。
        3。用ida载入主程序分析。分析完后在字符串列表里找到Invalid user name or register code这个字符串。来到引用该字符串的地
          方,如下:
===================================================================================================           
.text:0042B6D1            push   1
.text:0042B6D3            mov    ecx, esi
.text:0042B6D5            call   CWnd::UpdateData(int)
.text:0042B6DA            lea    edi, [esi+64h]
.text:0042B6DD            push   0Ah
.text:0042B6DF            mov    ecx, edi
.text:0042B6E1            call   MFC42_6874
.text:0042B6E6            push   0Dh
.text:0042B6E8            mov    ecx, edi
.text:0042B6EA            call   MFC42_6874
.text:0042B6EF            push   9
.text:0042B6F1            mov    ecx, edi
.text:0042B6F3            call   MFC42_6874
.text:0042B6F8            push   20h
.text:0042B6FA            mov    ecx, edi
.text:0042B6FC            call   MFC42_6874
.text:0042B701            mov    eax, [edi]
.text:0042B703            mov    ecx, [esi+60h]
.text:0042B706            push   eax
.text:0042B707            push   ecx
.text:0042B708            call   sub_402752    //这里就是判断注册是否成功的函数了。成功返回1,失败返回0
.text:0042B70D            add    esp, 8
.text:0042B710            test   eax, eax
.text:0042B712            jnz    short loc_42B73F
.text:0042B714            push   40h
.text:0042B716            push   offset aSorry  ; "Sorry"
.text:0042B71B            push   offset aInvalidUserNam ; "Invalid user name or register code"
.text:0042B720            mov    ecx, esi
.text:0042B722            call   CWnd::MessageBoxA(char const *,char const *,uint)
.text:0042B727            push   3F3h
.text:0042B72C            mov    ecx, esi
.text:0042B72E            call   CWnd::GetDlgItem(int)
.text:0042B733            mov    ecx, eax
.text:0042B735            call   CWnd::SetFocus(void)
.text:0042B73A            jmp    loc_42B88C
.text:0042B73F
.text:0042B73F loc_42B73F:                  
.text:0042B73F            mov    dword ptr [ebp+0C4h], 1
.text:0042B749            mov    eax, [esi+60h]
.text:0042B74C            push   eax
.text:0042B74D            lea    ecx, [ebp+0CCh]
.text:0042B753            call   CString::operator=(char const *)
.text:0042B758            mov    eax, [esi+60h]
.text:0042B75B            push   eax
.text:0042B75C            lea    eax, [esp+218h]
.text:0042B763            push   offset aLicenseToS ; "License to:%s"
.text:0042B768            push   eax
.text:0042B769            call   ds:sprintf
.text:0042B76F            add    esp, 0Ch
.text:0042B772            lea    ecx, [esp+214h]
.text:0042B779            push   40h
.text:0042B77B            push   offset aThankYou ; "Thank you"
.text:0042B780            push   ecx
.text:0042B781            mov    ecx, esi
.text:0042B783            call   CWnd::MessageBoxA(char const *,char const *,uint)
.text:0042B788            mov    eax, [esi+60h]
.text:0042B78B            lea    edx, [esp+14h]
.text:0042B78F            sub    edx, eax
.text:0042B791
.text:0042B791 loc_42B791:                  
.text:0042B791            mov    cl, [eax]
.text:0042B793            mov    [edx+eax], cl
.text:0042B796            inc    eax
.text:0042B797            test   cl, cl
.text:0042B799            jnz    short loc_42B791
.text:0042B79B            mov    edi, [edi]
.text:0042B79D            lea    ecx, [esp+114h]
.text:0042B7A4            sub    ecx, edi
.text:0042B7A6
.text:0042B7A6 loc_42B7A6:                  
.text:0042B7A6            mov    al, [edi]
.text:0042B7A8            mov    [ecx+edi], al
.text:0042B7AB            inc    edi
.text:0042B7AC            test   al, al
.text:0042B7AE            jnz    short loc_42B7A6
.text:0042B7B0            lea    ecx, [esp+0Ch]
.text:0042B7B4            call   CString::CString(void)
.text:0042B7B9            lea    edx, [esp+10h]
.text:0042B7BD            mov    dword ptr [esp+31Ch], 0
.text:0042B7C8            push   edx
.text:0042B7C9            call   sub_401D5C
.text:0042B7CE            add    esp, 4
.text:0042B7D1            push   eax
.text:0042B7D2            lea    ecx, [esp+10h]
.text:0042B7D6            mov    byte ptr [esp+320h], 1
.text:0042B7DE            call   CString::operator=(CString const &)
.text:0042B7E3            lea    ecx, [esp+10h]
.text:0042B7E7            mov    byte ptr [esp+31Ch], 0
.text:0042B7EF            call   CString::~CString(void)
.text:0042B7F4            lea    eax, [esp+0Ch]
.text:0042B7F8            push   offset aDataRegdata_in ; "data\\regdata.ini" //注册信息保存到regdata.ini里
.text:0042B7FD            lea    ecx, [esp+14h]
.text:0042B801            push   eax
.text:0042B802            push   ecx
.text:0042B803            call   operator+(CString const &,char const *)
.text:0042B808            push   eax
.text:0042B809            lea    ecx, [esp+10h]
.text:0042B80D            mov    byte ptr [esp+320h], 2
.text:0042B815            call   CString::operator=(CString const &)
.text:0042B81A            lea    ecx, [esp+10h]
.text:0042B81E            mov    byte ptr [esp+31Ch], 0
.text:0042B826            call   CString::~CString(void)
.text:0042B82B            mov    edx, [esp+0Ch]
.text:0042B82F            mov    edi, ds:WritePrivateProfileStringA
.text:0042B835            lea    eax, [esp+14h]
.text:0042B839            push   edx
.text:0042B83A            push   eax
.text:0042B83B            push   offset aUserName ; "User name"
.text:0042B840            push   offset aRegister ; "Register"
.text:0042B845            call   edi ; WritePrivateProfileStringA
.text:0042B847            mov    ecx, [esp+0Ch]
.text:0042B84B            lea    edx, [esp+114h]
.text:0042B852            push   ecx
.text:0042B853            push   edx
.text:0042B854            push   offset aRegistrationCo ; "Registration code"
.text:0042B859            push   offset aRegister ; "Register"
.text:0042B85E            call   edi ; WritePrivateProfileStringA
.text:0042B860            mov    eax, [ebp+0]
.text:0042B863            mov    ecx, ebp

   让我们跟进函数402752,来到下面:
   看看下面这段函数,我猜测是RSA算法,并且是RSA256。猜算法并没有什么好的方法,大多是凭经验。
   这段函数我结合ollydbg来分析,并且用我修改的RsaKit来验证。:) 详细分析见注释:
   
===================================================================================================
.text:0042AFF0 loc_42AFF0:                  
.text:0042AFF0            push   0FFFFFFFFh
.text:0042AFF2            push   offset loc_4C3349
.text:0042AFF7            mov    eax, large fs:0
.text:0042AFFD            push   eax
.text:0042AFFE            mov    large fs:0, esp
.text:0042B005            sub    esp, 94h
.text:0042B00B            mov    eax, [esp+0A4h]
.text:0042B012            push   ebx
.text:0042B013            push   esi
.text:0042B014            push   eax
.text:0042B015            lea    ecx, [esp+10h]
.text:0042B019            mov    dword ptr [esp+60h], 0FBF8A47h
.text:0042B021            mov    dword ptr [esp+64h], 234E94C9h
.text:0042B029            mov    dword ptr [esp+68h], 0E4475D85h
.text:0042B031            mov    dword ptr [esp+6Ch], 0DBF030EEh
.text:0042B039            mov    dword ptr [esp+70h], 323B9C06h
.text:0042B041            mov    dword ptr [esp+74h], 0E3D3C333h
.text:0042B049            mov    dword ptr [esp+78h], 0C9BF2B1Ah
.text:0042B051            mov    dword ptr [esp+7Ch], 385AC5EEh  //这里是N
.text:0042B059            call   CString::CString(char const *)  //用户名
.text:0042B05E            mov    ecx, [esp+0B0h]
.text:0042B065            mov    dword ptr [esp+0A4h], 0
.text:0042B070            push   ecx
.text:0042B071            lea    ecx, [esp+0Ch]
.text:0042B075            call   CString::CString(char const *)  //注册码
.text:0042B07A            mov    edx, [esp+0Ch]
.text:0042B07E            mov    esi, ds:_mbscmp
.text:0042B084            push   offset ValueName
.text:0042B089            push   edx
.text:0042B08A            mov    byte ptr [esp+0ACh], 1
.text:0042B092            call   esi ; _mbscmp          //比较用户名是否为空
.text:0042B094            add    esp, 8
.text:0042B097            test   eax, eax
.text:0042B099            jz    loc_42B2AE
.text:0042B09F            mov    eax, [esp+8]
.text:0042B0A3            push   offset ValueName
.text:0042B0A8            push   eax
.text:0042B0A9            call   esi ; _mbscmp          //比较注册码是否为空
.text:0042B0AB            add    esp, 8
.text:0042B0AE            test   eax, eax
.text:0042B0B0            jz    loc_42B2AE
.text:0042B0B6            push   edi
.text:0042B0B7            push   0
.text:0042B0B9            lea    ecx, [esp+44h]
.text:0042B0BD            call   sub_4016D1            //初始化大数1
.text:0042B0C2            push   0
.text:0042B0C4            lea    ecx, [esp+4Ch]
.text:0042B0C8            mov    byte ptr [esp+0ACh], 2
.text:0042B0D0            call   sub_4016D1            //初始化大数2
.text:0042B0D5            mov    bl, 3
.text:0042B0D7            push   10001h
.text:0042B0DC            lea    ecx, [esp+5Ch]
.text:0042B0E0            mov    [esp+0ACh], bl
.text:0042B0E7            call   sub_4016D1            //初始化大数E(10001)
.text:0042B0EC            lea    ecx, [esp+58h]         //我根据这个猜测是RSA
.text:0042B0F0            mov    byte ptr [esp+0A8h], 4
.text:0042B0F8            push   ecx
.text:0042B0F9            lea    ecx, [esp+4Ch]
.text:0042B0FD            call   sub_401D07            //复制大数E到大数2
.text:0042B102            lea    ecx, [esp+58h]
.text:0042B106            mov    [esp+0A8h], bl
.text:0042B10D            call   sub_401BC7
.text:0042B112            lea    edx, [esp+60h]
.text:0042B116            push   8
.text:0042B118            push   edx
.text:0042B119            lea    ecx, [esp+48h]
.text:0042B11D            call   sub_40276B            //大数1赋值为N
.text:0042B122            mov    ecx, 8
.text:0042B127            xor    eax, eax
.text:0042B129            lea    edi, [esp+18h]         //这里32个字节清零,准备读入注册码
.text:0042B12D            lea    edx, [esp+2Ch]
.text:0042B131            rep stosd
.text:0042B133            lea    eax, [esp+34h]
.text:0042B137            lea    ecx, [esp+30h]
.text:0042B13B            push   eax
.text:0042B13C            push   ecx
.text:0042B13D            lea    eax, [esp+30h]
.text:0042B141            push   edx
.text:0042B142            lea    ecx, [esp+30h]
.text:0042B146            push   eax
.text:0042B147            lea    edx, [esp+30h]
.text:0042B14B            push   ecx
.text:0042B14C            lea    eax, [esp+30h]
.text:0042B150            push   edx
.text:0042B151            mov    edx, [esp+24h]
.text:0042B155            lea    ecx, [esp+30h]
.text:0042B159            push   eax
.text:0042B15A            push   ecx
.text:0042B15B            push   offset a08lx08lx08lx08 ; "%08lX-%08lX-%08lX-%08lX-%08lX-%08lX-%08"...
.text:0042B160            push   edx
.text:0042B161            call   ds:sscanf           //读入注册码,从这里可以看出注册码的格式
.text:0042B167            mov    eax, [esp+50h]        //第五组注册码
.text:0042B16B            mov    ecx, [esp+4Ch]        //第四组注册码
.text:0042B16F            mov    edi, [esp+48h]        //第三组注册码
.text:0042B173            mov    edx, [esp+44h]        //第二组注册码
.text:0042B177            add    eax, ecx            //第五组加上第四组
.text:0042B179            mov    ecx, [esp+5Ch]        //第八组注册码
.text:0042B17D            add    eax, edi            //和加上第三组
.text:0042B17F            mov    edi, [esp+58h]        //第七组注册码
.text:0042B183            add    eax, edx            //和加上第二组
.text:0042B185            mov    edx, [esp+54h]        //第六组注册码
.text:0042B189            xor    ecx, eax            //和异或上第八组注册码
.text:0042B18B            mov    eax, [esp+40h]        //第一组注册码
.text:0042B18F            add    esp, 28h
.text:0042B192            add    edx, eax            //第六组加上第一组
.text:0042B194            mov    [esp+34h], ecx        //异或后的结果保存到原来第八组的位置(8=(5+4+3+2)xor8)
.text:0042B198            xor    edi, edx            //和异或上第七组
.text:0042B19A            push   0
.text:0042B19C            lea    ecx, [esp+3Ch]
.text:0042B1A0            mov    [esp+34h], edi        //异或后的结果保存到原来第七组的位置(7=(1+6)xor7)
.text:0042B1A4            call   sub_4016D1          //初始化大数3
.text:0042B1A9            lea    ecx, [esp+18h]
.text:0042B1AD            push   8
.text:0042B1AF            push   ecx      
.text:0042B1B0            lea    ecx, [esp+40h]
.text:0042B1B4            mov    byte ptr [esp+0B0h], 5
.text:0042B1BC            call   sub_40276B          //大数3读入处理后的注册码
.text:0042B1C1            lea    edx, [esp+38h]
.text:0042B1C5            lea    eax, [esp+50h]
.text:0042B1C9            push   edx               //大数3
.text:0042B1CA            push   eax               //用来保存结果
.text:0042B1CB            lea    ecx, [esp+48h]
.text:0042B1CF            call   loc_402A0E          //RSA运算
.text:0042B1D4            mov    ecx, 8
.text:0042B1D9            xor    eax, eax
.text:0042B1DB            lea    edi, [esp+18h]
.text:0042B1DF            push   8
.text:0042B1E1            rep stosd                //清零32个字节缓冲区
.text:0042B1E3            lea    ecx, [esp+1Ch]
.text:0042B1E7            mov    byte ptr [esp+0ACh], 6
.text:0042B1EF            push   ecx
.text:0042B1F0            lea    ecx, [esp+58h]
.text:0042B1F4            call   sub_401C99          //输出RSA运算结果
.text:0042B1F9            mov    ecx, 8
.text:0042B1FE            xor    eax, eax
.text:0042B200            lea    edi, [esp+80h]
.text:0042B207            rep stosd
.text:0042B209            pop    edi
.text:0042B20A
.text:0042B20A loc_42B20A:                  
.text:0042B20A            mov    dl, [esp+eax+17h]      //转换大小尾
.text:0042B20E            mov    cl, [esp+eax+16h]
.text:0042B212            mov    [esp+eax+7Ch], dl
.text:0042B216            mov    edx, [esp+eax+14h]
.text:0042B21A            mov    [esp+eax+7Dh], cl
.text:0042B21E            mov    cl, [esp+eax+14h]
.text:0042B222            shr    edx, 8
.text:0042B225            mov    [esp+eax+7Eh], dl
.text:0042B229            mov    [esp+eax+7Fh], cl
.text:0042B22D            add    eax, 4
.text:0042B230            cmp    eax, 20h
.text:0042B233            jl    short loc_42B20A
.text:0042B235            lea    edx, [esp+7Ch]
.text:0042B239            lea    ecx, [esp+10h]
.text:0042B23D            push   edx
.text:0042B23E            call   CString::CString(char const *)
.text:0042B243            mov    eax, [esp+10h]
.text:0042B247            mov    ecx, [esp+0Ch]
.text:0042B24B            push   eax              //RSA结果
.text:0042B24C            push   ecx              //用户名
.text:0042B24D            call   esi ; _mbscmp       //比较两个字符串是否相等
.text:0042B24F            add    esp, 8
.text:0042B252            lea    ecx, [esp+10h]
.text:0042B256            test   eax, eax
.text:0042B258            mov    byte ptr [esp+0A4h], 6
.text:0042B260            jz    loc_42B2EC         //相等则返回1
.text:0042B266            call   CString::~CString(void)
.text:0042B26B            lea    ecx, [esp+4Ch]
.text:0042B26F            mov    byte ptr [esp+0A4h], 5
.text:0042B277            call   sub_401BC7
.text:0042B27C            lea    ecx, [esp+34h]
.text:0042B280            mov    [esp+0A4h], bl
.text:0042B287            call   sub_401BC7
.text:0042B28C            lea    ecx, [esp+44h]
.text:0042B290            mov    byte ptr [esp+0A4h], 8
.text:0042B298            call   sub_401BC7
.text:0042B29D            lea    ecx, [esp+3Ch]
.text:0042B2A1            mov    byte ptr [esp+0A4h], 1
.text:0042B2A9            call   sub_401BC7
.text:0042B2AE
.text:0042B2AE loc_42B2AE:                    
.text:0042B2AE                           
.text:0042B2AE            lea    ecx, [esp+8]
.text:0042B2B2            mov    byte ptr [esp+0A4h], 0
.text:0042B2BA            call   CString::~CString(void)
.text:0042B2BF            lea    ecx, [esp+0Ch]
.text:0042B2C3            mov    dword ptr [esp+0A4h], 0FFFFFFFFh
.text:0042B2CE            call   CString::~CString(void)
.text:0042B2D3            pop    esi
.text:0042B2D4            xor    eax, eax
.text:0042B2D6            pop    ebx
.text:0042B2D7            mov    ecx, [esp+94h]
.text:0042B2DE            mov    large fs:0, ecx
.text:0042B2E5            add    esp, 0A0h
.text:0042B2EB            retn

===================================================================================================
   总结:1。预处理注册码。
         注册码分为8组,第8组 = (5,4,3,2组之和)异或 第8组
                   第7组 = (1,6组之和)异或 第7组
                  
       2。RSA256运算
         N : 385AC5EEC9BF2B1AE3D3C333323B9C06DBF030EEE4475D85234E94C90FBF8A47
         E : 10001
         
       3。变换RSA256运算结果   
         把形如12 34 56 78 90 ab cd ef 的形式转换为78 56 34 12 ef cd ab 90的形式
         
       4。变换后的结果和用户名比较,相等则注册成功,不等则失败。

   
   注册算法是上面的逆运算,分解一个256位的N在我的机器上大概半小时的时间,注册算法就不给出了。感兴趣的可以自己做一下。
====================================================================
     [全文完]

TOP

发新话题