控制游戏的速度

I

import

Unregistered / Unconfirmed
GUEST, unregistred user!
:sahee, 时间:2001-6-15 16:53:43, ID:568284 注:为节省篇幅,本文对一些计算机术语直接使用而没有作详细的解释,读者若有不熟悉之处,建议参考清华大学出版社出版,周明德编著的《微型计算机系统原理及应用》一书中关于8253/8254定时器和x86保护模式的相应章节。
“变速齿轮”研究手记
 
也许是我孤陋寡闻吧,说出来不怕您笑话,对于“变速齿轮”这样著名的软件,我一直到五天前,也就是2001年2月28号才第一次听说。我有几个同学很喜欢玩图形MUD,整天见了面就在一起切磋“泥”技。我对MUD本身并没有多大兴趣,但是那天早上偶尔听他们说某个MUD站点明文规定严禁使用“齿轮”,这才好奇地问他们什么是“齿轮”。别人告诉我,“齿轮”是一个软件,能对Windows下的游戏加速,他们在玩MUD时就依靠这个软件作弊。这不禁令我一头雾水,能让Windows游戏改变速度,太神奇了!
我一贯对技术很有兴趣,听说有这么一个神奇的软件,当然要想想它是怎么实现的。这个软件看起来并不复杂,我原以为一个早自习好好琢磨琢磨就行,可是我想了好几节课,始终不得其要领。说来也巧,我们这学期有一面必修课是Linux内核原理分析,这几天正好学到了进程调度,老师说,当一个时钟中断发生的时候,操作系统要做很多事情,比如必要时要重新调度进程从而实现抢先式多任务,还要更新系统时钟......慢着,我突发奇想,如果让时钟中断产生的更快,会发生什么事情呢?
我们已经学过“微机原理”这门课程,我知道让时钟中断产生的更快不是难事,以前我就用DOS下的汇编语言写过这样的程序,这是我们当时的作业。可是我以前的程序在Windows下虽然可以运行,但并不能对Windows系统加速,道理很显然:Windows9x是使用x86虚拟机的机制来兼容DOS程序的,我的程序只能改变虚拟机,就是那个黑窗口的时钟中断。
于是我试图把以前的DOS程序搬到32位环境中。用VC内嵌汇编做这件事再合适不过了,在一个VC程序框架中加上一个__asm,然后只管把以前的汇编程序往里贴就行。我满怀希望地运行这样一个拼凑出来的怪物,结果,出现了一个大家都很熟悉的“该程序执行了非法操作”,我的试验以失败告终。
后来冷静下来仔细想想,这次失败的原因是显然的。Windows作为一个复杂的32位操作系统,如果能让你随便对硬件进行操作,那也许运行不了几个程序就崩溃了。但是如何绕过操作系统去操作硬件呢?我首先想到了vxd,编写一个驱动程序肯定可以操作硬件,但是,很可惜,我不会设计驱动程序。于是我想到了以前看到的CIH的源码,CIH没有写vxd,却能操作硬件去烧毁BIOS,陈盈豪真是太伟大了,他的程序精巧之处我至今记忆犹新。于是我模仿他的技术,修改IDT表,创建一个中断门,然后发生中断,进入ring0,现在我可以做任何事情了,按照以前的DOS程序那样,往8253定时器里写一个控制字,再分两次写入新的时钟中断发生频率,一切顺利!(详细技术请您参考我的“兄弟变速器”源码)我看到VC编辑区的光标疯狂的闪烁;双击已经失效了,因为Windows认为我双击的时间间隔太长;Windows任务栏右方的时间飞快跳动,应该说,我已经成功了。
当时我想当然的以为“变速齿轮”的原理也是如此,可是当我从同学那里把“齿轮”拷来并研究时,发现Windows的时钟并不变快,而游戏速度照样可以加上去,也就是说,“齿轮”采用了与我的程序不同的技术,是什么技术呢?我决定继续研究。
我访问了“变速齿轮”的主页,这个主页上有一个“你问我答”的栏目,由“齿轮”的作者王荣先生进行技术支持。我试图在这里找到一些关于“齿轮”的技术细节,但是很可惜,没有找到,王荣先生只是告诉大家这个程序不能用VB编写等等根本连皮毛也不涉及的问题,好不容易见到一个外国人问能不能公布源代码,其实这也是我想问的,但是王荣先生明确表示不行,这不禁令我感到非常失望。
我也想过写信去索取原码,也许他不向外国人公布,中国人可不一定。但是咱们“臭老九”最爱一个面子,我实在拉不下脸去问。这时已经是晚上10点了,我决定祭出SoftIce,用一夜时间去研究他的程序。
当时使用的工具是SoftIce,WD32ASM和VC,手边两本参考书是《微型计算机系统原理及应用》和《Linux操作系统内核分析》(都是我们的课本,呵呵)。
起初,“变速齿轮”0.2版的一个叫hook.dll的文件很大程度上吸引了我的注意力,我怀疑他使用Windows消息钩子实现变速,消息钩子我很熟悉,但我把MSDN上面关于钩子的介绍看了好久,也没有想出它和变速有什么联系,这时偶然看了一下在王荣先生的主页上得到的“变速齿轮”0.1版,才发现老版本中并没有这个文件,也就是说,我只需要反汇编他的主程序就够了,于是,二话不说,用WD32ASM先把0.1版的“齿轮”给拆了,汇编代码5000多行,并不算多。
我是从这个程序的导入函数着手的,以前编程时用于定时的SetTimer,timeGetTime,timeSetEvent等等这里都导入了,看看它们被引用的地方,我发现这些函数都是集中出现的,而且大都以这样的形式出现:
* Reference To: WINMM.timeGetTime, Ord:0098h
:00401F3E 8B0D64424000 mov ecx, dword ptr [00404264]
:00401F44 8B11 mov edx, dword ptr [ecx]
也就是说,他并没有调用这些函数,只是取得了函数的入口地址,保存在ecx中,然后又根据这个入口地址得到了函数的前面几个字节,保存在edx中。
这让我想到了前些日子在CSDN上面和别人讨论的Hook API的原理,当时我还索取了一份Hook API的例程,如果我要Hook这里的函数timeGetTime,修改ecx中的地址或者修改edx处的头几条指令就行,用汇编语言写,与上面看到的这段代码类似。
为了测试“齿轮”是不是要Hook这里的timeGetTime,我自己编写了一个很简单的小程序,调用timeGetTime,每秒钟显示一个数字。用“齿轮”进行加速后,果然显示的速度快多了。再用SoftIce跟进这个timeGetTime函数,第一条指令变成一个跳转,这充分说明“齿轮”确实Hook了这几个API,不难猜测,他要改变函数的返回值,也就是说在timeGetTime结束时还要再跳入“齿轮”自身的代码,耐心跟下去,我发现回到timeGetTime时栈里多压了一个地址,这样,当timeGetTime用ret指令返回时,先返回“齿轮”的代码(这个思想确实很巧),返回值经过处理后,才跳回我的应用程序。至于怎么处理这个返回值就简单了,改到原先的2倍,应用程序速度也就提高了2倍。
回头再看WD32ASM反汇编的代码,我又发现在Hook API前面的不远处使用了一次SGDT指令和两次SLDT指令,这是x86保护方式的特有指令,用于获得全局描述符表,进一步得到局部描述符表,这段代码引起了我的兴趣,用SoftIce跟进去,往下走几步,一边跟一边猜,大致整理出了这样的思路:
1.创建一个内存映射,把自己的代码映射到0x80000000以上的地方,在Win9x下,这块虚存是所有进程共享的。
2.先得到局部描述符表的地址,然后利用这张表修改代码段的特权级。
3.用局部描述符表创建一个调用门,在x86的保护模式下要进入ring0必须通过门来进行,CIH是用中断门完成的,这里用调用门完成,异曲同工。
4.保存几个关键函数前六个字节,改为一条跳转指令,跳到自己已经映射到高端的代码。
5.发生函数调用时进入自己的代码,通过调用门进入ring0,恢复函数开头的几个字节,修改返回值。
这时已经是凌晨5点了,既然主要思想已经掌握,我也就没有细看这段代码,8点钟还要上课,睡觉去也。
回头想想,我认为王荣先生的代码还有几点值得推敲之处:
1.如果要Hook API,一定要改变函数的第一条指令吗?如果仅仅改变函数的入口地址,不是既容易编也容易调试吗?
2.即使要改变函数第一条指令,一定要进入ring0吗?
3.即使要进入ring0,使用中断门不是比用调用门更方便吗?
当然,按照王荣先生在他的主页上的说法,“变速齿轮”0.1版是他在三年前即1997年写的,那时Windows95刚刚出来两年,能有这样的技术已经难能可贵了,这里对王荣先生的钻研精神表示由衷的敬佩。
在我研究出“变速齿轮”的原理后三天,我以自己原先的研究结果为核心,编写出了“兄弟变速器”的最初版本,不用“变速齿轮”的技术是因为我认为我的技术更优越,何况也没有拾人牙慧之嫌了 ^_^
最后再次对王荣先生表示感谢,这样精彩的创意值得我们敬佩。
摘录自http://www.vrbrothers.com(感谢作者还提供源吗,我本人非常敬仰这种精神)
 
