APP下载

一种新的抵抗动态分析软件保护模型设计与实现

2015-05-30余彦万毅

计算机时代 2015年5期
关键词:动态分析序列号

余彦 万毅

摘 要: 作为最常用的软件保护方式之一,序列号保护面临着最多的攻击者的研究。破解者主要的攻击过程分为黑盒阶段,动态分析阶段,静态分析阶段和编辑阶段。动态分析可以理解成一个遵循“定位保护代码-修改二进制代码-测试”的破解循环。从该破解循环入手,提出一种新的程序架构,在校验代码之前加入某种规则决定是否进行校验,并将其嵌入主程序的不同位置,形成的对主程序的校验位置的组合有2N种,这可为软件提供更有效的保护措施。

关键词: 软件保护; 序列号; 动态分析; 软件破解

中图分类号:TP311.1 文献标志码:A 文章编号:1006-8228(2015)05-22-04

Abstract: As one of the most commonly used method of software protection, serial number protection is facing up to the crackers' research. The main process of software attacking is divided into black box stage, dynamic analysis stage, static analysis stage and editing stage. Dynamic analysis stage can be understood as a follow "positioning the protection code-modify the binary code-test" of the work cycle. From the work cycle of dynamic analysis stage, we put forward a new program architecture, by adding certain rules before deciding whether to execute the code for checking serial number, and to embed them into the main program for n times, so there are 2n different kinds of combinations of the code for checking serial number to form. Thus the software can be protected more effectively.

Key words: software protection; serial number; dynamic analysis; software cracking

0 引言

在计算机软件技术高速发展的今天,软件产品早已作为知识产权受到法律保护。可是在我国,即使有各种各样的法律,软件被盗版问题依然很严重。根据商业软件联盟(Business Software Alliance)公布的调查报告[1]显示,2013年的盗版软件安装率为74%,虽然较前几年(2011:77%,2009:79%,2007:84%)有所下降,但依然处于非常高的比例,据该调查报告显示,盗版软件的商业价值达到87亿美元。因此,软件保护技术的研究依然是热点课题。

软件保护技术中最常见的是序列号保护技术。针对序列号保护,本文提出了一种新的程序架构,其关键是将校验的代码随机多次嵌入主程序的不同位置,而校验代码之前加入某种规则决定是否进行授权校验,使得程序可以根据不同运行状态而进入不同位置的校验代码段,从而增加盗版者的破解难度。

1 序列号保护机制原理

作为最常见的软件保护模型,序列号保护[2]的结构如图1所示。每次程序开始运行时,需要先校验保存在本地的序列号。如果校验未通过,如序列号不正确或序列号有效期已过,则要求用户输入合法的序列号,否则不允许进入受保护的主程序。当校验通过,程序便处于合法运行状态,可以使用受保护的功能或算法等。

[启动程序][用户程序][校验序列号] [进入主程序][程序结束][输入序列号] [T][F]

图1 序列号校验流程

对于获得了序列号的用户来说,校验过程是透明的,用户只需要输入从软件厂商购买的序列号,校验过程由本地程序自动完成[3]。校验过程可用如下公式表示。

⑴ 软件厂商获得用户信息后计算序列号:

序列号=F(用户信息)

⑵ 用户获得序列号后在本地进行校验:

用户信息=G(序列号)

购买者如果随意将用户信息和对应的序列号非法分发给其他未授权使用者,软件厂商无法禁止其使用。因此本文采取硬件信息作为用户信息,如此,即使序列号被非法分发,也因为硬件不同而无法在不同的机器上使用,从而可以更好的保护软件。

2 破解者的主要攻击方法

整个破解的过程可以分为若干个阶段,在最初的几个阶段中,破解者的任务主要是分析程序,试图弄明白程序的内部结构及其行为模式。而在后面几个阶段,破解者则会使用前几个阶段中获得的信息,按具体需要对程序进行修改。我们把破解过程大致分为四个阶段[4]。

⑴ 黑盒阶段

在黑盒分析阶段,破解者并不了解程序的内部构造,对其而言,程序就是一个“黑盒”。破解者会试图给程序输入一些数据,并观察程序的输出,然后根据程序的行为做出某些推断。

⑵ 动态分析阶段

