在机房环境中,学生常常面临着各种机房管理软件的限制,想要去除这些限制成为很多人的迫切需求。不管是采用暴力杀线程还是其他特殊方法,这其中涉及很多复杂操作以及产生的一系列连锁反应,是值得探讨的。
暴力杀线程相关问题
暴力杀线程这种方法听起来就很生猛。这种做法可能是不得已而为之的手段。在某些版本的机房管理软件中,可以采用这样的方法。比如在特定的7.8、7.5、7.4、7.2和7.1以下版本等。但是这样做可能会有很多潜在风险。这可能会影响系统的稳定性。因为它可能干扰到软件正常运行的线程关系,导致一些不可预知的错误。
#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;
}
然而这种做法也有它存在的意义。在一些限制非常严格的情况下,可能这是唯一能突破限制的途径。例如在没有管理员权限又急需某种功能的场景下,这个方法或许值得一试。
清零ntdll基址
虽然代码中有清零ntdll基址这样的做法,但是实际没有使用。这或许是因为这种做法太过极端。ntdll基址一旦被清零,强制卸载ntdll模块,对于整个系统的影响难以估量。从系统结构来说,ntdll在Windows系统中有重要作用。它就像是大厦的一块基石,一旦被动摇,可能引发形形色色的问题。
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);
在实际测试过程中,也许在开发过程中考虑过使用它,但权衡利弊后放弃了。毕竟维护整个系统的基本功能和稳定性是必须要考虑的重要方面。
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);
重启电脑与改时间杀进程
解决机房管理软件限制这个问题,有一种相对简单的办法。那就是重启电脑,或者临时改系统时间为机房助手启动时的时间,然后在这个时间杀掉进程。在实际的机房场景中,那些想要突破限制的学生可能会去尝试这个方法。比如在学校的机房里,当限制软件启动后,学生可以按照这个步骤操作。
这里存在限制软件终止后的情况,其退出码为2表明异常崩溃。之后经过复杂的系统调用过程,winlogon.exe会自动重启该软件。这种自动重启机制是系统默认的自我保护措施,但这也往往限制了突破限制的持续性效果。
解除USB限制相关情况
//写在程序前面定义处!
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);
}
}
关于解除USB的限制,与改注册表相关。不过这里不是改系统的注册表键值,而是改了机房助手的注册表。这是为了防止蓝屏情况出现。在正常的机房使用中,如果误操作改了系统注册表可能会产生严重的蓝屏问题。而这种方式只针对机房助手本身进行调整。比如曾经在某个机房的操作中,有人试图通过常规改注册表方式解除USB限制,结果导致蓝屏,这就是没有区分注册表类型的后果。
窗口操作产生的问题
在向桌面发送消息这种操作中存在着差异。使用某些特殊操作时会弹出关闭Windows的窗口,这个时候发送者程序将会无响应,必须要等到用户对弹出窗口作出操作才可以。不同的操作就会产生不同的结果。就像在操作极域软件时,不同的功能调用就会有不一样的反馈情况。这种有差异的反馈会影响整体的使用体验,也影响突破限制的欲望和效果。
PostMessage(topHwnd,WM_CLOSE,0,0);//异步
而且有操作存在bug,它会销毁子窗口而不管其所属关系。这种无差别化的销毁可能是程序逻辑上的缺陷。不过人们也发现了应对办法,通过新建窗口等间接手段来达到目的。
极域窗口化广播操作
//创建一个透明零大小的父窗口
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);
极域窗口化广播时显示出工具条这一情况也有研究的价值。其中的全屏按钮可以进行全屏与窗口的切换。通过spy++查看广播窗口,可以发现有趣的现象,工具条没有消失只是沉底了且全屏按钮控件有特定ID是1004。在分析和应对极域的控制时,这些细节都是可以挖掘利用的地方。在很多实际的机房中,人员可能针对这个按钮进行操作或者反向分析。
对于这样复杂的机房管理软件的限制解除等行为,你觉得在合法合规的前提下是否合理的自我需求?