【1.2,已适配机房助手7.8】更新中!淦翻极域、机房助手的超强软件,附代码思路(附带解断网、U盘)
本文内容仅供学习,不得用于商业用途,使用本工具造成的任何后果与本软件及其作者无关!

本软件最新版是1.2。传送门
使用说明
源码也在内!
下载:https://wwt.lanzoub.com/b00pu06li
密码:bbzl
GitHub:https://github.com/BengbuGuards/MythwareToolkit/
GitHub上的版本库持续更新中,欢迎星标以追踪更新!
任务栏托盘图标

直接点击关闭按钮或最小化时大图标从任务栏隐藏,会藏到任务栏托盘
快捷键
Alt+C双击杀掉当前进程,Alt+W最小化顶层窗口(也可以把鼠标移动到屏幕左上角,移动到右上角可关闭窗口,默认关闭此功能),Alt+B唤起主窗口
下面是原理
杀掉极域进程
大多数工具都用了ntsd或taskkill来杀进程,不过容易被封杀(机房助手已经禁用了,映像劫持)。去除控制使用的方法,具体是暴力杀线程(即下方方法)或者清零ntdll基址(强制卸载ntdll模块,代码中存在,但是没有使用)。为什么不用最简单的TerminateProcess()
?请看:

这个函数被极域hook了(其实准确地说它hook的发挥作用的函数是NtOpenProcess()
,SSDT Hook,无论哪个程序调用都被它拦),如果结束的是极域的进程,就拦截。其实有个简单的办法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| #define KILL_FORCE 1 #define KILL_DEFAULT 2
bool KillProcess(DWORD dwProcessID, int way) { if (way == KILL_FORCE) { HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, dwProcessID);
if (hSnapshot != INVALID_HANDLE_VALUE) { bool rtn = false; THREADENTRY32 te = {sizeof(te)}; BOOL fOk = Thread32First(hSnapshot, &te); for (; fOk; fOk = Thread32Next(hSnapshot, &te)) { if (te.th32OwnerProcessID == dwProcessID) { HANDLE hThread = OpenThread(THREAD_TERMINATE, FALSE, te.th32ThreadID); if (TerminateThread(hThread, 0)) rtn = true; CloseHandle(hThread); } } CloseHandle(hSnapshot); return rtn; } return false; } else if (way == KILL_DEFAULT) { HANDLE handle = OpenProcess(PROCESS_TERMINATE, FALSE, dwProcessID); WINBOOL sta = TerminateProcess(handle, 0); CloseHandle(handle); return sta; } return false; }
|
如果把进程看作一个团伙,那么线程就是团伙的成员,如果把每个成员都干掉了,那么这个团伙就也完蛋了。极域并没有hookTerminateThread()
,所以用这种办法来干掉进程。
有些反极域软件声称是驱动级杀进程,其实没这个必要,又不是终止杀毒软件,用驱动开销太大了。
挂起(即冻结)/恢复极域
原理详见win32 判断进程状态(挂起/运行中)、用API挂起/恢复进程。挂起极域后,老师那里显示的屏幕被冻结,固定画面,时间长一些可能会掉线。
破解密码
这里用的是这个文章的算法,原算法位于https://github.com/MuliMuri/Mythware/blob/master/Test/Program.cs,由此博文作者改写:(更新中)极域破解分析(杀死和重启,挂起和恢复,解除全屏按钮限制,解除键盘锁,获取极域安装路径,极域密码破解)
杀掉学生机房管理助手
机房助手有两个进程,prozs.exe
和jfglzs.exe
,其中prozs.exe
的名字是随机的,每天都不一样,具体看我的文章:
最新支持7.2!用C++干掉讨厌的学生机房管理助手
全网首发!逆向分析学生机房管理助手7.4随机进程名算法
逆向分析学生机房管理助手7.5随机进程名算法
逆向分析学生机房管理助手7.8随机进程名算法
这里支持7.8,7.5、7.4、7.2和7.1以下版本,还有更古老的,名字是固定的(是哪几个进程看这里:【去除控制】对学生机房管理助手6.8的分析与突破(链接已失效)),估计也没有什么机房还用这么老的版本,就不做支持了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| char version[6]; HKEY retKey; LONG ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\WOW6432Node\\ZM软件工作室\\学生机房管理助手", 0, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &retKey); DWORD size = sizeof(version); RegQueryValueEx(retKey, "Version", NULL, NULL, (LPBYTE)&version, &size); RegCloseKey(retKey); if (ret != ERROR_SUCCESS) { SetWindowText(TxOut, "执行失败,可能未安装学生机房管理助手"); break; }
SYSTEMTIME time; GetLocalTime(&time); int n3 = time.wMonth + time.wDay; int n4, n5, n6; DWORD prozsPid; if (version[0] == '7' &&(version[2] == '5' || version[2] == '8')) { PROCESSENTRY32 pe; pe.dwSize = sizeof(PROCESSENTRY32); HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (Process32First(hSnapshot, &pe)) { do { size_t uImageLength = strlen(pe.szExeFile); if ((version[2] == '5')?(uImageLength == 14):(uImageLength >= 8)) { for (size_t j = 0; ((version[2] == '5')?(j < 10):(j < uImageLength - 4)); j++) { char n7 = pe.szExeFile[j]; if (!(n7 >= 100 && n7 <= 109))goto IL_226; } sLog += pe.szExeFile; prozsPid = pe.th32ProcessID; break; } IL_226:; } while (Process32Next(hSnapshot, &pe)); } CloseHandle(hSnapshot); } else if (version[0] == '7' && version[2] == '4') { char c1, c2, c3, c4; n3 = time.wMonth * time.wDay, n4 = n3 % 7, n5 = n3 % 5, n6 = n3 % 3; int n = n3 % 9; if (n3 % 2 == 0) { c1 = 108 + n4, c2 = 75 + n, c3 = 98 + n5, c4 = 65 + n6; } else { c1 = 98 + n, c2 = 65 + n4, c3 = 108 + n5, c4 = 75 + n6; } char c[5] = {c1, c2, c3, c4, '\0'}; prozsPid = GetProcessIDFromName(strcat(c, ".exe")); } else if (version[0] == '7' && version[2] == '2') { char c1, c2, c3, c4; n4 = n3 % 7, n5 = n3 % 9, n6 = n3 % 5; if (n3 % 2 != 0) { c1 = 103 + n5, c2 = 111 + n4, c3 = 107 + n6, c4 = 48 + n4; } else { c1 = 97 + n4, c2 = 109 + n5, c3 = 101 + n6, c4 = 48 + n5; } char c[5] = {c1, c2, c3, c4, '\0'}; prozsPid = GetProcessIDFromName(strcat(c, ".exe")); } else { n4 = n3 % 3 + 3, n5 = n3 % 4 + 4; char c[4] = {'p'}; if (n3 % 2 != 0) c[1] = n4 + 102, c[2] = n5 + 98; else c[1] = n4 + 99, c[2] = n5 + 106; prozsPid = GetProcessIDFromName(strcat(c, ".exe")); } KillProcess(prozsPid, KILL_DEFAULT); KillProcess(GetProcessIDFromName("jfglzs.exe"), KILL_DEFAULT);
SC_HANDLE sc = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); SC_HANDLE zm = OpenService(sc, TEXT("zmserv"), SERVICE_STOP); SERVICE_STATUS ss = {}; ControlService(zm, SERVICE_CONTROL_STOP, &ss); CloseServiceHandle(sc); CloseServiceHandle(zm);
|
不过有个问题:在半夜12点前启动机房助手,过了12点再启动本程序,算出的进程名为新一天的。解决办法也不难:重启电脑,或者临时改系统时间为机房助手启动时的时间,在这个时间杀掉进程即可。
解除一些系统工具的禁用和重启资源管理器
原理是改注册表键值,详见此文:改注册表实现解禁部分系统功能。失败的话,用管理员权限运行,也有可能是杀毒软件拦截。
重启资源管理器的办法 ,我最初是先终止explorer.exe再命令行启动,但是后来发现一个简单的办法:
1 2 3 4 5 6 7 8 9 10 11
| HWND hwnd = FindWindow("Shell_TrayWnd", NULL); DWORD pid; GetWindowThreadProcessId(hwnd, &pid); if (pid == 0 || hwnd == NULL) { WinExec("explorer.exe", SW_SHOW); return; } HANDLE handle = OpenProcess(PROCESS_TERMINATE, FALSE, pid); TerminateProcess(handle, 2); CloseHandle(handle);
|
Shell_TrayWnd
这个窗口类名属于任务栏,任务栏又属于explorer.exe,用这个办法,可以得到explorer.exe的pid而无需用进程快照Toolhelp32
遍历进程。退出码为2,终止进程后,系统认为它异常崩溃了,经过复杂的调用,最终winlogon.exe(Windows 登录应用程序)会自动重启它。
需要说明的是,解除USB的限制是改了机房助手的注册表,防止蓝屏,而不是改系统的注册表键值(机房助手也说明了嘛,非注册表法)
黑屏或者全屏广播怎么办(最小化和关闭窗口)
用Timer
每秒计时,然后判断鼠标是否在屏幕左上角,如果在,就弹出提示框,可以最小化当前窗口

