【软件名称】Photo Screensaver Maker V5.0.0
【破文作者】forever[RCT]
【编程语言】VC
【保护方式】RSA256
【使用工具】ida4.6,ollydbg1.1
【软件简介】一款幻灯屏幕保护程序制作软件,你可以用它来制作带照片、音乐和文本的屏保。支持的图片格式:jpg,gif,bmp,png,tif,tga,pcx。支持音频格式:mp3,midi和wav。可以为图片添加文本,并为图片设置各种转场过渡效果
【下载地址】http://www3.skycn.com/soft/22288.html
【破文正文】这个软件不错,使用简单,做出的屏保有很多特效。
破解的基本步骤如下:
1。用peid检测一下编程语言,并且顺便用插件查看一下使用算法。编程语言是VC++,检测到的算法是CRC。不过软件实际使用的算
法却不是CRC。
2。运行程序,看看注册过程能提供给我们什么信息。注册需要注册名和注册码,没有和硬件绑定。填入注册名,随便填一个注册码:
12345678,弹出一个出错的对话框,给出提示信息:Invalid user name or register code。
3。用ida载入主程序分析。分析完后在字符串列表里找到Invalid user name or register code这个字符串。来到引用该字符串的地
方,如下:
===================================================================================================
.text:0042B6D1 push 1
.text:0042B6D3 mov ecx, esi
.text:0042B6D5 call CWnd::UpdateData(int)
.text:0042B6DA lea edi, [esi+64h]
.text:0042B6DD push 0Ah
.text:0042B6DF mov ecx, edi
.text:0042B6E1 call MFC42_6874
.text:0042B6E6 push 0Dh
.text:0042B6E8 mov ecx, edi
.text:0042B6EA call MFC42_6874
.text:0042B6EF push 9
.text:0042B6F1 mov ecx, edi
.text:0042B6F3 call MFC42_6874
.text:0042B6F8 push 20h
.text:0042B6FA mov ecx, edi
.text:0042B6FC call MFC42_6874
.text:0042B701 mov eax, [edi]
.text:0042B703 mov ecx, [esi+60h]
.text:0042B706 push eax
.text:0042B707 push ecx
.text:0042B708 call sub_402752 //这里就是判断注册是否成功的函数了。成功返回1,失败返回0
.text:0042B70D add esp, 8
.text:0042B710 test eax, eax
.text:0042B712 jnz short loc_42B73F
.text:0042B714 push 40h
.text:0042B716 push offset aSorry ; "Sorry"
.text:0042B71B push offset aInvalidUserNam ; "Invalid user name or register code"
.text:0042B720 mov ecx, esi
.text:0042B722 call CWnd::MessageBoxA(char const *,char const *,uint)
.text:0042B727 push 3F3h
.text:0042B72C mov ecx, esi
.text:0042B72E call CWnd::GetDlgItem(int)
.text:0042B733 mov ecx, eax
.text:0042B735 call CWnd::SetFocus(void)
.text:0042B73A jmp loc_42B88C
.text:0042B73F
.text:0042B73F loc_42B73F:
.text:0042B73F mov dword ptr [ebp+0C4h], 1
.text:0042B749 mov eax, [esi+60h]
.text:0042B74C push eax
.text:0042B74D lea ecx, [ebp+0CCh]
.text:0042B753 call CString::operator=(char const *)
.text:0042B758 mov eax, [esi+60h]
.text:0042B75B push eax
.text:0042B75C lea eax, [esp+218h]
.text:0042B763 push offset aLicenseToS ; "License to:%s"
.text:0042B768 push eax
.text:0042B769 call ds:sprintf
.text:0042B76F add esp, 0Ch
.text:0042B772 lea ecx, [esp+214h]
.text:0042B779 push 40h
.text:0042B77B push offset aThankYou ; "Thank you"
.text:0042B780 push ecx
.text:0042B781 mov ecx, esi
.text:0042B783 call CWnd::MessageBoxA(char const *,char const *,uint)
.text:0042B788 mov eax, [esi+60h]
.text:0042B78B lea edx, [esp+14h]
.text:0042B78F sub edx, eax
.text:0042B791
.text:0042B791 loc_42B791:
.text:0042B791 mov cl, [eax]
.text:0042B793 mov [edx+eax], cl
.text:0042B796 inc eax
.text:0042B797 test cl, cl
.text:0042B799 jnz short loc_42B791
.text:0042B79B mov edi, [edi]
.text:0042B79D lea ecx, [esp+114h]
.text:0042B7A4 sub ecx, edi
.text:0042B7A6
.text:0042B7A6 loc_42B7A6:
.text:0042B7A6 mov al, [edi]
.text:0042B7A8 mov [ecx+edi], al
.text:0042B7AB inc edi
.text:0042B7AC test al, al
.text:0042B7AE jnz short loc_42B7A6
.text:0042B7B0 lea ecx, [esp+0Ch]
.text:0042B7B4 call CString::CString(void)
.text:0042B7B9 lea edx, [esp+10h]
.text:0042B7BD mov dword ptr [esp+31Ch], 0
.text:0042B7C8 push edx
.text:0042B7C9 call sub_401D5C
.text:0042B7CE add esp, 4
.text:0042B7D1 push eax
.text:0042B7D2 lea ecx, [esp+10h]
.text:0042B7D6 mov byte ptr [esp+320h], 1
.text:0042B7DE call CString::operator=(CString const &)
.text:0042B7E3 lea ecx, [esp+10h]
.text:0042B7E7 mov byte ptr [esp+31Ch], 0
.text:0042B7EF call CString::~CString(void)
.text:0042B7F4 lea eax, [esp+0Ch]
.text:0042B7F8 push offset aDataRegdata_in ; "data\\regdata.ini" //注册信息保存到regdata.ini里
.text:0042B7FD lea ecx, [esp+14h]
.text:0042B801 push eax
.text:0042B802 push ecx
.text:0042B803 call operator+(CString const &,char const *)
.text:0042B808 push eax
.text:0042B809 lea ecx, [esp+10h]
.text:0042B80D mov byte ptr [esp+320h], 2
.text:0042B815 call CString::operator=(CString const &)
.text:0042B81A lea ecx, [esp+10h]
.text:0042B81E mov byte ptr [esp+31Ch], 0
.text:0042B826 call CString::~CString(void)
.text:0042B82B mov edx, [esp+0Ch]
.text:0042B82F mov edi, ds:WritePrivateProfileStringA
.text:0042B835 lea eax, [esp+14h]
.text:0042B839 push edx
.text:0042B83A push eax
.text:0042B83B push offset aUserName ; "User name"
.text:0042B840 push offset aRegister ; "Register"
.text:0042B845 call edi ; WritePrivateProfileStringA
.text:0042B847 mov ecx, [esp+0Ch]
.text:0042B84B lea edx, [esp+114h]
.text:0042B852 push ecx
.text:0042B853 push edx
.text:0042B854 push offset aRegistrationCo ; "Registration code"
.text:0042B859 push offset aRegister ; "Register"
.text:0042B85E call edi ; WritePrivateProfileStringA
.text:0042B860 mov eax, [ebp+0]
.text:0042B863 mov ecx, ebp
让我们跟进函数402752,来到下面:
看看下面这段函数,我猜测是RSA算法,并且是RSA256。猜算法并没有什么好的方法,大多是凭经验。
这段函数我结合ollydbg来分析,并且用我修改的RsaKit来验证。:) 详细分析见注释:
===================================================================================================
.text:0042AFF0 loc_42AFF0:
.text:0042AFF0 push 0FFFFFFFFh
.text:0042AFF2 push offset loc_4C3349
.text:0042AFF7 mov eax, large fs:0
.text:0042AFFD push eax
.text:0042AFFE mov large fs:0, esp
.text:0042B005 sub esp, 94h
.text:0042B00B mov eax, [esp+0A4h]
.text:0042B012 push ebx
.text:0042B013 push esi
.text:0042B014 push eax
.text:0042B015 lea ecx, [esp+10h]
.text:0042B019 mov dword ptr [esp+60h], 0FBF8A47h
.text:0042B021 mov dword ptr [esp+64h], 234E94C9h
.text:0042B029 mov dword ptr [esp+68h], 0E4475D85h
.text:0042B031 mov dword ptr [esp+6Ch], 0DBF030EEh
.text:0042B039 mov dword ptr [esp+70h], 323B9C06h
.text:0042B041 mov dword ptr [esp+74h], 0E3D3C333h
.text:0042B049 mov dword ptr [esp+78h], 0C9BF2B1Ah
.text:0042B051 mov dword ptr [esp+7Ch], 385AC5EEh //这里是N
.text:0042B059 call CString::CString(char const *) //用户名
.text:0042B05E mov ecx, [esp+0B0h]
.text:0042B065 mov dword ptr [esp+0A4h], 0
.text:0042B070 push ecx
.text:0042B071 lea ecx, [esp+0Ch]
.text:0042B075 call CString::CString(char const *) //注册码
.text:0042B07A mov edx, [esp+0Ch]
.text:0042B07E mov esi, ds:_mbscmp
.text:0042B084 push offset ValueName
.text:0042B089 push edx
.text:0042B08A mov byte ptr [esp+0ACh], 1
.text:0042B092 call esi ; _mbscmp //比较用户名是否为空
.text:0042B094 add esp, 8
.text:0042B097 test eax, eax
.text:0042B099 jz loc_42B2AE
.text:0042B09F mov eax, [esp+8]
.text:0042B0A3 push offset ValueName
.text:0042B0A8 push eax
.text:0042B0A9 call esi ; _mbscmp //比较注册码是否为空
.text:0042B0AB add esp, 8
.text:0042B0AE test eax, eax
.text:0042B0B0 jz loc_42B2AE
.text:0042B0B6 push edi
.text:0042B0B7 push 0
.text:0042B0B9 lea ecx, [esp+44h]
.text:0042B0BD call sub_4016D1 //初始化大数1
.text:0042B0C2 push 0
.text:0042B0C4 lea ecx, [esp+4Ch]
.text:0042B0C8 mov byte ptr [esp+0ACh], 2
.text:0042B0D0 call sub_4016D1 //初始化大数2
.text:0042B0D5 mov bl, 3
.text:0042B0D7 push 10001h
.text:0042B0DC lea ecx, [esp+5Ch]
.text:0042B0E0 mov [esp+0ACh], bl
.text:0042B0E7 call sub_4016D1 //初始化大数E(10001)
.text:0042B0EC lea ecx, [esp+58h] //我根据这个猜测是RSA
.text:0042B0F0 mov byte ptr [esp+0A8h], 4
.text:0042B0F8 push ecx
.text:0042B0F9 lea ecx, [esp+4Ch]
.text:0042B0FD call sub_401D07 //复制大数E到大数2
.text:0042B102 lea ecx, [esp+58h]
.text:0042B106 mov [esp+0A8h], bl
.text:0042B10D call sub_401BC7
.text:0042B112 lea edx, [esp+60h]
.text:0042B116 push 8
.text:0042B118 push edx
.text:0042B119 lea ecx, [esp+48h]
.text:0042B11D call sub_40276B //大数1赋值为N
.text:0042B122 mov ecx, 8
.text:0042B127 xor eax, eax
.text:0042B129 lea edi, [esp+18h] //这里32个字节清零,准备读入注册码
.text:0042B12D lea edx, [esp+2Ch]
.text:0042B131 rep stosd
.text:0042B133 lea eax, [esp+34h]
.text:0042B137 lea ecx, [esp+30h]
.text:0042B13B push eax
.text:0042B13C push ecx
.text:0042B13D lea eax, [esp+30h]
.text:0042B141 push edx
.text:0042B142 lea ecx, [esp+30h]
.text:0042B146 push eax
.text:0042B147 lea edx, [esp+30h]
.text:0042B14B push ecx
.text:0042B14C lea eax, [esp+30h]
.text:0042B150 push edx
.text:0042B151 mov edx, [esp+24h]
.text:0042B155 lea ecx, [esp+30h]
.text:0042B159 push eax
.text:0042B15A push ecx
.text:0042B15B push offset a08lx08lx08lx08 ; "%08lX-%08lX-%08lX-%08lX-%08lX-%08lX-%08"...
.text:0042B160 push edx
.text:0042B161 call ds:sscanf //读入注册码,从这里可以看出注册码的格式
.text:0042B167 mov eax, [esp+50h] //第五组注册码
.text:0042B16B mov ecx, [esp+4Ch] //第四组注册码
.text:0042B16F mov edi, [esp+48h] //第三组注册码
.text:0042B173 mov edx, [esp+44h] //第二组注册码
.text:0042B177 add eax, ecx //第五组加上第四组
.text:0042B179 mov ecx, [esp+5Ch] //第八组注册码
.text:0042B17D add eax, edi //和加上第三组
.text:0042B17F mov edi, [esp+58h] //第七组注册码
.text:0042B183 add eax, edx //和加上第二组
.text:0042B185 mov edx, [esp+54h] //第六组注册码
.text:0042B189 xor ecx, eax //和异或上第八组注册码
.text:0042B18B mov eax, [esp+40h] //第一组注册码
.text:0042B18F add esp, 28h
.text:0042B192 add edx, eax //第六组加上第一组
.text:0042B194 mov [esp+34h], ecx //异或后的结果保存到原来第八组的位置(8=(5+4+3+2)xor8)
.text:0042B198 xor edi, edx //和异或上第七组
.text:0042B19A push 0
.text:0042B19C lea ecx, [esp+3Ch]
.text:0042B1A0 mov [esp+34h], edi //异或后的结果保存到原来第七组的位置(7=(1+6)xor7)
.text:0042B1A4 call sub_4016D1 //初始化大数3
.text:0042B1A9 lea ecx, [esp+18h]
.text:0042B1AD push 8
.text:0042B1AF push ecx
.text:0042B1B0 lea ecx, [esp+40h]
.text:0042B1B4 mov byte ptr [esp+0B0h], 5
.text:0042B1BC call sub_40276B //大数3读入处理后的注册码
.text:0042B1C1 lea edx, [esp+38h]
.text:0042B1C5 lea eax, [esp+50h]
.text:0042B1C9 push edx //大数3
.text:0042B1CA push eax //用来保存结果
.text:0042B1CB lea ecx, [esp+48h]
.text:0042B1CF call loc_402A0E //RSA运算
.text:0042B1D4 mov ecx, 8
.text:0042B1D9 xor eax, eax
.text:0042B1DB lea edi, [esp+18h]
.text:0042B1DF push 8
.text:0042B1E1 rep stosd //清零32个字节缓冲区
.text:0042B1E3 lea ecx, [esp+1Ch]
.text:0042B1E7 mov byte ptr [esp+0ACh], 6
.text:0042B1EF push ecx
.text:0042B1F0 lea ecx, [esp+58h]
.text:0042B1F4 call sub_401C99 //输出RSA运算结果
.text:0042B1F9 mov ecx, 8
.text:0042B1FE xor eax, eax
.text:0042B200 lea edi, [esp+80h]
.text:0042B207 rep stosd
.text:0042B209 pop edi
.text:0042B20A
.text:0042B20A loc_42B20A:
.text:0042B20A mov dl, [esp+eax+17h] //转换大小尾
.text:0042B20E mov cl, [esp+eax+16h]
.text:0042B212 mov [esp+eax+7Ch], dl
.text:0042B216 mov edx, [esp+eax+14h]
.text:0042B21A mov [esp+eax+7Dh], cl
.text:0042B21E mov cl, [esp+eax+14h]
.text:0042B222 shr edx, 8
.text:0042B225 mov [esp+eax+7Eh], dl
.text:0042B229 mov [esp+eax+7Fh], cl
.text:0042B22D add eax, 4
.text:0042B230 cmp eax, 20h
.text:0042B233 jl short loc_42B20A
.text:0042B235 lea edx, [esp+7Ch]
.text:0042B239 lea ecx, [esp+10h]
.text:0042B23D push edx
.text:0042B23E call CString::CString(char const *)
.text:0042B243 mov eax, [esp+10h]
.text:0042B247 mov ecx, [esp+0Ch]
.text:0042B24B push eax //RSA结果
.text:0042B24C push ecx //用户名
.text:0042B24D call esi ; _mbscmp //比较两个字符串是否相等
.text:0042B24F add esp, 8
.text:0042B252 lea ecx, [esp+10h]
.text:0042B256 test eax, eax
.text:0042B258 mov byte ptr [esp+0A4h], 6
.text:0042B260 jz loc_42B2EC //相等则返回1
.text:0042B266 call CString::~CString(void)
.text:0042B26B lea ecx, [esp+4Ch]
.text:0042B26F mov byte ptr [esp+0A4h], 5
.text:0042B277 call sub_401BC7
.text:0042B27C lea ecx, [esp+34h]
.text:0042B280 mov [esp+0A4h], bl
.text:0042B287 call sub_401BC7
.text:0042B28C lea ecx, [esp+44h]
.text:0042B290 mov byte ptr [esp+0A4h], 8
.text:0042B298 call sub_401BC7
.text:0042B29D lea ecx, [esp+3Ch]
.text:0042B2A1 mov byte ptr [esp+0A4h], 1
.text:0042B2A9 call sub_401BC7
.text:0042B2AE
.text:0042B2AE loc_42B2AE:
.text:0042B2AE
.text:0042B2AE lea ecx, [esp+8]
.text:0042B2B2 mov byte ptr [esp+0A4h], 0
.text:0042B2BA call CString::~CString(void)
.text:0042B2BF lea ecx, [esp+0Ch]
.text:0042B2C3 mov dword ptr [esp+0A4h], 0FFFFFFFFh
.text:0042B2CE call CString::~CString(void)
.text:0042B2D3 pop esi
.text:0042B2D4 xor eax, eax
.text:0042B2D6 pop ebx
.text:0042B2D7 mov ecx, [esp+94h]
.text:0042B2DE mov large fs:0, ecx
.text:0042B2E5 add esp, 0A0h
.text:0042B2EB retn
===================================================================================================
总结:1。预处理注册码。
注册码分为8组,第8组 = (5,4,3,2组之和)异或 第8组
第7组 = (1,6组之和)异或 第7组
2。RSA256运算
N : 385AC5EEC9BF2B1AE3D3C333323B9C06DBF030EEE4475D85234E94C90FBF8A47
E : 10001
3。变换RSA256运算结果
把形如12 34 56 78 90 ab cd ef 的形式转换为78 56 34 12 ef cd ab 90的形式
4。变换后的结果和用户名比较,相等则注册成功,不等则失败。
注册算法是上面的逆运算,分解一个256位的N在我的机器上大概半小时的时间,注册算法就不给出了。感兴趣的可以自己做一下。
===================================================================================================
[全文完]
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课