【文章标题】: PsmPlayer的算法分析
【文章作者】: Pants
【作者邮箱】: [email]20323497@qq.com[/email]
【作者QQ号】: 20323497
【软件名称】: PsmPlayer 5.1 简体中文版
【软件大小】: 165 KB
【下载地址】: 自己搜索下载
【加壳方式】: nPack
【保护方式】: Name/Serial
【编写语言】: Borland C++
【使用工具】: OD、Filemon、PEiD
【软件介绍】: 可将 MIDI、WAV 转换为 MMF 格式的和弦铃声
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
PsmPlayer是一个小巧的手机和弦转换工具,未注册版本有功能限制。
本人没¥买铃声,只能自己做了传入手机,为了得到“淡入淡出”功能,不得已拿起了屠刀……
这个软件有点怪怪的,软件本身的界面上没有输入注册名和注册码的地方。(也许是我下的版本的问题)
那它怎么注册呢?
可能是读取某个文件的内容,或是某个注册表项吧。
用Filemon发现程序读取了"C:\WINDOWS\psmplay.ini",打开后看到:
[section]
regist=0
username=
可以想到第一行就是注册码,第二行就是注册名了。
我输入了
regist=12345678
username=Pants
保存退出。
打开OD,载入PsmPlayer,发现有加壳,用PEiD查看,EP段为".nPack"。
00478280 > 833D 408F4700 0>cmp dword ptr [478F40], 0 ; 检测标志
00478287 75 05 jnz short 0047828E ; 标志是0的话就退出程序
00478289 E9 01000000 jmp 0047828F
0047828E C3 retn
0047828F E8 41000000 call 004782D5 ; 内存空间申请
00478294 B8 80824700 mov eax, offset <模块入口点>
00478299 2B05 088E4700 sub eax, dword ptr [478E08]
0047829F A3 3C8F4700 mov dword ptr [478F3C], eax
004782A4 E8 5E000000 call 00478307 ; 解码
004782A9 E8 EC010000 call 0047849A ; dll加载
004782AE E8 F8060000 call 004789AB ; iat地址填充
004782B3 E8 03060000 call 004788BB ; 重定位处理
004782B8 A1 3C8F4700 mov eax, dword ptr [478F3C] ; 计算oep
004782BD C705 408F4700 0>mov dword ptr [478F40], 1
004782C7 0105 008E4700 add dword ptr [478E00], eax
004782CD FF35 008E4700 push dword ptr [478E00]
004782D3 C3 retn ; 返回程序的真正入口
然后到达
00401000 A1 db A1
00401001 5A db 5A ; CHAR 'Z'
00401002 70 db 70 ; CHAR 'p'
00401003 43 db 43 ; CHAR 'C'
00401004 00 db 00
光标停在[00401000]处时,用OD插件OllyDump脱壳。
载入脱壳后的PsmPlayer,用OD字符串查找插件找username和regist,找到username后双击来到这里
004070CC |> \68 99774300 push 00437799 ; /psmplay.ini; Case 15F of switch 00404472
004070D1 |. 6A 0A push 0A ; |BufSize = A (10.)
004070D3 |. 68 30134400 push 00441330 ; |ReturnBuffer = PsmPlaye.00441330
004070D8 |. 68 98774300 push 00437798 ; |Default = ""
004070DD |. 68 8F774300 push 0043778F ; |username *停在这行,下断,F9
004070E2 |. 68 87774300 push 00437787 ; |section
004070E7 |. E8 D2F00200 call <jmp.&kernel32.GetPrivateProfile>; \GetPrivateProfileStringA *取注册名
004070EC |. 68 B4774300 push 004377B4 ; /psmplay.ini
004070F1 |. 6A 00 push 0 ; |Default = 0
004070F3 |. 68 AD774300 push 004377AD ; |regist
004070F8 |. 68 A5774300 push 004377A5 ; |section
004070FD |. E8 9CEF0200 call <jmp.&kernel32.GetPrivateProfile>; \GetPrivateProfileIntA *取注册码
00407102 |. 66:A3 2E13440>mov word ptr [44132E], ax
00407108 |. 66:8B15 2E134>mov dx, word ptr [44132E]
0040710F |. 52 push edx ; /Arg1
00407110 |. E8 C6B3FFFF call 004024DB ; \PsmPlaye.004024DB *这里是关键了
00407115 |. 59 pop ecx
00407116 |. 66:A3 2C13440>mov word ptr [44132C], ax
跟进[00407110]的call
004024DB /$ 55 push ebp
004024DC |. 8BEC mov ebp, esp
004024DE |. 53 push ebx
004024DF |. 56 push esi
004024E0 |. 8B5D 08 mov ebx, dword ptr [ebp+8]
004024E3 |. 68 30134400 push 00441330 ; /String = "Pants"
004024E8 |. E8 3B3C0300 call <jmp.&kernel32.lstrlen> ; \lstrlenA
004024ED |. 8BF0 mov esi, eax
004024EF |. 0FBFC6 movsx eax, si
004024F2 |. 50 push eax ; /Arg2 = 00000005
004024F3 |. 68 30134400 push 00441330 ; |Arg1 = 00441330 ASCII "Pants"
004024F8 |. E8 490F0100 call 00413446 ; \PsmPlaye.00413446
要对注册名进行运算了,跟进
00413446 /$ 55 push ebp
00413447 |. 8BEC mov ebp, esp
00413449 |. 53 push ebx
0041344A |. 8B5D 08 mov ebx, dword ptr [ebp+8]
0041344D |. 66:B8 FFFF mov ax, 0FFFF ; 将十六进制数FFFF放入ax中
00413451 |. 33C9 xor ecx, ecx
00413453 |. 3B4D 0C cmp ecx, dword ptr [ebp+C] ; 判断注册名是否为空
00413456 |. 7D 28 jge short 00413480 ; 为空就玩完了
00413458 |> 33D2 /xor edx, edx ; edx置零
0041345A |. 8A140B |mov dl, byte ptr [ebx+ecx] ; 取注册名的一个字符
0041345D |. C1E2 08 |shl edx, 8 ; 左移8位
00413460 |. 66:33C2 |xor ax, dx ; 与OxFFFF异或
00413463 |. 33D2 |xor edx, edx ; edx置零
00413465 |> F6C4 80 |/test ah, 80 ; ax中的高8位ah与0x80进行与运算
00413468 |. 74 08 ||je short 00413472 ; ah的最高位为1就跳
0041346A |. 03C0 ||add eax, eax ; 自加一次
0041346C |. 66:35 2110 ||xor ax, 1021 ; ax与0x1021异或
00413470 |. EB 02 ||jmp short 00413474
00413472 |> 03C0 ||add eax, eax ; 自加一次
00413474 |> 42 ||inc edx ; 计数器加1
00413475 |. 83FA 08 ||cmp edx, 8 ; 循环8次
00413478 |.^ 7C EB |\jl short 00413465
0041347A |. 41 |inc ecx ; 计数器加1
0041347B |. 3B4D 0C |cmp ecx, dword ptr [ebp+C] ; 与注册名长度比较
0041347E |.^ 7C D8 \jl short 00413458
00413480 |> 66:F7D0 not ax ; ax中数据取反
00413483 |. 66:25 FFFF and ax, 0FFFF ; 再与0xFFFF进行与运算
00413487 |. 5B pop ebx
00413488 |. 5D pop ebp
00413489 \. C3 retn
出来后到
004024FD |. 83C4 08 add esp, 8
00402500 |. 0FB7C0 movzx eax, ax ; eax中为前面算出的值
00402503 |. B9 F0580000 mov ecx, 58F0
00402508 |. 99 cdq
00402509 |. F7F9 idiv ecx ; eax的值除以0x58F0
0040250B |. 8BC2 mov eax, edx ; 将余数放入eax
0040250D |. 66:81FB 9D00 cmp bx, 9D
00402512 |. 75 05 jnz short 00402519
00402514 |. 83C8 FF or eax, FFFFFFFF
00402517 |. EB 71 jmp short 0040258A
00402519 |> 66:83FB 74 cmp bx, 74
0040251D |. 75 05 jnz short 00402524
0040251F |. 83C8 FF or eax, FFFFFFFF
00402522 |. EB 66 jmp short 0040258A
00402524 |> 66:83FB 68 cmp bx, 68
00402528 |. 75 05 jnz short 0040252F
0040252A |. 83C8 FF or eax, FFFFFFFF
0040252D |. EB 5B jmp short 0040258A
0040252F |> 66:83FB 71 cmp bx, 71
00402533 |. 75 05 jnz short 0040253A
00402535 |. 83C8 FF or eax, FFFFFFFF
00402538 |. EB 50 jmp short 0040258A
0040253A |> 66:81FB B100 cmp bx, 0B1
0040253F |. 75 05 jnz short 00402546
00402541 |. 83C8 FF or eax, FFFFFFFF
00402544 |. EB 44 jmp short 0040258A
00402546 |> 66:81FB BA00 cmp bx, 0BA
0040254B |. 75 06 jnz short 00402553
0040254D |. 66:B8 0100 mov ax, 1
00402551 |. EB 37 jmp short 0040258A
00402553 |> 66:81FB 8211 cmp bx, 1182
00402558 |. 75 06 jnz short 00402560
0040255A |. 66:B8 0500 mov ax, 5
0040255E |. EB 2A jmp short 0040258A
00402560 |> 0FB7D3 movzx edx, bx ; 取注册码转为十六进制数后的低8位
00402563 |. 0FBFC8 movsx ecx, ax ; 取注册名经过运算后的低8位
00402566 |. 81C1 10270000 add ecx, 2710 ; 余数加上0x2710
0040256C |. 3BD1 cmp edx, ecx ; ①比较是否相等
0040256E |. 0F94C0 sete al
00402571 |. 83E0 01 and eax, 1
00402574 |. 66:83FE 06 cmp si, 6 ; ②注册名不能少于6个字符
00402578 |. 0F9DC2 setge dl
0040257B |. 83E2 01 and edx, 1
0040257E |. 23C2 and eax, edx ; ①②同时满足,注册成功
00402580 |. 74 06 je short 00402588
00402582 |. 66:B8 0700 mov ax, 7
00402586 |. EB 02 jmp short 0040258A
00402588 |> 33C0 xor eax, eax
0040258A |> 5E pop esi
0040258B |. 5B pop ebx
0040258C |. 5D pop ebp
0040258D \. C3 retn
一组可用的注册码
regist=22765
username=PantsT
注册成功后,“关于”里面显示 Special User。
本小鸟第一次发帖,如果分析过程有问题,请各位大侠指正。谢谢!
--------------------------------------------------------------------------------
【经验总结】
贴上 C 编写的注册机。
本人编程习惯不是太好,代码没优化,望各位看客多多包涵。
#include<stdio.h>
#include<string.h>
main()
{
char name[20];
unsigned int serial=0xffff;
unsigned int i,j,temp;
re: printf("Name:\t");
gets(name);
if(strlen(name)<6)
{
printf("Error!\n\n");
goto re;
}
for(i=0;i<strlen(name);i++)
{
temp=name[i];
temp<<=8;
serial^=temp;
for(j=0;j<8;j++)
{
if(serial>>15)
{
serial+=serial;
serial^=0x1021;
}
else serial+=serial;
}
}
serial=~serial;
serial&=0xffff;
serial%=0x58f0;
serial+=0x2710;
printf("Serial:\t%d\n",serial);
getchar();
}
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2006年10月24日 下午 9:49:12
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!