在动态分析阶段,破解者开始分析程序的内部行为,虽然这时他仍然会执行程序,但是他这时会记录在输入不同的数据后,程序会执行哪些不同的部分。

⑶ 静态分析阶段

为了更好的理解程序的作用,破解者在动态分析过后会直接分析代码本身,这就是静态分析。

⑷ 编辑阶段

前三个阶段的工作使得破解者可以弄清楚他所关心的算法,找到了秘钥所在。但如果破解者还需要对程序进行修改,例如删除检查软件序列号部分的代码,或者是抹除程序中用来标识用户信息的指纹水印等,则需要惊醒这个步骤对原程序进行编辑。

动态分析中的破解循环,对于破解者来说,对一个程序进行动态分析是需要遵循“定位保护代码-修改二进制代码-测试”的破解循环来工作。如图2所示,在定位保护代码的阶段,破解者需要找到程序的保护代码(比如校验序列号的代码段)在程序中的位置,并且在接下来的修改阶段对其进行一系列的修改使程序能按其方式来运行。对二进制代码进行的修改包括去除旧的指令,增加新的指令以及对原有指令进行修改。最后,破解者还要测试经过修改后的程序是否能按照其意愿进行工作,否则将进行下一次破解循环。本文提出的程序结构就是从破解循环入手,增加其动态分析程序的阻力,通过增加程序运行时的不确定性让程序在每次独立运行时都会动态的选择不同的执行路径,让破解者无法轻易找到序列号的校验代码所在。

图3是采用objdump工具对作者的程序进行反汇编得到的结果。图3左侧是未经过修改的程序,MainWindow::core()是一个函数,用于代表程序的主体部分,其地址为0x00405040。图片左侧下方的内容是软件的序列号校验模块其中的一段。进入程序主体部分之前,需要经过序列号的校验。这段汇编代码中有一条判断语句:test %al,%al,其功能是如果用户输入的序列号通过了校验,那么就进入主程序部分(地址0x00405040)继续执行,否则就跳转至程序的结束部分的地址(0x004059b0)。可以看出,对软件的保护依赖于序列号的校验是否成功。如果攻击者对程序先进行反汇编,然后找到这段控制序列号校验逻辑的代码,将其的跳转逻辑修改成无论序列号校验是否成功都跳转至程序的主体部分继续执行,那么序列号的校验模块也就无法对软件提供保护了。如图3右下方代码段所示,将汇编程序跳转逻辑修改后,无论序列号校验的结果如何,程序始终都会执行MainWindow::core()(在修改过的程序中该函数的地址为0x00404fd0)。也就是说,如果通过动态分析的手段找出了软件的序列号校验的代码并对其功能进行修改,那么即使不知道序列号校验的算法,也可以直接绕过序列号校验的部分直接非法的使用该软件。

3 一种新的抵抗动态分析的软件模式

如前文所述,破解者在动态分析阶段会试图找出程序的序列号校验模块,并修改其逻辑已获得非法使用程序的目的。动态分析主要是遵循“定位保护代码-修改二进制代码-测试”的破解循环来工作的,其中最重要的环节就是定位二进制代码,如果破解者无法顺利定位序列号校验部分的代码,也就无法针对其进行攻击。传统的商业软件对于程序的保护一般是将程序的序列号校验部分放在程序的最开始,这样,攻击者跟踪程序的运行步骤不久后比较容易找出程序的校验模块。本系统的设计主要目的是提高破解者对代码动态分析的难度,并且辅助以注册码的安全生成机制而提高软件的安全性。

防止动态分析的手段,从动态分析阶段入手,我们提出了以下更具复杂性和随机性的机制来保护软件。

⑴ 增加程序中校验序列号的次数,也就是说,不仅仅在软件安装时校验序列号,而在软件的使用过程中可以嵌入多段校验序列号的代码。

⑵ 校验序列号时不采用函数调用的方式,而是直接将代码嵌入到需要校验序列号的位置,这样一来,攻击者无法通过函数的调用频率来分析该函数是否是校验序列号的函数。

