一、免责声明
包含且不限于本文、截图、分析,版权均归本人所有,如需转载,请与本人联系(看雪|吾爱ID相同),软件版权归软件官方所有,如有侵权,请联系管理或本人删帖。
仅供学术交流研究使用,不得用于非法、商业用途!!
请支持正版,购买正版以获得新版更新及更好地服务。
二、软件相关信息
软件名:sofeh music studio 4551
软件官网:http://www.sofeh.net/e/?page_id=15
貌似。。被更新了网站地址?可能是访问量突然增加吧。大家尽量从官网的域名进。。。
软件类型:win
软件大小:74.7MB
下载地址:从官网进入(之前的链接失效了)但目前最新版算法没有变化。
本人分析时所用版本的原版软件(https://www.lanzouj.com/i49p1uj
密码:67bd)
注册方式:请求码(机器码生成),本地注册
分析方式:动态
使用软件:吾爱专版 OD(Ollydbg)(下载见爱盘)
分析人员:涛之雨
分析环境:WinXp
鸣谢:感谢 @KaQqi大佬抽出宝贵时间进行指导。
安卓APP版本
请移步本人的另一篇文章
Google Play的一款专业电子琴。ORG 2020 汉化 && 破解版
https://www.52pojie.cn/thread-947671-1-1.html
(出处:吾爱破解论坛)
三、查壳
额。。我先说一下吧。。有能力的朋友也可以试验一下脱壳。。。
KaQqi大佬说,这个软件是:新版enigma的壳。。。我还搞不定。。
查壳完毕,继续。
四、分析软件注册流程
不管破解什么,如何破解,都是至少要对软件注册的流程十分熟悉,
如果不了解流程就去尝试破解,有可能会误入歧途,然后最终导致放弃。
流程如图1所示:
Help
-Activate the Professional freatures
-输入注册码
-判断是否成功
-错误代码
(图1)
五、I D A载入
因为是加密压缩壳,所以没有分析出什么有效信息,故不附图了,该做的流程还是要有的,以防万一有什么发现。
六、OD载入
因为没有检测调试器,可以直接拖入OD调试,或是附加调试。
这里推荐附加的方法,因为是虚拟壳,直接载入有时有可能会出问题。这里我们附加到调试器。
如图2所示:右上角文件
-附加
-选择【music studio】进程
-确定
。
(图2)
因为是附加调试会暂停在系统领空,先按图4所示:
点运行程序
(F9
)让程序跑起来,
点E
(快捷键:Alt+E
【Modules】,)显示模块列表
双击Music Studio.exe
软件主模块,
(图3)
(一)、找关键跳转
1、查看代码
进入软件,发现软件内机器码全部都是00
(图4中所示)应该是虚拟化后释放了
(图4)
2、搜索字符串
回到软件的内存里,如图5所示:右键
-转到
-表达式
(快捷键:Ctrl+G
)【Goto】-输入00401000
(图5)
(注:winxp软件的基址一般都是401000
,如果是win7及以上版本的系统则不一定。需要自行点M
(快捷键:Alt+M
)[memory]查看内存,获取基址。详细教程可以看论坛的教程或是到搜索引擎进行搜索)
如图6所示,进行右键
-中文搜索引擎
-智能搜索
的操作。
(图6)
根据四、分析软件注册流程
的结果,需要找到弹窗的call
由弹窗的信息,可以尝试搜索关键词Error
, activation
, code
, wrong
等以定位弹窗的call,从而向上查找关键跳转。
注:搜索关键词的时候可以稍微减少一点,以防关键词被拆分。
如图7所示,本人搜索的就是activation
,有且仅有一处。上下字符串的内容也是符合该处其他内容的,因此可以初步判断,该处即为弹窗的内容。
(图7)
(二)、尝试爆破
双击改行(或是选中该行后按Enter
键),查看该处代码。
1、分析、猜测
如图8
(图8)
该段代码比较长,因此可以猜测此处上方有判断语句,
向下观察,发现有一处jmp
指令,再次猜测上方有个跳转,可以实现跳过该段错误提示的弹窗。
向上观察,发现有一处jnz
指令,鼠标点击改行指令,根据左侧的引导线箭头可知,恰好跳过了错误弹窗的一段内容。
猜测该处为关键跳转。
2、验证猜想
经过分析,猜测如图12中005D81C2
处为判断是否注册成功的关键跳转。
如图9所示:选中改行
-右键
-断点
-切换
(快捷键:F2
)在该处下一个断点
(图9)
如图10所示,再次重复注册操作,可以看到再点击Activate
后,软件断在了下断点改行,并且左上角显示暂停
字样。
(图10)
断点行左侧引导线为灰色,证明跳转不成立,双击右侧寄存器窗口的控制符Z
以使该跳转成立。
更改后,效果如图11,引导线变为红色,即跳转成立。点击如图15所示左上角运行
按钮(快捷键:F9
)。
(图11)
运行后发现成功!
结果如图12所示。
(图12)
再次运行该软件,发现存在如图13所示的问题:
软件依旧为试用版,未解锁专业版
软件注册按钮没有消失(官网说注册成功后Activate
按钮会消失)
(图13)
因此破解到此尚未成功。
(三)、尝试追码
1、定位关键call
回到刚才下断点的地址,
注:如果没有找到可以
1:按上文【误解】的内容跳转到指定地址。)
2:点击菜单下侧B
按钮(快捷键:Alt+B
)【Break】
向上查看关键比较代码
如图14,关键跳转上方的三个call
都很可疑,均需要分析。
(图14)
3、单步步过,猜测call的作用
如图15,一路按F8
单步步过(图中右侧绿色
箭头所示按钮;白色
箭头所示为:单步步入),不跟入call
内部,先猜测每个call
的作用,然后重点分析怀疑对象,以提高效率和成功率。
(图15)
跟到如图16所示的地方,刚刚经过一个call,通过分析、查看下侧信息窗口
、右侧寄存器窗口
及堆栈窗口
返回的数值,可以猜测005D81A6
处call
是得到假码的call,继续分析下面两个call
可以猜测出下面第二个call
判断注册是否成功
,而根据返回的al
标志符的值,判断是否注册成功。
(图16)
4、跟进关键call
因此需要着重跟进该处call
进行分析
如图17所示,在该处call
下断点,重复注册操作,进程在该处断下,按F7
单步跟入,追踪真码。
(图17)
如图18所示,发现在上下移动代码行后,EIP
所在行出现了错误。
此处因为本人理解出错,感谢H大纠正。
这是编译器编译出的数据,od可以按ctrl+A
分析
(图18)
或是像本人一样手动改为00或90
分析完,代码如图19所示,因为篇幅原因,下面的两个call
已经分析过了,依然是单步步过
下几行。
(图19)
分析如下图20。至此,真码已经出炉了。在寄存器的EAX
和EDX
中,已经把真码告诉我们了。。。
(图20)
5、测试追出的真码
如图28所示,虽然已经确认了是真的注册码,但测试一下还是要令人愉悦的23333。
至此可以利用论坛的其他教程写出内存注册机
了。(善用论坛搜索功能)
(图21)
(四)、注册码算法分析
1、取消已有的注册码授权
要分析算法,首先要取消刚刚注册码,方法如下,任选其一即可:
1) 再次打开注册窗口,改动注册码,按回车键;
2) 如图22所示,在软件根目录下,注册成功后会新生成一个Activation
注册文件,以文本方式打开该文件,即可发现请求码和注册码。删掉该文件即可。
注:软件需要重新打开才会生效
(图22)
2、跟进关键call
之前追码追到的算法关键call
地址,如图23所示,我的电脑是004DFE68
,观察下面的代码,发现OD
识别出了字符-
,结合上面的je
跳转判断,再联系到注册码的结构,应该是在此处进行连接的,但是前面没有4个call
,因此可能是循环。
(图23)
依然是单步步过
每一个call
,分析、猜测每一个call
可能的含义。如图31所示,第一此到达该je
的时候为跳转状态(没有连接符-
),注意到后面的jnz
前的判断代码:
inc esi
cmp esi,0x4
即:如果esi
不大于4则跳转到上面(循环)。
(图24)
单步步过
下面四个call
以猜测每个call
的含义。
本段详细含义见图25。
(图25)
到此厘清了软件注册码生成结构和流程:
判断是否需要加上"-"
连接字符串
生成四位数(整数)
转换为字符串
如果不满四位,转到1
生成了四段,则退出循环
接下来就是一个找到如图25中004DFEAD
的call
对应的生成算法了。
3、跟进生成四位数的call
如图26所示,单步步入
该函数,依旧是出现编译问题,ctrl+A
分析之!去后效果如图27所示。
(图26)
(图27)
如图28,单步步过
到第一个call
处,寄存器eax
出现请求码,是传入该call
的参数。
(图28)
如图29,再次步过
该call
下一行eax
变为00000047
(H),即71
(D),联系传入的注册码,发现是注册码的位数(注:每台计算机的请求码位数不统一)。
(图29)
继续分析代码。分析的截图如图30、图31所示。点击可查看大图
(图30)
(图31)
七、注册机的实现
易语言实现
咳咳大佬误笑。。
完整代码就不贴了,以防被大佬笑话。。。上图吧。
全工程代码:见图32、图33。
(图32)
(图33)
实验结果:如图34所示,算法无误,成功!
(图34)
C语言实现
咳咳qt,mfc都不懂。。。刚开始学习。。
那就用控制台打印一个界面吧。。
C语言精简版
第一版注册机。。。要手动输入请求码,生成的注册码也不方便取出。
代码的截图及运行截图如图35、图36所示:
(图35)
(图36)
#include <stdio.h>
#include <windows.h>
#include <string.h>
int getSignCode ( long myCode )
{
int mySignedCode[4]= {27,16,47,34},i=0,retSignCode[4];
for ( ; i<4; i++ )
{
long a,b;
a = myCode;
while ( 1 )
{
b = a * 16 / mySignedCode[i];
if ( b <= 9999 )
break;
a = a /2;
}
retSignCode[i]=b;
printf ( "%ld",b);
if(i!=3) printf("-");
}
return *retSignCode;
}
int main()
{
char code[90];
long codeSum=0;
int i;
printf ( "请输入您的请求码!\n" );
scanf ( "%s",code );
//strcpy ( code,"459111219222217181919201718181927282329343637-121525877-7161211-8126676" );//我的注册码
printf ( "\n" );
for ( i=0; i<strlen ( code )+1; i++ )
codeSum+=code[i]* ( i+1 );
printf ( "\n请求码算出的校验值为%ld\n\n",codeSum );
getSignCode ( codeSum );
return 0;
}
c语言 (相对)完整版
在上一段代码的基础上加上了读取剪贴板、写入剪贴板的功能,
添加上了吾爱的免责声明。
源代码附在下面,需要的可以自行修改、编译
代码的截图及运行截图如图37、图38所示:
(图37)
(图38)
#include <stdio.h>
#include <windows.h>
#include <string.h>
#include <stdlib.h>
#include<ctype.h> //需要使用到判断字符的函数
void echo52PJ()
{
printf ( "#########################################################\n" );
printf ( "版权声明:不得用于非法及盈利用途\n" );
printf ( "请支持正版!到官网购买正品以获取最新版和更好地服务\n" );
printf ( "POWER BY 涛之雨\n" );
printf ( "吾爱破解独发!\n" );
printf ( "未经被人允许禁止转载!\n" );
printf ( "#########################################################\n" );
printf ( "\n\n" );
printf ( "免责声明:\n" );
printf ( "吾爱破解所发布的一切破解补丁、注册机和注册信息及软件的解密分析文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。\n\n\n" );
return;
}
int * getSignCode ( long myCode )
{
int mySignedCode[4]= {27,16,47,34},i=0;
static int retSignCode[4];
for ( ; i<4; i++ )
{
long a,b;
a = myCode;
while ( 1 )
{
b = a * 16 / mySignedCode[i];
if ( b <= 9999 )
break;
a = a /2;
}
retSignCode[i]=b;
//printf ( "%ld", b );
//if(i!=3) printf("-");
}
return retSignCode;
}
BOOL setClipCode ( char* setStr )
{
HGLOBAL hclip;//剪切板句柄
if ( OpenClipboard ( NULL ) ==0 )
{
printf ( "打开剪切板失败!\n" );
return FALSE;
}
if ( !EmptyClipboard( ) )
{
printf ( "清空剪切板失败!\n" );
CloseClipboard();
return FALSE;
}
TCHAR *strToSet=setStr;
hclip = GlobalAlloc ( GMEM_MOVEABLE, ( ( strlen ( strToSet )+1 ) *sizeof ( TCHAR ) ) );
if ( !hclip )
{
printf ( "内存分配失败!\n" );
CloseClipboard();
return FALSE;
}
LPSTR lpstr= ( LPSTR ) GlobalLock ( hclip ); //加锁,返回一个VOID类型的指针
memcpy ( lpstr,strToSet, ( ( strlen ( strToSet ) ) *sizeof ( TCHAR ) ) );
//lpstr[strlen ( strToSet )]= ( TCHAR ) 0; //字符串结尾的'\0'
GlobalUnlock ( hclip ); //解锁
SetClipboardData ( CF_TEXT,lpstr );
CloseClipboard();
printf("注册码已成功复制到剪贴板");
return TRUE;
}
char * getClipCode()
{
//局部变量
static char *pbuf=NULL;
HANDLE hclip;//剪切板句柄
//打开剪切板,获取里面的数据
if ( OpenClipboard ( NULL ) ==0 )
{
printf ( "打开剪切板失败!\n" );
return "ERR";
}
//剪切板当中的数据是不是文本类型的
if ( !IsClipboardFormatAvailable ( CF_TEXT ) )
{
printf ( "剪切板当中的数据类型非文本!\n自动跳过。" );
CloseClipboard();//关闭剪切板,不然其他程序无法正常0使用剪切板
return "ERR";
}
//获取剪切板里面的数据
hclip=GetClipboardData ( CF_TEXT );
pbuf= ( char * ) GlobalLock ( hclip ); //加锁,返回一个VOID类型的指针
GlobalUnlock ( hclip ); //解锁
//清除前导的非字母和数字字符
while ( *pbuf&&!isalnum ( *pbuf ) )
++pbuf;
//测试剪切板是否能使用
printf ( " 检测到剪贴板内的文本如下:\n =======================================================================\n %s\n =======================================================================\n 是否使用该数据作为请求码?\n\nY/N\n",pbuf );
CloseClipboard();//关闭剪切板,不然其他程序无法正常0使用剪切板
Sleep(1000);
char Kword=getchar();
if ( Kword!='y'&&Kword !='Y' ) return "ERR";
return pbuf;
}
int main ( void )
{
system ( "color 1f" );
system ( "mode con:cols=80 lines=20" );
system ( "title 请支持正版!到官网购买正品以获取最新版和更好地服务 POWER BY 吾爱破解 涛之雨" );
echo52PJ();
printf ( "按下回车键开始,并且表示接受以上条款!!" );
getchar();
system ( "cls" );
long codeSum=0;
int i;
char code[90];
strcpy ( code,getClipCode() );
if ( !strcmp ( code,"ERR" ) )
{
printf ( " 请手动输入请求码,形如\n =======================================================================\n 459111219222217181919201718181927282329343637-121525877-7161211-8126676\n =======================================================================\n 按回车继续\n" );
scanf ( "%s",code );
}
system ( "cls" );
printf ( " 获取到的请求码如下:\n =======================================================================\n %s\n =======================================================================\n",code );
//strcpy ( code,"459111219222217181919201718181927282329343637-121525877-7161211-8126676" );
printf ( "\n" );
for ( i=0; i<strlen ( code )+1; i++ )
{
codeSum+=code[i] * ( i+1 );
}
printf ( "\n请求码算出的校验值为%ld\n",codeSum );
int *regCode=getSignCode ( codeSum );
printf ( "\n\n计算出的注册码为:\n\n" );
for ( i=0; i<4; i++ )
{
sprintf ( code+i*5,"%d", regCode[i] );
if ( i!=3 ) strcat ( code-1,"-");
}
printf ( "%s", code );
printf ( "是否将该注册码复制到剪贴板?\n\nY/N\n" );
char Kwd;
scanf("%c",&Kwd);
Kwd=getchar();
//scanf("%c",&Kword);
if ( Kwd=='y'||Kwd=='Y' )
{
setClipCode ( code );
}
printf ( "\n\n任意键键退出\n\n POWER By 涛之雨" );
system ( "pause>nul" );
return 0;
}
VC的QT界面版
请移步KaQqi大佬的
【原创破解】music studio算法注册机
https://www.52pojie.cn/thread-953570-1-1.html
(出处:吾爱破解论坛)
bat(cmd|dos)版
bat没有获取ASCII的方法,所以很蛋疼的写了个call,不是很聪明的办法。
使用起来其实比上面两个都简单:
复制该段代码,新建一个文本,粘贴代码,保存,后缀改为.bat|.cmd
双击即可使用。。。
界面就没做,懒得。。。
注:因为论坛的网页编码是UTF-8,因此直接复制到文本也是UTF-8的。请注意转码。。
@echo off
setlocal enableextensions enabledelayedexpansion
title 请支持正版!到官网购买正品以获取最新版和更好地服务 POWER BY 吾爱破解 涛之雨
color 1f
mode con:cols=80 lines=20
cls
set z=0
set /p w=请输入请求码,以回车键结束:
echo 加载中。。。。
set q=1
:nexti
if not "%w%"=="" (
set w_%q%=%w:~0,1%
call :v !w_%q%!
set x=!errorlevel!
set "x=!x!*%q%"
set /a "z=!x!+!z!"
set "w=%w:~1%"
set /a q+=1
goto :nexti)
echo 请稍后。。
set str=-
for /l %%i in (1,1,4) do (
call :s !z! %%i
set x=!errorlevel!
set m=!m!!x!
if %%i neq 4 set m=!m!%str%)
echo 请求码算出的校验值为:!m!
ping 127.0.0.1 > nul
echo 任意键退出
pause>nul
exist
:v
if %1==9 exit /b 57
if %1==8 exit /b 56
if %1==7 exit /b 55
if %1==6 exit /b 54
if %1==5 exit /b 53
if %1==4 exit /b 52
if %1==3 exit /b 51
if %1==2 exit /b 50
if %1==1 exit /b 49
if %1==0 exit /b 48
if %1==- exit /b 45
exit /b 0
:s
if %2==1 set l= 27
if %2==2 set l= 16
if %2==3 set l= 47
if %2==4 set l= 34
set /a tempcode = %1
set b = 0
:whilestart
set /a b = !tempcode! * 16 / l
if !b! leq 9999 exit /b !b!
set /a tempcode = !tempcode! /2
goto whilestart
效果图见图39。
(图39)
结束语
小计:
本文较完整的记录了本人由爆破,到追码,再到编写注册机的全过程
全过程,是因为本文写的十分详细,就是为了想和那些想写注册机,又没有多少基础的小白们一起学习,共同进步,
较完整,是因为其实写出来的是想做为教程,而不是完整的再现我是如何一步步走错而又从头开始分析的,
我需要告诉大家的是正确的(或者是比较正确)过程,而不是和大家分享我是如何走错的,
这个软件我破解的时候大概用了三四种方法找到这个关键的call,
但是其他的或多或少都会有一些繁琐或是错误之处,最后,在写教程的时候,我才发现之前走错的路是多么奇葩,
经过这次教程,我本身也学到很多,为什么前面几大块没有什么内容,我依然要打出来?不是为了字数,而是思路。。。
之前破解的时候,因为搜索了过多的(还是打错了)关键词,没有搜索到关键的字符串,即六
-(一)
-2
的步骤,
所以我是通过了弹窗回溯的方法
、还有按钮事件的方法
注:有兴趣的朋友也可以自己试验一下,就会发现这么走是多么的困难。
另外,本软件是MFC
写的,但是貌似是把MFC
内置了?
万能断点是能用的,不过要在程序领空才能找到,一开始走了很多的弯路,正文没有体现出来,就在最后稍微吐个槽吧23333~
最后,祝大家都能在吾爱破解学有所成,
伸手、模仿的进步是微弱甚至没有的,需要自行钻研,不会就去查资料。
有疑惑就去提问
(最后再次感谢KaQqi 大佬和H大)
全文终
全文终!撒花~~~~