diff --git a/src/Components/Modules/Exception.cpp b/src/Components/Modules/Exception.cpp index cf2ce4d9..3a70b3e4 100644 --- a/src/Components/Modules/Exception.cpp +++ b/src/Components/Modules/Exception.cpp @@ -9,6 +9,26 @@ namespace Components { + void Exception::UploadMinidump(std::string filename) + { +// Utils::WebIO webio("Firefucks", UPLOAD_URL); +// +// if (Utils::IO::FileExists(filename)) +// { +// std::string buffer = Utils::IO::ReadFile(filename); +// std::string result = webio.PostFile(buffer); +// +// MessageBoxA(0, result.data(), "Minidump", 0); +// } + +// mg_mgr mgr; +// mg_mgr_init(&mgr, NULL); +// +// mg_connect_http +// +// mg_mgr_free(&mgr); + } + LONG WINAPI Exception::ExceptionFilter(LPEXCEPTION_POINTERS ExceptionInfo) { char filename[MAX_PATH]; @@ -23,11 +43,13 @@ namespace Components if (hFile && hFile != INVALID_HANDLE_VALUE) { - MINIDUMP_EXCEPTION_INFORMATION ex = { GetCurrentThreadId(),ExceptionInfo, FALSE }; + MINIDUMP_EXCEPTION_INFORMATION ex = { GetCurrentThreadId(), ExceptionInfo, FALSE }; MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &ex, NULL, NULL); CloseHandle(hFile); } + Exception::UploadMinidump(filename); + if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW) { Logger::Error("Termination because of a stack overflow.\n"); @@ -35,7 +57,7 @@ namespace Components } else { - Logger::Error("Fatal error (0x%08x) at 0x%08x.", ExceptionInfo->ExceptionRecord->ExceptionCode, ExceptionInfo->ExceptionRecord->ExceptionAddress); + Logger::Error("Fatal error (0x%08X) at 0x%08X.", ExceptionInfo->ExceptionRecord->ExceptionCode, ExceptionInfo->ExceptionRecord->ExceptionAddress); } return EXCEPTION_CONTINUE_SEARCH; diff --git a/src/Components/Modules/Exception.hpp b/src/Components/Modules/Exception.hpp index af0b04df..c9f3c5d0 100644 --- a/src/Components/Modules/Exception.hpp +++ b/src/Components/Modules/Exception.hpp @@ -1,13 +1,17 @@ -namespace Components -{ - class Exception : public Component - { - public: - Exception(); - const char* GetName() { return "Exception"; }; - - private: - static LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS ExceptionInfo); - static LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilterStub(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter); - }; -} +#define UPLOAD_URL "https://momo5502.com/test/upload.php" + +namespace Components +{ + class Exception : public Component + { + public: + Exception(); + const char* GetName() { return "Exception"; }; + + private: + static LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS ExceptionInfo); + static LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilterStub(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter); + + static void UploadMinidump(std::string filename); + }; +} diff --git a/src/Components/Modules/QuickPatch.cpp b/src/Components/Modules/QuickPatch.cpp index 2c1a4a07..6a48aab8 100644 --- a/src/Components/Modules/QuickPatch.cpp +++ b/src/Components/Modules/QuickPatch.cpp @@ -331,6 +331,11 @@ namespace Components QuickPatch::UnlockStats(); }); + Command::Add("crash", [] (Command::Params params) + { + throw new std::exception(); + }); + // Debug patches #ifdef DEBUG diff --git a/src/Components/Modules/Renderer.cpp b/src/Components/Modules/Renderer.cpp index 8125ec8c..ea5cdc00 100644 --- a/src/Components/Modules/Renderer.cpp +++ b/src/Components/Modules/Renderer.cpp @@ -1,57 +1,118 @@ -#include "STDInclude.hpp" - -namespace Components -{ - Utils::Hook Renderer::DrawFrameHook; - wink::signal> Renderer::FrameSignal; - wink::signal> Renderer::FrameOnceSignal; - - void __declspec(naked) Renderer::FrameHook() - { - __asm - { - call Renderer::FrameHandler - jmp Renderer::DrawFrameHook.Original - } - } - - void Renderer::FrameHandler() - { - Renderer::FrameSignal(); - Renderer::FrameOnceSignal(); - Renderer::FrameOnceSignal.clear(); - } - - void Renderer::Once(Renderer::Callback* callback) - { - Renderer::FrameOnceSignal.connect(callback); - } - - void Renderer::OnFrame(Renderer::Callback* callback) - { - Renderer::FrameSignal.connect(callback); - } - - int Renderer::Width() - { - return Utils::Hook::Get(0x66E1C68); - } - - int Renderer::Height() - { - return Utils::Hook::Get(0x66E1C6C); - } - - Renderer::Renderer() - { - // Frame hook - Renderer::DrawFrameHook.Initialize(0x5ACB99, Renderer::FrameHook, HOOK_CALL)->Install(); - } - - Renderer::~Renderer() - { - Renderer::DrawFrameHook.Uninstall(); - Renderer::FrameOnceSignal.clear(); - Renderer::FrameSignal.clear(); - } -} +#include "STDInclude.hpp" + +namespace Components +{ + Utils::Hook Renderer::DrawFrameHook; + wink::signal> Renderer::FrameSignal; + wink::signal> Renderer::FrameOnceSignal; + wink::signal> Renderer::BackendFrameSignal; + + void __declspec(naked) Renderer::FrameStub() + { + __asm + { + call Renderer::FrameHandler + jmp Renderer::DrawFrameHook.Original + } + } + + void Renderer::FrameHandler() + { + Renderer::FrameSignal(); + Renderer::FrameOnceSignal(); + Renderer::FrameOnceSignal.clear(); + } + + void __declspec(naked) Renderer::BackendFrameStub() + { + __asm + { + call Renderer::BackendFrameHandler + + mov eax, ds:66E1BF0h + mov ecx, 536A85h + jmp ecx + } + } + + void Renderer::BackendFrameHandler() + { + IDirect3DDevice9* device = *Game::dx_ptr; + + if (device) + { + device->AddRef(); + Renderer::BackendFrameSignal(device); + device->Release(); + } + } + + void Renderer::Once(Renderer::Callback* callback) + { + Renderer::FrameOnceSignal.connect(callback); + } + + void Renderer::OnFrame(Renderer::Callback* callback) + { + Renderer::FrameSignal.connect(callback); + } + + void Renderer::OnBackendFrame(Renderer::BackendCallback* callback) + { + Renderer::BackendFrameSignal.connect(callback); + } + + int Renderer::Width() + { + return Utils::Hook::Get(0x66E1C68); + } + + int Renderer::Height() + { + return Utils::Hook::Get(0x66E1C6C); + } + + Renderer::Renderer() + { +// Renderer::OnBackendFrame([] (IDirect3DDevice9* device) +// { +// if (Game::Sys_Milliseconds() % 2) +// { +// device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, 0, 0, 0); +// } +// +// return; +// +// IDirect3DSurface9* buffer = nullptr; +// +// device->CreateOffscreenPlainSurface(Renderer::Width(), Renderer::Height(), D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &buffer, nullptr); +// device->GetFrontBufferData(0, buffer); +// +// if (buffer) +// { +// D3DSURFACE_DESC desc; +// D3DLOCKED_RECT lockedRect; +// +// buffer->GetDesc(&desc); +// +// HRESULT res = buffer->LockRect(&lockedRect, NULL, D3DLOCK_READONLY); +// +// +// buffer->UnlockRect(); +// } +// }); + + // Frame hook + Renderer::DrawFrameHook.Initialize(0x5ACB99, Renderer::FrameStub, HOOK_CALL)->Install(); + + Utils::Hook(0x536A80, Renderer::BackendFrameStub, HOOK_JUMP).Install()->Quick(); + } + + Renderer::~Renderer() + { + Renderer::DrawFrameHook.Uninstall(); + Renderer::BackendFrameSignal.clear(); + Renderer::FrameOnceSignal.clear(); + Renderer::FrameSignal.clear(); + } +} diff --git a/src/Components/Modules/Renderer.hpp b/src/Components/Modules/Renderer.hpp index 4b703cf1..99f57488 100644 --- a/src/Components/Modules/Renderer.hpp +++ b/src/Components/Modules/Renderer.hpp @@ -1,26 +1,32 @@ -namespace Components -{ - class Renderer : public Component - { - public: - typedef void(Callback)(); - - Renderer(); - ~Renderer(); - const char* GetName() { return "Renderer"; }; - - static int Width(); - static int Height(); - - static void Once(Callback* callback); - static void OnFrame(Callback* callback); - - private: - static void FrameHook(); - static void FrameHandler(); - - static wink::signal> FrameSignal; - static wink::signal> FrameOnceSignal; - static Utils::Hook DrawFrameHook; - }; -} +namespace Components +{ + class Renderer : public Component + { + public: + typedef void(Callback)(); + typedef void(BackendCallback)(IDirect3DDevice9*); + + Renderer(); + ~Renderer(); + const char* GetName() { return "Renderer"; }; + + static int Width(); + static int Height(); + + static void Once(Callback* callback); + static void OnFrame(Callback* callback); + static void OnBackendFrame(BackendCallback* callback); + + private: + static void FrameStub(); + static void FrameHandler(); + + static void BackendFrameStub(); + static void BackendFrameHandler(); + + static wink::signal> FrameSignal; + static wink::signal> FrameOnceSignal; + static wink::signal> BackendFrameSignal; + static Utils::Hook DrawFrameHook; + }; +} diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index 571fb1b0..62aa1ee4 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -230,6 +230,9 @@ namespace Game SpawnVar* spawnVars = (SpawnVar*)0x1A83DE8; MapEnts** marMapEntsPtr = (MapEnts**)0x112AD34; + IDirect3D9** d3d9 = (IDirect3D9**)0x66DEF84; + IDirect3DDevice9** dx_ptr = (IDirect3DDevice9**)0x66DEF88; + XAssetHeader ReallocateAssetPool(XAssetType type, unsigned int newSize) { int elSize = DB_GetXAssetSizeHandlers[type](); diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index 30fc95cd..18c3adbf 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -459,6 +459,9 @@ namespace Game extern SpawnVar* spawnVars; extern MapEnts** marMapEntsPtr; + extern IDirect3D9** d3d9; + extern IDirect3DDevice9** dx_ptr; + XAssetHeader ReallocateAssetPool(XAssetType type, unsigned int newSize); void Menu_FreeItemMemory(Game::itemDef_t* item); const char* TableLookup(StringTable* stringtable, int row, int column); diff --git a/src/Utils/WebIO.cpp b/src/Utils/WebIO.cpp index 064cdc3f..5a6e01a7 100644 --- a/src/Utils/WebIO.cpp +++ b/src/Utils/WebIO.cpp @@ -134,6 +134,29 @@ namespace Utils return body; } + std::string WebIO::PostFile(std::string url, std::string data) + { + WebIO::SetURL(url); + return WebIO::PostFile(data); + } + + std::string WebIO::PostFile(std::string data) + { + WebIO::Params headers; + + std::string boundary = "xxxxxxxxx"; + headers["Content-Type"] = "multipart/form-data, boundary=" + boundary; + headers["Content-Length"] = fmt::sprintf("%u", data.size()); + + std::string body = "--" + boundary + "\r\n"; + body += "Content-Disposition: form-data; name=\"contents\"; filename=\"minidump.dmp\"\r\n"; + body += "Content-Type: application/octet-stream\r\n\r\n"; + body += data + "\r\n"; + body += "--" + boundary + "--"; + + return WebIO::Execute("POST", body, headers); + } + std::string WebIO::Post(std::string url, std::string body) { WebIO::SetURL(url); @@ -203,7 +226,7 @@ namespace Utils return this; } - std::string WebIO::Execute(const char* command, std::string body) + std::string WebIO::Execute(const char* command, std::string body, WebIO::Params headers) { if (!WebIO::OpenConnection()) return ""; @@ -225,8 +248,22 @@ namespace Utils return ""; } - const char* headers = "Content-type: application/x-www-form-urlencoded"; - HttpSendRequestA(WebIO::m_hFile, headers, strlen(headers), const_cast(body.data()), body.size() + 1); + if (headers.find("Content-type") == headers.end()) + { + headers["Content-type"] = "application/x-www-form-urlencoded"; + } + + std::string finalHeaders; + + for (auto i = headers.begin(); i != headers.end(); ++i) + { + finalHeaders.append(i->first); + finalHeaders.append(": "); + finalHeaders.append(i->second); + finalHeaders.append("\r\n"); + } + + HttpSendRequestA(WebIO::m_hFile, finalHeaders.data(), finalHeaders.size(), const_cast(body.data()), body.size() + 1); std::string returnBuffer; diff --git a/src/Utils/WebIO.hpp b/src/Utils/WebIO.hpp index ae47c9ac..a30c9331 100644 --- a/src/Utils/WebIO.hpp +++ b/src/Utils/WebIO.hpp @@ -1,105 +1,108 @@ -/* - This project is released under the GPL 2.0 license. - Some parts are based on research by Bas Timmer and the OpenSteamworks project. - Please do no evil. - - Initial author: (https://github.com/)momo5502 - Started: 2015-03-01 - Notes: - Small FTP and HTTP utility class using WinAPI -*/ - -namespace Utils -{ - class WebIO - { - public: - - typedef std::map Params; - - WebIO(); - WebIO(std::string useragent); - WebIO(std::string useragent, std::string url); - - ~WebIO(); - - void SetURL(std::string url); - void SetCredentials(std::string username, std::string password); - - std::string Post(std::string url, WebIO::Params params); - std::string Post(std::string url, std::string body); - std::string Post(WebIO::Params params); - std::string Post(std::string body); - - std::string Get(std::string url); - std::string Get(); - - WebIO* SetTimeout(DWORD mseconds); - - // FTP - bool Connect(); - void Disconnect(); // Not necessary - - bool SetDirectory(std::string directory); - bool SetRelativeDirectory(std::string directory); - bool GetDirectory(std::string &directory); - bool CreateDirectory(std::string directory); - bool DeleteDirectory(std::string directory); - bool RenameDirectory(std::string directory, std::string newDir); - - bool ListDirectories(std::string directory, std::vector &list); - bool ListFiles(std::string directory, std::vector &list); - - bool DeleteFile(std::string file); - bool RenameFile(std::string file, std::string newFile); - bool UploadFile(std::string file, std::string localfile); - bool DownloadFile(std::string file, std::string localfile); - - bool UploadFileData(std::string file, std::string data); - bool DownloadFileData(std::string file, std::string &data); - - private: - - enum Command - { - COMMAND_POST, - COMMAND_GET, - }; - - struct WebURL - { - std::string protocol; - std::string server; - std::string document; - std::string raw; - }; - - bool m_isFTP; - std::string m_username; - std::string m_password; - - WebURL m_sUrl; - - HINTERNET m_hSession; - HINTERNET m_hConnect; - HINTERNET m_hFile; - - DWORD m_timeout; - - std::string BuildPostBody(WebIO::Params params); - - bool IsSecuredConnection(); - - std::string Execute(const char* command, std::string body); - - bool ListElements(std::string directory, std::vector &list, bool files); - - void OpenSession(std::string useragent); - void CloseSession(); - - bool OpenConnection(); - void CloseConnection(); - - void FormatPath(std::string &path, bool win); /* if (win == true): / -> \\ */ - }; -} +/* + This project is released under the GPL 2.0 license. + Some parts are based on research by Bas Timmer and the OpenSteamworks project. + Please do no evil. + + Initial author: (https://github.com/)momo5502 + Started: 2015-03-01 + Notes: + Small FTP and HTTP utility class using WinAPI +*/ + +namespace Utils +{ + class WebIO + { + public: + + typedef std::map Params; + + WebIO(); + WebIO(std::string useragent); + WebIO(std::string useragent, std::string url); + + ~WebIO(); + + void SetURL(std::string url); + void SetCredentials(std::string username, std::string password); + + std::string PostFile(std::string url, std::string data); + std::string PostFile(std::string data); + + std::string Post(std::string url, WebIO::Params params); + std::string Post(std::string url, std::string body); + std::string Post(WebIO::Params params); + std::string Post(std::string body); + + std::string Get(std::string url); + std::string Get(); + + WebIO* SetTimeout(DWORD mseconds); + + // FTP + bool Connect(); + void Disconnect(); // Not necessary + + bool SetDirectory(std::string directory); + bool SetRelativeDirectory(std::string directory); + bool GetDirectory(std::string &directory); + bool CreateDirectory(std::string directory); + bool DeleteDirectory(std::string directory); + bool RenameDirectory(std::string directory, std::string newDir); + + bool ListDirectories(std::string directory, std::vector &list); + bool ListFiles(std::string directory, std::vector &list); + + bool DeleteFile(std::string file); + bool RenameFile(std::string file, std::string newFile); + bool UploadFile(std::string file, std::string localfile); + bool DownloadFile(std::string file, std::string localfile); + + bool UploadFileData(std::string file, std::string data); + bool DownloadFileData(std::string file, std::string &data); + + private: + + enum Command + { + COMMAND_POST, + COMMAND_GET, + }; + + struct WebURL + { + std::string protocol; + std::string server; + std::string document; + std::string raw; + }; + + bool m_isFTP; + std::string m_username; + std::string m_password; + + WebURL m_sUrl; + + HINTERNET m_hSession; + HINTERNET m_hConnect; + HINTERNET m_hFile; + + DWORD m_timeout; + + std::string BuildPostBody(WebIO::Params params); + + bool IsSecuredConnection(); + + std::string Execute(const char* command, std::string body, WebIO::Params headers = WebIO::Params()); + + bool ListElements(std::string directory, std::vector &list, bool files); + + void OpenSession(std::string useragent); + void CloseSession(); + + bool OpenConnection(); + void CloseConnection(); + + void FormatPath(std::string &path, bool win); /* if (win == true): / -> \\ */ + }; +}