playboysen 发表于 2009-5-5 16:25

LaptopAlarm V2.20算法解析 + MD5汇编注册机源码

本帖最后由 playboysen 于 2012-3-2 23:20 编辑

【破文标题】LaptopAlarm V2.20算法解析 +MD5汇编注册机源码
【破文作者】Playboysen
【作者邮箱】playboysen#126.com
【破解工具】OD
【破解平台】Windows XP
【软件语言】英文
【原版下载】http://www.syfer.nl/
【保护方式】用户名 注册码
【软件简介】LaptopAlarm V2.20最新版,目前唯一一款笔记本防盗软件,一旦你锁定电脑,必须输入密码正常解锁,在未解锁期间任何人都不可以拔掉鼠标等外设,不能关机或重启、不能合上笔记本待机,否则电脑会大声呼救(呼救声音可自定义),即使本本处于静音状态。强烈推荐常蜗居宿舍的学生族使用!
【破解声明】一点心得,愿与大家分享o(∩_∩)o 版权所有,转载注明作者!
【破解内容】

   主程序VC++ 8语言编写,无壳,注册验证无提示,打开对话框有试用提示。输入假码后搜索注册表发现以下痕迹:
Windows Registry Editor Version 5.00


"email"="playboysen@126.com"
"serial"="1234567890abcdef"

   但是尝试下注册表类断点、文件访问断点、对话框类断点均无果而终,直接查找字符无重大发现。最后偶然发现一处重大疑点,即先输入假码然后点击“OK”按钮,这时打开OD,Alt+E双击进入LaptopAlarm.exe模块,搜索字符串后发现几处假码字符,逐处排查后找到注册验证处。00405BFE|.8B0D 701A4100 mov   ecx, dword ptr
