Update 2022-1-30
今天看到这软件更新了7.1版本,然后又被以前那个程序破解了。
属实是更新了个寂寞。
如果你只想要破解程序就点我 密码:55oe
前言
道高一尺,魔高一百丈 ——xys
前几天上信息课时,插入U盘,然后…

???什么阴间玩意
重启电脑后发现是初中部机房新装的一个软件,叫"学生机房管理助手"。

一看官网,“保护26种电子教室” “禁止学生10种常见脱控方法”,专门防止学生脱离控制的。
还附赠了个特别阴间的视频:
无法容忍禁用USB,遂尝试破解之。
分析
安装
刚到家就在虚拟机里安装了一份来以身试毒。
设置极域主程序后,只要对极域有任何操作(包括但不限于结束进程、冻结进程、DLL注入等)都会造成蓝屏,只能重启。
在网上搜索这个东西的资料,发现做了混淆,无法破解密码,可以考虑直接吔掉主程序。
研究
分析进程 - jfglzs.exe
"学生机房管理助手"在安装后会禁用任务管理器、CMD、“运行”、和注册表编辑器。
使用工具解除了任务管理器限制,发现有可疑进程 jfglzs.exe
,显然就是这玩意的主程序。

但是当我把jfglzs.exe
关掉的时候,又蓝屏了,显然有双进程保护。

双进程保护
程序使用两个进程互相保护的行为。例如程序A
与B
进行保护,互相检测对方进程是否存在,如果你将A
结束B
就会将A
再启动,反之同理。
分析进程 - 2
打开jfglzs.exe
的exe
位置…

jfglzs.exe
不用说;main.exe
经测试是这东西的UI
面板。

srvany.exe
似乎是一个辅助程序,用途不明。
最有意思的是pfn.exe
和prozs.exe
。
pfn.exe
显然就是机房管理助手的保护进程,但如果试图把它关掉也会蓝屏。
而当我运行prozs.exe
时发现没有效果,给它拖到了桌面上,发现每次点开就会生成并运行一个新的pfn.exe
…而且这个新生成文件的文件名和日期有关,是随机的。

