From 25a9919498699d624923c71aae598c0f7dce06c6 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Tue, 24 Sep 2019 23:00:50 +0200 Subject: [PATCH] Fix steam proxy --- src/module/dw.cpp | 852 ++++++++++++++++++------------------- src/module/steam_proxy.cpp | 17 +- 2 files changed, 433 insertions(+), 436 deletions(-) diff --git a/src/module/dw.cpp b/src/module/dw.cpp index c6b87f4..5b11020 100644 --- a/src/module/dw.cpp +++ b/src/module/dw.cpp @@ -1,426 +1,426 @@ -#include -#include "dw.hpp" -#include "utils/hook.hpp" -#include "game/game.hpp" -#include "utils/nt.hpp" -#include "utils/cryptography.hpp" - -#include "game/demonware/services/bdLSGHello.hpp" // 7 -#include "game/demonware/services/bdStorage.hpp" // 10 -#include "game/demonware/services/bdDediAuth.hpp" // 12 -#include "game/demonware/services/bdTitleUtilities.hpp" // 12 -#include "game/demonware/services/bdDML.hpp" // 27 -#include "game/demonware/services/bdDediRSAAuth.hpp" // 26 -#include "game/demonware/services/bdSteamAuth.hpp" // 28 - -namespace demonware -{ - namespace io - { - int __stdcall send_to(const SOCKET s, const char* buf, const int len, const int flags, const sockaddr* to, - const int tolen) - { - if (tolen == sizeof(sockaddr_in)) - { - const auto in_addr = reinterpret_cast(to); - const auto server = dw::find_stun_server_by_address(in_addr->sin_addr.s_addr); - if (server) return server->send(s, buf, len, to, tolen); - } - - return sendto(s, buf, len, flags, to, tolen); - } - - int __stdcall recv_from(const SOCKET s, char* buf, const int len, const int flags, sockaddr* from, int* fromlen) - { - auto res = dw::recv_datagam_packet(s, buf, len, from, fromlen); - if (res != 0) return res; - - res = recvfrom(s, buf, len, flags, from, fromlen); - - return res; - } - - int __stdcall send(const SOCKET s, const char* buf, const int len, const int flags) - { - auto server = dw::find_server_by_socket(s); - if (server) return server->send(buf, len); - - return ::send(s, buf, len, flags); - } - - int __stdcall recv(const SOCKET s, char* buf, const int len, const int flags) - { - auto server = dw::find_server_by_socket(s); - if (server) - { - const auto blocking = dw::is_blocking_socket(s, TCP_BLOCKING); - - int result; - do - { - result = server->recv(buf, len); - if (blocking && result < 0) std::this_thread::sleep_for(1ms); - } - while (blocking && result < 0); - - if (!blocking && result < 0) - { - WSASetLastError(WSAEWOULDBLOCK); - } - - return result; - } - - return ::recv(s, buf, len, flags); - } - - int __stdcall connect(const SOCKET s, const sockaddr* addr, const int len) - { - if (len == sizeof(sockaddr_in)) - { - const auto* in_addr = reinterpret_cast(addr); - if (dw::link_socket(s, in_addr->sin_addr.s_addr)) return 0; - } - - return ::connect(s, addr, len); - } - - int __stdcall close_socket(const SOCKET s) - { - dw::remove_blocking_socket(s); - dw::unlink_socket(s); - return closesocket(s); - } - - int __stdcall ioctl_socket(const SOCKET s, const long cmd, u_long* argp) - { - if (static_cast(cmd) == (FIONBIO)) - { - dw::set_blocking_socket(s, *argp == 0); - } - - return ioctlsocket(s, cmd, argp); - } - - hostent* __stdcall get_host_by_name(char* name) - { - static std::mutex mutex; - std::lock_guard _(mutex); - - unsigned long addr = 0; - const auto server = dw::find_server_by_name(name); - if (server) addr = server->get_address(); - - const auto stun_server = dw::find_stun_server_by_name(name); - if (stun_server) addr = stun_server->get_address(); - - if (server || stun_server) - { - static in_addr address; - address.s_addr = addr; - - static in_addr* addr_list[2]; - addr_list[0] = &address; - addr_list[1] = nullptr; - - static hostent host; - host.h_name = name; - host.h_aliases = nullptr; - host.h_addrtype = AF_INET; - host.h_length = sizeof(in_addr); - host.h_addr_list = reinterpret_cast(addr_list); - - return &host; - } - -#pragma warning(push) -#pragma warning(disable: 4996) - - // ReSharper disable once CppDeprecatedEntity - return gethostbyname(name); - -#pragma warning(pop) - } - - bool register_hook(const std::string& process, void* stub) - { - const utils::nt::module main; - - auto result = false; - result = result || utils::hook::iat(main, "wsock32.dll", process, stub); - result = result || utils::hook::iat(main, "WS2_32.dll", process, stub); - return result; - } - } -} - -namespace demonware -{ - bool dw::terminate_; - std::thread dw::message_thread_; - std::recursive_mutex dw::server_mutex_; - std::map dw::blocking_sockets_; - std::map> dw::socket_links_; - std::map> dw::servers_; - std::map> dw::stun_servers_; - std::map>> dw::datagram_packets_; - - uint8_t dw::encryption_key_[24]; - uint8_t dw::decryption_key_[24]; - - std::shared_ptr dw::find_server_by_name(const std::string& name) - { - std::lock_guard _(server_mutex_); - return find_server_by_address(utils::cryptography::jenkins_one_at_a_time::compute(name)); - } - - std::shared_ptr dw::find_server_by_address(const unsigned long address) - { - std::lock_guard _(server_mutex_); - - const auto server = servers_.find(address); - if (server != servers_.end()) - { - return server->second; - } - - return std::shared_ptr(); - } - - std::shared_ptr dw::find_stun_server_by_name(const std::string& name) - { - std::lock_guard _(server_mutex_); - return find_stun_server_by_address(utils::cryptography::jenkins_one_at_a_time::compute(name)); - } - - std::shared_ptr dw::find_stun_server_by_address(const unsigned long address) - { - std::lock_guard _(server_mutex_); - - const auto server = stun_servers_.find(address); - if (server != stun_servers_.end()) - { - return server->second; - } - - return std::shared_ptr(); - } - - std::shared_ptr dw::find_server_by_socket(const SOCKET s) - { - std::lock_guard _(server_mutex_); - - const auto server = socket_links_.find(s); - if (server != socket_links_.end()) - { - return server->second; - } - - return std::shared_ptr(); - } - - bool dw::link_socket(const SOCKET s, const unsigned long address) - { - std::lock_guard _(server_mutex_); - - const auto server = find_server_by_address(address); - if (!server) return false; - - socket_links_[s] = server; - return true; - } - - void dw::unlink_socket(const SOCKET sock) - { - std::lock_guard _(server_mutex_); - - const auto server = socket_links_.find(sock); - if (server != socket_links_.end()) - { - socket_links_.erase(server); - } - - const auto dgram_packets = datagram_packets_.find(sock); - if (dgram_packets != datagram_packets_.end()) - { - datagram_packets_.erase(dgram_packets); - } - } - - int dw::recv_datagam_packet(const SOCKET s, char* buf, const int len, sockaddr* from, int* fromlen) - { - std::unique_lock lock(server_mutex_); - - auto queue = datagram_packets_.find(s); - if (queue != datagram_packets_.end()) - { - const bool blocking = is_blocking_socket(s, UDP_BLOCKING); - - lock.unlock(); - while (blocking && queue->second.empty()) - { - std::this_thread::sleep_for(1ms); - } - lock.lock(); - - if (!queue->second.empty()) - { - auto packet = queue->second.front(); - queue->second.pop(); - - *fromlen = INT(packet.first.size()); - std::memcpy(from, packet.first.data(), *fromlen); - - const int size = std::min(len, INT(packet.second.size())); - std::memcpy(buf, packet.second.data(), size); - - return size; - } - - WSASetLastError(WSAEWOULDBLOCK); - return -1; - } - - return 0; - } - - void dw::send_datagram_packet(const SOCKET s, const std::string& data, const sockaddr* to, const int tolen) - { - std::lock_guard _(server_mutex_); - datagram_packets_[s].push({std::string(LPSTR(to), tolen), data}); - } - - bool dw::is_blocking_socket(const SOCKET s, const bool def) - { - std::lock_guard _(server_mutex_); - - if (blocking_sockets_.find(s) != blocking_sockets_.end()) - { - return blocking_sockets_[s]; - } - - return def; - } - - void dw::remove_blocking_socket(const SOCKET s) - { - std::lock_guard _(server_mutex_); - - const auto entry = blocking_sockets_.find(s); - if (entry != blocking_sockets_.end()) - { - blocking_sockets_.erase(entry); - } - } - - void dw::set_blocking_socket(const SOCKET s, const bool blocking) - { - std::lock_guard _(server_mutex_); - blocking_sockets_[s] = blocking; - } - - uint8_t* dw::get_key(const bool encrypt) - { - return encrypt ? encryption_key_ : decryption_key_; - } - - void dw::set_key(const bool encrypt, uint8_t* key) - { - static_assert(sizeof encryption_key_ == sizeof decryption_key_); - std::memcpy(encrypt ? encryption_key_ : decryption_key_, key, sizeof encryption_key_); - } - - void dw::server_thread() - { - terminate_ = false; - while (!terminate_) - { - std::unique_lock lock(server_mutex_); - - for (auto& server : servers_) - { - server.second->run_frame(); - } - - lock.unlock(); - - std::this_thread::sleep_for(50ms); - } - } - - void dw::pre_destroy() - { - std::lock_guard _(server_mutex_); - - terminate_ = true; - if (message_thread_.joinable()) - { - message_thread_.join(); - } - - servers_.clear(); - stun_servers_.clear(); - socket_links_.clear(); - blocking_sockets_.clear(); - datagram_packets_.clear(); - } - - dw::dw() - { - register_stun_server("mw3-stun.us.demonware.net"); - register_stun_server("mw3-stun.eu.demonware.net"); - register_stun_server("stun.jp.demonware.net"); - register_stun_server("stun.au.demonware.net"); - register_stun_server("stun.eu.demonware.net"); - register_stun_server("stun.us.demonware.net"); - - auto lsg_server = register_server("mw3-pc-lobby.prod.demonware.net"); - auto auth_server = register_server("mw3-pc-auth.prod.demonware.net"); - - auth_server->register_service(); - auth_server->register_service(); - auth_server->register_service(); - - lsg_server->register_service(); - lsg_server->register_service(); - lsg_server->register_service(); - lsg_server->register_service(); - /*lsg_server->register_service(); - lsg_server->register_service(); - lsg_server->register_service(); - lsg_server->register_service(); - lsg_server->register_service();*/ - } - - void dw::post_load() - { - message_thread_ = std::thread(server_thread); - - io::register_hook("send", io::send); - io::register_hook("recv", io::recv); - io::register_hook("sendto", io::send_to); - io::register_hook("recvfrom", io::recv_from); - io::register_hook("connect", io::connect); - io::register_hook("closesocket", io::close_socket); - io::register_hook("ioctlsocket", io::ioctl_socket); - io::register_hook("gethostbyname", io::get_host_by_name); - - utils::hook(SELECT_VALUE(0x6F40A0, 0x6EE1C0, 0x611310), bd_logger_stub, HOOK_JUMP).install()->quick(); - } - - void dw::bd_logger_stub(int /*type*/, const char* const /*channelName*/, const char*, const char* const /*file*/, - const char* const function, const unsigned int /*line*/, const char* const msg, ...) - { - char buffer[2048]; - - va_list ap; - va_start(ap, msg); - - vsnprintf_s(buffer, sizeof(buffer), _TRUNCATE, msg, ap); - printf("%s: %s\n", function, buffer); - - va_end(ap); - } - - REGISTER_MODULE(dw) -} +#include +#include "dw.hpp" +#include "utils/hook.hpp" +#include "game/game.hpp" +#include "utils/nt.hpp" +#include "utils/cryptography.hpp" + +#include "game/demonware/services/bdLSGHello.hpp" // 7 +#include "game/demonware/services/bdStorage.hpp" // 10 +#include "game/demonware/services/bdDediAuth.hpp" // 12 +#include "game/demonware/services/bdTitleUtilities.hpp" // 12 +#include "game/demonware/services/bdDML.hpp" // 27 +#include "game/demonware/services/bdDediRSAAuth.hpp" // 26 +#include "game/demonware/services/bdSteamAuth.hpp" // 28 + +namespace demonware +{ + namespace io + { + int __stdcall send_to(const SOCKET s, const char* buf, const int len, const int flags, const sockaddr* to, + const int tolen) + { + if (tolen == sizeof(sockaddr_in)) + { + const auto in_addr = reinterpret_cast(to); + const auto server = dw::find_stun_server_by_address(in_addr->sin_addr.s_addr); + if (server) return server->send(s, buf, len, to, tolen); + } + + return sendto(s, buf, len, flags, to, tolen); + } + + int __stdcall recv_from(const SOCKET s, char* buf, const int len, const int flags, sockaddr* from, int* fromlen) + { + auto res = dw::recv_datagam_packet(s, buf, len, from, fromlen); + if (res != 0) return res; + + res = recvfrom(s, buf, len, flags, from, fromlen); + + return res; + } + + int __stdcall send(const SOCKET s, const char* buf, const int len, const int flags) + { + auto server = dw::find_server_by_socket(s); + if (server) return server->send(buf, len); + + return ::send(s, buf, len, flags); + } + + int __stdcall recv(const SOCKET s, char* buf, const int len, const int flags) + { + auto server = dw::find_server_by_socket(s); + if (server) + { + const auto blocking = dw::is_blocking_socket(s, TCP_BLOCKING); + + int result; + do + { + result = server->recv(buf, len); + if (blocking && result < 0) std::this_thread::sleep_for(1ms); + } + while (blocking && result < 0); + + if (!blocking && result < 0) + { + WSASetLastError(WSAEWOULDBLOCK); + } + + return result; + } + + return ::recv(s, buf, len, flags); + } + + int __stdcall connect(const SOCKET s, const sockaddr* addr, const int len) + { + if (len == sizeof(sockaddr_in)) + { + const auto* in_addr = reinterpret_cast(addr); + if (dw::link_socket(s, in_addr->sin_addr.s_addr)) return 0; + } + + return ::connect(s, addr, len); + } + + int __stdcall close_socket(const SOCKET s) + { + dw::remove_blocking_socket(s); + dw::unlink_socket(s); + return closesocket(s); + } + + int __stdcall ioctl_socket(const SOCKET s, const long cmd, u_long* argp) + { + if (static_cast(cmd) == (FIONBIO)) + { + dw::set_blocking_socket(s, *argp == 0); + } + + return ioctlsocket(s, cmd, argp); + } + + hostent* __stdcall get_host_by_name(char* name) + { + static std::mutex mutex; + std::lock_guard _(mutex); + + unsigned long addr = 0; + const auto server = dw::find_server_by_name(name); + if (server) addr = server->get_address(); + + const auto stun_server = dw::find_stun_server_by_name(name); + if (stun_server) addr = stun_server->get_address(); + + if (server || stun_server) + { + static in_addr address; + address.s_addr = addr; + + static in_addr* addr_list[2]; + addr_list[0] = &address; + addr_list[1] = nullptr; + + static hostent host; + host.h_name = name; + host.h_aliases = nullptr; + host.h_addrtype = AF_INET; + host.h_length = sizeof(in_addr); + host.h_addr_list = reinterpret_cast(addr_list); + + return &host; + } + +#pragma warning(push) +#pragma warning(disable: 4996) + + // ReSharper disable once CppDeprecatedEntity + return gethostbyname(name); + +#pragma warning(pop) + } + + bool register_hook(const std::string& process, void* stub) + { + const utils::nt::module main; + + auto result = false; + result = result || utils::hook::iat(main, "wsock32.dll", process, stub); + result = result || utils::hook::iat(main, "WS2_32.dll", process, stub); + return result; + } + } +} + +namespace demonware +{ + bool dw::terminate_; + std::thread dw::message_thread_; + std::recursive_mutex dw::server_mutex_; + std::map dw::blocking_sockets_; + std::map> dw::socket_links_; + std::map> dw::servers_; + std::map> dw::stun_servers_; + std::map>> dw::datagram_packets_; + + uint8_t dw::encryption_key_[24]; + uint8_t dw::decryption_key_[24]; + + std::shared_ptr dw::find_server_by_name(const std::string& name) + { + std::lock_guard _(server_mutex_); + return find_server_by_address(utils::cryptography::jenkins_one_at_a_time::compute(name)); + } + + std::shared_ptr dw::find_server_by_address(const unsigned long address) + { + std::lock_guard _(server_mutex_); + + const auto server = servers_.find(address); + if (server != servers_.end()) + { + return server->second; + } + + return std::shared_ptr(); + } + + std::shared_ptr dw::find_stun_server_by_name(const std::string& name) + { + std::lock_guard _(server_mutex_); + return find_stun_server_by_address(utils::cryptography::jenkins_one_at_a_time::compute(name)); + } + + std::shared_ptr dw::find_stun_server_by_address(const unsigned long address) + { + std::lock_guard _(server_mutex_); + + const auto server = stun_servers_.find(address); + if (server != stun_servers_.end()) + { + return server->second; + } + + return std::shared_ptr(); + } + + std::shared_ptr dw::find_server_by_socket(const SOCKET s) + { + std::lock_guard _(server_mutex_); + + const auto server = socket_links_.find(s); + if (server != socket_links_.end()) + { + return server->second; + } + + return std::shared_ptr(); + } + + bool dw::link_socket(const SOCKET s, const unsigned long address) + { + std::lock_guard _(server_mutex_); + + const auto server = find_server_by_address(address); + if (!server) return false; + + socket_links_[s] = server; + return true; + } + + void dw::unlink_socket(const SOCKET sock) + { + std::lock_guard _(server_mutex_); + + const auto server = socket_links_.find(sock); + if (server != socket_links_.end()) + { + socket_links_.erase(server); + } + + const auto dgram_packets = datagram_packets_.find(sock); + if (dgram_packets != datagram_packets_.end()) + { + datagram_packets_.erase(dgram_packets); + } + } + + int dw::recv_datagam_packet(const SOCKET s, char* buf, const int len, sockaddr* from, int* fromlen) + { + std::unique_lock lock(server_mutex_); + + auto queue = datagram_packets_.find(s); + if (queue != datagram_packets_.end()) + { + const bool blocking = is_blocking_socket(s, UDP_BLOCKING); + + lock.unlock(); + while (blocking && queue->second.empty()) + { + std::this_thread::sleep_for(1ms); + } + lock.lock(); + + if (!queue->second.empty()) + { + auto packet = queue->second.front(); + queue->second.pop(); + + *fromlen = INT(packet.first.size()); + std::memcpy(from, packet.first.data(), *fromlen); + + const int size = std::min(len, INT(packet.second.size())); + std::memcpy(buf, packet.second.data(), size); + + return size; + } + + WSASetLastError(WSAEWOULDBLOCK); + return -1; + } + + return 0; + } + + void dw::send_datagram_packet(const SOCKET s, const std::string& data, const sockaddr* to, const int tolen) + { + std::lock_guard _(server_mutex_); + datagram_packets_[s].push({std::string(LPSTR(to), tolen), data}); + } + + bool dw::is_blocking_socket(const SOCKET s, const bool def) + { + std::lock_guard _(server_mutex_); + + if (blocking_sockets_.find(s) != blocking_sockets_.end()) + { + return blocking_sockets_[s]; + } + + return def; + } + + void dw::remove_blocking_socket(const SOCKET s) + { + std::lock_guard _(server_mutex_); + + const auto entry = blocking_sockets_.find(s); + if (entry != blocking_sockets_.end()) + { + blocking_sockets_.erase(entry); + } + } + + void dw::set_blocking_socket(const SOCKET s, const bool blocking) + { + std::lock_guard _(server_mutex_); + blocking_sockets_[s] = blocking; + } + + uint8_t* dw::get_key(const bool encrypt) + { + return encrypt ? encryption_key_ : decryption_key_; + } + + void dw::set_key(const bool encrypt, uint8_t* key) + { + static_assert(sizeof encryption_key_ == sizeof decryption_key_); + std::memcpy(encrypt ? encryption_key_ : decryption_key_, key, sizeof encryption_key_); + } + + void dw::server_thread() + { + terminate_ = false; + while (!terminate_) + { + std::unique_lock lock(server_mutex_); + + for (auto& server : servers_) + { + server.second->run_frame(); + } + + lock.unlock(); + + std::this_thread::sleep_for(50ms); + } + } + + void dw::pre_destroy() + { + std::lock_guard _(server_mutex_); + + terminate_ = true; + if (message_thread_.joinable()) + { + message_thread_.join(); + } + + servers_.clear(); + stun_servers_.clear(); + socket_links_.clear(); + blocking_sockets_.clear(); + datagram_packets_.clear(); + } + + dw::dw() + { + register_stun_server("mw3-stun.us.demonware.net"); + register_stun_server("mw3-stun.eu.demonware.net"); + register_stun_server("stun.jp.demonware.net"); + register_stun_server("stun.au.demonware.net"); + register_stun_server("stun.eu.demonware.net"); + register_stun_server("stun.us.demonware.net"); + + auto lsg_server = register_server("mw3-pc-lobby.prod.demonware.net"); + auto auth_server = register_server("mw3-pc-auth.prod.demonware.net"); + + auth_server->register_service(); + auth_server->register_service(); + auth_server->register_service(); + + lsg_server->register_service(); + lsg_server->register_service(); + lsg_server->register_service(); + lsg_server->register_service(); + /*lsg_server->register_service(); + lsg_server->register_service(); + lsg_server->register_service(); + lsg_server->register_service(); + lsg_server->register_service();*/ + } + + void dw::post_load() + { + message_thread_ = std::thread(server_thread); + + io::register_hook("send", io::send); + io::register_hook("recv", io::recv); + io::register_hook("sendto", io::send_to); + io::register_hook("recvfrom", io::recv_from); + io::register_hook("connect", io::connect); + io::register_hook("closesocket", io::close_socket); + io::register_hook("ioctlsocket", io::ioctl_socket); + io::register_hook("gethostbyname", io::get_host_by_name); + + //utils::hook(SELECT_VALUE(0x6F40A0, 0x6EE1C0, 0x611310), bd_logger_stub, HOOK_JUMP).install()->quick(); + } + + void dw::bd_logger_stub(int /*type*/, const char* const /*channelName*/, const char*, const char* const /*file*/, + const char* const function, const unsigned int /*line*/, const char* const msg, ...) + { + char buffer[2048]; + + va_list ap; + va_start(ap, msg); + + vsnprintf_s(buffer, sizeof(buffer), _TRUNCATE, msg, ap); + printf("%s: %s\n", function, buffer); + + va_end(ap); + } + + REGISTER_MODULE(dw) +} diff --git a/src/module/steam_proxy.cpp b/src/module/steam_proxy.cpp index a83c6ba..60a31df 100644 --- a/src/module/steam_proxy.cpp +++ b/src/module/steam_proxy.cpp @@ -12,18 +12,17 @@ class steam_proxy final : public module public: void post_start() override { - if (game::is_dedi()) return; - this->run_mod(); - this->load_client(); - - this->clean_up_on_error(); } void post_load() override { if (game::is_dedi()) return; + this->load_client(); + + this->clean_up_on_error(); + try { if (game::is_sp()) @@ -116,10 +115,8 @@ private: this->steam_pipe_ = this->steam_client_module_.invoke("Steam_CreateSteamPipe"); this->global_user_ = this->steam_client_module_.invoke("Steam_ConnectToGlobalUser", this->steam_pipe_); - this->client_user_ = this->client_engine_.invoke(8, this->steam_pipe_, this->global_user_, - "CLIENTUSER_INTERFACE_VERSION001"); // GetIClientUser - this->client_utils_ = this->client_engine_.invoke(13, this->steam_pipe_, - "CLIENTUTILS_INTERFACE_VERSION001"); // GetIClientUtils + this->client_user_ = this->client_engine_.invoke(8, this->steam_pipe_, this->global_user_); // GetIClientUser + this->client_utils_ = this->client_engine_.invoke(13, this->steam_pipe_); // GetIClientUtils } void start_mod(const std::string& title, size_t app_id) @@ -175,4 +172,4 @@ private: } }; -//REGISTER_MODULE(steam_proxy) +REGISTER_MODULE(steam_proxy)