兄弟变速器 1.0 中文版自 述 文 件
--------------------------------------------------------------------------------
 
 
兄弟制作组 2001.3
欢迎您访问我们的网站http://www.vrbrothers.com,获取升级信息和最新版本!
1.概述
2.软件特色
3.软件的安装和配置
4.软件功能详解
5.关于制作组
6.疑难解答
 
1.概述
兄弟变速器是一个可以调节Windows系统速度的神奇软件,您可以用它随意加快或放慢Windows
本身和所有应用软件的速度,同时支持热键定义,您可以随时按下热键呼出窗口,加速,减速,
或者立即调节到您设定的速度。
我们用星际争霸,红色警戒2,FIFA2001等游戏进行了测试,效果非常理想,比如,在FIFA中
您可以带球靠近球门,然后按热键减速,从容不迫地完成整个射门动作!
 
2.软件特色
与同类的软件(如著名的“变速齿轮”)相比,本软件具有以下优势:
1) 支持操作系统广泛,全面支持Windows95,97,98,98SE,ME,NT4,2000等多种操作系统。
2) 线性无级变速,您可以随意拖动滑块,自由调节。(“变速齿轮”最新版仅支持十几档速度)
3) 支持的软件更广泛。由于我们采用了和“变速齿轮”完全不同的技术,对整个Windows系统进
行变速,因此能够支持更多的软件。
4) 方便的界面设计,您可以设定呼出窗口,加速,减速,恢复速度,以及6个自定义热键,随时切换。
5) 软件退出后速度的改变仍然有效,直到您下一次重新启动计算机。
6) 公布了采用Visual C++编写的源代码(当然是免费的),今后还会开发出针对其他编程语言如
VB,Delphi的开发包,喜欢编程的朋友也可以定制自己的变速器。
 
