要知道怎么過“-mh”命令,首先得知道地圖的“-mh”做了些什么事情,從地圖提取出war3map.j文件,搜索關鍵詞“可能作弊”檢測MH的觸發器
function Trig_EagelAMH_Actions takes nothing returns nothing call DisableTrigger(GetTriggeringTrigger()) call PolledWait(2.00) call EnableTrigger(gg_trg_EagelSeekA) call EnableTrigger(gg_trg_EagelSeekB) call SetUserControlForceOff(bj_FORCE_ALL_PLAYERS) call CreateNUnitsAtLoc(1,'hfoo',Player(15),udg_EagelAMHp,bj_UNIT_FACING) set udg_EagelAMHu=bj_lastCreatedUnit set bj_forLoopAIndex=1 set bj_forLoopAIndexEnd=12 loop exitwhen bj_forLoopAIndex>bj_forLoopAIndexEnd if(Trig_EagelAMH_Func007Func001C())then call CreateFogModifierRadiusLocBJ(true,Player(-1+(bj_forLoopAIndex)),FOG_OF_WAR_VISIBLE,udg_EagelAMHp,512) set udg_EagelAMHfog[bj_forLoopAIndex]=bj_lastCreatedFogModifier call SelectUnitForPlayerSingle(udg_EagelAMHu,Player(-1+(bj_forLoopAIndex))) call DestroyFogModifier(udg_EagelAMHfog[bj_forLoopAIndex]) endif set bj_forLoopAIndex=bj_forLoopAIndex+1 endloop call PolledWait(1.) call RemoveUnit(udg_EagelAMHu) call TriggerExecute(gg_trg_EagelPrint) call SetUserControlForceOn(bj_FORCE_ALL_PLAYERS) call DisableTrigger(gg_trg_EagelSeekA) call DisableTrigger(gg_trg_EagelSeekB) call EnableTrigger(GetTriggeringTrigger()) endfunction
創建一個單位,再選中單位是一般地圖反MH的做法,Lynn的那篇文章說的也是這種,而新真三藍寶石也是使用了這種種方法來檢測MH,先調用CreateFogModifierRadiusLocBJ,創建一塊迷霧,再該坐標創建一個單位(好像是個人族步兵),然后再讓玩家選擇該單位,反正我們的目的就是破壞這段代碼的功能,最直接的就是讓他不做事,直接retn(好像沒什么技術含量,都是Lynn說過的...)...
下面給出關鍵C++代碼
void CbypassDlg::OnBnClickedPatch() { // TODO: 在此添加控件通知處理程序代碼 DWORD pid; HWND hwar3=::FindWindow(L"Warcraft III",L"Warcraft III"); if(!hwar3) { MessageBox(L"can't find Warcraft III!"); return; } GetWindowThreadProcessId(hwar3, &pid); HANDLE hopen = OpenProcess(PROCESS_ALL_ACCESS, false, pid); // BYTE _data1[]= {0x33,0xC0,0xE9,0x96,0x01,0x00,0x00,0x90,0x90,0x90,0x90,0x90};//改寫CreateFogModifierRadiusLoc 函數入口處的代碼 BYTE _data2[]= {0x33,0xC0,0xE9,0xFC,0x00,0x00,0x00,0x90,0x90,0x90,0x90,0x90};//改寫SelectUnit函數入口處的代碼 //CreateFogModifierRadiusLoc 函數入口處 地址為0x6F2B3170 //SelectUnit函數入口處 地址為 0x6F2C59A0 // if(!WriteProcessMemory(hopen,(LPVOID)(0x6F2B3170), &_data1,12, NULL) || !WriteProcessMemory(hopen,(LPVOID)(0x6F2C59A0), &_data2,12, NULL)) if(!WriteProcessMemory(hopen,(LPVOID)(0x6F2C59A0), &_data2,12, NULL)) { MessageBox(L"patch error!"); return; } else MessageBox(L"success!"); }
在上面的代碼里可以看到我注釋掉了修改CreateFogModifierRadiusLoc 函數入口處的部分,因為這樣做是不行的,也就是說任何創建單位,創建物品之類的函數,如果retn掉的話,魔獸就會出現數據同步錯誤而掉線,所以只能修改操作函數,而不能修改影響魔獸數據的函數(在這里曾經犯過錯誤= =!)...
void CbypassDlg::OnBnClickedRecovery() { // 恢復函數 DWORD pid; HWND hwar3=::FindWindow(L"Warcraft III",L"Warcraft III"); if(!hwar3) { MessageBox(L"can't find Warcraft III!"); return; } GetWindowThreadProcessId(hwar3, &pid); HANDLE hopen = OpenProcess(PROCESS_ALL_ACCESS, false, pid); // BYTE _data1[]= {0x55,0x8B,0xEC,0x83,0xEC,0x3C,0x8B,0x0D,0xBC,0x22,0x87,0x6F}; BYTE _data2[]= {0x55,0x8B,0xEC,0x83,0xEC,0x08,0x8B,0x0D,0xBC,0x22,0x87,0x6F}; // if(!WriteProcessMemory(hopen,(LPVOID)(0x6F2B3170), &_data1,12, NULL) || !WriteProcessMemory(hopen,(LPVOID)(0x6F2C59A0), &_data2,12, NULL)) if(!WriteProcessMemory(hopen,(LPVOID)(0x6F2C59A0), &_data2,12, NULL)) { MessageBox(L"recovery error!"); return; } else MessageBox(L"success!"); }
============================================還是分割線===========================
相信已經說的夠清楚了,程序源代碼也沒必要給出了,有上面兩處關鍵代碼就足夠了
