DisableThreadLibraryCalls

本文详细介绍了 DisableThreadLibraryCalls 函数的功能与用法,包括如何禁用特定 DLL 的 DLL_THREAD_ATTACH 和 DLL_THREAD_DETACH 通知,以减少某些程序的工作集大小。文章还列举了该函数的参数、返回值及注意事项。

1、函数原型

BOOL WINAPI DisableThreadLibraryCalls(

  __in          HMODULE hModule

);

功能:

       禁用指定的DLL的DLL_THREAD_ATTACH和DLL_THREAD_DETACH通知,这样可以减小某些程序的工作集大小。

 

参数:

         HMODULE hModule,将要被禁用DLL_THREAD_ATTACH和DLL_THREAD_DETACH通知的dll的模块句柄。

 

返回值:

        成功返回非零值;失败则返回零值。

 

注意事项:

        1)当dll使用静态C运行时库进行链接(CRT,C run-time library ).时,不要使用该函数,因为此时dll需要DLL_THREAD_ATTACH 和DLL_THREAD_DETATCH通知才能发挥正常作用。

        2)Header   Declared in Winbase.h; include Windows.h.

        3)Library     Use Kernel32.lib.

        4)DLL     Requires Kernel32.dll.



该函数在有许多DLL,频繁创建和删除线程,并且DLL不需要线程级消息如DLL_THREAD_ATTACH and DLL_THREAD_DETACH时的多线程应用中是很有效的优化。
#define WIN32_LEAN_AND_MEAN #define _WINSOCK_DEPRECATED_NO_WARNINGS #include <winsock2.h> #include <windows.h> #include <iostream> #include <iomanip> #include <sstream> #include <string> #include <fstream> #include <unordered_map> #include <algorithm> #include <cstring> #include <atomic> #include <thread> #include <chrono> #include <vector> #include <queue> #include <mutex> #include <condition_variable> #pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "mswsock.lib") // 用于AcceptEx等异步操作 using namespace std; // 常量定义 constexpr DWORD CLIENT_SUB_ADDRESS = 0xAED9F0; constexpr DWORD CRAG_CONNECTION_INSTANCE_R_ADDRESS = 0xAEDE00; constexpr DWORD RECV_PTR_ADDRESS = 0x1424E18; constexpr int RING_BUFFER_SIZE = 64 * 1024; // 64KB环形缓冲区 constexpr int PACKET_POOL_SIZE = 1024; // 预分配1024个封包对象 constexpr int MAX_PACKET_SIZE = 8192; // 最大封包大小8KB constexpr DWORD TIMEOUT = 600000; // 10分钟超时 constexpr DWORD RECONNECT_INTERVAL = 3000; // 3秒重连间隔 constexpr DWORD PING_INTERVAL = 5000; // 5秒Ping间隔 constexpr DWORD SLEEP_TIME = 5; // 5ms休眠 constexpr DWORD HOOK_DELAY = 3000; // 3秒延迟应用Hook constexpr int WORKER_THREAD_COUNT = 4; // 工作线程数量 constexpr int MAX_ASYNC_OPS = 100; // 最大异步操作数量 enum e_PacketType { RECEIVED = 0, SENDED = 1 }; // 原子类型定义 using atomic_socket = atomic<SOCKET>; using atomic_bool = atomic<bool>; using atomic_dword = atomic<DWORD>; // 前向声明 typedef int(__thiscall* SendToClientFunc)(void* CragConnection, size_t size, char* buffer); typedef void* (__stdcall* originalInstanceR)(void); // 异步操作上下文 struct AsyncOperationContext { OVERLAPPED overlapped; SOCKET socket; WSABUF wsaBuf; char buffer[MAX_PACKET_SIZE]; DWORD bytesTransferred; DWORD flags; atomic_bool inUse; AsyncOperationContext() : socket(INVALID_SOCKET), bytesTransferred(0), flags(0) { ZeroMemory(&overlapped, sizeof(OVERLAPPED)); ZeroMemory(buffer, MAX_PACKET_SIZE); inUse.store(false, memory_order_relaxed); } void reset() { ZeroMemory(&overlapped, sizeof(OVERLAPPED)); bytesTransferred = 0; flags = 0; inUse.store(false, memory_order_relaxed); } }; // 线程安全的队列 template<typename T> class ThreadSafeQueue { private: queue<T> queue_; mutable mutex mutex_; condition_variable cond_; public: void push(T value) { lock_guard<mutex> lock(mutex_); queue_.push(move(value)); cond_.notify_one(); } bool try_pop(T& value) { lock_guard<mutex> lock(mutex_); if (queue_.empty()) { return false; } value = move(queue_.front()); queue_.pop(); return true; } bool empty() const { lock_guard<mutex> lock(mutex_); return queue_.empty(); } size_t size() const { lock_guard<mutex> lock(mutex_); return queue_.size(); } }; // 极简环形缓冲区 class SimpleRingBuffer { private: char* buffer; atomic<uint32_t> read_pos; atomic<uint32_t> write_pos; uint32_t size_mask; public: SimpleRingBuffer(uint32_t size) { // 确保大小为2的幂 uint32_t actual_size = 1; while (actual_size < size) actual_size <<= 1; buffer = new char[actual_size]; size_mask = actual_size - 1; read_pos.store(0, memory_order_relaxed); write_pos.store(0, memory_order_relaxed); } ~SimpleRingBuffer() { delete[] buffer; } uint32_t available_read() const { return write_pos.load(memory_order_acquire) - read_pos.load(memory_order_acquire); } uint32_t available_write() const { return size_mask + 1 - (write_pos.load(memory_order_acquire) - read_pos.load(memory_order_acquire)); } bool push(const char* data, uint32_t len) { uint32_t wp = write_pos.load(memory_order_acquire); uint32_t rp = read_pos.load(memory_order_acquire); uint32_t available = size_mask + 1 - (wp - rp); if (available < len) return false; uint32_t index = wp & size_mask; uint32_t first_chunk = min(len, size_mask + 1 - index); memcpy(buffer + index, data, first_chunk); if (first_chunk < len) { memcpy(buffer, data + first_chunk, len - first_chunk); } write_pos.store(wp + len, memory_order_release); return true; } uint32_t pop(char* dest, uint32_t len) { uint32_t rp = read_pos.load(memory_order_acquire); uint32_t wp = write_pos.load(memory_order_acquire); uint32_t available = wp - rp; if (available == 0) return 0; uint32_t to_read = min(len, available); uint32_t index = rp & size_mask; uint32_t first_chunk = min(to_read, size_mask + 1 - index); memcpy(dest, buffer + index, first_chunk); if (first_chunk < to_read) { memcpy(dest + first_chunk, buffer, to_read - first_chunk); } read_pos.store(rp + to_read, memory_order_release); return to_read; } void clear() { read_pos.store(0, memory_order_relaxed); write_pos.store(0, memory_order_relaxed); } }; // 极简内存池 class SimplePacketPool { private: struct PacketNode { char data[MAX_PACKET_SIZE]; uint16_t size; atomic<PacketNode*> next; }; PacketNode* nodes; atomic<PacketNode*> free_head; public: SimplePacketPool(size_t count) { nodes = new PacketNode[count]; // 构建链表 for (size_t i = 0; i < count - 1; ++i) { nodes[i].next.store(&nodes[i + 1], memory_order_relaxed); } nodes[count - 1].next.store(nullptr, memory_order_relaxed); free_head.store(nodes, memory_order_relaxed); } ~SimplePacketPool() { delete[] nodes; } PacketNode* acquire() { PacketNode* current_head = free_head.load(memory_order_acquire); while (current_head) { if (free_head.compare_exchange_weak(current_head, current_head->next.load(memory_order_acquire), memory_order_acq_rel, memory_order_acquire)) { return current_head; } } return nullptr; } void release(PacketNode* node) { if (!node) return; PacketNode* current_head = free_head.load(memory_order_acquire); node->next.store(current_head, memory_order_relaxed); while (!free_head.compare_exchange_weak(current_head, node, memory_order_acq_rel, memory_order_acquire)) { node->next.store(current_head, memory_order_relaxed); } } }; // 全局变量 atomic_socket koreClient(INVALID_SOCKET); atomic_socket roServer(INVALID_SOCKET); atomic_bool koreClientIsAlive(false); atomic_bool keepMainThread(true); atomic_bool imalive(false); atomic_bool hook_applied(false); atomic_bool hook_delayed(false); SimpleRingBuffer sendBuffer(RING_BUFFER_SIZE); SimplePacketPool packetPool(PACKET_POOL_SIZE); string koreServerIP; DWORD koreServerPort; bool allowMultiClient = false; // Hook相关 typedef int (WINAPI* recv_func_t)(SOCKET s, char* buf, int len, int flags); recv_func_t original_recv = nullptr; // 异步I/O相关 HANDLE iocpHandle = NULL; vector<AsyncOperationContext*> asyncContexts; ThreadSafeQueue<AsyncOperationContext*> freeContexts; mutex contextMutex; // 工作线程池 vector<thread> workerThreads; atomic_bool workersRunning(false); // 函数声明 void AllocateConsole(); void debug(const char* msg); bool CreateDefaultConfig(const std::string& filename); bool LoadConfig(const std::string& filename); bool ApplyHook(); void RemoveHook(); bool isConnected(SOCKET s); SOCKET createSocket(const std::string& ip, int port); DWORD GetUserPort(); void init(); void finish(); // 异步I/O函数声明 bool InitializeAsyncIO(); void CleanupAsyncIO(); AsyncOperationContext* GetAsyncContext(); void ReturnAsyncContext(AsyncOperationContext* context); bool PostAsyncRecv(SOCKET socket); void WorkerThreadProc(); bool InitializeWorkerThreads(); void CleanupWorkerThreads(); // 优化函数声明 SOCKET createOptimizedSocket(const std::string& ip, int port); void optimizedSendToKore(const char* data, uint16_t len, e_PacketType type); DWORD WINAPI highPerformancePacketProcessor(LPVOID lpParam); DWORD WINAPI koreConnectionMainOptimized(LPVOID lpParam); bool ApplyHookOptimized(); void initOptimized(); void finishOptimized(); void DelayedHookApplication(); // IOCP优化器 class IOCPOptimizer { private: HANDLE iocp_handle; public: IOCPOptimizer() : iocp_handle(NULL) {} bool initialize() { iocp_handle = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); return iocp_handle != NULL; } bool associateSocket(SOCKET socket) { return CreateIoCompletionPort((HANDLE)socket, iocp_handle, 0, 0) != NULL; } HANDLE getHandle() { return iocp_handle; } ~IOCPOptimizer() { if (iocp_handle) { CloseHandle(iocp_handle); } } }; IOCPOptimizer iocp_optimizer; // 异步I/O初始化 bool InitializeAsyncIO() { // 创建IOCP句柄 iocpHandle = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, WORKER_THREAD_COUNT); if (iocpHandle == NULL) { cout << "[错误] 创建IOCP句柄失败: " << GetLastError() << endl; return false; } // 预分配异步操作上下文 for (int i = 0; i < MAX_ASYNC_OPS; ++i) { AsyncOperationContext* context = new AsyncOperationContext(); asyncContexts.push_back(context); freeContexts.push(context); } cout << "[成功] 异步I/O初始化完成,预分配 " << MAX_ASYNC_OPS << " 个上下文" << endl; return true; } // 清理异步I/O资源 void CleanupAsyncIO() { if (iocpHandle) { CloseHandle(iocpHandle); iocpHandle = NULL; } // 清理异步上下文 for (auto context : asyncContexts) { delete context; } asyncContexts.clear(); // 清空空闲队列 while (!freeContexts.empty()) { AsyncOperationContext* context = nullptr; freeContexts.try_pop(context); } } // 获取异步操作上下文 AsyncOperationContext* GetAsyncContext() { AsyncOperationContext* context = nullptr; if (freeContexts.try_pop(context)) { context->inUse.store(true, memory_order_relaxed); return context; } // 如果没有空闲上下文,动态创建一个(应该很少发生) lock_guard<mutex> lock(contextMutex); context = new AsyncOperationContext(); context->inUse.store(true, memory_order_relaxed); asyncContexts.push_back(context); cout << "[警告] 动态创建异步上下文,当前总数: " << asyncContexts.size() << endl; return context; } // 归还异步操作上下文 void ReturnAsyncContext(AsyncOperationContext* context) { if (context) { context->reset(); freeContexts.push(context); } } // 提交异步接收操作 bool PostAsyncRecv(SOCKET socket) { AsyncOperationContext* context = GetAsyncContext(); if (!context) { cout << "[错误] 无法获取异步上下文" << endl; return false; } context->socket = socket; context->wsaBuf.buf = context->buffer; context->wsaBuf.len = MAX_PACKET_SIZE; context->bytesTransferred = 0; context->flags = 0; DWORD bytesReceived = 0; // 使用WSARecv进行异步接收 int result = WSARecv(socket, &context->wsaBuf, 1, &bytesReceived, &context->flags, &context->overlapped, NULL); if (result == SOCKET_ERROR) { int error = WSAGetLastError(); if (error != WSA_IO_PENDING) { cout << "[错误] WSARecv失败: " << error << endl; ReturnAsyncContext(context); return false; } } return true; } // 工作线程处理函数 void WorkerThreadProc() { while (workersRunning.load(memory_order_acquire)) { DWORD bytesTransferred = 0; ULONG_PTR completionKey = 0; LPOVERLAPPED overlapped = nullptr; // 等待IOCP完成事件 BOOL success = GetQueuedCompletionStatus(iocpHandle, &bytesTransferred, &completionKey, &overlapped, INFINITE); if (!workersRunning.load(memory_order_acquire)) { break; } if (!overlapped) { // 收到退出信号 continue; } // 获取异步上下文 AsyncOperationContext* context = CONTAINING_RECORD(overlapped, AsyncOperationContext, overlapped); if (!success) { DWORD error = GetLastError(); if (error != WAIT_TIMEOUT) { cout << "[错误] IOCP操作失败: " << error << endl; // 处理连接断开 if (context->socket == koreClient.load(memory_order_acquire)) { koreClient.store(INVALID_SOCKET, memory_order_release); koreClientIsAlive.store(false, memory_order_release); } } ReturnAsyncContext(context); continue; } // 处理接收到的数据 if (bytesTransferred > 0) { // 处理数据包逻辑 char* data = context->buffer; int remaining = bytesTransferred; while (remaining >= 3) { char packet_type = data[0]; uint16_t packet_len = *reinterpret_cast<uint16_t*>(data + 1); if (remaining < 3 + packet_len) break; if (packet_type == 'S' && packet_len > 0) { // 发送到RO客户端 auto* sendFunc = reinterpret_cast<SendToClientFunc>(CLIENT_SUB_ADDRESS); auto* instanceR = reinterpret_cast<originalInstanceR>(CRAG_CONNECTION_INSTANCE_R_ADDRESS); if (sendFunc && instanceR) { void* instance = instanceR(); if (instance) { sendFunc(instance, packet_len, data + 3); } } } int packet_total_size = 3 + packet_len; data += packet_total_size; remaining -= packet_total_size; } // 继续提交异步接收 if (context->socket != INVALID_SOCKET) { PostAsyncRecv(context->socket); } } else { // 连接关闭 if (context->socket == koreClient.load(memory_order_acquire)) { koreClient.store(INVALID_SOCKET, memory_order_release); koreClientIsAlive.store(false, memory_order_release); } ReturnAsyncContext(context); } } } // 初始化工作线程池 bool InitializeWorkerThreads() { workersRunning.store(true, memory_order_release); for (int i = 0; i < WORKER_THREAD_COUNT; ++i) { workerThreads.emplace_back(WorkerThreadProc); } cout << "[成功] 启动 " << WORKER_THREAD_COUNT << " 个工作线程" << endl; return true; } // 清理工作线程池 void CleanupWorkerThreads() { workersRunning.store(false, memory_order_release); // 向所有线程发送退出信号 for (size_t i = 0; i < workerThreads.size(); ++i) { PostQueuedCompletionStatus(iocpHandle, 0, 0, NULL); } // 等待线程退出 for (auto& thread : workerThreads) { if (thread.joinable()) { thread.join(); } } workerThreads.clear(); cout << "[信息] 工作线程池已清理" << endl; } // 优化的recv钩子函数 int WINAPI hooked_recv(SOCKET s, char* buf, int len, int flags) { int result = original_recv(s, buf, len, flags); if (result > 0) { roServer.store(s, memory_order_release); // 使用内存池避免动态分配 auto packet_node = packetPool.acquire(); if (packet_node) { packet_node->size = static_cast<uint16_t>(result); memcpy(packet_node->data, buf, result); // 构建发送数据 char send_buf[3 + MAX_PACKET_SIZE]; send_buf[0] = 'R'; *reinterpret_cast<uint16_t*>(send_buf + 1) = packet_node->size; memcpy(send_buf + 3, packet_node->data, packet_node->size); // 非阻塞写入环形缓冲区 if (!sendBuffer.push(send_buf, 3 + packet_node->size)) { // 缓冲区满,直接发送到RO服务器(降级处理) SOCKET ro_sock = roServer.load(memory_order_acquire); if (ro_sock != INVALID_SOCKET) { send(ro_sock, buf, result, 0); } } packetPool.release(packet_node); } } return result; } // 控制台分配 void AllocateConsole() { AllocConsole(); freopen_s((FILE**)stdout, "CONOUT$", "w", stdout); freopen_s((FILE**)stderr, "CONOUT$", "w", stderr); freopen_s((FILE**)stdin, "CONIN$", "r", stdin); #ifdef UNICODE SetConsoleTitle(L"xKore优化版 - 调试控制台"); #else SetConsoleTitle("xKore优化版 - 调试控制台"); #endif } // 调试输出 void debug(const char* msg) { cout << "[调试] " << msg << endl; } // 创建默认配置 bool CreateDefaultConfig(const std::string& filename) { ofstream fout(filename); if (!fout.is_open()) { cout << "[错误] 无法创建配置文件: " << filename << endl; return false; } fout << "# xKore服务器配置\n"; fout << "koreServerIP=127.0.0.1\n"; fout << "koreServerPort=2350\n"; fout << "\n"; fout << "# 多客户端配置\n"; fout << "# 如果为true, 每次执行时在终端询问端口\n"; fout << "# 如果为false, 总是使用koreServerPort的默认端口\n"; fout << "allowMultiClient=true"; fout.close(); cout << "[成功] 默认配置文件已创建: " << filename << endl; return true; } // 加载配置 bool LoadConfig(const std::string& filename) { ifstream fin(filename); if (!fin.is_open()) { if (!CreateDefaultConfig(filename)) { return false; } cout << "\n*** 注意: 使用前请配置 '" << filename << "' 文件! ***" << endl; cout << "========================\n" << endl; fin.open(filename); if (!fin.is_open()) { cout << "[错误] 无法打开创建的配置文件: " << filename << endl; return false; } } string line; unordered_map<string, string> mapa; while (getline(fin, line)) { if (line.empty()) continue; if (line[0] == '#' || line[0] == ';') continue; size_t pos = line.find('='); if (pos == string::npos) continue; string chave = line.substr(0, pos); string valor = line.substr(pos + 1); while (!chave.empty() && isspace(chave.back())) chave.pop_back(); while (!valor.empty() && isspace(valor.front())) valor.erase(0, 1); while (!valor.empty() && isspace(valor.back())) valor.pop_back(); mapa[chave] = valor; } fin.close(); if (mapa.count("koreServerIP") == 0 || mapa.count("koreServerPort") == 0) { cout << "[错误] config_recv.txt中缺少必要的键。需要:\n" << " koreServerIP\n" << " koreServerPort\n"; return false; } try { koreServerIP = mapa.at("koreServerIP"); koreServerPort = static_cast<DWORD>(stoul(mapa.at("koreServerPort"), nullptr, 10)); if (mapa.count("allowMultiClient") > 0) { string allowMultiStr = mapa.at("allowMultiClient"); transform(allowMultiStr.begin(), allowMultiStr.end(), allowMultiStr.begin(), ::tolower); allowMultiClient = (allowMultiStr == "true" || allowMultiStr == "1" || allowMultiStr == "yes"); } } catch (exception& e) { cout << "[错误] 转换值时出现异常: " << e.what() << endl; return false; } cout << "[信息] 配置加载成功:\n\n" << " koreServerIP = " << koreServerIP << "\n" << " koreServerPort = " << koreServerPort << "\n" << " allowMultiClient = " << (allowMultiClient ? "true" : "false") << endl; return true; } // 应用Hook(优化版) bool ApplyHookOptimized() { if (original_recv != nullptr) { return true; // 已经hook } recv_func_t* recv_ptr = reinterpret_cast<recv_func_t*>(RECV_PTR_ADDRESS); original_recv = *recv_ptr; if (original_recv == nullptr) { cout << "错误: 原始recv指针为空!" << endl; return false; } *recv_ptr = hooked_recv; // 验证hook是否成功 if (*recv_ptr == hooked_recv) { hook_applied.store(true, memory_order_release); cout << "Hook应用成功!" << endl; return true; } return false; } // 延迟应用Hook函数 void DelayedHookApplication() { cout << "[信息] 等待3秒后应用Hook(避免强壳和NP检测)..." << endl; // 等待3秒 this_thread::sleep_for(chrono::milliseconds(HOOK_DELAY)); cout << "[信息] 开始应用Hook..." << endl; if (ApplyHookOptimized()) { cout << "[成功] 延迟Hook应用成功" << endl; hook_delayed.store(true, memory_order_release); } else { cout << "[错误] 延迟Hook应用失败" << endl; } } // 移除Hook void RemoveHook() { if (original_recv) { recv_func_t* recv_ptr = reinterpret_cast<recv_func_t*>(RECV_PTR_ADDRESS); *recv_ptr = original_recv; cout << "Hook已移除!" << endl; } } // 检查socket连接状态 bool isConnected(SOCKET s) { if (s == INVALID_SOCKET) return false; fd_set readfds; FD_ZERO(&readfds); FD_SET(s, &readfds); timeval timeout = { 0, 0 }; int result = select(0, &readfds, NULL, NULL, &timeout); if (result == SOCKET_ERROR) return false; return true; } // 创建优化socket SOCKET createOptimizedSocket(const std::string& ip, int port) { sockaddr_in addr; SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sock == INVALID_SOCKET) { cout << "[错误] 创建socket失败: " << WSAGetLastError() << endl; return INVALID_SOCKET; } // 关键TCP优化参数 int nodelay = 1; if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&nodelay, sizeof(nodelay)) == SOCKET_ERROR) { cout << "[警告] 设置TCP_NODELAY失败: " << WSAGetLastError() << endl; } // 设置发送缓冲区大小 int send_buf_size = 64 * 1024; setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&send_buf_size, sizeof(send_buf_size)); // 设置接收缓冲区大小 int recv_buf_size = 64 * 1024; setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&recv_buf_size, sizeof(recv_buf_size)); addr.sin_family = AF_INET; addr.sin_port = htons(static_cast<u_short>(port)); addr.sin_addr.s_addr = inet_addr(ip.c_str()); // 非阻塞连接 unsigned long mode = 1; ioctlsocket(sock, FIONBIO, &mode); int connect_result = connect(sock, (struct sockaddr*)&addr, sizeof(addr)); // 等待连接完成 fd_set writefds; FD_ZERO(&writefds); FD_SET(sock, &writefds); timeval timeout = { 3, 0 }; // 3秒超时 int select_result = select(0, NULL, &writefds, NULL, &timeout); if (select_result <= 0) { cout << "[错误] 连接超时或失败: " << WSAGetLastError() << endl; closesocket(sock); return INVALID_SOCKET; } // 检查socket错误 int error = 0; int error_len = sizeof(error); getsockopt(sock, SOL_SOCKET, SO_ERROR, (char*)&error, &error_len); if (error != 0) { cout << "[错误] 连接失败: " << error << endl; closesocket(sock); return INVALID_SOCKET; } // 恢复阻塞模式 mode = 0; ioctlsocket(sock, FIONBIO, &mode); // 关联到IOCP if (iocpHandle) { CreateIoCompletionPort((HANDLE)sock, iocpHandle, 0, 0); } return sock; } // 优化数据发送 void optimizedSendToKore(const char* data, uint16_t len, e_PacketType type) { if (!koreClientIsAlive.load(memory_order_acquire)) return; char header[3]; header[0] = (type == RECEIVED) ? 'R' : 'S'; *reinterpret_cast<uint16_t*>(header + 1) = len; // 先尝试写入header if (!sendBuffer.push(header, 3)) { return; // 缓冲区满,丢弃数据 } // 再写入数据 if (!sendBuffer.push(data, len)) { // 回滚header写入 char temp[3]; sendBuffer.pop(temp, 3); } } // 高性能封包处理线程 DWORD WINAPI highPerformancePacketProcessor(LPVOID lpParam) { char local_buf[4096]; atomic_dword last_send_time(GetTickCount()); atomic_dword last_ping_time(GetTickCount()); while (keepMainThread.load(memory_order_acquire)) { DWORD current_time = GetTickCount(); // 处理发送缓冲区 uint32_t available = sendBuffer.available_read(); if (available > 0) { SOCKET kore_sock = koreClient.load(memory_order_acquire); if (kore_sock != INVALID_SOCKET) { uint32_t bytes_read = sendBuffer.pop(local_buf, min(available, sizeof(local_buf))); if (bytes_read > 0) { int sent = send(kore_sock, local_buf, bytes_read, 0); if (sent == SOCKET_ERROR) { // 发送失败,可能连接已断开 koreClient.store(INVALID_SOCKET, memory_order_release); koreClientIsAlive.store(false, memory_order_release); } else { last_send_time.store(current_time, memory_order_relaxed); } } } } // 定期Ping(保持连接活跃) if (current_time - last_ping_time.load(memory_order_relaxed) > PING_INTERVAL) { SOCKET kore_sock = koreClient.load(memory_order_acquire); if (kore_sock != INVALID_SOCKET) { char ping_packet[3] = { 'K', 0, 0 }; send(kore_sock, ping_packet, 3, 0); } last_ping_time.store(current_time, memory_order_relaxed); } // 智能休眠:有数据时忙等待,无数据时短暂休眠 if (available == 0) { Sleep(1); // 1ms休眠减少CPU占用 } } return 0; } // 主连接线程(优化版) DWORD WINAPI koreConnectionMainOptimized(LPVOID lpParam) { // 等待Hook应用完成 while (!hook_delayed.load(memory_order_acquire) && keepMainThread.load(memory_order_acquire)) { cout << "[信息] 等待Hook应用完成..." << endl; Sleep(500); } if (!hook_applied.load(memory_order_acquire)) { cout << "[错误] Hook未应用,连接线程退出" << endl; return 1; } // 创建专用的封包处理线程 HANDLE packet_thread = CreateThread(NULL, 0, highPerformancePacketProcessor, NULL, CREATE_SUSPENDED, NULL); if (!packet_thread) { cout << "[错误] 创建封包处理线程失败: " << GetLastError() << endl; return 1; } // 设置线程优先级 SetThreadPriority(packet_thread, THREAD_PRIORITY_ABOVE_NORMAL); SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); // 禁用线程库通知减少开销 DisableThreadLibraryCalls(GetModuleHandle(NULL)); // 启动封包处理线程 ResumeThread(packet_thread); char recv_buf[8192]; atomic_dword last_connect_attempt(0); atomic_dword last_activity_time(GetTickCount()); cout << "[信息] xKore连接线程已启动" << endl; while (keepMainThread.load(memory_order_acquire)) { DWORD current_time = GetTickCount(); SOCKET current_kore_client = koreClient.load(memory_order_acquire); // 连接管理 if (current_kore_client == INVALID_SOCKET || !isConnected(current_kore_client)) { if (current_time - last_connect_attempt.load(memory_order_relaxed) > RECONNECT_INTERVAL) { if (current_kore_client != INVALID_SOCKET) { shutdown(current_kore_client, SD_BOTH); closesocket(current_kore_client); } SOCKET new_socket = createOptimizedSocket(koreServerIP, koreServerPort); if (new_socket != INVALID_SOCKET) { koreClient.store(new_socket, memory_order_release); koreClientIsAlive.store(true, memory_order_release); imalive.store(true, memory_order_release); last_activity_time.store(current_time, memory_order_relaxed); // 提交异步接收操作 if (iocpHandle) { PostAsyncRecv(new_socket); } cout << "[成功] 已连接到xKore服务器 " << koreServerIP << ":" << koreServerPort << endl; } else { koreClientIsAlive.store(false, memory_order_release); imalive.store(false, memory_order_release); cout << "[错误] 连接xKore服务器失败" << endl; } last_connect_attempt.store(current_time, memory_order_relaxed); } Sleep(100); // 连接失败时短暂休眠 continue; } // 检查超时 if (current_time - last_activity_time.load(memory_order_relaxed) > TIMEOUT) { cout << "[警告] 连接超时,重新连接..." << endl; koreClient.store(INVALID_SOCKET, memory_order_release); continue; } // 如果没有使用异步I/O,则使用传统的recv if (!iocpHandle) { int bytes_received = recv(current_kore_client, recv_buf, sizeof(recv_buf), 0); if (bytes_received > 0) { last_activity_time.store(current_time, memory_order_relaxed); // 处理接收到的封包 const char* data_ptr = recv_buf; int remaining = bytes_received; while (remaining >= 3) { char packet_type = data_ptr[0]; uint16_t packet_len = *reinterpret_cast<const uint16_t*>(data_ptr + 1); if (remaining < 3 + packet_len) break; // 数据不完整 if (packet_type == 'S' && packet_len > 0) { // 发送到RO客户端 auto* sendFunc = reinterpret_cast<SendToClientFunc>(CLIENT_SUB_ADDRESS); auto* instanceR = reinterpret_cast<originalInstanceR>(CRAG_CONNECTION_INSTANCE_R_ADDRESS); if (sendFunc && instanceR) { void* instance = instanceR(); if (instance) { sendFunc(instance, packet_len, const_cast<char*>(data_ptr + 3)); } } } int packet_total_size = 3 + packet_len; data_ptr += packet_total_size; remaining -= packet_total_size; } } else if (bytes_received == 0) { // 连接关闭 cout << "[信息] xKore服务器断开连接" << endl; shutdown(current_kore_client, SD_BOTH); closesocket(current_kore_client); koreClient.store(INVALID_SOCKET, memory_order_release); koreClientIsAlive.store(false, memory_order_release); imalive.store(false, memory_order_release); } else if (bytes_received == SOCKET_ERROR) { int error = WSAGetLastError(); if (error != WSAEWOULDBLOCK) { cout << "[错误] 接收数据失败: " << error << endl; koreClient.store(INVALID_SOCKET, memory_order_release); } } } // 轻微休眠避免过高CPU占用 Sleep(SLEEP_TIME); } // 清理线程 keepMainThread.store(false, memory_order_release); WaitForSingleObject(packet_thread, 5000); CloseHandle(packet_thread); cout << "[信息] xKore连接线程已退出" << endl; return 0; } // 获取用户端口(多客户端模式) DWORD GetUserPort() { char input[256]; cout << "\n[多客户端模式]" << endl; cout << "请输入xKore服务器端口(默认: " << koreServerPort << "): "; if (fgets(input, sizeof(input), stdin)) { input[strcspn(input, "\r\n")] = 0; if (strlen(input) == 0) { cout << "使用默认端口: " << koreServerPort << endl; return koreServerPort; } int inputPort = atoi(input); if (inputPort > 0 && inputPort <= 65535) { cout << "使用自定义端口: " << inputPort << endl; return static_cast<DWORD>(inputPort); } else { cout << "无效端口! 使用默认端口: " << koreServerPort << endl; return koreServerPort; } } cout << "读取错误! 使用默认端口: " << koreServerPort << endl; return koreServerPort; } // 初始化函数 void initOptimized() { AllocateConsole(); cout << "=== xKore优化版 ===" << endl; cout << "架构: x86 (32位)" << endl; cout << "优化: 原子操作 + 内存池 + 环形缓冲区 + 异步I/O" << endl; cout << "特性: 3秒延迟Hook(避免强壳检测)" << endl; // 初始化Winsock WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { cout << "[错误] Winsock初始化失败" << endl; return; } // 加载配置 if (!LoadConfig("config_recv.txt")) { cout << "[致命] 加载配置文件失败" << endl; keepMainThread.store(false, memory_order_release); return; } // 多客户端模式 if (allowMultiClient) { koreServerPort = GetUserPort(); } // 初始化异步I/O系统 if (!InitializeAsyncIO()) { cout << "[警告] 异步I/O初始化失败,使用传统模式" << endl; } else { // 初始化工作线程池 if (!InitializeWorkerThreads()) { cout << "[警告] 工作线程池初始化失败,使用传统模式" << endl; CleanupAsyncIO(); } } // 创建延迟Hook应用线程 HANDLE hook_thread = CreateThread(NULL, 0, [](LPVOID) -> DWORD { DelayedHookApplication(); return 0; }, NULL, 0, NULL); if (hook_thread) { cout << "[信息] 延迟Hook线程已启动" << endl; CloseHandle(hook_thread); // 不需要保持句柄 } else { cout << "[错误] 创建延迟Hook线程失败: " << GetLastError() << endl; // 直接应用Hook作为备选方案 cout << "[信息] 尝试直接应用Hook..." << endl; ApplyHookOptimized(); } // 创建优化版主线程 HANDLE hThread = CreateThread(NULL, 0, koreConnectionMainOptimized, NULL, 0, NULL); if (hThread) { cout << "[成功] xKore主线程已启动" << endl; CloseHandle(hThread); // 不需要保持句柄 } else { cout << "[错误] 创建主线程失败: " << GetLastError() << endl; keepMainThread.store(false, memory_order_release); } cout << "====================\n" << endl; } // 清理函数 void finishOptimized() { cout << "[信息] 开始清理资源..." << endl; keepMainThread.store(false, memory_order_release); // 等待线程退出 Sleep(100); // 清理工作线程池和异步I/O CleanupWorkerThreads(); CleanupAsyncIO(); // 关闭socket连接 SOCKET sock = koreClient.exchange(INVALID_SOCKET, memory_order_acq_rel); if (sock != INVALID_SOCKET) { shutdown(sock, SD_BOTH); closesocket(sock); } sock = roServer.exchange(INVALID_SOCKET, memory_order_acq_rel); if (sock != INVALID_SOCKET) { closesocket(sock); } // 移除hook if (original_recv) { RemoveHook(); } // 清理Winsock WSACleanup(); cout << "[信息] 资源清理完成" << endl; } // DLL主入口 BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: // 禁用线程通知以减少开销 DisableThreadLibraryCalls(hModule); initOptimized(); break; case DLL_PROCESS_DETACH: finishOptimized(); break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: break; } return TRUE; }针对 RO 的1 对 1 单 IP 连接、高频小封包场景,IOCP 的 “恰到好处” 核心是:聚焦 “单连接下的高频 IO 效率”,砍掉多连接场景的冗余设计,用最小的资源开销解决 “卡顿、丢包” 问题,避免为 “用而用” 的过度优化。具体需在 6 个关键环节做到精准控制,既保留 IOCP 的核心优势,又不引入不必要的复杂度: 一、完成端口(IOCP)初始化:极简配置,不浪费内核资源 单连接场景下,IOCP 无需配置多连接的 “高并发参数”,核心是 “轻量化创建 + 绑定单 Socket”,避免内核资源闲置: 并发线程数设为 1,而非 CPU 核心数CreateIoCompletionPort 的第 4 个参数(NumberOfConcurrentThreads)控制允许同时处理 IO 事件的线程数。多连接场景会设为 CPU 核心数(如 4 核设 4),但单连接下 IO 事件是 “串行触发”(同一时间仅 1 个小封包待处理),设为1即可 —— 多线程反而会导致 “线程切换开销”(比如 2 个线程抢 1 个 IO 事件,浪费 CPU)。文档中IOCPOptimizer::initialize()用了默认的0(等于 CPU 核心数),可优化为1,更贴合单连接: cpp 运行 iocp_handle = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1); // 最后一个参数设为1 仅关联 1 个目标 Socket,不做批量绑定单连接场景下,仅需将 RO 客户端与服务器的 Socket(或 xKore 代理的 Socket)关联到 IOCP,无需设计 “批量 Socket 绑定逻辑”(如循环绑定多个连接)。文档中associateSocket()单次绑定 1 个 Socket 的逻辑已适配,无需额外扩展。 二、线程池设计:1 个工作线程足够,拒绝 “多线程冗余” IOCP 的线程池是 “事件消费者”,单连接下高频小封包的 IO 事件是 “连续且串行” 的,1 个工作线程即可高效处理,多线程反而会引入 “锁竞争”(如抢读环形缓冲区),属于过度优化: 固定 1 个 IO 工作线程,不动态增减无需设计 “根据 IO 压力动态创建 / 销毁线程” 的逻辑(多连接场景才需要),直接创建 1 个常驻线程处理 IO 事件即可。比如文档中的highPerformancePacketProcessor线程,可固定为 1 个,无需用线程池库(如CreateThreadPool)—— 代码中SetThreadPriority设为THREAD_PRIORITY_ABOVE_NORMAL是合理的(保证 IO 处理优先级高于普通逻辑,避免小封包延迟),但无需多线程。 线程与 IO 事件 “一对一绑定”,避免线程切换单线程处理所有 IO 事件(读 / 写 / 错误),无需拆分 “读线程”“写线程”—— 拆分后会增加 “线程间通信开销”(如写线程通知读线程处理数据),反而降低效率。文档中 “1 个线程处理发送缓冲区 + Ping + 超时检测” 的逻辑已适配,无需修改。 三、IO 请求投递:预投递 + 小缓冲区,适配高频小封包 RO 的小封包(10~512 字节)若 “每次投递 1 个 IO 请求”,会导致系统调用(WSARecv/WSASend)频繁,反而增加开销。需用 “预投递 + 固定小缓冲区” 优化,平衡效率与资源: 预投递 1 个读请求,而非多次投递单连接下,Socket 接收缓冲区的小封包是 “连续到达” 的,可预先投递 1 个WSARecv请求(挂起等待数据),数据到达后处理完再投递下 1 个 —— 避免 “每收到 1 个小封包就投递 1 次请求” 的高频系统调用。示例逻辑: cpp 运行 // 预投递读请求(初始化时执行1次) OVERLAPPED ov; memset(&ov, 0, sizeof(ov)); char recv_buf[512]; // 适配RO小封包,不用8192字节大缓冲区 WSARecv(sock, &wsabuf, 1, NULL, &flags, &ov, NULL); // 处理完成事件后,再次投递下1个请求 while (keepRunning) { GetQueuedCompletionStatus(iocp_handle, &bytesTransferred, &key, &ov, INFINITE); processSmallPacket(recv_buf, bytesTransferred); // 处理小封包 WSARecv(sock, &wsabuf, 1, NULL, &flags, &ov, NULL); // 再次预投递 } 这里缓冲区设为512 字节(RO 小封包最大通常不超过 512),比文档中recv_buf[8192]更节省内存,且避免 “大缓冲区空闲浪费”。 写请求 “批量合并”,减少 WSASend 调用高频小封包发送时,若每次调用WSASend发送 1 个小封包(如 10 字节),系统调用开销占比极高。可结合文档中的环形缓冲区(sendBuffer) ,积累多个小封包(如累计到 1KB 或等待 1ms)后,一次性调用WSASend发送 —— 但需注意 “延迟平衡”(累计时间不超过 1ms,避免 RO 实时交互卡顿)。文档中 “有数据就发送” 的逻辑可微调:增加 “最小累计字节数”(如 128 字节),减少系统调用次数,又不影响延迟。 四、缓冲区与内存管理:贴合小封包,避免 “大缓冲冗余” RO 的小封包不需要大缓冲区,过度分配会导致内存浪费;同时需避免动态内存分配(高频小封包易引发内存碎片),文档中的内存池已适配,需进一步贴合场景: Socket 缓冲区设为 64KB,不盲目调大SO_SNDBUF/SO_RCVBUF 的大小需适配小封包:设为 64KB 足够(RO 每秒数百个小封包,总流量仅几十 KB),设为 128KB 或更大反而会增加 “缓冲区数据拷贝开销”(内核到用户态)。文档中send_buf_size = 64 * 1024的配置已恰到好处,无需修改。 内存池单包大小设为 512 字节,而非 8KB文档中MAX_PACKET_SIZE = 8192(8KB)过大,RO 小封包最大仅 512 字节,可改为512,减少内存池的内存占用(1024 个包仅 512KB,原 8KB 需 8MB)。同时避免 “大缓冲区拆分小封包” 的逻辑,简化内存池管理。 五、错误处理与降级:简单可靠,不做复杂容错 单连接场景下,IO 错误类型少(如连接断开、超时),无需设计 “复杂的错误重试逻辑”(如多连接的 “故障转移”),做到 “快速检测 + 优雅降级” 即可: 仅处理关键错误,避免冗余判断重点处理 3 类错误:WSAECONNRESET(连接被重置)、WSAETIMEDOUT(超时)、ERROR_NETNAME_DELETED(连接关闭),其他错误直接触发 “重连逻辑”(如文档中的koreClient.store(INVALID_SOCKET))。无需遍历所有 WSA 错误码,减少判断开销。 IOCP 初始化失败时,降级为 “简化异步 IO”若 IOCP 创建失败(如老旧系统不支持),无需崩溃,可降级为 “WSAEventSelect”(比 select 高效,比 IOCP 简单),而非直接用 select。文档中 “IOCP 关联失败仅警告” 的逻辑可优化为降级逻辑,保证兼容性,又不引入过度容错。 六、避免 “为 IOCP 而加的冗余特性” 单连接场景下,多连接 IOCP 的常见特性(如 “连接池”“负载均衡”“多完成端口拆分”)均无需实现,属于典型的过度优化: 不做 “连接池”:单连接无需缓存多个 Socket,直接创建 / 关闭即可; 不做 “多完成端口”:1 个完成端口足够处理单连接,多完成端口会增加内核调度开销; 不做 “IO 事件优先级”:单连接下所有小封包优先级相同(如移动、技能封包无先后),无需设计事件优先级队列。 总结:IOCP “恰到好处” 的核心原则 针对 RO 1 对 1 单连接、高频小封包场景,IOCP 的优化需围绕 “最小资源开销解决核心问题”: 资源上:1 个完成端口 + 1 个工作线程 + 64KB Socket 缓冲区 + 512 字节内存池,不浪费内存与 CPU; 逻辑上:预投递 1 个读请求 + 批量合并写请求 + 简单错误处理,不引入多线程、多完成端口等冗余设计; 目标上:仅解决 “select 轮询开销”“小封包延迟”“缓冲区溢出丢包” 三大问题,不追求 “多连接扩展性”“极致并发” 等无关特性。 这种设计既保留了 IOCP “异步无轮询” 的核心优势(从根源解决卡顿、丢包),又避免了过度优化带来的复杂度与资源浪费,完全适配 RO 的单连接高频小封包场景。
09-24
#include <windows.h> #include <tlhelp32.h> #include <stdio.h> #include <psapi.h> #include <sddl.h> // 全局变量 DWORD_PTR g_HookAddr = 0; // Hook 目标地址 DWORD_PTR g_OriginalFunc = 0; // 原始函数地址 PVOID g_VehHandler = nullptr; // VEH 句柄 bool g_Is64BitProcess = false; // 进程位数标识 // 调试寄存器控制值 #ifdef _WIN64 const DWORD DR7_EXECUTE_ENABLED = (1 << 0) | (0 << 16) | (0 << 18); // L0=1, R/W0=00 (执行) #else const DWORD DR7_EXECUTE_ENABLED = 0x00000401; // L0=1, R/W0=00 (执行) #endif // 函数声明 LONG WINAPI VectoredExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo); bool EnableDebugPrivilege(); bool SetHardwareBreakpoint(HANDLE hThread, DWORD_PTR address); void SetCurrentThreadBreakpoint(); void SetAllThreadsBreakpoints(); void LogToFile(const char* format, ...); void InitializeHook(); void MonitorNewThreads(); // VEH 异常处理函数 LONG WINAPI VectoredExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo) { if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP) { if ((DWORD_PTR)ExceptionInfo->ExceptionRecord->ExceptionAddress == g_HookAddr) { // ====== Hook 逻辑 ====== const char* text = nullptr; const char* caption = nullptr; #ifdef _WIN64 // 64位系统:参数在寄存器中 text = (const char*)ExceptionInfo->ContextRecord->Rcx; caption = (const char*)ExceptionInfo->ContextRecord->R8; #else // 32位系统:参数在栈上 DWORD* stack = (DWORD*)ExceptionInfo->ContextRecord->Esp; text = (const char*)stack[1]; caption = (const char*)stack[2]; #endif // 记录调用信息 LogToFile("[VEH HOOK] MessageBoxA called\n"); LogToFile(" Text: %s\n", text ? text : "NULL"); LogToFile(" Caption: %s\n", caption ? caption : "NULL"); LogToFile(" Thread ID: %d\n\n", GetCurrentThreadId()); // ====== 恢复执行 ====== // 清除单步标志防止无限循环 ExceptionInfo->ContextRecord->EFlags &= ~0x100; // 继续执行原始函数 #ifdef _WIN64 ExceptionInfo->ContextRecord->Rip = g_OriginalFunc; #else ExceptionInfo->ContextRecord->Eip = g_OriginalFunc; #endif return EXCEPTION_CONTINUE_EXECUTION; } } return EXCEPTION_CONTINUE_SEARCH; } // 启用调试权限 bool EnableDebugPrivilege() { HANDLE hToken; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { return false; } TOKEN_PRIVILEGES tp; LUID luid; if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) { CloseHandle(hToken); return false; } tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) { CloseHandle(hToken); return false; } CloseHandle(hToken); return GetLastError() == ERROR_SUCCESS; } // 设置硬件断点 bool SetHardwareBreakpoint(HANDLE hThread, DWORD_PTR address) { CONTEXT ctx = { 0 }; ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS; if (!GetThreadContext(hThread, &ctx)) { return false; } // 选择可用的调试寄存器 if (ctx.Dr0 == 0) { ctx.Dr0 = address; } else if (ctx.Dr1 == 0) { ctx.Dr1 = address; } else if (ctx.Dr2 == 0) { ctx.Dr2 = address; } else if (ctx.Dr3 == 0) { ctx.Dr3 = address; } else { // 所有调试寄存器已使用 return false; } ctx.Dr7 |= DR7_EXECUTE_ENABLED; return SetThreadContext(hThread, &ctx); } // 设置当前线程的硬件断点 void SetCurrentThreadBreakpoint() { HANDLE hThread = GetCurrentThread(); SetHardwareBreakpoint(hThread, g_HookAddr); } // 遍历并设置所有线程的硬件断点 void SetAllThreadsBreakpoints() { HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); if (hSnapshot == INVALID_HANDLE_VALUE) return; THREADENTRY32 te32; te32.dwSize = sizeof(THREADENTRY32); DWORD currentProcessId = GetCurrentProcessId(); DWORD currentThreadId = GetCurrentThreadId(); if (Thread32First(hSnapshot, &te32)) { do { if (te32.th32OwnerProcessID == currentProcessId && te32.th32ThreadID != currentThreadId) { // 尝试打开线程 HANDLE hThread = OpenThread( THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME, FALSE, te32.th32ThreadID ); if (!hThread) { DWORD err = GetLastError(); LogToFile("Failed to open thread %d: %d\n", te32.th32ThreadID, err); continue; } // 暂停线程 DWORD suspendCount = SuspendThread(hThread); if (suspendCount != (DWORD)-1) { // 设置硬件断点 if (!SetHardwareBreakpoint(hThread, g_HookAddr)) { LogToFile("Failed to set breakpoint for thread %d\n", te32.th32ThreadID); } ResumeThread(hThread); } CloseHandle(hThread); } } while (Thread32Next(hSnapshot, &te32)); } CloseHandle(hSnapshot); } // 监控新线程创建 void MonitorNewThreads() { // 使用事件钩子监控线程创建 // 实际应用中应使用更可靠的方法(如PsSetCreateThreadNotifyRoutine) LogToFile("Thread monitoring started\n"); } // 安全的日志记录函数 void LogToFile(const char* format, ...) { FILE* logFile = nullptr; if (fopen_s(&logFile, "veh_hook_log.txt", "a") == 0 && logFile) { va_list args; va_start(args, format); vfprintf(logFile, format, args); va_end(args); fclose(logFile); } } // 初始化 Hook void InitializeHook() { // 1. 启用调试权限 EnableDebugPrivilege(); // 2. 获取目标函数地址 HMODULE hUser32 = LoadLibraryA("user32.dll"); if (!hUser32) { LogToFile("Failed to load user32.dll\n"); return; } g_HookAddr = (DWORD_PTR)GetProcAddress(hUser32, "MessageBoxA"); if (!g_HookAddr) { LogToFile("Failed to get MessageBoxA address\n"); return; } g_OriginalFunc = g_HookAddr; LogToFile("Hook target: 0x%p\n", (void*)g_HookAddr); // 3. 注册 VEH 异常处理 g_VehHandler = AddVectoredExceptionHandler(1, VectoredExceptionHandler); if (!g_VehHandler) { LogToFile("Failed to register VEH handler\n"); return; } LogToFile("VEH handler registered: 0x%p\n", g_VehHandler); // 4. 设置所有现有线程的硬件断点 SetAllThreadsBreakpoints(); // 5. 设置当前线程的硬件断点 SetCurrentThreadBreakpoint(); // 6. 启动线程监控 MonitorNewThreads(); LogToFile("VEH Hook initialized successfully\n"); } // DLL 入口点 BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(hModule); // 创建新线程初始化 Hook HANDLE hThread = CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)InitializeHook, nullptr, 0, nullptr); if (hThread) CloseHandle(hThread); break; case DLL_PROCESS_DETACH: if (g_VehHandler) { RemoveVectoredExceptionHandler(g_VehHandler); LogToFile("VEH handler unregistered\n"); } break; } return TRUE; } 严重性 代码 说明 项目 文件 行 禁止显示状态 详细信息 错误 C2360 “hThread”的初始化操作由“case”标签跳过 veh hook C:\Users\17116\source\repos\veh hook\veh hook\源.cpp 258
07-25
以上代码存在问题:第一次直接运行的时候所有功能都完善,可以正常捕获键盘、鼠标输入,设置全屏等 然而,host应用改变分辨率或不是前台全屏之后无法重新捕获键盘输入,只能捕获鼠标,不能捕获键盘。 (附加信息:如果使用快捷键调起别的应用,比如微信,此时不会断键盘连结 我是64位系统,进行深度思考,理解为什么出现第一次可以之后不可以的问题,帮我看看如何修改,确保修改后无论怎么操作都可以正常鼠标操作和键盘操作,不准动我的底层逻辑 (附件:我使用的dll: // KeyboardInput.dll #define UNICODE #define _UNICODE #include <windows.h> #include <thread> #include <string> #include <vector> #include <iostream> // For to_wstring, if used in logging #define PIPE_NAME L"\\\\.\\pipe\\UnityKeyboardPipe" // Must match Host #define KEY_EVENT_BUFFER_SIZE 1024 // Not directly used for pipe buffer, but good constant // This MUST match the Host's structure struct PipeKeyMessage { UINT uMsg; WPARAM vkCode; DWORD scanCode; DWORD flags; // KBDLLHOOKSTRUCT flags }; HANDLE hPipe = INVALID_HANDLE_VALUE; std::thread pipeThread; // bool pipeConnected = false; // Status can be inferred from hPipe and ConnectNamedPipe result HWND g_unityMainWindow = NULL; bool g_stopPipeThread = false; // For graceful shutdown HANDLE g_hStopEvent = NULL; // Event for signaling thread to stop // Function to log messages (using OutputDebugString) void Log(const std::wstring& message) { OutputDebugStringW((L"DLL_LOG: " + message + L"\n").c_str()); } HWND FindActualUnityWindow() { HWND foundHwnd = NULL; EnumWindows([](HWND currentHwnd, LPARAM lParam) -> BOOL { DWORD processId; GetWindowThreadProcessId(currentHwnd, &processId); if (processId == GetCurrentProcessId()) { if (IsWindowVisible(currentHwnd)) { // Only consider visible windows wchar_t className[256]; GetClassName(currentHwnd, className, 256); // Common Unity class name (may vary, e.g. UnityContainerWndClass for embedded via -parentHWND) if (wcsstr(className, L"UnityWndClass") != NULL || wcsstr(className, L"UnityContainer") != NULL) { // Further check: Does it have children? Is it a top-level window (if not embedded)? // For simplicity, we'll take the first one that matches. // A more robust solution might check GetParent() if we expect it to be a child of a known host. *reinterpret_cast<HWND*>(lParam) = currentHwnd; Log(L"FindActualUnityWindow: Found Unity window with class: " + std::wstring(className) + L", HWND: " + std::to_wstring((uintptr_t)currentHwnd)); return FALSE; // Found } // Fallback: if no specific class found yet, store any visible window of the process // This is less reliable. // if (*reinterpret_cast<HWND*>(lParam) == NULL && GetWindowTextLength(currentHwnd) > 0) { // *reinterpret_cast<HWND*>(lParam) = currentHwnd; // } } } return TRUE; }, reinterpret_cast<LPARAM>(&foundHwnd)); if (!foundHwnd) { Log(L"FindActualUnityWindow: Unity main window not found."); } return foundHwnd; } void SimulateKeyEvent(UINT uMsg, WPARAM vkCode, DWORD scanCode, DWORD originalFlags, HWND targetHwnd) { if (!targetHwnd || !IsWindow(targetHwnd)) { Log(L"SimulateKeyEvent - Target window invalid or destroyed."); g_unityMainWindow = NULL; // Mark for re-search return; } INPUT input[1] = {0}; input[0].type = INPUT_KEYBOARD; input[0].ki.wVk = (WORD)vkCode; input[0].ki.wScan = (WORD)scanCode; input[0].ki.dwFlags = 0; if (uMsg == WM_KEYUP || uMsg == WM_SYSKEYUP) { input[0].ki.dwFlags |= KEYEVENTF_KEYUP; } if (originalFlags & LLKHF_EXTENDED) { // Check KBDLLHOOKSTRUCT's extended flag input[0].ki.dwFlags |= KEYEVENTF_EXTENDEDKEY; } // If scan code is present and it's not a virtual key that implies its own scan code (like VK_PACKET) // you might want to add KEYEVENTF_SCANCODE. For most VKs, this is handled. // Some games are very particular about wScan vs wVk. // if (scanCode != 0) { // input[0].ki.dwFlags |= KEYEVENTF_SCANCODE; // } // Log((L"Simulating: uMsg=" + std::to_wstring(uMsg) + L" vk=" + std::to_wstring(vkCode) + L" scan=" + std::to_wstring(scanCode) + L" flags=" + std::to_wstring(originalFlags) + L" -> SendInputFlags=" + std::to_wstring(input[0].ki.dwFlags)).c_str()); UINT sent = SendInput(1, input, sizeof(INPUT)); if (sent == 0) { Log(L"SendInput failed. Error: " + std::to_wstring(GetLastError())); } } void PipeThreadProc() { Log(L"PipeThreadProc started."); hPipe = CreateNamedPipeW( PIPE_NAME, PIPE_ACCESS_INBOUND, // DLL only reads PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 1, // Only one host instance expected sizeof(PipeKeyMessage) * 10, // Buffer size for pipe (e.g., 10 messages) sizeof(PipeKeyMessage) * 10, NMPWAIT_USE_DEFAULT_WAIT, NULL); if (hPipe == INVALID_HANDLE_VALUE) { Log(L"CreateNamedPipeW failed. Error: " + std::to_wstring(GetLastError())); return; } Log(L"Named pipe created. Waiting for connection..."); while (WaitForSingleObject(g_hStopEvent, 0) == WAIT_TIMEOUT) { // Loop until stop event is signaled BOOL connected = ConnectNamedPipe(hPipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); if (connected) { Log(L"Pipe connected to host."); if (g_unityMainWindow == NULL || !IsWindow(g_unityMainWindow)) { // Check if window is still valid g_unityMainWindow = FindActualUnityWindow(); } PipeKeyMessage km; DWORD bytesRead; while (WaitForSingleObject(g_hStopEvent, 0) == WAIT_TIMEOUT) { BOOL success = ReadFile(hPipe, &km, sizeof(PipeKeyMessage), &bytesRead, NULL); if (!success || bytesRead == 0) { DWORD error = GetLastError(); if (error == ERROR_BROKEN_PIPE) { Log(L"Pipe broken (host disconnected)."); } else if (error != ERROR_IO_PENDING) { // ERROR_IO_PENDING is not an error for overlapped, but we are synchronous Log(L"ReadFile failed. Error: " + std::to_wstring(error)); } DisconnectNamedPipe(hPipe); Log(L"Disconnected from host. Waiting for new connection..."); break; } if (bytesRead != sizeof(PipeKeyMessage)) { Log(L"ReadFile: Received incomplete message. Expected " + std::to_wstring(sizeof(PipeKeyMessage)) + L" got " + std::to_wstring(bytesRead)); // This is a more serious error, might indicate pipe corruption or mismatched structures. // Consider breaking and re-establishing connection. DisconnectNamedPipe(hPipe); Log(L"Disconnected due to malformed message. Waiting for new connection..."); break; } // Log(L"Received KeyMessage: uMsg=" + std::to_wstring(km.uMsg) + L", vkCode=" + std::to_wstring(km.vkCode) + L", scanCode=" + std::to_wstring(km.scanCode) + L", flags=" + std::to_wstring(km.flags)); if (g_unityMainWindow == NULL || !IsWindow(g_unityMainWindow)) { Log(L"Attempting to find Unity window again before simulating key..."); g_unityMainWindow = FindActualUnityWindow(); } if (g_unityMainWindow) { SimulateKeyEvent(km.uMsg, km.vkCode, km.scanCode, km.flags, g_unityMainWindow); } else { Log(L"Unity main window not found, cannot simulate key."); } } } else { DWORD error = GetLastError(); // ERROR_PIPE_LISTENING is normal if no client has connected yet. // Don't log spam for this one unless it persists. // if (error != ERROR_PIPE_LISTENING) { // Log(L"ConnectNamedPipe failed. Error: " + std::to_wstring(error) + L". Retrying..."); // } Sleep(100); // Wait before retrying connection } } Log(L"PipeThreadProc stopping."); if (hPipe != INVALID_HANDLE_VALUE) { DisconnectNamedPipe(hPipe); // Ensure client is disconnected CloseHandle(hPipe); hPipe = INVALID_HANDLE_VALUE; } Log(L"PipeThreadProc finished."); } BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(hModule); Log(L"DLL_PROCESS_ATTACH"); g_hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); // Manual-reset, initially non-signaled if (g_hStopEvent == NULL) { Log(L"Failed to create stop event."); return FALSE; // Critical failure } // It's better to find window after pipe connection, as Unity might not be fully up yet. // g_unityMainWindow = FindActualUnityWindow(); pipeThread = std::thread(PipeThreadProc); // pipeThread.detach(); // No, make it joinable for clean shutdown break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: Log(L"DLL_PROCESS_DETACH"); if (g_hStopEvent != NULL) { Log(L"Signaling pipe thread to stop."); SetEvent(g_hStopEvent); // Signal thread to stop } if (pipeThread.joinable()) { Log(L"Waiting for pipe thread to join..."); pipeThread.join(); // Wait for thread to finish Log(L"Pipe thread joined."); } if (g_hStopEvent != NULL) { CloseHandle(g_hStopEvent); g_hStopEvent = NULL; } Log(L"DLL cleanup finished."); break; } return TRUE; }
06-11
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值