实现:(写在Timer
的事件中)
1 2 3 4 5 6 7 8 9 10
| POINT p;
GetCursorPos(&p); if (p.x == 0 && p.y == 0) { HWND topHwnd = GetForegroundWindow(); if (MessageBox(hwnd,"检测到了鼠标位置变化!是否最小化置顶窗口?", "实时监测", MB_YESNO | MB_ICONINFORMATION | MB_SETFOREGROUND | MB_TOPMOST) == IDYES) { ShowWindow(topHwnd, SW_MINIMIZE); } }
|
这样,控制窗口就最小化到任务栏了,可以随时恢复。
如下方法可以关闭窗口

选择“关闭”:
1
| PostMessage(topHwnd,WM_CLOSE,0,0);
|
这里是向窗口发送了关闭消息,就是按下Alt+F4的效果。有些窗口拦截此消息,这样的话就无效了。至于为什么要用PostMessage()
而不是SendMessage()
呢?前者只是把消息放进队列里就返回了,而后者则等消息处理完,返回结果才继续,在此期间会堵塞执行。例如,使用后者向桌面发送消息,会弹出关闭Windows的窗口,此时发送者程序将会无响应,直到用户对弹出窗口作出操作,前者则不会。
选择“强制关闭”(对UWP窗口无效):
1 2 3 4 5 6
| HWND hParent = CreateWindowEx(0, WC_STATIC, "", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
SetParent(topHwnd, hParent);
PostMessage(hParent, WM_CLOSE, 0, 0);
|
若是目标窗口拦截WM_CLOSE
消息,前面的方法就无效了,而这个可以。为什么?如果窗口没拦截WM_CLOSE
,就会调用DefWindowProc()
,这个函数对WM_CLOSE
的处理是调用DestroyWindow()
,它负责销毁窗口、删除计时器、销毁子窗口和发送WM_DESTROY
消息等操作,但是必须要在窗口所处的线程调用它才行,否则返回ERROR_ACCESS_DENIED
拒绝访问。
但是它有个bug,它会销毁子窗口,而不管这个子窗口是否属于调用线程,那么我们自己新建一个窗口,把目标窗口设为它的子窗口,然后销毁我们新建的窗口,子窗口也就一并销毁。SetParent()
这个函数虽然文档说是同一个线程才行,但是实际上没有这种限制,就给了我们可乘之机。
广播窗口化
很多其他博客都说用SetWindowLong()
设置极域广播窗口样式来显示菜单栏,把广播和全屏时的样式记下来调用即可。事实上,这样做确实可以显示工具条来,但是一旦你尝试拖动边边调整大小,它会不屈地尝试填满屏幕。也就是说,在全屏状态下,哪怕你用各种办法调整了它的大小,它也会复原,这种方法无效!
有些时候,极域窗口化广播时会显示一个工具条,其中一个按钮是全屏按钮,可以自如在全屏与窗口之间切换。而全屏广播时它会不见,并且就算你弄出来了,它也是灰色的,禁用状态。用spy++查看广播窗口,可以发现工具条没有消失,只是沉底了而已,并且全屏按钮的控件ID是1004
。
我们知道,当点击一个控件后,会发送WM_COMMAND
消息给窗口,其中的wParam
参数包含了动作(高位)与ID(低位)信息。极域是MFC程序,也是这样子的。那么,我们就可以模拟点击,发送消息给它,它会以为全屏按钮可用并照做,就能实现广播窗口化。再发送一次就能复原。代码:
1 2 3 4
| HWND bdCst = FindWindow(NULL, "屏幕广播");
PostMessage(bdCst, WM_COMMAND, WPARAM((BM_CLICK << 16) | 1004), NULL);
|
解断网限制
极域的断网分多种,有完全不能上网(右下角图标有感叹号)、白/黑名单(没有感叹号,但是出现“该网页已被阻止!”,实现这些极域也是各有分工,既有驱动,也有网关服务。那么通过反编译和其他分析(【干货最多】逆向分析学生机房管理助手7.8随机进程名算法、极域U盘、网络、键盘限制,还没写完),我们的思路就是想欺骗驱动,然后杀了网关服务及其守护进程,再干脆干掉驱动。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
HANDLE hNetFilter = CreateFile("\\\\.\\TDNetFilter", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if(!GetLastError()){ DeviceIoControl(hNetFilter, 0x120014, NULL, 0, NULL, 0, NULL, 0); CloseHandle(hNetFilter); }
KillProcess(GetProcessIDFromName("MasterHelper.exe"),KILL_DEFAULT); KillProcess(GetProcessIDFromName("GATESRV.exe"),KILL_DEFAULT);
SC_HANDLE sc = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); SC_HANDLE hFilt = OpenService(sc, "TDNetFilter", SERVICE_STOP | DELETE); SERVICE_STATUS ss = {}; ControlService(hFilt, SERVICE_CONTROL_STOP, &ss); DeleteService(hFilt); CloseServiceHandle(sc); CloseServiceHandle(hFilt);
|
解禁USB
详见此博客。
解键盘锁
解锁方法参考了https://www.52pojie.cn/thread-542884-1-1.html,表示感谢
具体分析参见对极域64位禁止终止进程、键盘锁定的分析
极域会有键盘锁,也是Hook。Hook有个特点就是后来居上,你先Hook,我再Hook,那最后优先生效的就是我的。那就好办,覆盖它就好!不过极域定时锁键盘,所以要循环。
1 2 3 4 5 6 7 8 9 10 11 12 13
| HHOOK kbdHook;
LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam){ return FALSE; } DWORD WINAPI KeyHookThreadProc(LPVOID lpParameter) { while (true) { kbdHook = (HHOOK)SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)HookProc, GetModuleHandle(NULL), 0); Sleep(25); UnhookWindowsHookEx(kbdHook); } return 0; }
|
为了随时开启和关闭,新建一个线程,不用就挂起,需要就恢复。原文没有Sleep()
延时,吃CPU,加上延时25ms即可。
可能会出现解锁后,大多数按键可以正常使用,但是Ctrl+Alt+Delete无法使用的情况,这是因为WH_KEYBOARD_LL
这个系统hook没法拦住这三个键,极域就装了个底层的键盘驱动来拦截,这个在应用层很难恢复,想卸载它,还比较麻烦。
而最终的解决方案便是欺骗这个键盘驱动,如下所示:(控制码可通过IDA Pro反编译得到)
1 2 3 4 5 6 7 8
| HANDLE hDevice = CreateFile("\\\\.\\TDKeybd", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (!GetLastError()) { BOOL bEnable = TRUE; DeviceIoControl(hDevice, 0x220000, &bEnable, 4, NULL, 0, NULL, NULL)); CloseHandle(hDevice); }
|
另外一个软件JiYuTrainer(破解极域电子教室,老师再也控制不了我了!极域电子教室防控制)给极域注入了dll不让它锁键盘,算是治根了。
启动置顶任务管理器
好多软件都有类似功能,但是都是启动后自己循环调用SetWindowPos()
置顶它,其实这与它自带的置顶功能是不同的,win10/11的任务管理器勾选“置于顶层”后,可以覆盖住大多数窗口(包括极域还有绝大多数软件,当然也包括你自己置顶的窗口)因为它们都不是一个Z序段了。其实它用了一个未文档化的函数CreateWindowInBand()
,这个函数只有微软自己的程序才能用。如果我们要置顶任务管理器,可行的方法就是模拟勾选“置于顶层”。
用spy++可以得到“置于顶层”这个菜单项的ID:0x7704
(Windows 10),向任务管理器发送WM_COMMAND
,wParam就填这个ID,任务管理器就会觉得你勾选了它,会自动置顶。(当然如果已经置顶,它就会取消置顶,所以我们必须事先判断勾选没,没勾选才发送。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| HWND h=FindWindow("TaskManagerWindow", NULL); if(!h){ WinExec("taskmgr", SW_SHOW); do{ Sleep(50); h=FindWindow("TaskManagerWindow", NULL); }while(!h); }
HMENU hm = GetMenu(h); MENUITEMINFO mii = {sizeof(MENUITEMINFO), MIIM_STATE}; GetMenuItemInfo(hm, 0x7704, FALSE, &mii);
if(!(mii.fState & MFS_CHECKED)) PostMessage(h, WM_COMMAND, 0x7704, 0);
|
顺便说说
这个程序是win32程序,无需易语言或MFC,用Dev C++就可以打开开发,方便大家学习哈。编译环境选择高版本的MinGW GCC即可。
附录1:学生机房管理助手的软件黑名单(9.0版本)
进程名包含这些词就会蓝屏(加粗的名字不仅匹配进程名,还匹配窗口名):
vmware、VirtualBox、Virtual PC、 虚拟机 、 电子教室 、ProcView、IceSword、Procmast.exe、ProcessManager.exe、rstray.exe、PFW.exe、FTCleaner.exe、Wsyscheck.exe、XueTr.exe、prom.exe、ProcessX.exe、pchunter、 Killer.exe 、procmgr.exe、ProcessHacker.exe、killcontrol、PowerTool32.exe、360taskmgr、YtWinAst、KVFWMain.exe、ECQ-PS.exe、SnipeSword、procexp、 MsgFlood.exe 、ProcessOVER、procdeal、 桌面 、 任务 、 进程 、Prayaya、dexpot.exe、vdeskman.exe、mdesk.exe、 virtualdesk 、multideskt.exe、VirDsk.exe、IDesktop.exe、YtMDesk.exe、coon.exe、zmqh.exe、DexpotProPortable.exe、Desktops.exe、wisedesktop.exe、DESKTOP.exe、Vdesktop.exe、MagicDesktop.exe、multidesktop.exe、 v13 (这个有特别关照,在蓝屏窗口加载时还会自动杀掉带有这个名字的进程)、RegWX64.exe、QQPCNetFlow.exe、BDMANetLimiter.exe、netmon.exe、360netman.exe、HelloTeacher.exe、EHacker.exe、PowerTool64.exe、zydesk.exe、perfmon.exe、 吾爱破解 、 极域 、prcview.exe、processlasso.exe、netfuke.exe、 去除控制 、 课堂狂欢器 、 课堂工具 、fuckmythware、SpecialSet.exe、JiYuTrainer.exe、skieskiller、WindowsKernelExplorer.exe、msconfig.exe。当然也包括我们的尊贵的任务管理器啦!
附录2:在线根据明文生成学生机房管理助手密码(7.2以上)
访问这个网站,在代码运行窗口输入如下内容,便可生成密文,将密文写入注册表HKEY_CURRENT_USER\Software:n(REG_SZ),机房助手密码将会被立即更改:(也可以本地运行)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| using System; using System.Security.Cryptography; using System.Text; using System.IO;
public class Program { public static void Main() { string string_3 = "12345678"; string value = "C:\\WINDOWS"; string s = value.Substring(0, 8); string s2 = value.Substring(1, 8); DESCryptoServiceProvider descryptoServiceProvider = new DESCryptoServiceProvider(); descryptoServiceProvider.Key = Encoding.UTF8.GetBytes(s); descryptoServiceProvider.IV = Encoding.UTF8.GetBytes(s2); MemoryStream memoryStream = new MemoryStream(); CryptoStream cryptoStream = new CryptoStream(memoryStream, descryptoServiceProvider.CreateEncryptor(), CryptoStreamMode.Write); StreamWriter streamWriter = new StreamWriter(cryptoStream); streamWriter.Write(string_3); streamWriter.Flush(); cryptoStream.FlushFinalBlock(); memoryStream.Flush(); string string_4 = Convert.ToBase64String(memoryStream.GetBuffer(), 0, checked((int)memoryStream.Length)); StringBuilder stringBuilder = new StringBuilder(); for(int i = 0; i < string_4.Length; i++) stringBuilder.Append((char)(string_4[i] - 10)); string_3 = stringBuilder.ToString(); MD5CryptoServiceProvider md5CryptoServiceProvider = new MD5CryptoServiceProvider(); byte[] array2 = md5CryptoServiceProvider.ComputeHash(Encoding.Default.GetBytes(string_3)); stringBuilder.Clear(); for (int i = 0; i < array2.Length; i++) stringBuilder.Append(array2[i].ToString("x2")); string str = stringBuilder.ToString().Substring(10);
Console.WriteLine(str); } }
|