⑶ 在校验的代码段前增加一个开关,这个开关的状态决定了是否进入校验代码段。如果开关的状态可以随机化,那么对于整个程序来说,不同位置的校验状态组合结果也就是随机的。开关的状态可以由开发人员自己决定,例如使用主程序的某个变量来决定,或者使用当前的时间,还可以将二者结合某个随机值运算而成。加入这种机制后,如果在主程序代码段内嵌入了N段校验代码,对于整个程序的校验位置的组合来说理论上有2N种状态。这种随机性的加入使得代码的破解难度呈指数级增加。

在设计开关时,我们提出三种方法。第一种是取系统的时间,根据其奇偶性作为开关的值;第二种是取系统中一个叫做State_Output_Counts的全局变量的值,State_Output_Counts是软件中用于记录程序运行状态语句输出次数的变量,根据其奇偶性作为开关的值;第三种是将系统当前时间和上述State_Output_Counts变量结合起来进行异或计算,根据得到的结果的奇偶性作为开关变量的值。每次决定具体使用哪一种方法之前取随机数,根据随机数的值对3求模,根据其结果决定使用哪一种开关。具体代码如下:

r=rand();

seconds=time(NULL);

r=r%3;

switch (r)

{ case 0:Check_Switch=seconds;break;

case 1: Check_Switch=State_Output_counts; break;

case 2: Check_Switch=seconds^State_Output_Counts; bresk;

}

⑷ 将校验序列号的代码和程序的运算模块结合起来,将校验序列号的代码段嵌入程序的运算模块内,并且根据序列号校验的结果决定运算模块的结果是否正确,如果通过校验代码的验证后,运算模块可以正常使用。如果序列号校验不通过,则可以通过校验模块传递给运算模块一个错误的变量值使运算模块失效或者输出错误的结果。攻击者很难发现运算模块发生错误,而攻击者如果采用修改二进制代码的方式绕过校验代码部分,运算模块也无法使用,也就起到了保护程序的作用。如果再结合第⑶步所描述的方法,运算模块中的序列号校验代码不一定每次都会执行,因此在序列号不合法时运算模块的功能有时会产生正确的结果而有时又会产生错误的结果,更加迷惑攻击者。当序列号不正确时,程序并不会提示用户序列号错误,而是直接给出错误的运算结果,因此攻击者很难分析出序列号校验代码段的位置。

例如,原始代码在主程序中完成一个加法功能的语句a+b,我们将其更改成为一个函数int Add(int a,int b),并且将序列号校验的代码嵌入其中,如果序列号校验通过就正常的返回两个参数的和,如果序列号校验不通过,并不会有错误提示,但是返回值会是两个参数的乘积,如此一来,攻击者无法找到校验的位置,也无法发现最终的运算结果是一个错误的答案。具体代码如下:

int Add(int a,int b)

{ switch (Prog_State)

{ case true: return a+b;break;

case false: return a*b;break;

}

}

具体实现中,本文在主程序代码中嵌入了5次校验序列号的代码,理论上应该有25种校验状态的组合。当校验不通过时,计算结果产生了错误,也从另一个方面阻止了软件的非法使用。

4 系统设计和实现

如图4所示,该架构中客户在程序开始时先获得用户ID,本系统中的用户ID采用CPUID与MAC地址组合的方式生成。得到用户ID后进入客户端的序列号校验模块。校验通过以后,可以进入主程序,序列号的校验部分是由开发人员无规律随机的分散在主程序代码中的,校验代码段之前会有一个开关决定进入或是跳过校验代码,开关的状态可以由多种变量的状态决定。

对于服务器端,在用户需要注册时可以通过通信模块接收用户ID并通过序列号生成模块计算出序列号并返回给用户,并将用户ID和生成的序列号保存在服务器本身的数据库中。

4.1 序列号申请模块

服务器计算出序列号的过程可用公式:序列号=F(用户ID)来表示。其中用户ID代表了用户的个人信息,可以是电话号码或者是银行卡号等信息。但这些信息很容易被重复使用并且无法保证是否是用户本人,本文采取提取用户机器的硬件序列号(CPU ID和MAC地址)作为用户ID来保证其惟一性和不可传播性。由于用户的硬件基本上不会随便更换,因此可以保证用户在使用软件的过程中不会因此产生麻烦。公式中F代表的是根据用户ID生成序列号所使用的算法,本文中使用的是MD5消息摘要算法。

