1444 字
7 分钟
局域网聊天室管理控制台
局域网聊天室客户端
-std=c++11//局域网聊天室控制台 - v1.1#include <iostream>#include <string>#include <vector>#include <chrono>#include <sstream>#include <iomanip>#include <regex>#include <winsock2.h>#include <windows.h>#define BCRYPT_ECDSA_P256_ALGORITHM L"ECDSA_P256"using namespace std;
// ----------公钥----------const string ADMIN_PUB_KEY = "d27605efb07c8a1e79c41c85e48172b4ece6579ff810eb775606a294763aeb4c9ef8aa24b9c504005c8b959ceaa13b099a100fe4ecf45d15705821b83913f37e";string admin_priv_key = ""; // 用户输入的私钥标量d// ----------公钥----------
// ======= BCrypt (CNG) 动态加载相关的类型定义 =======typedef PVOID BCRYPT_ALG_HANDLE;typedef PVOID BCRYPT_KEY_HANDLE;typedef PVOID BCRYPT_HASH_HANDLE;#ifndef NTSTATUStypedef LONG NTSTATUS;#endif
typedef int(WSAAPI *P_WS)(WORD, LPWSADATA); typedef int(WSAAPI *P_WC)(void); typedef SOCKET(WSAAPI *P_SK)(int, int, int);typedef int(WSAAPI *P_CS)(SOCKET); typedef int(WSAAPI *P_SD)(SOCKET, const char*, int, int);typedef int(WSAAPI *P_ST)(SOCKET, const char*, int, int, const struct sockaddr*, int);typedef int(WSAAPI *P_RF)(SOCKET, char*, int, int, struct sockaddr*, int*);typedef int(WSAAPI *P_SO)(SOCKET, int, int, const char*, int); typedef u_short(WSAAPI *P_HS)(u_short);typedef unsigned long(WSAAPI *P_IA)(const char*); typedef char*(WSAAPI *P_IN)(struct in_addr);
typedef NTSTATUS(WINAPI *P_BCryptOpenAlgorithmProvider)(BCRYPT_ALG_HANDLE*, LPCWSTR, LPCWSTR, ULONG);typedef NTSTATUS(WINAPI *P_BCryptCloseAlgorithmProvider)(BCRYPT_ALG_HANDLE, ULONG);typedef NTSTATUS(WINAPI *P_BCryptImportKeyPair)(BCRYPT_ALG_HANDLE, BCRYPT_KEY_HANDLE, LPCWSTR, BCRYPT_KEY_HANDLE*, PUCHAR, ULONG, ULONG);typedef NTSTATUS(WINAPI *P_BCryptCreateHash)(BCRYPT_ALG_HANDLE, BCRYPT_HASH_HANDLE*, PUCHAR, ULONG, PUCHAR, ULONG, ULONG);typedef NTSTATUS(WINAPI *P_BCryptHashData)(BCRYPT_HASH_HANDLE, PUCHAR, ULONG, ULONG);typedef NTSTATUS(WINAPI *P_BCryptFinishHash)(BCRYPT_HASH_HANDLE, PUCHAR, ULONG, ULONG);typedef NTSTATUS(WINAPI *P_BCryptDestroyHash)(BCRYPT_HASH_HANDLE);typedef NTSTATUS(WINAPI *P_BCryptSignHash)(BCRYPT_KEY_HANDLE, VOID*, PUCHAR, ULONG, PUCHAR, ULONG, ULONG*, ULONG);typedef NTSTATUS(WINAPI *P_BCryptDestroyKey)(BCRYPT_KEY_HANDLE);
struct API_HUB { HMODULE hS; P_WS ws; P_WC wc; P_SK sk; P_CS cs; P_ST st; P_RF rf; P_SO so; P_HS hs; P_IA ia; P_IN in; HMODULE hBcrypt; P_BCryptOpenAlgorithmProvider bOpenAlg; P_BCryptCloseAlgorithmProvider bCloseAlg; P_BCryptImportKeyPair bImportKey; P_BCryptCreateHash bCreateHash; P_BCryptHashData bHashData; P_BCryptFinishHash bFinishHash; P_BCryptDestroyHash bDestroyHash; P_BCryptSignHash bSignHash; P_BCryptDestroyKey bDestroyKey;
void init() { hS = LoadLibraryA("ws2_32.dll"); ws = (P_WS)GetProcAddress(hS, "WSAStartup"); wc = (P_WC)GetProcAddress(hS, "WSACleanup"); sk = (P_SK)GetProcAddress(hS, "socket"); cs = (P_CS)GetProcAddress(hS, "closesocket"); st = (P_ST)GetProcAddress(hS, "sendto"); rf = (P_RF)GetProcAddress(hS, "recvfrom"); so = (P_SO)GetProcAddress(hS, "setsockopt"); hs = (P_HS)GetProcAddress(hS, "htons"); ia = (P_IA)GetProcAddress(hS, "inet_addr"); in = (P_IN)GetProcAddress(hS, "inet_ntoa");
hBcrypt = LoadLibraryA("bcrypt.dll"); if (hBcrypt) { bOpenAlg = (P_BCryptOpenAlgorithmProvider)GetProcAddress(hBcrypt, "BCryptOpenAlgorithmProvider"); bCloseAlg = (P_BCryptCloseAlgorithmProvider)GetProcAddress(hBcrypt, "BCryptCloseAlgorithmProvider"); bImportKey = (P_BCryptImportKeyPair)GetProcAddress(hBcrypt, "BCryptImportKeyPair"); bCreateHash = (P_BCryptCreateHash)GetProcAddress(hBcrypt, "BCryptCreateHash"); bHashData = (P_BCryptHashData)GetProcAddress(hBcrypt, "BCryptHashData"); bFinishHash = (P_BCryptFinishHash)GetProcAddress(hBcrypt, "BCryptFinishHash"); bDestroyHash = (P_BCryptDestroyHash)GetProcAddress(hBcrypt, "BCryptDestroyHash"); bSignHash = (P_BCryptSignHash)GetProcAddress(hBcrypt, "BCryptSignHash"); bDestroyKey = (P_BCryptDestroyKey)GetProcAddress(hBcrypt, "BCryptDestroyKey"); } }} API;
SOCKET udp_socket = INVALID_SOCKET;sockaddr_in broadcast_addr;
long long wall_now_ms() { return std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::system_clock::now().time_since_epoch() ).count();}
vector<BYTE> hex2bytes(const string& hex) { vector<BYTE> bytes; for (size_t i = 0; i < hex.length(); i += 2) { bytes.push_back((BYTE)strtol(hex.substr(i, 2).c_str(), NULL, 16)); } return bytes;}
string bytes2hex(const vector<BYTE>& bytes) { stringstream ss; ss << hex << setfill('0'); for (auto b : bytes) ss << setw(2) << (int)b; return ss.str();}
bool is_valid_ip(const string& ip) { regex ip_regex("^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"); return regex_match(ip, ip_regex);}
string trim(const string& s) { size_t start = s.find_first_not_of(" \t\r\n"); if (start == string::npos) return ""; return s.substr(start, s.find_last_not_of(" \t\r\n") - start + 1);}
// 基于 ECDSA P-256 对消息进行签名string sign_message(const string& msg) { if (admin_priv_key.length() != 64) return "";
vector<BYTE> pub_bytes = hex2bytes(ADMIN_PUB_KEY); vector<BYTE> priv_bytes = hex2bytes(admin_priv_key);
if (pub_bytes.size() != 64 || priv_bytes.size() != 32) return "";
#pragma pack(push, 1) struct { ULONG dwMagic; // BCRYPT_ECDSA_PRIVATE_P256_MAGIC (0x32534345) ULONG cbKey; BYTE X[32]; BYTE Y[32]; BYTE d[32]; } eccBlob; #pragma pack(pop)
eccBlob.dwMagic = 0x32534345; // "ESC2" eccBlob.cbKey = 32; memcpy(eccBlob.X, pub_bytes.data(), 32); memcpy(eccBlob.Y, pub_bytes.data() + 32, 32); memcpy(eccBlob.d, priv_bytes.data(), 32);
BCRYPT_ALG_HANDLE hSignAlg = NULL, hHashAlg = NULL; BCRYPT_KEY_HANDLE hKey = NULL; BCRYPT_HASH_HANDLE hHash = NULL; string signature_hex = ""; NTSTATUS status;
do { // 使用更具体的算法名称 status = API.bOpenAlg(&hSignAlg, BCRYPT_ECDSA_P256_ALGORITHM, NULL, 0); if (status != 0) break;
status = API.bImportKey(hSignAlg, NULL, L"ECCPRIVATEBLOB", &hKey, (PUCHAR)&eccBlob, sizeof(eccBlob), 0); if (status != 0) { cout << "\n[错误] 私钥导入失败(这里报错通常是因为公钥和输入的私钥不匹配), Status: 0x" << hex << status << dec << endl; break; }
status = API.bOpenAlg(&hHashAlg, L"SHA256", NULL, 0); if (status != 0) break;
status = API.bCreateHash(hHashAlg, &hHash, NULL, 0, NULL, 0, 0); if (status != 0) break;
status = API.bHashData(hHash, (PUCHAR)msg.data(), (ULONG)msg.size(), 0); if (status != 0) break;
BYTE hashResult[32]; status = API.bFinishHash(hHash, hashResult, sizeof(hashResult), 0); if (status != 0) break;
ULONG cbSig = 0; status = API.bSignHash(hKey, NULL, hashResult, sizeof(hashResult), NULL, 0, &cbSig, 0); if (status != 0) break;
vector<BYTE> sig(cbSig); status = API.bSignHash(hKey, NULL, hashResult, sizeof(hashResult), sig.data(), cbSig, &cbSig, 0); if (status == 0) { signature_hex = bytes2hex(sig); } } while (false);
if (hHash) API.bDestroyHash(hHash); if (hKey) API.bDestroyKey(hKey); if (hHashAlg) API.bCloseAlg(hHashAlg, 0); if (hSignAlg) API.bCloseAlg(hSignAlg, 0);
return signature_hex;}
void send_admin_command(const string& body) { long long ts = wall_now_ms(); string data_to_verify = to_string(ts) + "\n" + body; string sig = sign_message(data_to_verify);
if (sig.empty()) { cout << "[错误] 签名失败,私钥可能无效或系统不支持。" << endl; return; }
string packet = "LANCHAT1\nTYPE=ADMIN_CMD\nTS=" + to_string(ts) + "\nSIG=" + sig + "\n\n" + body; API.st(udp_socket, packet.c_str(), (int)packet.size(), 0, (struct sockaddr*)&broadcast_addr, sizeof(broadcast_addr));}
void handle_list_command() { send_admin_command("list");
cout << "=> 已发送探测广播,正在监听响应 (2秒)..." << endl;
// 设置非阻塞接收超时 2秒 int timeout = 2000; API.so(udp_socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
long long start = wall_now_ms(); int count = 0;
while (wall_now_ms() - start < 2000) { char buf[2048]; sockaddr_in from; int flen = sizeof(from); int r_len = API.rf(udp_socket, buf, sizeof(buf), 0, (sockaddr*)&from, &flen);
if (r_len > 0) { string raw(buf, r_len); if (raw.find("TYPE=ADMIN_REP") != string::npos && raw.find("ONLINE") != string::npos) { cout << " [+] 发现存活节点 IP: " << API.in(from.sin_addr) << endl; count++; } } } cout << "=> 扫描完毕,共响应 " << count << " 个存活节点。" << endl;}
void print_help() { cout << "================== 支持的命令 ==================\n"; cout << " list - 扫描局域网内所有在线用户\n"; cout << " remove <ip> - 强制踢出指定IP的用户\n"; cout << " blacklist <ip> - 将指定IP加入黑名单并踢出\n"; cout << " whitelist <ip> - 将指定IP移出黑名单\n"; cout << " help - 查看此帮助信息\n"; cout << " exit - 退出程序\n"; cout << "================================================\n";}
int main() { system("chcp 936 > nul"); API.init(); WSADATA w; API.ws(MAKEWORD(2, 2), &w);
udp_socket = API.sk(AF_INET, SOCK_DGRAM, IPPROTO_UDP); int opt = 1; API.so(udp_socket, SOL_SOCKET, SO_BROADCAST, (char*)&opt, sizeof(opt));
memset(&broadcast_addr, 0, sizeof(broadcast_addr)); broadcast_addr.sin_family = AF_INET; broadcast_addr.sin_port = API.hs(8888); broadcast_addr.sin_addr.s_addr = API.ia("255.255.255.255");
cout << "=================================================\n"; cout << " 局域网聊天室 - 管理控制台 (v1.0) \n"; cout << "=================================================\n\n";
// 验证私钥 while (1) { cout << "请输入验证令牌: "; string input_key; getline(cin, input_key); input_key = trim(input_key);
if (input_key.length() == 64 && input_key.find_first_not_of("0123456789abcdefABCDEF") == string::npos) { admin_priv_key = input_key; cout << "[成功] 密钥格式有效!即将进入控制台...\n"; system("pause"); break; } else { cout << "[错误] 无效的私钥格式!"; system("cls"); } } system("cls"); // 交互式命令主循环 while (1) { cout << "> "; string cmd; getline(cin, cmd); cmd = trim(cmd); if (cmd.empty()) continue;
if (cmd == "exit") { break; } else if (cmd == "help") { print_help(); } else if (cmd == "list") { handle_list_command(); } else if (cmd.find("remove ") == 0) { string ip = trim(cmd.substr(7)); if (is_valid_ip(ip)) { send_admin_command("remove " + ip); cout << "=> 已下发踢出指令给 IP: " << ip << endl; } else { cout << "[错误] 无效的IP地址格式!" << endl; } } else if (cmd.find("blacklist ") == 0) { string ip = trim(cmd.substr(10)); if (is_valid_ip(ip)) { send_admin_command("blacklist " + ip); cout << "=> 已下发拉黑指令给 IP: " << ip << endl; } else { cout << "[错误] 无效的IP地址格式!" << endl; } } else if (cmd.find("whitelist ") == 0) { string ip = trim(cmd.substr(10)); if (is_valid_ip(ip)) { send_admin_command("whitelist " + ip); cout << "=> 已下发解除黑名单指令给 IP: " << ip << endl; } else { cout << "[错误] 无效的IP地址格式!" << endl; } } else { cout << "[错误] 未知命令!输入 'help' 查看支持的指令。" << endl; } }API.cs(udp_socket);API.wc(); return 0;}