用C++Builder的MD5控件实现软件防护[1]
来源:学生作业帮助网 编辑:作业帮 时间:2024/05/11 17:45:05 计算机应用能力考试
用C++Builder的MD5控件实现软件防护[1]计算机应用能力考试
【网络综合 - 计算机应用能力考试】
一、共享==免费?
随着Internet大行其道,“共享+注册”模式日渐成为程序员发布自己软件的主要手段,但是随之而来的破解手段也越来越高明。如何保护自己的劳动成果不被暴力破解或修改?用MD5摘要值验证是一个很常用的方法。
MD5作为一个公开算法,实现的方法很多,比如开源软件、Windows自带的API等,C++ Builder和Delphi中集成的Indy里面也有现成的MD5控件。
用API实现MD5虽然效率高,但是毕竟太繁琐,具体方法可以参阅MSDN上crypt开头的那几个函数说明。用C++ Builder的MD5控件虽然方便,但是速度较慢,而且只能处理以‘’结尾的字符串,所以要用这个控件还需要我们对待验证数据做一些预处理。预处理的关键在于把较重要的内容挑出来计算,这样一方面可以去除‘’,另一方面可以极大减少待验证内容的长度,只计算关键代码的摘要值。
二、源程序祥解
先要说明的是网上和Borland Help里面对Indy MD5控件介绍很少,这段程序基本上是我自己摸索的结果,在C++ Biulder 6.0和Indy 6.0下运行正常。
先在Indy misc中拖一个MD5控件,假设其name为cipher,程序如下:
/*
MD5计算函数 by DayDreamer 2004-04
功能:对文件名为fname的文件计算16个字节长的MD5值,放在result里面
输入:指向文件名的指针char *fname
输出:MD5值放在result指向的缓冲区里面
返回值:如果正确计算出MD5值则返回true,否则返回false
*/
bool MD5( char* fname, char *result)
{
unsigned int i=0; //用于记录读出文件的大小
bool flag=false; //正确计算md的话则置标记
static AnsiString ss; //用于临时存放得到的MD5值
char *buffer=new char[myFILE_SIZE]; //用于读取目标文件,文件大小不能超过myFILE_SIZE
TFileStream *tt=new TFileStream(fname,fmOpenRead); //用于读取目标文件的全部内容,使用此方法简单一点,也可以用标准的
CreateFile()读取
i=tt->Read(buffer,myFILE_SIZE); //i中保存实际读取的字节数
if ((i)&&(i!=1)) //如果读出字节数不为0或1,则进行处理
{ i=i-1; //最后一个字节必须留出,供结束符使用
_asm{ //这一段汇编主要是用来对文件预处理
mov ecx,i; //置计数器
mov ebx,buffer; //源地址指针
mov edx,buffer; //目的地址指针
l1: mov al, [ebx]; //取一个字节,因为如果文件过大会极大降低速龋员匦胍越舷噶6裙嗽创?/p>
cmp al,0x70; //只对大于0x70和小于0x91的字节进行摘要
jb l2 ; //因为主要的转移指令(jz,jnz)、空操作指令(nop)等都大于0x70小于0x91
cmp al,0x91; //也可以换成更宽松的条件,但至少应该把0x00滤掉,因为它被视为结束符
jnb l2 ;
mov [edx],al ; //符合条件的字节保存起来等待验证
inc edx;
l2: inc ebx;
dec ecx;
jnz l1;
mov byte ptr [edx+1],0; //在最后置结束符‘’
}
cipher->Reset(); //每次使用该控件之前应该重置其内部的一些参数
cipher->AutoCompleteInput=false; // 只有调用CompletedInput() 时才得到结果
cipher->CodeString(buffer); //输入预处理过的数据
ss=cipher->CompletedInput(); //输入完毕,得到摘要码
if(ss.Length()=MD5_LENGHTH) //如果摘要码正常(即为16位),则保存之
{ flag=true; //置正确标志<计算机应用能力考试
一、共享==免费?
随着Internet大行其道,“共享+注册”模式日渐成为程序员发布自己软件的主要手段,但是随之而来的破解手段也越来越高明。如何保护自己的劳动成果不被暴力破解或修改?用MD5摘要值验证是一个很常用的方法。
MD5作为一个公开算法,实现的方法很多,比如开源软件、Windows自带的API等,C++ Builder和Delphi中集成的Indy里面也有现成的MD5控件。
用API实现MD5虽然效率高,但是毕竟太繁琐,具体方法可以参阅MSDN上crypt开头的那几个函数说明。用C++ Builder的MD5控件虽然方便,但是速度较慢,而且只能处理以‘’结尾的字符串,所以要用这个控件还需要我们对待验证数据做一些预处理。预处理的关键在于把较重要的内容挑出来计算,这样一方面可以去除‘’,另一方面可以极大减少待验证内容的长度,只计算关键代码的摘要值。
二、源程序祥解
先要说明的是网上和Borland Help里面对Indy MD5控件介绍很少,这段程序基本上是我自己摸索的结果,在C++ Biulder 6.0和Indy 6.0下运行正常。
先在Indy misc中拖一个MD5控件,假设其name为cipher,程序如下:
/*
MD5计算函数 by DayDreamer 2004-04
功能:对文件名为fname的文件计算16个字节长的MD5值,放在result里面
输入:指向文件名的指针char *fname
输出:MD5值放在result指向的缓冲区里面
返回值:如果正确计算出MD5值则返回true,否则返回false
*/
bool MD5( char* fname, char *result)
{
unsigned int i=0; //用于记录读出文件的大小
bool flag=false; //正确计算md的话则置标记
static AnsiString ss; //用于临时存放得到的MD5值
char *buffer=new char[myFILE_SIZE]; //用于读取目标文件,文件大小不能超过myFILE_SIZE
TFileStream *tt=new TFileStream(fname,fmOpenRead); //用于读取目标文件的全部内容,使用此方法简单一点,也可以用标准的
CreateFile()读取
i=tt->Read(buffer,myFILE_SIZE); //i中保存实际读取的字节数
if ((i)&&(i!=1)) //如果读出字节数不为0或1,则进行处理
{ i=i-1; //最后一个字节必须留出,供结束符使用
_asm{ //这一段汇编主要是用来对文件预处理
mov ecx,i; //置计数器
mov ebx,buffer; //源地址指针
mov edx,buffer; //目的地址指针
l1: mov al, [ebx]; //取一个字节,因为如果文件过大会极大降低速龋员匦胍越舷噶6裙嗽创?/p>
cmp al,0x70; //只对大于0x70和小于0x91的字节进行摘要
jb l2 ; //因为主要的转移指令(jz,jnz)、空操作指令(nop)等都大于0x70小于0x91
cmp al,0x91; //也可以换成更宽松的条件,但至少应该把0x00滤掉,因为它被视为结束符
jnb l2 ;
mov [edx],al ; //符合条件的字节保存起来等待验证
inc edx;
l2: inc ebx;
dec ecx;
jnz l1;
mov byte ptr [edx+1],0; //在最后置结束符‘’
}
cipher->Reset(); //每次使用该控件之前应该重置其内部的一些参数
cipher->AutoCompleteInput=false; // 只有调用CompletedInput() 时才得到结果
cipher->CodeString(buffer); //输入预处理过的数据
ss=cipher->CompletedInput(); //输入完毕,得到摘要码
if(ss.Length()=MD5_LENGHTH) //如果摘要码正常(即为16位),则保存之
{ flag=true; //置正确标志<计算机应用能力考试