3.软件的安装和配置
本软件是绿色软件,无需安装。对于Windows9x可以即拷即用;对于WindowsNT4和Windows2000操
作系统,只需要把文件zntport.sys拷贝到
Windows目录下的System32子目录中,即可使用。
我们提供了一个变速效果演示程序demo.exe,运行它,按照提示操作,您可以很明显的看到变速效果。
本软件公布源代码,您可以在我们的主页http://www.vrbrothers.com上找到。
 
4.软件功能详解
本软件的使用非常简单。在“设置速度 ”区域内,您可以拖动滑块选择速度,或者直接输入50-20000
之间的速度值,完成后,按下“确认”,速度改变生效。您也可以按“设置默认”将当前速度设为默认
值,以后按“恢复默认”即可立即调节到您设定的默认速度。
在“设置热键”区域内,您可以设置呼出窗口,加速,减速,恢复默认速度,以及六个自定义速度的热
键,对于自定义速度,还要进一步指定速度或者按“当前值”使用当前滑块值作为自定义速度。
其余主要功能包括自动校正鼠标双击速度,窗口隐藏等。对Windows加速后,双击操作将失效,因为Windows
认为您双击的时间间隔太短,如果您选择“自动校正鼠标双击速度”即可解决这一问题;按下“窗口隐藏”
后本窗口将不在任务栏出现,您可以按呼出热键或单击右下角的图标呼出窗口。
把鼠标在控件上停留数秒,会出现当前控件的简单介绍。
 
5.关于制作组
本软件由 Brothers 兄弟软件制作小组 创作完成。
创意:李玮 褚瑞
程序设计:褚瑞
Brothers的其他作品包括:
英语四级考试辅导1.0版(for DOS)
英语四级考试辅导2.0版(for Windows)
黑白棋1.0版
驱动器隐藏工具
Spy Brothers
程式猎人(目前最新版本1.27版)
Brothers目前的全部成员包括:
褚瑞(组长) (rchu@263.net)
乔宜臼(chinatang@yeah.net)
朱永春(zhuzhuzhu@netease.com)
叶成名(yy_cc_mm@263.net)
李玮(leo1979@sina.com)
洪流(南非籍)(hongleon@crosswinds.net)
关于Brothers制作组的详细信息,欢迎您到http://www.vrbrothers.com访问。在这里您不仅可以获得
我们的全部信息,还可以下载本软件的最新版本或我们的其他作品,也可以了解我们的一些最新动态。
Brothers随时欢迎各路高手的加盟!
 
