From 8b85399de591d55d4599fb3c6d790f47cd1b5307 Mon Sep 17 00:00:00 2001 From: project-bo4 Date: Wed, 12 Jul 2023 00:03:55 -0700 Subject: [PATCH] Added Blackbox --- README.md | 27 +++- .../component/{exception.cpp => blackbox.cpp} | 136 +++++++++++++++--- 2 files changed, 141 insertions(+), 22 deletions(-) rename source/proxy-dll/component/{exception.cpp => blackbox.cpp} (53%) diff --git a/README.md b/README.md index 7218be1..60ff4bf 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ + ![code](https://raw.githubusercontent.com/project-bo4/shield-development/master/assets/readme_header.jpg) ## SHIELD @@ -9,12 +10,19 @@ As of May11, 2023 we merged 'demonware' branch into 'master'. it includes a buil ## INSTRUCTION --- you should have publisher files required for play online under LPC folder of your game installation. if its not the case then start original game through battlenet launcher once to get those downloaded. + +> you should have publisher files required for playing online under LPC folder of your game directory. +> if its not the case then start original game through battlenet launcher once to get those downloaded. 1- clone repository with its sub-modules and use generate.bat to make visual studio solution then compile project and copy ``d3d11.dll`` into your bo4 folder. 2- start BlackOps4.exe +*in case you wanted to revert back to original battlenet servers just delete ``d3d11.dll``. you can put it back later whenever you want to re-install client.* + + +## SUBMITTING ISSUES +github issues section is only for reporting programmatically errors of client. please dont use it for requesting features or seeking help with personal issues such as faulty game data or similar problems. use battlenet's scan and repair feature to fix those problems. ## NOTES @@ -22,4 +30,19 @@ As of May11, 2023 we merged 'demonware' branch into 'master'. it includes a buil - There are some 3rd-party project/tools that have influenced and helped the project in particular ways; If you belive there is something originated from you and want to be credited please contact any of our social media accounts. -- This Project is created purely for educational purposes. its free and open-sourced under gnu license. developers are not responsible or liable for misuse of this product. \ No newline at end of file +- This Project is created purely for educational purposes. its free and open-sourced under gnu license. developers are not responsible or liable for misuse of this product. + + +## Roadmap +### CLIENT-SIDE: +- [x] Online Battlenet Connection Requirement Removal +- [x] Built-in Demonware Server Emulation +- [x] BlackBox Crash Reporting Component +- [ ] Enable Aim-Assist for Game Controllers +- [ ] In-game Interactable Console +- [ ] Miscellaneous Features such as 1st person view fov + +### SERVER-SIDE: +- [X] Fully Functional Online Server Emulator +- [ ] Implement Basic Matchmaking with QOS Logics +- [ ] Try to Create Dedicated Server off Public Ship Builds diff --git a/source/proxy-dll/component/exception.cpp b/source/proxy-dll/component/blackbox.cpp similarity index 53% rename from source/proxy-dll/component/exception.cpp rename to source/proxy-dll/component/blackbox.cpp index 42f7ceb..b2c2912 100644 --- a/source/proxy-dll/component/exception.cpp +++ b/source/proxy-dll/component/blackbox.cpp @@ -9,7 +9,7 @@ #include #include -namespace exception +namespace blackbox { namespace { @@ -120,8 +120,101 @@ namespace exception return timestamp; } + const char* get_exception_string(DWORD exception) + { +#define EXCEPTION_CASE(CODE) case EXCEPTION_##CODE : return "EXCEPTION_" #CODE + switch (exception) + { + EXCEPTION_CASE(ACCESS_VIOLATION); + EXCEPTION_CASE(DATATYPE_MISALIGNMENT); + EXCEPTION_CASE(BREAKPOINT); + EXCEPTION_CASE(SINGLE_STEP); + EXCEPTION_CASE(ARRAY_BOUNDS_EXCEEDED); + EXCEPTION_CASE(FLT_DENORMAL_OPERAND); + EXCEPTION_CASE(FLT_DIVIDE_BY_ZERO); + EXCEPTION_CASE(FLT_INEXACT_RESULT); + EXCEPTION_CASE(FLT_INVALID_OPERATION); + EXCEPTION_CASE(FLT_OVERFLOW); + EXCEPTION_CASE(FLT_STACK_CHECK); + EXCEPTION_CASE(FLT_UNDERFLOW); + EXCEPTION_CASE(INT_DIVIDE_BY_ZERO); + EXCEPTION_CASE(INT_OVERFLOW); + EXCEPTION_CASE(PRIV_INSTRUCTION); + EXCEPTION_CASE(IN_PAGE_ERROR); + EXCEPTION_CASE(ILLEGAL_INSTRUCTION); + EXCEPTION_CASE(NONCONTINUABLE_EXCEPTION); + EXCEPTION_CASE(STACK_OVERFLOW); + EXCEPTION_CASE(INVALID_DISPOSITION); + EXCEPTION_CASE(GUARD_PAGE); + EXCEPTION_CASE(INVALID_HANDLE); + default: + return "UNKNOWN"; + } +#undef EXCEPTION_CASE + } + + std::string get_memory_registers(const LPEXCEPTION_POINTERS exceptioninfo) + { + if (IsBadReadPtr(exceptioninfo, sizeof(EXCEPTION_POINTERS))) + return ""; + + const auto* ctx = exceptioninfo->ContextRecord; + + std::string registers_scroll{}; + registers_scroll.append("registers:\r\n{\r\n"); + + const auto x64register = [®isters_scroll](const char* key, DWORD64 value) + { + registers_scroll.append(utils::string::va("\t%s = 0x%llX\r\n", key, value)); + }; + + x64register("rax", ctx->Rax); + x64register("rbx", ctx->Rbx); + x64register("rcx", ctx->Rcx); + x64register("rdx", ctx->Rdx); + x64register("rsp", ctx->Rsp); + x64register("rbp", ctx->Rbp); + x64register("rsi", ctx->Rsi); + x64register("rdi", ctx->Rdi); + x64register("r8", ctx->R8); + x64register("r9", ctx->R9); + x64register("r10", ctx->R10); + x64register("r11", ctx->R11); + x64register("r12", ctx->R12); + x64register("r13", ctx->R13); + x64register("r14", ctx->R14); + x64register("r15", ctx->R15); + x64register("rip", ctx->Rip); + + registers_scroll.append("}"); + + return registers_scroll; + } + + std::string get_callstack_summary(int trace_max_depth = 18) + { + std::string callstack_scroll("callstack:\r\n{\r\n"); + void* stack[32]; if (trace_max_depth > 32) trace_max_depth = 32; + uint16_t count = RtlCaptureStackBackTrace(1, trace_max_depth, stack, NULL); + + for (uint16_t i = 0; i < count; i++) + { + const auto prnt = utils::nt::library::get_by_address(stack[i]); + size_t rva = reinterpret_cast(stack[i]) - reinterpret_cast(prnt.get_ptr()); + + callstack_scroll.append(std::format("\t{}: {:012X}\r\n", prnt.get_name(), rva)); + } + callstack_scroll.append("}"); + + return callstack_scroll; + } + std::string generate_crash_info(const LPEXCEPTION_POINTERS exceptioninfo) { + const auto main_module = utils::nt::library{}; + const auto& build_info = game::version_string; + const auto thread_id = ::GetCurrentThreadId(); // TODO: Find Thread's Name + std::string info{}; const auto line = [&info](const std::string& text) { @@ -129,35 +222,38 @@ namespace exception info.append("\r\n"); }; - line("Project-BO4 Crash Dump"); - line(""); - line(game::version_string); - //line("Version: "s + VERSION); - line("Timestamp: "s + get_timestamp()); - line(utils::string::va("Exception: 0x%08X", exceptioninfo->ExceptionRecord->ExceptionCode)); - line(utils::string::va("Address: 0x%llX", exceptioninfo->ExceptionRecord->ExceptionAddress)); - line(utils::string::va("Base: 0x%llX", get_base())); + line(build_info + " Crash Report\r\n"); -#pragma warning(push) -#pragma warning(disable: 4996) - OSVERSIONINFOEXA version_info; - ZeroMemory(&version_info, sizeof(version_info)); - version_info.dwOSVersionInfoSize = sizeof(version_info); - GetVersionExA(reinterpret_cast(&version_info)); -#pragma warning(pop) + line(utils::string::va("Exception Code: 0x%08X(%s)", exceptioninfo->ExceptionRecord->ExceptionCode, + get_exception_string(exceptioninfo->ExceptionRecord->ExceptionCode))); + line(utils::string::va("Exception Addr: 0x%llX[%s]", exceptioninfo->ExceptionRecord->ExceptionAddress, + utils::nt::library::get_by_address(exceptioninfo->ExceptionRecord->ExceptionAddress).get_name().c_str())); + line(utils::string::va("Main Module: %s[0x%llX]", main_module.get_name().c_str(), main_module.get_ptr())); + line(utils::string::va("Thread ID: %d(%s)", GetCurrentThreadId(), is_game_thread() ? "Main Thread" : "Auxiliary Threads")); - line(utils::string::va("OS Version: %u.%u", version_info.dwMajorVersion, version_info.dwMinorVersion)); + if (exceptioninfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) + { + line(utils::string::va("\r\nExtended Info: Attempted to %s 0x%012X", + exceptioninfo->ExceptionRecord->ExceptionInformation[0] == 1 ? "write to" : "read from", + exceptioninfo->ExceptionRecord->ExceptionInformation[1])); + } + + line("\r\n"); + line(get_callstack_summary(18)); + line(get_memory_registers(exceptioninfo)); + + line("\r\nTimestamp: "s + get_timestamp()); return info; } void write_minidump(const LPEXCEPTION_POINTERS exceptioninfo) { - const std::string crash_name = utils::string::va("minidumps/bo4-crash-%s.zip", + const std::string crash_name = utils::string::va("minidumps/shield-crash-%s.zip", get_timestamp().data()); utils::compression::zip::archive zip_file{}; - zip_file.add("crash.dmp", create_minidump(exceptioninfo)); + zip_file.add("crash.dmp", exception::create_minidump(exceptioninfo)); zip_file.add("info.txt", generate_crash_info(exceptioninfo)); zip_file.write(crash_name, "Project-bo4 Crash Dump"); } @@ -210,4 +306,4 @@ namespace exception }; } -REGISTER_COMPONENT(exception::component) \ No newline at end of file +REGISTER_COMPONENT(blackbox::component) \ No newline at end of file