| yes2 |
2006-06-20 00:33 |
本篇侧重于程序编写,不知道合不合版规,反正至少是游戏相关了:) 哪里写的不清楚的请大家提意见~
上次,我们找到了双星物语跳光盘验证的地址,这次写个简单的程序来做免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补丁了,虽然简单了点:) 如果有时间的话,还可以加上更多的判断,比如文件是否已经打过补丁之类的,那就完美了。
代码修改了一下,按钮改成自己的,看着习惯些:) |
|