本文内容仅供学习,不得用于商业用途,使用本工具造成的任何后果与本软件及其作者无关!

截图
本软件最新版是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,无论哪个程序调用都被它拦),如果结束的是极域的进程,就拦截。其实有个简单的办法:

#define KILL_FORCE 1
#define KILL_DEFAULT 2
//用杀掉每个线程的方法解决某些进程hook住了TerminateProcess()的问题
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.exejfglzs.exe,其中prozs.exe的名字是随机的,每天都不一样,具体看我的文章:
最新支持7.2!用C++干掉讨厌的学生机房管理助手
全网首发!逆向分析学生机房管理助手7.4随机进程名算法
逆向分析学生机房管理助手7.5随机进程名算法
逆向分析学生机房管理助手7.8随机进程名算法
这里支持7.8,7.5、7.4、7.2和7.1以下版本,还有更古老的,名字是固定的(是哪几个进程看这里:【去除控制】对学生机房管理助手6.8的分析与突破(链接已失效)),估计也没有什么机房还用这么老的版本,就不做支持了

char version[6];//考虑极端值如6.9.5
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;
}
//取时间用于计算prozs.exe的随机进程名
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')) {
	//以下为7.5、7.8版本逻辑
	PROCESSENTRY32 pe;
	pe.dwSize = sizeof(PROCESSENTRY32);
	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (Process32First(hSnapshot, &pe)) {
		do {
			//筛选长度为10(7.5)或大于等于4(7.8)的进程名(不包含末尾“.exe”)
			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];
					//符不符合d-m之间
					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') {
	//以下为7.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;
	//以下为7.2版本逻辑
	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 {
	//以下为7.2版本之前的逻辑
	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);
//停止zmserv服务防止关机
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再命令行启动,但是后来发现一个简单的办法:

HWND hwnd = FindWindow("Shell_TrayWnd", NULL);//有这个类名的窗口一定隶属于explorer.exe
DWORD pid;
GetWindowThreadProcessId(hwnd, &pid);//反查出窗口PID
if (pid == 0 || hwnd == NULL) { //资源管理器没在运行
	WinExec("explorer.exe", SW_SHOW);//先直接运行,系统检测到explorer.exe是系统权限会自动重启它以降权(否则权限被继承,出现奇妙问题)
	return;
	//pid = GetProcessIDFromName("explorer.exe");
}
HANDLE handle = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
TerminateProcess(handle, 2);//退出码为2
CloseHandle(handle);

Shell_TrayWnd这个窗口类名属于任务栏,任务栏又属于explorer.exe,用这个办法,可以得到explorer.exe的pid而无需用进程快照Toolhelp32遍历进程。退出码为2,终止进程后,系统认为它异常崩溃了,经过复杂的调用,最终winlogon.exe(Windows 登录应用程序)会自动重启它。

需要说明的是,解除USB的限制是改了机房助手的注册表,防止蓝屏,而不是改系统的注册表键值(机房助手也说明了嘛,非注册表法)

黑屏或者全屏广播怎么办(最小化和关闭窗口)

Timer每秒计时,然后判断鼠标是否在屏幕左上角,如果在,就弹出提示框,可以最小化当前窗口

好用

实现:(写在Timer的事件中)

//写在程序前面定义处!
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);
	}
}

这样,控制窗口就最小化到任务栏了,可以随时恢复。

如下方法可以关闭窗口

更好用
选择“关闭”:

PostMessage(topHwnd,WM_CLOSE,0,0);//异步

这里是向窗口发送了关闭消息,就是按下Alt+F4的效果。有些窗口拦截此消息,这样的话就无效了。至于为什么要用PostMessage()而不是SendMessage()呢?前者只是把消息放进队列里就返回了,而后者则等消息处理完,返回结果才继续,在此期间会堵塞执行。例如,使用后者向桌面发送消息,会弹出关闭Windows的窗口,此时发送者程序将会无响应,直到用户对弹出窗口作出操作,前者则不会。

选择“强制关闭”(对UWP窗口无效):

//创建一个透明零大小的父窗口
HWND hParent = CreateWindowEx(0, WC_STATIC/*头文件commctrl.h*/, "", 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程序,也是这样子的。那么,我们就可以模拟点击,发送消息给它,它会以为全屏按钮可用并照做,就能实现广播窗口化。再发送一次就能复原。代码:

//获取广播窗口句柄
HWND bdCst = FindWindow(NULL, "屏幕广播");
//模拟点击
PostMessage(bdCst, WM_COMMAND, WPARAM((BM_CLICK << 16) | 1004), NULL);

解断网限制

极域的断网分多种,有完全不能上网(右下角图标有感叹号)、白/黑名单(没有感叹号,但是出现“该网页已被阻止!”,实现这些极域也是各有分工,既有驱动,也有网关服务。那么通过反编译和其他分析(【干货最多】逆向分析学生机房管理助手7.8随机进程名算法、极域U盘、网络、键盘限制,还没写完),我们的思路就是想欺骗驱动,然后杀了网关服务及其守护进程,再干脆干掉驱动。

//以下代码依然不稳定!!!
//发送终止指令
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,那最后优先生效的就是我的。那就好办,覆盖它就好!不过极域定时锁键盘,所以要循环。

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反编译得到)

//打开符号链接
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,任务管理器就会觉得你勾选了它,会自动置顶。(当然如果已经置顶,它就会取消置顶,所以我们必须事先判断勾选没,没勾选才发送。)

//判断有没有启动
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),机房助手密码将会被立即更改:(也可以本地运行)

// 代码来自学生机房管理助手9.0 set.exe,逆向、整理:小流汗黄豆
using System;
using System.Security.Cryptography;
using System.Text;
using System.IO;

public class Program
{
	public static void Main()
	{
		// 更改这里的内容
		string string_3 = "12345678";
		// Class6.smethod_0()
		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));
		// Class6.smethod_3()
		StringBuilder stringBuilder = new StringBuilder();
		for(int i = 0; i < string_4.Length; i++)
			stringBuilder.Append((char)(string_4[i] - 10));
		string_3 = stringBuilder.ToString();
		// Class6.smethod_2()
		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);
	}
}
// 期望输出:8a29cc29f5951530ac69f4
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