序列号申请模块主要分为生成用户ID和序列号的生成与验证两个部分。

4.1.1 生成用户ID的方式

本文采用了CPU ID和MAC地址共同作为用户ID,但是在获得了CPU ID和网卡MAC地址后需要构造一个可靠的用户ID,若是简单的将其连接必然会造成安全性上的欠缺,又因为通用的MD5算法是公开的,因此如果对用户ID 的构成方式进行复杂化则可以迷惑攻击者无法轻易的推测出用户ID 的构造方式。本文通过采取将CPU ID和MAC地址交叉组合的方式,并在其后添加一个附加的自定义字串。例如CPU ID为abcdefgh而MAC地址为12345678则构成的用户ID为a1b2c3d4e5f6g7h803914256。

4.1.2 序列号的生成与验证

本文采用MD5消息摘要算法来生成序列号。MD5算法的特点[5]包括:易于从原始信息计算出MD5值,而从MD5值无法逆推算出原始数据,任意长的数据计算后得出的MD5值都是固定长度的。对于序列号的生成过程和校验过程在计算上是同一个过程。客户端机器先在机器内计算出自己的用户ID并将其发送给服务器端,当服务器端收到了用户ID后根据收到的用户ID计算其MD5值,并以此作为合法的序列号返回给用户。如果用户收到了序列号后,再在本地重复这一过程,根据同一个公式去计算本地的用户ID是否与所得到的序列号相同。

4.2 程序运行结果

程序运行结果如图5所示。程序左侧的文本框采用独立线程每隔三秒会显示程序是否运行在合法状态,即使破解者找到了注册序列号的位置绕过了最初注册时的验证,但是每次运行程序时,随机出现的校验位置的状态组合都不一样,如果攻击者并不知晓序列号而只是绕过了验证部分,则在此处无法再次通过验证因此程序提示用户使用的是未注册版本,进而可以保护主程序无法轻易的被破解和非法使用。程序下方还显示了当前五个开关的状态,可以看出,当前的开关状态为“10110”,也就是说,主程序中的有五个位置需要进行序列号校验,而在程序运行完一次后只有第一个、第三个和第四个位置发生了校验,而第二个和第五个位置的校验代码并没有运行。多次运行得到的开关状态并不相同,具有随机性。

5 结束语

本文提出了一种新的抵抗动态分析的软件保护模型,并在LINXU平台下采用QT和C++编程实现了该系统,经过实验验证能完整地提供序列号保护所需的功能,并较传统序列号保护方式更具有复杂性和随机性。该系统可以较好地抵御攻击者对程序的动态分析过程。该程序结构简单,却能大大增加攻击者的破解难度和破解代价,并且其结构的复杂度可以自己控制。因此,该系统具有较好的实用性和应用前景。本系统还有需要改进的地方,如太过于频繁的验证可能影响计算的性能,用户如果更换硬件则需要更换序列号等问题,这些将是下一步需要研究的问题。

参考文献:

[1] Business Software Alliance. The Compliance Gap BSA GLOBAL SOFTWARE SURVEY[R/OL].Washington, DC: Business Software Alliance, 2014. [2014-06].http://globalstudy.bsa.org/2013/downloads/studies/2013GlobalSurvey_Study_en.pdf

[2] 许旭,潘志刚.一种基于一机一码的软件激活序列号生成方案[J].浙江科技学院学报,2010.4.

[3] 庞启宁.一种基于注册码的软件加密算法[J].通信与广播电视,2008.2.

[4] Christian Collberg,Jasvir Nagra,Surreption Software[M].人民邮电出版社,2012.

[5] 许琪.MD5加密算法的研究[J].福建电脑,2014.3.

猜你喜欢

动态分析序列号
宫腔镜唯一性标识设计在消毒供应质量追溯中的应用
一种离线电子钱包交易的双向容错控制方法
关于《国家税务总局 工业和信息化部关于加强车辆配置序列号管理有关事项的公告》的解读
recALL
基于污点传播动态分析的Android安全系统研究
基于组合评价法的企业融资效率动态综合评价
中国服装业上市公司财务状况动态分析
会计准则改革动态及相关研究
基于因子分析对我国30个地区的房地产发展水平的研究于丛
据题类析高中物理动态问题的部分解题技巧