免责声明:以下内容仅供学习使用
本文的工具成品下载见githubmythwarehelper仓库,附加资源也在内
已完成功能:杀死极域,获取极域安装路径,从注册表破解极域密码,重启极域,挂起极域,恢复极域,解除极域全屏窗口限制
搜索极域进程
极域主进程
极域的进程由StudentMain.exe
启动,因此,只需要使用CreateToolhelp32Snapshot
创建快照,遍历所有进程的所有模块,找到其中可执行文件为StudentMain.exe
那一个进程即可。
以下是代码实现
struct Jiyu {
DWORD id;
char filepath[260];
BOOL flag;
} jiyu;
Jiyu ModuleIsAble(DWORD ProcessPid, LPCSTR Modulename) {
Jiyu tj;
if (Modulename[0] == '\0') {
tj.flag = FALSE;
return tj;
}
MODULEENTRY32 me;
me.dwSize = sizeof(MODULEENTRY32);
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, ProcessPid);
if (Module32First(hSnapshot, &me)) {
do {
//printf("thread - %s\n", me.szModule);
if (!strcmp(Modulename, me.szModule)) {
CloseHandle(hSnapshot);
strcpy(tj.filepath, me.szExePath);
tj.id = ProcessPid;
tj.flag = TRUE;
return tj;
}
} while (Module32Next(hSnapshot, &me));
}
CloseHandle(hSnapshot);
tj.flag = FALSE;
return tj;
}
Jiyu GetProcessPidFromFilename(LPCSTR Filename) {
Jiyu tj;
if (Filename[0] == '\0') {
tj.flag = FALSE;
return tj;
}
PROCESSENTRY32 te;
te.dwSize = sizeof(PROCESSENTRY32);
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (Process32First(hSnapshot, &te)) {
do {
HANDLE temphandle = OpenProcess(PROCESS_ALL_ACCESS, false, te.th32ProcessID);
//printf("%ld\n", te.th32ProcessID);
tj = ModuleIsAble(te.th32ProcessID, Filename);
if (tj.flag == TRUE) {
CloseHandle(hSnapshot);
return tj;
}
CloseHandle(temphandle);
} while (Process32Next(hSnapshot, &te));
}
tj.flag = FALSE;
return tj;
}
极域广播窗口
极域广播窗口是一个窗体,窗体标题固定为“屏幕广播”,因此可以直接使用FindWindow(LPCSTR lpClassName,LPCSTR lpWindowName)
函数来获取进程句柄,在第二个参数处填入窗体名即可
HWND Class = FindWindowW(NULL, L"屏幕广播");//Class为获取到的窗口句柄
if (Class != NULL) {//广播窗口存在
GetWindowThreadProcessId(Class, &pid);//由窗口句柄获取pid
HANDlE ClassHandle = OpenThread(THREAD_ALL_ACCESS, false, GetMainThreadFromId(pid));//由pid获取可操控窗口的句柄
//...
}
else {//广播窗口不存在
//...
}
获取极域安装路径(用来在杀死极域后重启)
极域安装路径存储在系统注册表SOFTWARE\\WOW6432Node\\TopDomain\\e-Learning Class Standard\\1.00\\TargetDirectory
以下为获取函数
UINT GetMythwarePathFromRegedit(char *str) {
HKEY retKey;
char tstr[200] = "SOFTWARE\\WOW6432Node\\TopDomain\\e-Learning Class Standard\\1.00";
DWORD dwDisposition = REG_OPENED_EXISTING_KEY;
LONG ret = RegCreateKeyEx(HKEY_LOCAL_MACHINE, tstr, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ, NULL, &retKey, &dwDisposition);
if (ret != ERROR_SUCCESS) {
//打开注册表失败
return FALSE;
}
BYTE tByte[MAX_PATH * 2 + 1];
DWORD nSize = MAX_PATH * 2 + 1;
int sum = 0;
ret = RegQueryValueEx(retKey, "TargetDirectory", NULL, NULL, tByte, &nSize);
if (ret == ERROR_SUCCESS) {
for (int i = 0; i < int(nSize); i += 1) {
*(str + sum) = tByte[i];
if (*(str + sum++) == '\\') {
*(str + sum++) = '\\';
}
}
//获取极域安装路径成功
return TRUE;
}
//获取极域安装路径失败
return FALSE;
}
杀死极域进程
taskkill
在命令行中输入
taskkill /f /im studentmain.exe
即可杀死极域进程,但有时候会失效
ntsd
ntsd是一个用户态进程调试工具,从Windows 2000就开始被附随在System32目录下。它能够结束除System、smss.exe、csrss.exe、lsass.exe及各种rootkit程序外所有的程序。但在Windows Vista及以上版本的Windows中不含ntsd, 必须手动下载至电脑中才可使用。——百度百科
在命令行中输入
./ntsd.exe -c q -pn studentmain.exe
即可杀死极域进程,目前博主没有遇到失效的情况
如需下载ntsd.exe可访问我的mythwarehelper仓库
挂起和恢复极域进程
再不使用外部DLL的情况下,C++没有原生的挂起和回复进程的函数,因此不能白嫖 挂起进程只能自己实现,进程由线程构成,因此如果挂起了一个进程的每一个线程,就相当于是挂起了这个进程。挂起线程可使用SuspendThread
,恢复线程可使用ResumeThread
以下是代码实现
/*
函数功能:挂起进程中的所有线程
参数1:进程ID
参数2:若为TRUE时对进程中的所有线程调用SuspendThread,挂起线程
若为FALSE时对进程中的所有线程调用ResumeThread,恢复线程
*/
VOID SuspendProcess(DWORD dwProcessID, BOOL fSuspend) {
HANDLE hSnapshot = CreateToolhelp32Snapshot(
TH32CS_SNAPTHREAD, dwProcessID);
if (hSnapshot != INVALID_HANDLE_VALUE) {
THREADENTRY32 te = {sizeof(te)};
BOOL fOk = Thread32First(hSnapshot, &te);
for (; fOk; fOk = Thread32Next(hSnapshot, &te)) {
if (te.th32OwnerProcessID == dwProcessID) {
HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, te.th32ThreadID);
if (hThread != NULL) {
if (fSuspend) {
SuspendThread(hThread);
} else {
ResumeThread(hThread);
}
}
CloseHandle(hThread);
}
}
CloseHandle(hSnapshot);
}
}
解除全屏按钮限制
极域的广播窗口有一个全屏切换按钮,在强制全屏时会设置为无法使用,变成灰色,Windows的按钮即为控件,交互式控件有两个状态,一个是可用,一个是不可用,可以通过调用EnableWindow
函数来设置此类控件的状态,也可以借此设置全屏切换按钮的状态,在老师设置按钮为不可用时,调用此函数设置按钮为可用,就可以自行退出全屏了
以下是代码实现
//这是一个EnumChildWindows函数的回调函数,EnumChildWindows的父窗口句柄为极域的广播窗口句柄
BOOL CALLBACK EnumChildWindowsProc(HWND hwndChild, LPARAM lParam) {
HMENU hmenu = GetMenu(hwndChild);
if (LOWORD(hmenu) == 1004) {//1004为全屏切换按钮的HMENU值
if (!IsWindowEnabled(hwndChild)) {
EnableWindow(hwndChild, TRUE);
} else {
EnableWindow(hwndChild, FALSE);
}
//找到这个按钮就跳出遍历
return FALSE;
}
return TRUE;
}
破解极域密码
极域的密码存储在系统注册表SOFTWARE\\TopDomain\\e-Learning Class\\Student
极域的密码在部分版本中使用明文存储,但新版都是存储的密文
解密代码来源
解密分析视频
以下是破解代码:
BOOL GetMythwarePasswordFromRegedit(char *str) {
HKEY retKey;
BYTE retKeyVal[MAX_PATH * 10] = { 0 };
DWORD nSize = MAX_PATH * 10;
LONG ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\TopDomain\\e-Learning Class\\Student", 0, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &retKey);
if (ret != ERROR_SUCCESS) {
return FALSE;
}
ret = RegQueryValueExA(retKey, "knock1", NULL, NULL, (LPBYTE)retKeyVal, &nSize);
RegCloseKey(retKey);
if (ret != ERROR_SUCCESS) {
return FALSE;
}
for (int i = 0; i < int(nSize); i += 4) {
retKeyVal[i + 0] = (retKeyVal[i + 0] ^ 0x50 ^ 0x45);
retKeyVal[i + 1] = (retKeyVal[i + 1] ^ 0x43 ^ 0x4c);
retKeyVal[i + 2] = (retKeyVal[i + 2] ^ 0x4c ^ 0x43);
retKeyVal[i + 3] = (retKeyVal[i + 3] ^ 0x45 ^ 0x50);
}
for (int i = 0; i < int(nSize); i += 1) {
printf("%x ", retKeyVal[i]);
if (i % 8 == 0) puts("");
}
int sum = 0;
for (int i = 0; i < int(nSize); i += 1) {
if (retKeyVal[i + 1] == 0) {
*(str + sum) = retKeyVal[i];
sum++;
if (retKeyVal[i] == 0) break;
}
}
return TRUE;
}