【破文标题】Power Video Converter算法分析+另类注册机
【破文作者】Playboysen
【作者邮箱】playboysen@126.com
【作者主页】playboysen2.photo.163.com
【破解工具】PEiD,OD
【破解平台】Windows XP
【软件名称】Power Video Converter
【软件大小】1.01 MB
【软件类别】国外软件/视频转换
【软件授权】共享版
【软件语言】英文
【更新时间】2008-8-7
【原版下载】http://www.apussoft.com/
【保护方式】用户名、注册码
【软件简介】Power Video Converter可以在AVi, MPEG1, MPEG2, VCD, SVCD, DVD, WMV, ASF, DAT, VOB文件格式之间进行转换,同时具有很快的转换速度和友好的使用界面。
【破解声明】我是一只小菜鸟,偶得一点心得,愿与大家分享:)
初学破解与编程,只是感兴趣,没有其它目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------
【破解内容】
大三暑期的实习,嘴里能闲出鸟来。
趁没毕业不抓紧时间学点自己喜欢的东西,怕这后半生真像张雨生说的那样“在太阳下低头,流着汗水默默辛苦的工作”,所以啊,找资料学Delphi、找目标练习算法分析,这是近期我的第三篇算法总结了吧,也许大家不记得了,但我自己记得每次盯着几百行汇编代码反复来看一旦没头绪连睡觉都辗转反侧的无奈和辛苦。
没的说,就是这样,就算受了冷落,我也不会放弃自己想要的生活。加油!
试运行软件发现在其左侧有“Registration”按钮,注册错误有提示,PEID查壳得知软件无壳,OD载入查找字符很轻松找到关键处,不紧不慢咱们仔细分析:
00421BBA . 8B46 64 mov eax, dword ptr [esi+64] ; 假码"963852741" 00421BBD . 8B4E 60 mov ecx, dword ptr [esi+60] ; 用户名"senhuan" 00421BC0 . 8D5E 64 lea ebx, dword ptr [esi+64] 00421BC3 . 8D7E 60 lea edi, dword ptr [esi+60] 00421BC6 . 50 push eax 00421BC7 . 51 push ecx 00421BC8 . E8 73FEFFFF call 00421A40 ; 用户名和假码同时入栈,关键call 00421BCD . 83C4 08 add esp, 8 00421BD0 . 85C0 test eax, eax 00421BD2 . 75 15 jnz short 00421BE9 00421BD4 . 6A 40 push 40 00421BD6 . 68 14894300 push 00438914 ; sorry 00421BDB . 68 E8884300 push 004388E8 ; invalid username or registration code 00421BE0 . 8BCE mov ecx, esi 00421BE2 . E8 5F5C0000 call <jmp.&MFC42.#4224_CWnd::MessageBoxA>
00421A40 /$ 8B5424 04 mov edx, dword ptr [esp+4] ; 用户名“senhuan” 00421A44 |. 56 push esi 00421A45 |. 57 push edi 00421A46 |. BF F08B4300 mov edi, 00438BF0 00421A4B |. 8BF2 mov esi, edx 00421A4D |. B9 01000000 mov ecx, 1 00421A52 |. 33C0 xor eax, eax 00421A54 |. F3:A6 repe cmps byte ptr es:[edi], byte ptr [esi] ; 比较用户名是不是输入 00421A56 |. 74 2B je short 00421A83 00421A58 |. 8B4424 10 mov eax, dword ptr [esp+10] ; 假码“963852741” 00421A5C |. 53 push ebx 00421A5D |. BF F08B4300 mov edi, 00438BF0 00421A62 |. 8BF0 mov esi, eax 00421A64 |. B9 01000000 mov ecx, 1 00421A69 |. 33DB xor ebx, ebx 00421A6B |. F3:A6 repe cmps byte ptr es:[edi], byte ptr [esi] ; 比较假码是否输入 00421A6D |. 5B pop ebx 00421A6E |. 74 13 je short 00421A83 00421A70 |. 50 push eax 00421A71 |. 52 push edx 00421A72 |. E8 99FDFFFF call 00421810 ; 用户名和假码同时入栈,又是关键call,跟进 00421A77 |. 83C4 08 add esp, 8 00421A7A |. F7D8 neg eax 00421A7C |. 1BC0 sbb eax, eax 00421A7E |. 5F pop edi 00421A7F |. F7D8 neg eax 00421A81 |. 5E pop esi 00421A82 |. C3 retn 00421A83 |> 5F pop edi 00421A84 |. 33C0 xor eax, eax 00421A86 |. 5E pop esi 00421A87 \. C3 retn
…… 0042185F |. 8B4C24 38 mov ecx, dword ptr [esp+38] ; 假码放入ECX 00421863 |. 8BD8 mov ebx, eax ; 用户名放入EBX,下面关键处会用到 00421865 |. 51 push ecx 00421866 |. 8D4C24 14 lea ecx, dword ptr [esp+14] 0042186A |. E8 FD5D0000 call <jmp.&MFC42.#537_CString::CString> 0042186F |. 8D4C24 10 lea ecx, dword ptr [esp+10] 00421873 |. C64424 2C 01 mov byte ptr [esp+2C], 1 00421878 |. E8 DF610000 call <jmp.&MFC42.#6282_CString::TrimLeft> 0042187D |. 8D4C24 10 lea ecx, dword ptr [esp+10] 00421881 |. E8 D0610000 call <jmp.&MFC42.#6283_CString::TrimRight> 00421886 |. 6A 20 push 20 00421888 |. 8D4C24 14 lea ecx, dword ptr [esp+14] 0042188C |. E8 9F600000 call <jmp.&MFC42.#2915_CString::GetBuffer> 00421891 |. 8BD0 mov edx, eax ; 假码放入EDX 00421893 |. 83CE FF or esi, FFFFFFFF 00421896 |. 8BFA mov edi, edx 00421898 |. 8BCE mov ecx, esi 0042189A |. 33C0 xor eax, eax 0042189C |. 895424 20 mov dword ptr [esp+20], edx ; 放假码是用来求其长度 004218A0 |. F2:AE repne scas byte ptr es:[edi] 004218A2 |. F7D1 not ecx ; 这三句是用来求字符串长度的另一种方法 004218A4 |. 49 dec ecx 004218A5 |. 8BFB mov edi, ebx 004218A7 |. 8BE9 mov ebp, ecx 004218A9 |. 8BCE mov ecx, esi 004218AB |. F2:AE repne scas byte ptr es:[edi] 004218AD |. F7D1 not ecx ; 求用户名长度 004218AF |. 49 dec ecx 004218B0 |. 3BCD cmp ecx, ebp 004218B2 |. 0F87 54010000 ja 00421A0C ; 此处得知用户名长度必须小于注册码 004218B8 |. 8BFB mov edi, ebx 004218BA |. 8BCE mov ecx, esi 004218BC |. F2:AE repne scas byte ptr es:[edi] 004218BE |. F7D1 not ecx 004218C0 |. 49 dec ecx 004218C1 |. 0F84 45010000 je 00421A0C ; 检测用户名和注册码是不是为空 004218C7 |. 8BFA mov edi, edx 004218C9 |. 8BCE mov ecx, esi 004218CB |. F2:AE repne scas byte ptr es:[edi] 004218CD |. F7D1 not ecx 004218CF |. 49 dec ecx 004218D0 |. 0F84 36010000 je 00421A0C 004218D6 |. 894424 38 mov dword ptr [esp+38], eax 004218DA |> 8B5424 38 /mov edx, dword ptr [esp+38] 004218DE |. 8D4C24 34 |lea ecx, dword ptr [esp+34] 004218E2 |. 8A82 A8884300 |mov al, byte ptr [edx+4388A8] 004218E8 |. 884424 18 |mov byte ptr [esp+18], al 004218EC |. E8 BD5A0000 |call <jmp.&MFC42.#540_CString::CString> 004218F1 |. 8BFB |mov edi, ebx 004218F3 |. 83C9 FF |or ecx, FFFFFFFF 004218F6 |. 33C0 |xor eax, eax 004218F8 |. 33ED |xor ebp, ebp 004218FA |. F2:AE |repne scas byte ptr es:[edi] 004218FC |. F7D1 |not ecx 004218FE |. 49 |dec ecx ; 此时ECX中是用户名长度 004218FF |. C64424 2C 02 |mov byte ptr [esp+2C], 2 00421904 |. 74 4B |je short 00421951 00421906 |> 8A042B |/mov al, byte ptr [ebx+ebp] ; EBX中放的是用户名,用户名每个字母依次放入al中 00421909 |. 33F6 ||xor esi, esi 0042190B |> 3A0475 408843>||/cmp al, byte ptr [esi*2+438840] ; 在00438840处有一个密码表,是计算注册码的关键 00421912 |. 74 08 |||je short 0042191C 00421914 |. 46 |||inc esi 00421915 |. 83FE 34 |||cmp esi, 34 00421918 |.^ 7C F1 ||\jl short 0042190B 0042191A |. EB 11 ||jmp short 0042192D 0042191C |> 8A0C75 418843>||mov cl, byte ptr [esi*2+438841] ; 这里的字符串是用户名所对应的密码表转换后的值 00421923 |. 51 ||push ecx 00421924 |. 8D4C24 38 ||lea ecx, dword ptr [esp+38] 00421928 |. E8 1B5D0000 ||call <jmp.&MFC42.#940_CString::operator+=> 0042192D |> 83FE 34 ||cmp esi, 34 00421930 |. 75 0E ||jnz short 00421940 00421932 |. 8B5424 18 ||mov edx, dword ptr [esp+18] 00421936 |. 8D4C24 34 ||lea ecx, dword ptr [esp+34] 0042193A |. 52 ||push edx 0042193B |. E8 085D0000 ||call <jmp.&MFC42.#940_CString::operator+=> 00421940 |> 8BFB ||mov edi, ebx 00421942 |. 83C9 FF ||or ecx, FFFFFFFF 00421945 |. 33C0 ||xor eax, eax 00421947 |. 45 ||inc ebp 00421948 |. F2:AE ||repne scas byte ptr es:[edi] 0042194A |. F7D1 ||not ecx 0042194C |. 49 ||dec ecx 0042194D |. 3BE9 ||cmp ebp, ecx ; EBP是循环的次数,ECX是用户名位数 0042194F |.^ 72 B5 |\jb short 00421906 00421951 |> 8B4424 34 |mov eax, dword ptr [esp+34] ; 用户名和密码表对应换算成的一串字符(注册码一部分)设为R1 00421955 |. 8B48 F8 |mov ecx, dword ptr [eax-8] ; 用户名长度放入ECX 00421958 |. 83F9 10 |cmp ecx, 10 ; 比较用户名是不是大于16位 0042195B |. 7D 3A |jge short 00421997 0042195D |. 8BC1 |mov eax, ecx 0042195F |. B9 10000000 |mov ecx, 10 00421964 |. 2BC8 |sub ecx, eax ; 如果用户名长度(设为len)小于16位,算出(16-len) 00421966 |. 8D5424 1C |lea edx, dword ptr [esp+1C] 0042196A |. 51 |push ecx 0042196B |. 52 |push edx 0042196C |. B9 C48E4300 |mov ecx, 00438EC4 00421971 |. E8 D45A0000 |call <jmp.&MFC42.#4129_CString::Left> ; 可疑之处,等会跟进看看 00421976 |. 50 |push eax 00421977 |. 8D4C24 38 |lea ecx, dword ptr [esp+38] 0042197B |. C64424 30 03 |mov byte ptr [esp+30], 3 00421980 |. E8 BD5C0000 |call <jmp.&MFC42.#939_CString::operator+=> 00421985 |. 8D4C24 1C |lea ecx, dword ptr [esp+1C] 00421989 |. C64424 2C 02 |mov byte ptr [esp+2C], 2 0042198E |. E8 0F5A0000 |call <jmp.&MFC42.#800_CString::~CString> 00421993 |. 8B4424 34 |mov eax, dword ptr [esp+34] ; 两部分注册码连接,即R1+R2(出现了明码) 00421997 |> 8B4C24 20 |mov ecx, dword ptr [esp+20] 0042199B |. 51 |push ecx ; /s2 0042199C |. 50 |push eax ; |s1 0042199D |. FF15 B4D64200 |call dword ptr [<&MSVCRT._mbscmp>] ; \_mbscmp 比较真假码 004219A3 |. 83C4 08 |add esp, 8 004219A6 |. 8D4C24 34 |lea ecx, dword ptr [esp+34] 004219AA |. 85C0 |test eax, eax 004219AC |. C64424 2C 01 |mov byte ptr [esp+2C], 1 004219B1 |. 74 1B |je short 004219CE ; 真正的关键跳 004219B3 |. 33F6 |xor esi, esi 004219B5 |. E8 E8590000 |call <jmp.&MFC42.#800_CString::~CString> 004219BA |. 8B4424 38 |mov eax, dword ptr [esp+38] 004219BE |. 40 |inc eax 004219BF |. 83F8 03 |cmp eax, 3 004219C2 |. 894424 38 |mov dword ptr [esp+38], eax 004219C6 |.^ 0F8C 0EFFFFFF \jl 004218DA 004219CC |. EB 0A jmp short 004219D8 004219CE |> BE 01000000 mov esi, 1
…… 73D86480 33FF xor edi, edi 73D86482 8B01 mov eax, dword ptr [ecx] ; 另外一截密码表"ESqNCdaYoDciekuS" 73D86484 3B78 F8 cmp edi, dword ptr [eax-8] 73D86487 7C 0B jl short 73D86494 73D86489 51 push ecx 73D8648A 8B4D 08 mov ecx, dword ptr [ebp+8] 73D8648D E8 FFDEFAFF call #535_CString::CString 73D86492 EB 3C jmp short 73D864D0 73D86494 56 push esi 73D86495 8D4D 0C lea ecx, dword ptr [ebp+C] 73D86498 E8 BFC1FAFF call #540_CString::CString 73D8649D 8B4D F0 mov ecx, dword ptr [ebp-10] 73D864A0 6A 00 push 0 73D864A2 6A 00 push 0 73D864A4 33F6 xor esi, esi 73D864A6 57 push edi 73D864A7 8D45 0C lea eax, dword ptr [ebp+C] 73D864AA 46 inc esi 73D864AB 50 push eax 73D864AC 8975 FC mov dword ptr [ebp-4], esi 73D864AF E8 27710000 call #1589_CString::AllocCopy 73D864B4 8B4D 08 mov ecx, dword ptr [ebp+8] ; 加入刚刚算出的(16-len)为9,则从第一位开始截取第二组密码表"ESqNCdaYoDciekuS"9位并取出(注册码第二部分)设为R2 73D864B7 8D45 0C lea eax, dword ptr [ebp+C] 73D864BA 50 push eax 73D864BB E8 D1DEFAFF call #535_CString::CString
1、软件事先定义两组密码表如下:
单步走到0042190B处,查看数据窗口可知第一处密码表:aGbmcldSemfkgEhcixjsktlYmbnkoDptqarfswtlujvDwIxPyZzXAPBoCKDgEyFmGtHaIrJqKNLQMUNuOGPJQLRnSbTCUFVHWoXwYEZpvMw
在73D86482会出现第二处密码表:ESqNCdaYoDciekuS
2、软件依次取出用户名每一位根据第一处密码表换算成密码表中的字符,从而生成一个和用户自己输入的用户名相同的字符串
3、然后判断用户名是不是大于16位,若小于则算出(16-len),然后从第二处密码表开头依次取出(16-len)位,并且与第2步的字串连接作为注册码;若不小于16位,则直接把根据第一处密码表换算生成的字串作为注册码
根据研究发现要把这段汇编“翻译”成高级语言还真不太容易,灵机一动想到一个另类的方法,呵呵:
OD载入,用户名我们输入“abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ”,注册码随便,然后单步到004218B2时不要让跳转实现(会跳向错误),当单步到00421951时,出现一个字符串“GmlSmkEcxstYbkDtafwljDIPZXPoKgymtarqNQUuGJLnbCFHowEp”,呵呵,这就是大小写52个字母分别对应的注册码值,用这个字符串来选个注册码看看
用户名:playboysen
对应
注册码:tYGZmDZwmk
因为我们的用户名只有10位,那么16-10=6,从第二个密码表中取出前6位“ESqNCd”
最终注册码为: tYGZmDZwmkESqNCd
今天七夕,天比较晚了,还要赶着回去给GF打电话去呢,注册机就先不写了,有时间再补上,同时也祝愿大家有情人终成眷属,七夕快乐!
