【七夕礼物】Power Video Converter算法分析+另类注册机
【破文标题】Power Video Converter算法分析+另类注册机【破文作者】p layboysen
【作者主页】p layboysen2.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 ;假码"963852741"
00421BBD .8B4E 60 mov ecx, dword ptr ;用户名"senhuan"
00421BC0 .8D5E 64 lea ebx, dword ptr
00421BC3 .8D7E 60 lea edi, dword ptr
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>跟进00421BC8处的call:00421A40/$8B5424 04 mov edx, dword ptr ;用户名“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:, byte ptr ;比较用户名是不是输入
00421A56|.74 2B je short 00421A83
00421A58|.8B4424 10 mov eax, dword ptr ;假码“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:, byte ptr ;比较假码是否输入
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跟进00421A72的call(省略部分代码):……
0042185F|.8B4C24 38 mov ecx, dword ptr ;假码放入ECX
00421863|.8BD8 mov ebx, eax ;用户名放入EBX,下面关键处会用到
00421865|.51 push ecx
00421866|.8D4C24 14 lea ecx, dword ptr
0042186A|.E8 FD5D0000 call <jmp.&MFC42.#537_CString::CString>
0042186F|.8D4C24 10 lea ecx, dword ptr
00421873|.C64424 2C 01mov byte ptr , 1
00421878|.E8 DF610000 call <jmp.&MFC42.#6282_CString::TrimLeft>
0042187D|.8D4C24 10 lea ecx, dword ptr
00421881|.E8 D0610000 call <jmp.&MFC42.#6283_CString::TrimRight>
00421886|.6A 20 push 20
00421888|.8D4C24 14 lea ecx, dword ptr
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 , edx ;放假码是用来求其长度
004218A0|.F2:AE repne scas byte ptr es:
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:
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:
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:
004218CD|.F7D1 not ecx
004218CF|.49 dec ecx
004218D0|.0F84 36010000 je 00421A0C
004218D6|.894424 38 mov dword ptr , eax
004218DA|>8B5424 38 /mov edx, dword ptr
004218DE|.8D4C24 34 |lea ecx, dword ptr
004218E2|.8A82 A8884300 |mov al, byte ptr
004218E8|.884424 18 |mov byte ptr , 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:
004218FC|.F7D1 |not ecx
004218FE|.49 |dec ecx ;此时ECX中是用户名长度
004218FF|.C64424 2C 02|mov byte ptr , 2
00421904|.74 4B |je short 00421951
00421906|>8A042B |/mov al, byte ptr ;EBX中放的是用户名,用户名每个字母依次放入al中
00421909|.33F6 ||xor esi, esi
0042190B|>3A0475 408843>||/cmp al, byte ptr ;在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 ;这里的字符串是用户名所对应的密码表转换后的值
00421923|.51 ||push ecx
00421924|.8D4C24 38 ||lea ecx, dword ptr
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
00421936|.8D4C24 34 ||lea ecx, dword ptr
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:
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 ;用户名和密码表对应换算成的一串字符(注册码一部分)设为R1
00421955|.8B48 F8 |mov ecx, dword ptr ;用户名长度放入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
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
0042197B|.C64424 30 03|mov byte ptr , 3
00421980|.E8 BD5C0000 |call <jmp.&MFC42.#939_CString::operator+=>
00421985|.8D4C24 1C |lea ecx, dword ptr
00421989|.C64424 2C 02|mov byte ptr , 2
0042198E|.E8 0F5A0000 |call <jmp.&MFC42.#800_CString::~CString>
00421993|.8B4424 34 |mov eax, dword ptr ;两部分注册码连接,即R1+R2(出现了明码)
00421997|>8B4C24 20 |mov ecx, dword ptr
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
004219AA|.85C0 |test eax, eax
004219AC|.C64424 2C 01|mov byte ptr , 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
004219BE|.40 |inc eax
004219BF|.83F8 03 |cmp eax, 3
004219C2|.894424 38 |mov dword ptr , eax
004219C6|.^ 0F8C 0EFFFFFF \jl 004218DA
004219CC|.EB 0A jmp short 004219D8
004219CE|>BE 01000000 mov esi, 1跟进00421971的call:……
73D86480 33FF xor edi, edi
73D86482 8B01 mov eax, dword ptr ; 另外一截密码表"ESqNCdaYoDciekuS"
73D86484 3B78 F8 cmp edi, dword ptr
73D86487 7C 0B jl short 73D86494
73D86489 51 push ecx
73D8648A 8B4D 08 mov ecx, dword ptr
73D8648D E8 FFDEFAFF call #535_CString::CString
73D86492 EB 3C jmp short 73D864D0
73D86494 56 push esi
73D86495 8D4D 0C lea ecx, dword ptr
73D86498 E8 BFC1FAFF call #540_CString::CString
73D8649D 8B4D F0 mov ecx, dword ptr
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
73D864AA 46 inc esi
73D864AB 50 push eax
73D864AC 8975 FC mov dword ptr , esi
73D864AF E8 27710000 call #1589_CString::AllocCopy
73D864B4 8B4D 08 mov ecx, dword ptr ; 加入刚刚算出的(16-len)为9,则从第一位开始截取第二组密码表"ESqNCdaYoDciekuS"9位并取出(注册码第二部分)设为R2
73D864B7 8D45 0C lea eax, dword ptr
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个字母分别对应的注册码值,用这个字符串来选个注册码看看
用户名:p layboysen(因为我们论坛有文字自动过滤,所以我在p的后面故意加了一个空格,试验的时候请自行去除)
对应
注册码:tYGZmDZwmk
因为我们的用户名只有10位,那么16-10=6,从第二个密码表中取出前6位“ESqNCd”
最终注册码为: tYGZmDZwmkESqNCd
今天七夕,天比较晚了,还要赶着回去给GF打电话去呢,注册机就先不写了,有时间再补上,同时也祝愿大家有情人终成眷属,七夕快乐!/:013
[ 本帖最后由 playboysen 于 2008-8-8 08:12 编辑 ] 强烈支持
十分强大 学习一下,先谢谢楼主了 写得真详细,楼主辛苦了。 哎,我这水平能达到这样就好了! 版主是不是把论坛的文字过滤系统给改一下啊,连我的名字“p layboysen”都给我过滤了的,呜呜 原帖由 **sen 于 2008-8-8 08:07 发表 https://www.chinapyg.com/images/common/back.gif
版主是不是把论坛的文字过滤系统给改一下啊,连我的名字“p layboysen”都给我过滤了的,呜呜
坚持过奥运感谢兄弟分享 ~ 不错!学习了!感谢楼主分享:victory: 呵呵,补充注意事项:
1、软件会把任何单个中文字符用密码表换算成“vv”,即如果用户名是“飘云阁”,则在00421951设断会发现R1为“vvvvvv”(6位),然后再用16-6=10,从第二处密码表“ESqNCdaYoDciekuS”取出十位并连接,即为注册码(用户名:飘云阁 注册码:vvvvvvESqNCdaYoD)
2、注册成功后要重启软件才能在About中看到效果
3、注册码保存在软件根目录videoconvert.ini文件中
Enjoy~~
不错,不错
支持支持:loveliness: :loveliness: :loveliness:
页:
[1]
2