破解方式
分析完成。我们可以得出结论,只需要把以上提到的全部exe
都破坏即可关闭机房管理助手。
问题在于prozs.exe
随机生成的保护程序,这样便无法根据进程名找到进程。
但是这些全部的exe
文件都位于机房管理助手的安装目录(C:\
中的一个随机名称目录),prozs.exe
生成的保护程序也不例外,因此我们只需要获得jfglzs.exe
(只要机房管理助手开启这个进程是一定存在的)的exe
位置(即机房管理助手的安装目录)并控制所有exe
位置在安装目录的进程即可。
代码实现
先写出获取进程路径的代码:
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
| BOOL dos2nt(LPTSTR pszDosPath, LPTSTR pszNtPath) { TCHAR szDriveStr[500]; TCHAR szDrive[3]; TCHAR szDevName[100]; INT cchDevName; INT i; if(!pszDosPath || !pszNtPath ) return FALSE; if(GetLogicalDriveStrings(sizeof(szDriveStr), szDriveStr)) { for(i = 0; szDriveStr[i]; i += 4) { if(!lstrcmpi(&(szDriveStr[i]), TEXT("A:\\")) || !lstrcmpi(&(szDriveStr[i]), TEXT("B:\\"))) { continue; } szDrive[0] = szDriveStr[i]; szDrive[1] = szDriveStr[i + 1]; szDrive[2] = '\0'; if(!QueryDosDevice(szDrive, szDevName, 100)) { return FALSE; } cchDevName = lstrlen(szDevName); if(_tcsnicmp(pszDosPath, szDevName, cchDevName) == 0) { lstrcpy(pszNtPath, szDrive); lstrcat(pszNtPath, pszDosPath + cchDevName); return TRUE; } } } lstrcpy(pszNtPath, pszDosPath); return FALSE; } std::string get_path(DWORD dwPID) { TCHAR szImagePath[MAX_PATH]; TCHAR pszFullPath[MAX_PATH]; HANDLE hProcess; std::string fullPath = "NULL"; if(!pszFullPath) { return fullPath; } pszFullPath[0] = '\0'; hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, 0, dwPID); if(!hProcess) { return fullPath; } if(!GetProcessImageFileName(hProcess,szImagePath,MAX_PATH)) { CloseHandle(hProcess); return fullPath; } if(!dos2nt(szImagePath, pszFullPath)) { CloseHandle(hProcess); return fullPath; } CloseHandle(hProcess); fullPath = pszFullPath; return fullPath; }
|
再写出查找与冻结进程的代码:
为了防止触发双进程保护,我们使用冻结进程代替结束进程。
可以把这里的冻结进程函数用在一个正常的进程上测试冻结进程的效果。
这里有一个简单实用的测试程序。
1 2 3 4 5 6 7
| #include <Windows.h> #include <iostream> int cnt = 0; int main(){ while(1) std::cout << ++cnt << std::endl,Sleep(200); return 0; }
|
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
| inline PROCESSENTRY32 find_process(std::string name) { HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); PROCESSENTRY32 pi, nul; nul.th32ProcessID = 0; if (INVALID_HANDLE_VALUE == hSnapshot) return pi; pi.dwSize = sizeof(PROCESSENTRY32); BOOL bRet = Process32First(hSnapshot, &pi); while (bRet) { if(stricmp(pi.szExeFile, name.c_str()) == 0) return pi; bRet = Process32Next(hSnapshot, &pi); } return nul; } inline int get_pid(std::string name){ return find_process(name).th32ProcessID; } inline void suspend_process(int pid) { THREADENTRY32 th32; th32.dwSize = sizeof(th32); HANDLE hThreadSnap =::CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); if(hThreadSnap == INVALID_HANDLE_VALUE) return; BOOL bRet =::Thread32First(hThreadSnap, &th32); while(bRet) { if(th32.th32OwnerProcessID == pid) { HANDLE oth = OpenThread(THREAD_ALL_ACCESS, FALSE, th32.th32ThreadID); ::SuspendThread(oth); CloseHandle(oth); break; } bRet = ::Thread32Next(hThreadSnap, &th32); } ::CloseHandle(hThreadSnap); }
|
还需要一个函数获取全部的进程列表:
1 2 3 4 5 6 7 8 9 10 11 12 13
| inline std::vector<PROCESSENTRY32> process_list() { std::vector<PROCESSENTRY32> process; HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (INVALID_HANDLE_VALUE == hSnapshot) return process; PROCESSENTRY32 pi; pi.dwSize = sizeof(PROCESSENTRY32); BOOL bRet = Process32First(hSnapshot, &pi); while (bRet) { process.push_back(pi); bRet = Process32Next(hSnapshot, &pi); } return process; }
|
最后简单的写一个暴力主程序即可:
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
| inline void work() { cout << color(color::white) << "[!] F*cking jfglzs..." << endl; int proc = sys::process::get_pid(main_file); if(!proc) { cout << color(color::red) << "[!] ERROR: jfglzs.exe is not running." << endl; color::clear(); return; } string path = sys::process::get_path(proc); path.erase(path.begin()+path.find_last_of('\\'),path.end()); cout << color(color::white) << "[+] jfglzs.exe is in " << path << '.' << endl; cout << color(color::white) << "[!] Traverse process:" << endl; auto vec = sys::process::process_list(); for(auto elm:vec) { cout << color(color::white) << "[-] Scanning process: " << color(color::blue) << elm.szExeFile << " pid=" << elm.th32ProcessID << endl; if(!elm.th32ProcessID) continue; string str = sys::process::get_path(elm.th32ProcessID); if(str.size()&&str.find(path)!=string::npos) { cout << color(color::green) << "[!] Suspend process: " << elm.szExeFile << " pid=" << elm.th32ProcessID << endl; sys::process::suspend_process(elm.th32ProcessID); } } cout << color(color::green) << "[!] Crack complete." << endl; color::clear(); }
|
别忘了解除任务管理器、CMD等的禁用:
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
| inline bool CreateReg(HKEY Root,char*szSubKey,char* ValueName,char* Data) { HKEY key; long Ret=RegCreateKeyEx(Root,szSubKey,0,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&key,NULL); Ret=RegSetValueEx(key,ValueName,0,REG_SZ,(BYTE*)Data,strlen(Data)); if(Ret!=ERROR_SUCCESS) return true; RegCloseKey(key); return false; } inline void regfix() { cout << color(color::white) << "[!] Fixing register..." << endl; char val[32] = {0}; if(CreateReg(HKEY_CURRENT_USER,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System","DisableTaskMgr",val)==ERROR_SUCCESS) cout << color(color::green) << "[+] taskmgr.exe fixed." << endl; else cout << color(color::red) << "[-] Fix taskmgr.exe failed." << endl; if(CreateReg(HKEY_CURRENT_USER,"SOFTWARE\\Policies\\Microsoft\\Windows\\System","DisableCMD",val)==ERROR_SUCCESS) cout << color(color::green) << "[+] cmd.exe fixed." << endl; else cout << color(color::red) << "[-] Fix cmd.exe failed." << endl; if(CreateReg(HKEY_CURRENT_USER,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System","DisableRegistryTools",val)==ERROR_SUCCESS) cout << color(color::green) << "[+] regedit.exe fixed." << endl; else cout << color(color::red) << "[-] Fix regedit.exe failed." << endl; if(CreateReg(HKEY_CURRENT_USER,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\EXPLORER","RESTRICTRUN",val)==ERROR_SUCCESS) cout << color(color::green) << "[+] gpedit.msc fixed." << endl; else cout << color(color::red) << "[-] Fix gpedit.msc failed." << endl; if(CreateReg(HKEY_CURRENT_USER,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\EXPLORER","NoRun",val)==ERROR_SUCCESS) cout << color(color::green) << "[+] \"Run\" fixed." << endl; else cout << color(color::red) << "[-] Fix \"Run\" failed." << endl; color::clear(); }
|

Enjoy!
破解程序下载
蓝奏云 密码:55oe