6.疑难解答
1) 加速是不是“软超频”,会不会对CPU造成损害?
答:“软超频”是指用软件改变CPU的工作主频,而无论是“兄弟变速器”还是著名的“变速齿轮”都
没有改变CPU的主频,事实上您的计算机速度并没有改变,只是“欺骗”了操作系统和应用软件,让它
认为时间变化了。正如“变速齿轮”的作者说的那样,如果能改变计算机的速度,那Intel或AMD干脆
改行做软件得了。
当然,加速时您的CPU会工作在较高的负载下工作,但是对于CPU来讲,它是按照满负载运行设计的,只
要不超频,就不会造成损害。
2) 加速或减速会不会毁掉我的操作系统。
答:加速或减速并没有往您的硬盘中写任何信息,因此不论您如何加速,只要重新启动一切就会复原,不
会毁坏操作系统。
3) 为什么我变速一段后发现时间不对了?
答:这是必然的,对于现在的计算机系统,时钟由操作系统维持(这样才能避免“千年虫”问题的出现),本
软件改变了系统的速度,因此会影响到时钟。重新启动就一切正常了。我们正在考虑在后续版本中加入自动修
正时钟的功能。
4) 为什么加速后我的双击操作不灵了?
答:因为Windows认为您双击的时间间隔太短,如果您选中“自动校正鼠标双击速度”即可自动解决这一问题。
5) “兄弟变速器”退出后速度的变化仍然有效,怎么办?
答:这是本软件的特色之一,如果您希望退出后恢复默认速度,按“恢复退出”就行了。
6) 有的游戏不能改变速度,怎么办?
答:由于游戏的编写方法千变万化,难免会有个别游戏不能改变速度,试试在启动游戏前先变速。
7) 在上网时变速,连接时间也会变化,这会影响到我上网的费用吗?
答:请放心,100%的不会。否则中国电信岂不要亏本经营了?
8) 我把速度加到最快,为什么游戏速度反而变慢了?
答:加速时CPU会加大工作负载,如果负载大到一定程度而您的CPU不是很快,就反而会降低系统性能(但只
要您不超频,就不会损害CPU)。因此请您在加速时量力而行。
9) 我还有其他问题...
答:请到我们的主页www.vrbrothers.com下载最新版本或者进行咨询,您也可以和作者联系:rchu@263.net
附:兄弟变速器核心代码
附:兄弟变速器核心代码
// File name : SetClock.cpp
// Function1 : SetClock9x(int)
// Function2 : SetClockNT(int)
// Chu Rui 2001.3.1
#include "stdafx.h"
#include "ntport.h"
#define FREE_INT_NO 5
void Ring0()
{ //在Windows9x下进入ring0后进行的操作
__asm
{
cli
mov al,34h
out 43h,al //写入8253控制寄存器,设置写0号定时器
mov ax,bx
out 40h,al //写定时值低位
mov al,ah
out 40h,al //写定时值高位
sti
iretd;
}
}
void SetClockNT(int freq)
{ //NT下的操作
//这里使用了NT Port库
Outport(0x43,0x34); //写入8253控制寄存器,设置写0号定时器
Outport(0x40,freq&0xff); //写定时值低位
Outport(0x40,(freq>>8)&0xff); //写定时值高位
}
void SetClock9x(int freq)
{
union Function_Pointer
{
void (*pointer)();
char bytes[sizeof(void *)];
}OldIntAddress,NewIntAddress;
int IDTAddress; //IDT表基地址
int IDTItemAddress; //要修改的中断门所在地址
char *Pointer; //要修改的中断门所在地址,指针形式
__asm
{
push eax
sidt [esp-2]
pop eax
mov IDTAddress,eax //得到IDT表基地址
}
 
IDTItemAddress=FREE_INT_NO*8+IDTAddress;
Pointer=(char *)IDTItemAddress;
NewIntAddress.pointer=Ring0;
 
OldIntAddress.bytes[0]=Pointer[0];
OldIntAddress.bytes[1]=Pointer[1];
OldIntAddress.bytes[2]=Pointer[6];
OldIntAddress.bytes[3]=Pointer[7]; //保存旧的中断门
Pointer[0]=NewIntAddress.bytes[0];
Pointer[1]=NewIntAddress.bytes[1];
Pointer[6]=NewIntAddress.bytes[2];
Pointer[7]=NewIntAddress.bytes[3]; //设置新的中断门
 
__asm
{
mov ebx,freq
int FREE_INT_NO //产生中断,进入ring0
}
Pointer[0]=OldIntAddress.bytes[0];
Pointer[1]=OldIntAddress.bytes[1];
Pointer[6]=OldIntAddress.bytes[2];
Pointer[7]=OldIntAddress.bytes[3]; //恢复旧的中断门
}
 
顶部