- UID
- 37950
注册时间2007-12-1
阅读权限30
最后登录1970-1-1
龙战于野
TA的每日心情 | 难过 2022-2-6 09:25 |
---|
签到天数: 6 天 [LV.2]偶尔看看I
|
【破文标题】LaptopAlarm V2.20算法解析 + MD5汇编注册机源码
【破文作者】Playboysen
【作者邮箱】[email protected]
【破解工具】OD
【破解平台】Windows XP
【软件语言】英文
【原版下载】http://www.syfer.nl/
【保护方式】用户名 注册码
【软件简介】LaptopAlarm V2.20最新版,目前唯一一款笔记本防盗软件,一旦你锁定电脑,必须输入密码正常解锁,在未解锁期间任何人都不可以拔掉鼠标等外设,不能关机或重启、不能合上笔记本待机,否则电脑会大声呼救(呼救声音可自定义),即使本本处于静音状态。强烈推荐常蜗居宿舍的学生族使用!
【破解声明】一点心得,愿与大家分享o(∩_∩)o 版权所有,转载注明作者!
【破解内容】
主程序VC++ 8语言编写,无壳,注册验证无提示,打开对话框有试用提示。输入假码后搜索注册表发现以下痕迹:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Syfer\LaptopAlarm]
"email"="[email protected]"
"serial"="1234567890abcdef"
但是尝试下注册表类断点、文件访问断点、对话框类断点均无果而终,直接查找字符无重大发现。最后偶然发现一处重大疑点,即先输入假码然后点击“OK”按钮,这时打开OD,Alt+E双击进入LaptopAlarm.exe模块,搜索字符串后发现几处假码字符,逐处排查后找到注册验证处。- 00405BFE |. 8B0D 701A4100 mov ecx, dword ptr [411A70]
- 00405C04 |. 8B35 0CC34000 mov esi, dword ptr [<&USER32.SendMes>; USER32.SendMessageW
- 00405C0A |. 68 60194100 push 00411960 ; /[email protected]
- 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 [411A6C]
- 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 [411A68]
- 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 [411A64]
- 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 [411A60]
- 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 [esp+138]
- 00405C6C |. FF15 30C14000 call dword ptr [<&MSVCP80.std::basic_>
- 00405C72 |. 68 48194100 push 00411948 ; 5678
- 00405C77 |. 8D8C24 380100>lea ecx, dword ptr [esp+138]
- 00405C7E |. FF15 A8C14000 call dword ptr [<&MSVCP80.std::basic_>
- 00405C84 |. 68 3C194100 push 0041193C ; 90ab
- 00405C89 |. 8D8C24 380100>lea ecx, dword ptr [esp+138]
- 00405C90 |. FF15 A8C14000 call dword ptr [<&MSVCP80.std::basic_>
- 00405C96 |. 68 30194100 push 00411930 ; cdef
- 00405C9B |. 8D8C24 380100>lea ecx, dword ptr [esp+138]
- 00405CA2 |. FF15 A8C14000 call dword ptr [<&MSVCP80.std::basic_>
- 00405CA8 |. 68 60194100 push 00411960 ; [email protected]
- 00405CAD |. 8D8C24 540100>lea ecx, dword ptr [esp+154]
- 00405CB4 |. FF15 30C14000 call dword ptr [<&MSVCP80.std::basic_>
- 00405CBA |. 83EC 1C sub esp, 1C
- 00405CBD |. 8D8424 500100>lea eax, dword ptr [esp+150]
- 00405CC4 |. 8BCC mov ecx, esp
- 00405CC6 |. 896424 30 mov dword ptr [esp+30], 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 [esp+188]
- 00405CDB |. 8BCC mov ecx, esp
- 00405CDD |. 896424 50 mov dword ptr [esp+50], esp
- 00405CE1 |. 52 push edx
- 00405CE2 |. C68424 FC0100>mov byte ptr [esp+1FC], 0B
- 00405CEA |. FF15 24C14000 call dword ptr [<&MSVCP80.std::basic_>
- 00405CF0 |. C68424 F80100>mov byte ptr [esp+1F8], 1
- 00405CF8 |. E8 43100000 call 00406D40 ; 注册码验证,关键
- 00405CFD |. 85C0 test eax, eax
- 00405CFF |. 74 4F je short 00405D50
- ......
复制代码 跟入00405CF8关键call- 00406D40 /$ 6A FF push -1
- 00406D42 |. 68 1CAB4000 push 0040AB1C
- 00406D47 |. 64:A1 0000000>mov eax, dword ptr fs:[0]
- 00406D4D |. 50 push eax
- ......
- 00406D7A |. 8B8424 980000>mov eax, dword ptr [esp+98]
- 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 [esp+98]
- 00406DA3 |> 8BAC24 880000>/mov ebp, dword ptr [esp+88]
- 00406DAA |. BF 08000000 |mov edi, 8
- 00406DAF |. 39BC24 9C0000>|cmp dword ptr [esp+9C], edi
- 00406DB6 |. 73 07 |jnb short 00406DBF
- 00406DB8 |. 8DAC24 880000>|lea ebp, dword ptr [esp+88]
- 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 [esp+9C], edi
- 00406DD0 |. 8BBC24 880000>|mov edi, dword ptr [esp+88]
- 00406DD7 |. 73 07 |jnb short 00406DE0
- 00406DD9 |. 8DBC24 880000>|lea edi, dword ptr [esp+88]
- 00406DE0 |> 0FB74475 00 |movzx eax, word ptr [ebp+esi*2] ; 注册码逐位放入EAX,进行转化操作(ebp中存放的是假码)
- 00406DE5 |. 50 |push eax
- 00406DE6 |. FFD3 |call ebx ; MSVCR80.tolower函数 转大写为小写,数字不变
- 00406DE8 |. 66:890477 |mov word ptr [edi+esi*2], ax ; 保存转换后的结果(由数字和小写字母组成)
- 00406DEC |. 8B8424 9C0000>|mov eax, dword ptr [esp+9C] ; 注册码位数放入
- 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 [esp+68]
- 00406E01 |. 51 push ecx
- 00406E02 |. 8D4C24 3C lea ecx, dword ptr [esp+3C]
- 00406E06 |. FF15 24C14000 call dword ptr [<&MSVCP80.std::basic_>; 读取用户邮箱地址
- 00406E0C |. 68 E0CE4000 push 0040CEE0 ; 固定字符"yevjeprpsolsuis2001"
- 00406E11 |. 8D4C24 3C lea ecx, dword ptr [esp+3C]
- 00406E15 |. C64424 64 02 mov byte ptr [esp+64], 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 [esp+18], eax
- 00406E2B |. 83EC 18 sub esp, 18
- 00406E2E |. 8D5424 54 lea edx, dword ptr [esp+54]
- 00406E32 |. 8BCC mov ecx, esp
- 00406E34 |. 896424 34 mov dword ptr [esp+34], esp
- 00406E38 |. B3 03 mov bl, 3
- 00406E3A |. 52 push edx
- 00406E3B |. 889C24 800000>mov byte ptr [esp+80], bl
- 00406E42 |. FF15 24C14000 call dword ptr [<&MSVCP80.std::basic_>
- 00406E48 |. 8D4424 38 lea eax, dword ptr [esp+38]
- 00406E4C |. 50 push eax
- 00406E4D |. E8 DE1D0000 call 00408C30 ; 此call过去,堆栈窗口出现一串可疑32位值,莫非……
- 00406E52 |. 8B8424 980000>mov eax, dword ptr [esp+98]
复制代码 我们的目的不是爆破(男人,对自己要严一点!),毕竟只有了解算法才能写出注册机,所以我们跟入00406E4D关键call- 00408C30 /$ 6A FF push -1
- 00408C32 |. 68 D4A94000 push 0040A9D4
- 00408C37 |. 64:A1 0000000>mov eax, dword ptr fs:[0]
- ......
- 00408CBF |. 8D7C24 54 lea edi, dword ptr [esp+54] ; ECX中的值是"用户邮箱+yevjeprpsolsuis2001",参数之一
- 00408CC3 |. E8 B8FDFFFF call 00408A80 ; 此call过后,出现了一串32位可疑数值,难道是……
- 00408CC8 |. 50 push eax
- 00408CC9 |. 8D4C24 58 lea ecx, dword ptr [esp+58]
- 00408CCD |. C68424 9C0000>mov byte ptr [esp+9C], 3
- ......
复制代码 到这里,我禁不住想大胆的猜测——MD5算法。为了验证我们的猜测,跟入00408CC3处关键call- 00408A80 /$ 6A FF push -1
- 00408A82 |. 68 F9A54000 push 0040A5F9
- 00408A87 |. 64:A1 0000000>mov eax, dword ptr fs:[0]
- 00408A8D |. 50 push eax
- 00408A8E |. 83EC 78 sub esp, 78
- 00408A91 |. A1 18104100 mov eax, dword ptr [411018]
- 00408A96 |. 33C4 xor eax, esp
- 00408A98 |. 894424 70 mov dword ptr [esp+70], eax
- 00408A9C |. 53 push ebx
- 00408A9D |. 56 push esi
- 00408A9E |. A1 18104100 mov eax, dword ptr [411018]
- 00408AA3 |. 33C4 xor eax, esp
- 00408AA5 |. 50 push eax
- 00408AA6 |. 8D8424 840000>lea eax, dword ptr [esp+84]
- 00408AAD |. 64:A3 0000000>mov dword ptr fs:[0], eax
- 00408AB3 |. 33DB xor ebx, ebx
- 00408AB5 |. 897C24 10 mov dword ptr [esp+10], edi
- 00408AB9 |. 895C24 0C mov dword ptr [esp+C], ebx
- 00408ABD |. C78424 8C0000>mov dword ptr [esp+8C], 1
- 00408AC8 |. 83BC24 AC0000>cmp dword ptr [esp+AC], 10
- 00408AD0 |. 8B8424 980000>mov eax, dword ptr [esp+98]
- 00408AD7 |. 895C24 28 mov dword ptr [esp+28], ebx
- 00408ADB |. 895C24 24 mov dword ptr [esp+24], ebx
- 00408ADF |. C74424 14 012>mov dword ptr [esp+14], 67452301 ; 看到这里的四串数值,我们基本可以确定我们的猜测
- 00408AE7 |. C74424 18 89A>mov dword ptr [esp+18], EFCDAB89 ; 标准MD5算法
- 00408AEF |. C74424 1C FED>mov dword ptr [esp+1C], 98BADCFE
- 00408AF7 |. C74424 20 765>mov dword ptr [esp+20], 10325476
- 00408AFF |. 73 07 jnb short 00408B08
- 00408B01 |. 8D8424 980000>lea eax, dword ptr [esp+98]
复制代码 到这里我们基本已经了解此软件的算法,还算简单——主算法使用了标准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 [esp+88]
- 00406E70 |. BD 08000000 |mov ebp, 8
- 00406E75 |. 39AC24 9C0000>|cmp dword ptr [esp+9C], ebp
- 00406E7C |. 73 07 |jnb short 00406E85
- 00406E7E |. 8DBC24 880000>|lea edi, dword ptr [esp+88]
- 00406E85 |> 3B7424 30 |cmp esi, dword ptr [esp+30]
- 00406E89 |. 76 06 |jbe short 00406E91
- 00406E8B |. FF15 9CC24000 |call dword ptr [<&MSVCR80._invalid_p>
- 00406E91 |> 396C24 34 |cmp dword ptr [esp+34], ebp
- 00406E95 |. 8B4424 20 |mov eax, dword ptr [esp+20] ; 00406E4D处的call所求出的MD5值放入
- 00406E99 |. 73 04 |jnb short 00406E9F
- 00406E9B |. 8D4424 20 |lea eax, dword ptr [esp+20]
- 00406E9F |> 66:8B0C77 |mov cx, word ptr [edi+esi*2] ; 假码逐位放入(edi中存放的是假码)
- 00406EA3 |. 66:3B0C70 |cmp cx, word ptr [eax+esi*2] ; 比较处——我好像看到了曙光!(eax存放着MD5值)
- 00406EA7 |. 0F85 82000000 |jnz 00406F2F
- 00406EAD |. 8B8424 980000>|mov eax, dword ptr [esp+98]
- 00406EB4 |. 83C6 01 |add esi, 1
- 00406EB7 |. 3BF0 |cmp esi, eax
- 00406EB9 |.^ 72 AE \jb short 00406E69
- 00406EBB |> 8D4C24 1C lea ecx, dword ptr [esp+1C]
- 00406EBF |. 885C24 60 mov byte ptr [esp+60], bl
- 00406EC3 |. FF15 10C14000 call dword ptr [<&MSVCP80.std::basic_>s<wchar_t>,std::allocator<wchar_t> >
- 00406EC9 |. 8B4424 14 mov eax, dword ptr [esp+14]
- 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[esi]
- 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 [eax+0*4],67452301h ;magic 1
- mov dword ptr [eax+1*4],0EFCDAB89h ;magic 2
- mov dword ptr [eax+2*4],98BADCFEh ;magic 3
- mov dword ptr [eax+3*4],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,[MD5HashBuf+eax]
- .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、注册表中所保存的注册信息未经加密(解客可轻易查找到关键键值)——这些都要引以为戒!一个很小的疏忽,可能就会导致整个公司所有软件全盘功亏一篑。
[ 本帖最后由 playboysen 于 2009-5-6 10:15 编辑 ] |
|