本篇侧重于程序编写,不知道合不合版规,反正至少是游戏相关了:)
哪里写的不清楚的请大家提意见~
上次,我们找到了双星物语跳光盘验证的地址,这次写个简单的程序来做免CD补丁。
我现在用VC7的,大家凑合着看吧。
先建立工程:MFC程序
[attachment=329807]
选择应用程序类型为基于对话框,“MFC的使用”如果选择共享DLL的话程序较小,但是必须在装有VC7的机器上才能执行,或者要从自己的机器中找到一个什么dll一起传给别人才能用。
[attachment=329808]
自带的控件都删掉,放上两个按钮一个编辑框:
[attachment=329809]
“打开文件”按钮ID设为IDC_BROWSE,免CD按钮ID设为IDC_CRACK,编辑框ID设为IDC_EDIT_PROMPT,并把Read Only属性设置为True。
给编辑框建立变量m_strPrompt,用于提示各种信息和保存文件路径。
[attachment=329810]
[attachment=329811]
双击“打开文件”按钮,准备开始写代码了
void CZWEI_NoCDDlg::OnBnClickedBrowse()
{
// TODO: 在此添加控件通知处理程序代码
}
在大括号里面写代码:
void CZWEI_NoCDDlg::OnBnClickedBrowse()
{
// TODO: 在此添加控件通知处理程序代码
CFileDialog dlg(TRUE , NULL , _T("zweipet.exe") , OFN_HIDEREADONLY | OFN_FILEMUSTEXIST ,
_T("zweipet.exe | zweipet.exe||"));
if (dlg.DoModal() == IDOK)
{
m_strPrompt = dlg.GetPathName();
}
UpdateData(FALSE);
}
CFileDialog 是MFC提供的类,可以直接用,用法详见MSDN -_-~~~。是个文件打开对话框类,有个成员函数DoModal()就是弹出文件打开对话
框,返回IDOK就是用户按下了确定按钮,取消的话会返回IDCANCEL。GetPathName()返回文件全路径,带路径和文件名。UpdateData(FALSE);
则是刷新主对话框数据,把m_strPrompt 的值显示出来,如果是UpdateData(TRUE)的话则相反,是把对话框数据保存到成员变量中。
现在得到了文件路径了,下面写“免CD”按钮的代码。双击“免CD”按钮:
void CZWEI_NoCDDlg::OnBnClickedCrack()
{
// TODO: 在此添加控件通知处理程序代码
}
写完代码之后如下:
void CZWEI_NoCDDlg::OnBnClickedCrack()
{
// TODO: 在此添加控件通知处理程序代码
CFile file(m_strPrompt , CFile::modeReadWrite | CFile::typeBinary);
if (file.GetLength() == 225280)
{
WORD wRead = 0;
WORD wWrite = 0;
file.Seek(0x8884 , CFile::begin);
file.Read(&wRead , sizeof(WORD));
if (wRead == 0x1C75)
{
file.Seek(0x8884 , CFile::begin);
wWrite = 0x9090;
file.Write(&wWrite , sizeof(WORD));
}
file.Seek(0x8892 , CFile::begin);
file.Read(&wRead , sizeof(WORD));
if (wRead == 0x0E75)
{
file.Seek(0x8892 , CFile::begin);
wWrite = 0x9090;
file.Write(&wWrite , sizeof(WORD));
}
}
file.Close();
m_strPrompt = _T("操作完成");
UpdateData(FALSE);
}
CFile是MFC提供的文件操作类,第一个参数m_strPrompt是文件路径,第二个参数是打开方式,我们要读还要写,所以需要CFile::modeReadWrite,又因为是二进制数据操作,所以要CFile::typeBinary);
打开之后,判断文件长度是否正确,zweipet.exe文件长度是225280字节,用右键属性可以看到。用这个可以稍微防止出错,比如用户随便找个东西改名叫zweipet.exe拿来耍咱们玩。。。然后用Seek(0x8884 , CFile::begin)把文件指针移动到地址0x8884,这是昨天找到的要跳的地方,原来放的是75 1C,所以用Read(&wRead , sizeof(WORD))读取出来,判断是不是。这里wRead是用来存放读取出来的数据的,sizeof(WORD)是告诉他要读取几个字节,这里得到的是2个字节。0x1C75放到内存中就是75 1C,数据在内存中是反着放的。判断成功的话,再执行一次Seek(0x8884 , CFile::begin)因为刚才调用Read(&wRead , sizeof(WORD))的时候指针向后移动了2字节,所以要再定位一次。然后用Write(&wWrite , sizeof(WORD))把9090写进去,90就是nop,两个字节要跳走就是两个nop,所以是0x9090。下面的是第二个要跳的地方,同上。操作完毕之后,记得要file.Close(),避免潜在的错误。然后m_strPrompt = _T("操作完成")加上UpdateData(FALSE)则是告诉用户,操作完成。
基本上,这就是个不错的免CD补丁了,虽然简单了点:)
如果有时间的话,还可以加上更多的判断,比如文件是否已经打过补丁之类的,那就完美了。
代码修改了一下,按钮改成自己的,看着习惯些:)
[ 此贴被yes2在2006-06-20 01:32重新编辑 ]