【编程技术-使用SandboxiePlus加速植物大战僵尸游戏】此文章归类为:编程技术。
前言
前几天偶然发现一篇使用变速齿轮来加速植物大战僵尸的文章,这几天在研究SandboxiePlus的源码,其中也有加速的设置,但加速部分的代码写的很乱。举个例子:
1 2 3 4 5 6 7 8 | _FX DWORD Kernel_SleepEx( DWORD dwMiSecond, BOOL bAlert)
{
ULONG add = SbieApi_QueryConfNumber(NULL, L "AddSleepSpeed" , 1);
ULONG low = SbieApi_QueryConfNumber(NULL, L "LowSleepSpeed" , 1);
if (add != 0 && low != 0)
return __sys_SleepEx(dwMiSecond * add / low, bAlert);
return __sys_SleepEx(dwMiSecond, bAlert);
}
|
上述的代码是SleepEx的hook函数。按照changelog中介绍,AddSleepSpeed和LowSleepSpeed分别表示加速和降速的配置,AddSleepSpeed/LowSleepSpeed表示加速倍数,但上述的SleepEx hook函数中dwMiSecond * add / low其实增加了SleepEx的数值,正确应该修改为dwMiSecond * low / add。本文将变速齿轮的加速原理移植到SandboxiePlus中,实现了植物大战僵尸游戏的加速。
变速齿轮技术原理
我使用的变速齿轮中有三个文件,分别是:GearNT.exe、GearNTKe.dll和Hook.dll。其中加速部分的实现在GearNTKe.dll中,该DLL中hook了六个函数,如下:
1 2 3 4 5 6 7 8 9 10 11 | DWORD GetTickCount();
BOOL QueryPerformanceCounter([out] LARGE_INTEGER *lpPerformanceCount);
LONG GetMessageTime();
UINT_PTR SetTimer([in, optional] HWND hWnd, [in] UINT_PTR nIDEvent,
[in] UINT uElapse, [in, optional] TIMERPROC lpTimerFunc);
DWORD timeGetTime();
MMRESULT timeSetEvent( UINT uDelay, UINT uResolution,
LPTIMECALLBACK lpTimeProc, DWORD_PTR dwUser, UINT fuEvent);
|
上述函数可以分为两类:
- 类型一:设置基于时间的定时器回调函数,加速思路直接修改uDelay为uDelay/加速倍数。这类函数有SetTimer和timeSetEvent函数两个函数。




- 类型二:时刻做差获取时间。获取两个时刻t1和t2,然后t2 - t1作为具体代码消耗的时间。加速思路是在GearNTKe.dll加载的时候获取一个基点t,然后按照
t + (tt - t) * 加速倍数
公式计算返回值。其中tt是获取时刻函数,这类函数有GetTickCount、GetMessageTime和timeGetTime。下面是timeGetTime的hook函数的伪代码:



另外一个有意思的点是变速齿轮的加速刻度,每一个刻度为0.5,因为它使用的加速倍数公式倍数 = pow(2.0, (double)(距离原点的距离) / 10.0) * (2^22)
,(2^22)
扩大的倍数,倍数越大越精确。当a1等于0.5和1时加速倍数分别为1.41和2倍,加速倍数如下:


SandboxiePlus代码修改
SandboxiePlus的代码已经实现了hook功能,我们所要做的就是实现上述的hook函数即可。
类型一
1 2 3 4 5 6 7 8 9 10 | _FX UINT_PTR Gui_SetTimer( HWND hWnd, UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc)
{
ULONG add = SbieApi_QueryConfNumber(NULL, L "AddTimerSpeed" , 1), low = SbieApi_QueryConfNumber(NULL, L "LowTimerSpeed" , 1);
if (add != 0 && low != 0) {
UINT64 newElapse = uElapse;
newElapse = newElapse * low / add;
return __sys_SetTimer(hWnd, nIDEvent, ( UINT )newElapse, lpTimerFunc);
}
return 0;
}
|
- 修改timeSetEvent,该函数的hook函数如下:
1 2 3 4 5 6 7 8 9 10 11 | _FX MMRESULT Wimm_timeSetEvent( UINT uDelay, UINT uResolution, LPTIMECALLBACK lpTimeProc, DWORD_PTR dwUser, UINT fuEvent)
{
ULONG add = SbieApi_QueryConfNumber(NULL, L "AddTimerSpeed" , 1), low = SbieApi_QueryConfNumber(NULL, L "LowTimerSpeed" , 1);
if (add != 0 && low != 0) {
UINT64 newDelay = uDelay;
newDelay = newDelay * low / add;
return __sys_timeSetEvent(( UINT )newDelay, uResolution, lpTimeProc, dwUser, fuEvent);
}
return 0;
}
|
类型二
- 修改GetTickCount,该函数的hook函数如下:
1 2 3 4 5 6 7 8 9 10 | _FX DWORD Kernel_GetTickCount()
{
ULONG add = SbieApi_QueryConfNumber(NULL, L "AddTickSpeed" , 1);
ULONG low = SbieApi_QueryConfNumber(NULL, L "LowTickSpeed" , 1);
ULONG64 count = __sys_GetTickCount();
if (add != 0 && low != 0) {
count = Dll_FirstGetTickCountValue + (count - Dll_FirstGetTickCountValue) * add / low;
}
return ( DWORD )count;
}
|
- 修改timeGetTime,该函数的hook函数如下:
1 2 3 4 5 6 7 8 9 10 11 | _FX DWORD Wimm_timeGetTime()
{
ULONG add = SbieApi_QueryConfNumber(NULL, L "AddTimerSpeed" , 1), low = SbieApi_QueryConfNumber(NULL, L "LowTimerSpeed" , 1);
ULONG64 time = __sys_timeGetTime();
if (add != 0 && low != 0) {
time = Dll_FirsttimeGetTimeValue + ( time - Dll_FirsttimeGetTimeValue) * add / low;
}
return ( DWORD ) time ;
}
|
注意:QueryPerformanceCounter使用的是一个64位值,使用"t + (tt - t) * 加速倍数"可能会出现溢出,使用SandboxiePlus原来的hook函数。
测试
- 创建一个标准的box,修改box的配置,添加如下内容:

- 编译SandboxiePlus的SboxDll项目,生成32位和64位版本的SbieDll.dll,并替换SandboxiePlus安装目录中的SbieDll.dll。
- 运行植物大战僵尸主程序PlantsVsZombies.exe,可以感觉到阳光和僵尸的速度变快了。效果的话,可以在代码中加些日志。
1 2 3 4 | PlantsVsZombies.exe (5864, 5548) - 14:29:41.906 Hook (U) SetTimer => oldEplase=300, newElapse=200
PlantsVsZombies.exe (5864, 5548) - 14:29:41.906 Hook (U) SetTimer => oldEplase=100, newElapse=66
PlantsVsZombies.exe (5864, 5548) - 14:30:43.375 Hook (U) GetTickCount => oldCount=54518792, newCount=54549719
PlantsVsZombies.exe (5864, 5548) - 14:30:43.381 Hook (U) timeGetTime => oldTime=54518869, newTime=54549795
|
结论
通过修改SandboxiePlus的SboxDll,实现了和变速齿轮相同的加速效果,理论上变速齿轮加速的软件,现在的SandboxiePlus都可以加速。成品可以在"安全狗的开发日常"公众号中回复PlantsVsZombie关键字获取相关文件的下载链接,文件下载后替换SandboxiePlus安装目中的文件即可。
更多【编程技术-使用SandboxiePlus加速植物大战僵尸游戏】相关视频教程:www.yxfzedu.com