00405C04|.8B35 0CC34000 mov   esi, dword ptr [<&USER32.SendMes>;USER32.SendMessageW
00405C0A|.68 60194100   push    00411960                         ; /playboysen@126.com
00405C0F|.68 80000000   push    80                               ; |wParam = 80
00405C14|.6A 0D         push    0D                               ; |Message = WM_GETTEXT
00405C16|.51            push    ecx                              ; |hWnd => 301B2
00405C17|.FFD6          call    esi                              ; \SendMessageW
00405C19|.8B15 6C1A4100 mov   edx, dword ptr
00405C1F|.68 54194100   push    00411954                         ; /1234
00405C24|.6A 05         push    5                              ; |wParam = 5
00405C26|.6A 0D         push    0D                               ; |Message = WM_GETTEXT
00405C28|.52            push    edx                              ; |hWnd => 301FE
00405C29|.FFD6          call    esi                              ; \SendMessageW
00405C2B|.A1 681A4100   mov   eax, dword ptr
00405C30|.68 48194100   push    00411948                         ; /5678
00405C35|.6A 05         push    5                              ; |wParam = 5
00405C37|.6A 0D         push    0D                               ; |Message = WM_GETTEXT
00405C39|.50            push    eax                              ; |hWnd => 401B0
00405C3A|.FFD6          call    esi                              ; \SendMessageW
00405C3C|.8B0D 641A4100 mov   ecx, dword ptr
00405C42|.68 3C194100   push    0041193C                         ; /90ab
00405C47|.6A 05         push    5                              ; |wParam = 5
00405C49|.6A 0D         push    0D                               ; |Message = WM_GETTEXT
00405C4B|.51            push    ecx                              ; |hWnd => 40200
00405C4C|.FFD6          call    esi                              ; \SendMessageW
00405C4E|.8B15 601A4100 mov   edx, dword ptr
00405C54|.68 30194100   push    00411930                         ; /cdef
00405C59|.6A 05         push    5                              ; |wParam = 5
00405C5B|.6A 0D         push    0D                               ; |Message = WM_GETTEXT
00405C5D|.52            push    edx                              ; |hWnd => 80230
00405C5E|.FFD6          call    esi                              ; \SendMessageW
00405C60|.68 54194100   push    00411954                         ;1234
00405C65|.8D8C24 380100>lea   ecx, dword ptr
00405C6C|.FF15 30C14000 call    dword ptr [<&MSVCP80.std::basic_>
00405C72|.68 48194100   push    00411948                         ;5678
00405C77|.8D8C24 380100>lea   ecx, dword ptr
00405C7E|.FF15 A8C14000 call    dword ptr [<&MSVCP80.std::basic_>
00405C84|.68 3C194100   push    0041193C                         ;90ab
00405C89|.8D8C24 380100>lea   ecx, dword ptr
00405C90|.FF15 A8C14000 call    dword ptr [<&MSVCP80.std::basic_>
00405C96|.68 30194100   push    00411930                         ;cdef
00405C9B|.8D8C24 380100>lea   ecx, dword ptr
00405CA2|.FF15 A8C14000 call    dword ptr [<&MSVCP80.std::basic_>
00405CA8|.68 60194100   push    00411960                         ;playboysen@126.com
00405CAD|.8D8C24 540100>lea   ecx, dword ptr
00405CB4|.FF15 30C14000 call    dword ptr [<&MSVCP80.std::basic_>
00405CBA|.83EC 1C       sub   esp, 1C
00405CBD|.8D8424 500100>lea   eax, dword ptr
00405CC4|.8BCC          mov   ecx, esp
00405CC6|.896424 30   mov   dword ptr , esp
00405CCA|.50            push    eax
00405CCB|.FF15 24C14000 call    dword ptr [<&MSVCP80.std::basic_>
00405CD1|.83EC 1C       sub   esp, 1C
00405CD4|.8D9424 880100>lea   edx, dword ptr
00405CDB|.8BCC          mov   ecx, esp
00405CDD|.896424 50   mov   dword ptr , esp
00405CE1|.52            push    edx
00405CE2|.C68424 FC0100>mov   byte ptr , 0B
00405CEA|.FF15 24C14000 call    dword ptr [<&MSVCP80.std::basic_>
00405CF0|.C68424 F80100>mov   byte ptr , 1         
00405CF8|.E8 43100000   call    00406D40                        ; 注册码验证,关键                  
00405CFD|.85C0          test    eax, eax
00405CFF|.74 4F         je      short 00405D50
......
跟入00405CF8关键call00406D40/[      DISCUZ_CODE_36      ]nbsp; 6A FF         push    -1
00406D42|.68 1CAB4000   push    0040AB1C
00406D47|.64:A1 0000000>mov   eax, dword ptr fs:
00406D4D|.50            push    eax
......
00406D7A|.8B8424 980000>mov   eax, dword ptr
00406D81|.83F8 10       cmp   eax, 10                        ;注册码应为16位,否则不再运算
00406D84|.0F85 CF010000 jnz   00406F59
00406D8A|.8B1D A8C24000 mov   ebx, dword ptr [<&MSVCR80.tolowe>;MSVCR80.tolower
00406D90|.33F6          xor   esi, esi
00406D92|.3BF0          cmp   esi, eax
00406D94|.76 0D         jbe   short 00406DA3
00406D96|.FF15 9CC24000 call    dword ptr [<&MSVCR80._invalid_pa>
00406D9C|.8B8424 980000>mov   eax, dword ptr
00406DA3|>8BAC24 880000>/mov   ebp, dword ptr
00406DAA|.BF 08000000   |mov   edi, 8
00406DAF|.39BC24 9C0000>|cmp   dword ptr , edi
00406DB6|.73 07         |jnb   short 00406DBF
00406DB8|.8DAC24 880000>|lea   ebp, dword ptr
00406DBF|>3BF0          |cmp   esi, eax
00406DC1|.76 06         |jbe   short 00406DC9
00406DC3|.FF15 9CC24000 |call    dword ptr [<&MSVCR80._invalid_p>
00406DC9|>39BC24 9C0000>|cmp   dword ptr , edi
00406DD0|.8BBC24 880000>|mov   edi, dword ptr
00406DD7|.73 07         |jnb   short 00406DE0
00406DD9|.8DBC24 880000>|lea   edi, dword ptr
00406DE0|>0FB74475 00   |movzx   eax, word ptr        ;注册码逐位放入EAX,进行转化操作(ebp中存放的是假码)
00406DE5|.50            |push    eax
00406DE6|.FFD3          |call    ebx                           ;MSVCR80.tolower函数 转大写为小写,数字不变
00406DE8|.66:890477   |mov   word ptr , ax      ;保存转换后的结果(由数字和小写字母组成)
00406DEC|.8B8424 9C0000>|mov   eax, dword ptr          ;注册码位数放入
00406DF3|.83C6 01       |add   esi, 1
00406DF6|.83C4 04       |add   esp, 4
00406DF9|.3BF0          |cmp   esi, eax                        ;比较以便循环转换
00406DFB|.^ 72 A6         \jb      short 00406DA3
00406DFD|.8D4C24 68   lea   ecx, dword ptr
00406E01|.51            push    ecx
00406E02|.8D4C24 3C   lea   ecx, dword ptr
00406E06|.FF15 24C14000 call    dword ptr [<&MSVCP80.std::basic_>;读取用户邮箱地址
00406E0C|.68 E0CE4000   push    0040CEE0                         ;固定字符"yevjeprpsolsuis2001"
00406E11|.8D4C24 3C   lea   ecx, dword ptr
00406E15|.C64424 64 02mov   byte ptr , 2
00406E1A|.FF15 A4C14000 call    dword ptr [<&MSVCP80.std::basic_>;用户邮箱+固定字符串"yevjeprpsolsuis2001"
00406E20|.6A 01         push    1
00406E22|.E8 CD2C0000   call    <jmp.&MSVCR80.operator new>      ;operator new
00406E27|.894424 18   mov   dword ptr , eax
00406E2B|.83EC 18       sub   esp, 18
00406E2E|.8D5424 54   lea   edx, dword ptr
00406E32|.8BCC          mov   ecx, esp
00406E34|.896424 34   mov   dword ptr , esp
00406E38|.B3 03         mov   bl, 3
00406E3A|.52            push    edx
00406E3B|.889C24 800000>mov   byte ptr , bl
00406E42|.FF15 24C14000 call    dword ptr [<&MSVCP80.std::basic_>
00406E48|.8D4424 38   lea   eax, dword ptr          
00406E4C|.50            push    eax                           
00406E4D|.E8 DE1D0000   call    00408C30                         ; 此call过去,堆栈窗口出现一串可疑32位值,莫非……
00406E52|.8B8424 980000>mov   eax, dword ptr 我们的目的不是爆破(男人,对自己要严一点!),毕竟只有了解算法才能写出注册机,所以我们跟入00406E4D关键call00408C30/[      DISCUZ_CODE_37      ]nbsp; 6A FF         push    -1
00408C32|.68 D4A94000   push    0040A9D4
00408C37|.64:A1 0000000>mov   eax, dword ptr fs:
......
00408CBF|.8D7C24 54   lea   edi, dword ptr          ;ECX中的值是"用户邮箱+yevjeprpsolsuis2001",参数之一
00408CC3|.E8 B8FDFFFF   call    00408A80                        ;此call过后,出现了一串32位可疑数值,难道是……
00408CC8|.50            push    eax
00408CC9|.8D4C24 58   lea   ecx, dword ptr
00408CCD|.C68424 9C0000>mov   byte ptr , 3
......到这里,我禁不住想大胆的猜测——MD5算法。为了验证我们的猜测,跟入00408CC3处关键call00408A80/[      DISCUZ_CODE_38      ]nbsp; 6A FF         push    -1
00408A82|.68 F9A54000   push    0040A5F9
00408A87|.64:A1 0000000>mov   eax, dword ptr fs:
00408A8D|.50            push    eax
00408A8E|.83EC 78       sub   esp, 78
00408A91|.A1 18104100   mov   eax, dword ptr
00408A96|.33C4          xor   eax, esp
00408A98|.894424 70   mov   dword ptr , eax
00408A9C|.53            push    ebx
00408A9D|.56            push    esi
00408A9E|.A1 18104100   mov   eax, dword ptr
00408AA3|.33C4          xor   eax, esp
00408AA5|.50            push    eax
00408AA6|.8D8424 840000>lea   eax, dword ptr
00408AAD|.64:A3 0000000>mov   dword ptr fs:, eax
00408AB3|.33DB          xor   ebx, ebx
00408AB5|.897C24 10   mov   dword ptr , edi
00408AB9|.895C24 0C   mov   dword ptr , ebx
00408ABD|.C78424 8C0000>mov   dword ptr , 1
00408AC8|.83BC24 AC0000>cmp   dword ptr , 10
00408AD0|.8B8424 980000>mov   eax, dword ptr
00408AD7|.895C24 28   mov   dword ptr , ebx
00408ADB|.895C24 24   mov   dword ptr , ebx
00408ADF|.C74424 14 012>mov   dword ptr , 67452301   ;看到这里的四串数值,我们基本可以确定我们的猜测
00408AE7|.C74424 18 89A>mov   dword ptr , EFCDAB89   ;标准MD5算法
00408AEF|.C74424 1C FED>mov   dword ptr , 98BADCFE
00408AF7|.C74424 20 765>mov   dword ptr , 10325476
00408AFF|.73 07         jnb   short 00408B08
00408B01|.8D8424 980000>lea   eax, dword ptr 到这里我们基本已经了解此软件的算法,还算简单——主算法使用了标准MD5,参数是用户邮箱+固定字符串"yevjeprpsolsuis2001"。单步回到以下地方接着分析00406E59|.33F6          xor   esi, esi
00406E5B|.85C0          test    eax, eax
00406E5D|.76 5C         jbe   short 00406EBB
00406E5F|.3BF0          cmp   esi, eax
00406E61|.76 06         jbe   short 00406E69
00406E63|.FF15 9CC24000 call    dword ptr [<&MSVCR80._invalid_pa>
00406E69|>8BBC24 880000>/mov   edi, dword ptr
00406E70|.BD 08000000   |mov   ebp, 8
00406E75|.39AC24 9C0000>|cmp   dword ptr , ebp
00406E7C|.73 07         |jnb   short 00406E85
00406E7E|.8DBC24 880000>|lea   edi, dword ptr
00406E85|>3B7424 30   |cmp   esi, dword ptr
00406E89|.76 06         |jbe   short 00406E91
00406E8B|.FF15 9CC24000 |call    dword ptr [<&MSVCR80._invalid_p>
00406E91|>396C24 34   |cmp   dword ptr , ebp
00406E95|.8B4424 20   |mov   eax, dword ptr          ;00406E4D处的call所求出的MD5值放入
00406E99|.73 04         |jnb   short 00406E9F
00406E9B|.8D4424 20   |lea   eax, dword ptr
00406E9F|>66:8B0C77   |mov   cx, word ptr       ;假码逐位放入(edi中存放的是假码)
00406EA3|.66:3B0C70   |cmp   cx, word ptr       ;比较处——我好像看到了曙光!(eax存放着MD5值)
00406EA7|.0F85 82000000 |jnz   00406F2F
00406EAD|.8B8424 980000>|mov   eax, dword ptr
00406EB4|.83C6 01       |add   esi, 1
00406EB7|.3BF0          |cmp   esi, eax
00406EB9|.^ 72 AE         \jb      short 00406E69
00406EBB|>8D4C24 1C   lea   ecx, dword ptr
00406EBF|.885C24 60   mov   byte ptr , bl
00406EC3|.FF15 10C14000 call    dword ptr [<&MSVCP80.std::basic_>s<wchar_t>,std::allocator<wchar_t> >
00406EC9|.8B4424 14   mov   eax, dword ptr
00406ECD|.50            push    eax
00406ECE|.E8 272C0000   call    <jmp.&MSVCR80.operator delete>   ;operator delete
......
00406F22|.33CC          xor   ecx, esp
00406F24|.E8 722B0000   call    00409A9B
00406F29|.83C4 50       add   esp, 50
00406F2C|.C2 3800       retn    38从上面我们看到了,程序计算出的32位MD5值的前16位即为注册码。

附件中是MD5汇编注册机源码,其中主要代码如下:
注:原作者MiSSiNG iN ByTES,我只是针对本软件修改了部分代码,借花献佛了!
详情下载附件:.386
.model flat, stdcall;32 bit memory model
option casemap :none;case sensitive

include MD5_tut.inc
include md5_addin.asm

.code

start:

      invoke GetModuleHandle,NULL
      mov                hInstance,eax

    invoke InitCommonControls
      invoke DialogBoxParam,hInstance,IDD_DIALOG1,NULL,addr DlgProc,NULL
      invoke ExitProcess,0

;########################################################################

DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM

      mov                eax,uMsg
      .if eax==WM_INITDIALOG
                invoke DisplayBmp,hWin,10000,327,2,100
               
      .elseif eax==WM_COMMAND
                .if wParam == 1005
                        invoke GetDlgItemText,hWin,1002,addr UserName,256                ;gets the user name
                        invoke lstrcat,addr UserName,addr key                           
                        invoke MD5Init                                                      ;initialize MD5, here loads our magic numbers stored in md5_addin.asm source file
                        invoke lstrlen,addr UserName                                        ;returns the user name lenght in eax
                        invoke MD5Update,addr UserName,eax                              ;MD5Update sets the text to be hashed -- the username which is eax bytes long
                        invoke MD5Final                                                      ;hash to MD5
                        invoke max_ConvertBytesToAscii,addr Serial,eax,16                ;thanks to Maxtreme here we convert the returned from MD5Final bytes to ascii string
                        invoke lstrcpyn,addr FinalSerial,addr Serial,17                        ;please refer to Win32 API Reference for details
                        invoke SetDlgItemText,hWin,1003,addr FinalSerial                ;show the serial
                .endif
      .elseif eax==WM_CLOSE
                invoke EndDialog,hWin,0
      .else
                mov                eax,FALSE
                ret
      .endif
      mov                eax,TRUE
      ret

DlgProc endp

end start
MD5关键算法部分(源码中md5_addin.asm)如下:.code

max_ConvertBytesToAscii proc uses ebx esi edi lpDst:DWORD, lpSrc:DWORD, nSrcLen:DWORD
      
      mov esi,lpSrc
      mov edi,lpDst
      
@@:
      movzx eax,byte ptr
      invoke wsprintf,edi,chr$("%02x"),EAX
      add edi,2
      inc esi
      dec nSrcLen
      mov ecx,nSrcLen
      test ecx,ecx
      jne @b
      
      Ret
      
max_ConvertBytesToAscii EndP

MD5Init proc uses edi
      xor eax, eax
      mov MD5Len,eax
      MD5BURN
      mov eax,offset MD5Digest

      ;magic numbers
      mov dword ptr ,67452301h      ;magic 1
      mov dword ptr ,0EFCDAB89h      ;magic 2
      mov dword ptr ,98BADCFEh      ;magic 3
      mov dword ptr ,10325476h      ;magic 4
      
      ret
MD5Init endp

MD5Update proc uses esi edi ebx lpBuffer:dword, dwBufLen:dword
      mov ebx,dwBufLen
      mov esi,lpBuffer
      add MD5Len,ebx
      .while ebx
                mov eax,MD5Index
                mov ecx,64
                sub ecx,eax
                lea edi,      
                .if ecx <= ebx
                        sub ebx,ecx
                        rep movsb
                        call MD5Transform
                        MD5BURN
                .else
                        mov ecx,ebx
                        rep movsb
                        add MD5Index,ebx
                        .break
                .endif
      .endw
      ret
MD5Update endp

......我们来看看这次能学到什么:
1、此软件无注册错误对话框提示、尽量少的出现相关字符串提示(在解客面前尽可能少的漏出马脚)、避开常用API——这些都值得我们借鉴,我相信世界上没有不能被破解的软件,但通过程序员的重视和努力,尽可能地延长我们软件的生存周期还是可行的。
2、软件出现了试用提示而且这些字符串并没有加密(OD可直接搜索到)、主程序没有加壳或VM、关键算法直接套用标准MD5、注册表中所保存的注册信息未经加密(解客可轻易查找到关键键值)——这些都要引以为戒!一个很小的疏忽,可能就会导致整个公司所有软件全盘功亏一篑。


热火朝天 发表于 2009-5-5 16:29

不错哦,又学到了,原来这样也能找到线索哦,楼主加油为我们造福

sneaker 发表于 2009-5-5 19:37

不错,不错

playboysen 发表于 2009-5-6 10:21

应鹭影依凌邀请

添加MD5汇编注册机源码

wellen 发表于 2009-5-7 22:18

学习了

dark影 发表于 2009-5-8 12:35

学习了   精华 真不错

hc0107 发表于 2009-5-11 10:54

很不错,学习下!

cokago 发表于 2009-5-11 21:45

一旦你锁定电脑,必须输入密码正常解锁,否则电脑会大声呼救
这效果也太无聊了吧~

lin440w2 发表于 2009-7-3 23:46

收藏學習~~

homeros521 发表于 2009-7-3 23:58

楼主辛苦了啊
页: [1] 2
查看完整版本: LaptopAlarm V2.20算法解析 + MD5汇编注册机源码