从小学学会开始学魔兽地图制作之后,我就彻底爱上了编程,WE(魔兽地图编辑)一直伴随着我的成长,从学第一门脚本语言(Jass)到现在这么多都是它让我成长起来的。现在war3 也衰败了。朋友让我做个全开的小工具。我试了下,果真可以了。
网上一些让地图全开的方法大多是直接修改内存,如果学过作图的话 。war3 内部其实给作图开发者提供 jass native 函数。jass是 war3的地图脚本语言。其实我猜他是从lua(一种脚本语言)上精简过来的。做过图的朋友都知道,调用这些函数可以直接达到预期的效果。
但是我们现在要做的是在外部调用这些函数。好在war3已经把对应函数表的对应地址给我们了。
我们用OD打开war3 目录下的 Game.dll
搜索字符串 "FogEnable"
这个是war3 jass api用来启用战争迷雾的函数,我们在作图的时候在Trigger(触发器)中调用这个函数就可以禁用(启用)战争迷雾。
我们会看到如下的代码
6F3D58DA BA 68C5956F mov edx,Game.6F95C568 ; FogMaskEnable
6F3D58DF B9 50BD3B6F mov ecx,Game.6F3BBD50
6F3D58E4 E8 37030800 call Game.6F455C20
6F3D58E9 68 E85B946F push Game.6F945BE8 ; ()B
6F3D58EE BA 54C5956F mov edx,Game.6F95C554 ; IsFogMaskEnabled
6F3D58F3 B9 70BD3B6F mov ecx,Game.6F3BBD70
6F3D58F8 E8 23030800 call Game.6F455C20
6F3D58FD 68 A45B946F push Game.6F945BA4 ; (B)V
6F3D5902 BA 48C5956F mov edx,Game.6F95C548 ; FogEnable
6F3D5907 B9 20BD3B6F mov ecx,Game.6F3BBD20
6F3D590C E8 0F030800 call Game.6F455C20
6F3D5911 68 E85B946F push Game.6F945BE8 ; ()B
6F3D5916 BA 38C5956F mov edx,Game.6F95C538 ; IsFogEnabled
6F3D591B B9 40BD3B6F mov ecx,Game.6F3BBD40
6F3D5920 E8 FB020800 call Game.6F455C20
这是游戏开始war3用来注册 jass native api函数的
很显然这是 fastcall
如果在下面再按照它的形式多定义几条的话。我们就可以增加 jass native api ,可以用来扩充war3 的功能
其实 11 平台也是这么实现的。这里的这种方法并不能过掉 11 平台的检测。似乎 11平台 的检测技术确实比较厉害,我想了一下午都没有找到过 11 的方法。
当然这里只是简单的演示。
回归正题。
上面的FogMaskEnable 和 FogEnable 函数就是禁用(启用)战争迷雾和黑色阴影的函数。 分别有一个参数。是bool类型的
他在jass中的native common.j中的定义是。
native FogMaskEnable takes bool b returns nothing
native FogEnable takes bool b returns nothing
我们由此推测 ecx寄存器里面存的就是jass native api对应的物理地址。我们进去看一下头果真的stdcall.而且参数表和注册时压入栈中的一模一样.
然后我们只需要写个dll,然后直接调用ecx里的地址就可以了。
1.定义一个函数指针
typedef void(_war3_Fogable)(bool state);
_war3_Fogable *fog=(_war3_Fogable*)(0x03EABD20);
_war3_Fogable *mask=(_war3_Fogable*)(0x03EABD50);
2.然后设置一个键盘钩子。当按下哪个按键的时候 就调用 fog(0)和mask(0)
HHOOK g_LowKeyBoardHook=NULL;.
LRESULT CALLBACKLowLevelKeyboardProc(intnCode,
WPARAMwParam,
LPARAMlParam
)
{
if(nCode==HC_ACTION)
{
//当按下home键的时候
if(kblp->vkCode==VK_HOME&&wParam==WM_KEYDOWN)
{
fog(0);
mask(0);
returnTRUE;
}
}
returnCallNextHookEx(g_LowKeyBoardHook,nCode,wParam,lParam);
}
BOOL APIENTRYDllMain(HMODULEhModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
fog(0);
mask(0);
switch(ul_reason_for_call)
{
caseDLL_PROCESS_ATTACH:
{
// MessageBox(NULL, _T("DLL_PROCESS_ATTACH"), _T("!"), MB_OK);
g_LowKeyBoardHook=SetWindowsHookEx(WH_KEYBOARD_LL,(HOOKPROC)LowLevelKeyboardProc,hModule,0);
}
caseDLL_THREAD_ATTACH:
caseDLL_THREAD_DETACH:
caseDLL_PROCESS_DETACH:
break;
}
returnTRUE;
}
3.DLL注入
然后如何把这个DLL注入到war3进程中是个问题。
不过Wc3c.net 上有人发现当war3.exe启动的时候会把 war3\redist\miles 下所有扩展名为 m3d 的模块 载入进程。
所以只需要把dll的扩展名改成m3d放入war3\redist\miles目录下。
当war3启动时就会把它当做默认模块载入到游戏中。进入游戏后按Home键就可以了。