feat: prepare new domain

This commit is contained in:
Diavolo 2023-12-02 21:01:06 +01:00
parent 101a900b52
commit 3601909e99
23 changed files with 133 additions and 247 deletions

View File

@ -1,117 +0,0 @@
name: Bug Report
description: File a bug report for any software defects on the BOIII client or BOIII dedicated servers.
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Thank you for taking the time to fill out and document any bugs. We appreciate it!
Please fill out this form accurately and provide as much detail as possible. Providing full errors, console output, crashdumps/minidumps, screenshots and videos are all helpful for identifying problems.
- type: dropdown
id: type
attributes:
label: Bug Type
description: "Please indicate whether this bug affects the client, server, and/or something else. **NOTE: Client means that the bug impacts players or private matches.**"
multiple: true
options:
- Client
- Dedicated Server
- Other
validations:
required: true
- type: dropdown
id: version
attributes:
label: BOIII Version
description: "What version of BOIII are you reporting this bug for?"
options:
- v0.0.1 (Latest)
validations:
required: true
- type: dropdown
id: environment
attributes:
label: Environment (Operating System)
description: |
Which environment are you using to report this bug? Please select multiple if you confirm the bug impacts multiple environments.
**IMPORTANT NOTE:** Microsoft Windows 7 and 32-bit operating systems are not supported by this project.
multiple: true
options:
- Linux
- Microsoft Windows 11 (64-Bit)
- Microsoft Windows 10 (64-Bit)
- Microsoft Windows 8.1 (64-Bit)
- Microsoft Windows 8 (64-Bit)
- Windows Server 2022
- Windows Server 2019
- Windows Server 2016
- SteamOS
validations:
required: true
- type: dropdown
id: reproducibility-rate
attributes:
label: Reproducibility Rate
description: "How many often have you or others been able to reproduce this bug/error, using the exact steps provided below?"
options:
- "High: The bug can (almost) always be reproduced"
- "Medium: The bug can be reproduced intermittently"
- "Low: The bug has only occurred once or a small number of times"
validations:
required: true
- type: textarea
id: steps-to-reproduce
attributes:
label: Steps to Reproduce
description: "How do you reproduce this bug? Please walk us through step-by-step:"
value: |
<!-- NOTE: If this bug occurs while running a mod, please specify the mod name and version number. If the bug occurs on a specific map(s) or gamemode(s), please indicate which ones. -->
1.
2.
3.
placeholder: |
<!-- NOTE: If this bug occurs while running a mod, please specify the mod name and version number. If the bug occurs on a specific map(s) or gamemode(s), please indicate which ones. -->
1.
2.
3.
validations:
required: true
- type: textarea
id: expected-result
attributes:
label: Expected Result
description: "If you followed the above steps, what do you believe *should* happen? What is the desired outcome?"
validations:
required: true
- type: textarea
id: actual-result
attributes:
label: Actual Result
description: "What happens when the 'Steps to Reproduce' are completed? Does the application crash? Does nothing happen at all? Is an error displayed?"
validations:
required: true
- type: textarea
id: proof
attributes:
label: (Optional) Proof and Additional Information
description: |
Please provide full errors, console output, crashdumps/minidumps, screenshots, errors, or additional information.
Files may be uploaded directly to this GitHub by dragging and dropping the attachment (or pasting them into this box). Please note that GitHub may reject certain file extensions, in which case it may be necessary to upload the files as a ZIP archive.
For large files and videos, please upload them and provide a link to Google Drive, MEGA, YouTube, etc.
- type: dropdown
id: severity
attributes:
label: Severity/Priority
description: "In your personal opinion, what severity or priority should be assigned to this bug?"
options:
- High/Critical
- Medium
- Minor
validations:
required: true

View File

@ -1,5 +0,0 @@
blank_issues_enabled: true
# contact_links:
# - name: "Community Support (Discord)"
# url: https://discord.com/
# about: "Join our Discord server to get help from the community with common errors and modding."

View File

@ -1,24 +0,0 @@
name: Feature Request or Suggestion
description: Open a feature request or give a suggestion for the BOIII project.
labels: ["feature"]
body:
- type: markdown
attributes:
value: |
Use this form to request new features or suggest modifications to existing features.
- type: checkboxes
id: i-did-the-search
attributes:
label: Duplicate Issue Check
description: "Please double-check the [current list of open and closed issues](../issues?q=is%3Aissue) to ensure that this has not been submitted before."
options:
- label: I have searched the list of issues on this repository. I confirm that this is not a duplicate of any open or closed issue(s).
validations:
required: true
- type: textarea
id: content
attributes:
label: "Your feature request or suggestion:"
placeholder: Something super cool goes here...
validations:
required: true

7
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,7 @@
version: 2
updates:
- package-ecosystem: gitsubmodule
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10

View File

@ -25,7 +25,7 @@ jobs:
- Release
steps:
- name: Check out files
uses: actions/checkout@v3.5.2
uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0
@ -36,7 +36,7 @@ jobs:
uses: microsoft/setup-msbuild@v1.3.1
- name: Generate project files
run: tools/premake5 vs2022 --no-check
run: tools/premake5 vs2022
- name: Set up problem matching
uses: ammaraskar/msvc-problem-matcher@master
@ -46,7 +46,7 @@ jobs:
- name: Upload ${{matrix.configuration}} symbols
if: matrix.configuration == 'Release' && github.repository_owner == 'momo5502' && github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop')
uses: actions/upload-artifact@v3.1.2
uses: actions/upload-artifact@v3.1.3
with:
name: ${{matrix.configuration}} Symbols
path: |
@ -54,7 +54,7 @@ jobs:
- name: Upload ${{matrix.configuration}} binary
if: matrix.configuration == 'Release' && github.repository_owner == 'momo5502' && github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop')
uses: actions/upload-artifact@v3.1.2
uses: actions/upload-artifact@v3.1.3
with:
name: ${{matrix.configuration}} Binary
path: |
@ -62,7 +62,7 @@ jobs:
- name: Upload ${{matrix.configuration}} data artifacts
if: matrix.configuration == 'Release' && github.repository_owner == 'momo5502' && github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop')
uses: actions/upload-artifact@v3.1.2
uses: actions/upload-artifact@v3.1.3
with:
name: ${{matrix.configuration}} data artifacts
path: |
@ -72,19 +72,11 @@ jobs:
name: Deploy artifacts
needs: build
runs-on: ubuntu-latest
if: github.repository_owner == 'momo5502' && github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop')
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop')
steps:
- name: Setup environment
run: echo "BOIII_MASTER_PATH=${{ secrets.BOIII_MASTER_SSH_PATH }}" >> $GITHUB_ENV
#- name: Setup main environment
# if: github.ref == 'refs/heads/main'
# run: echo "BOIII_MASTER_PATH=${{ secrets.BOIII_MASTER_SSH_PATH }}" >> $GITHUB_ENV
#- name: Setup develop environment
# if: github.ref == 'refs/heads/develop'
# run: echo "BOIII_MASTER_PATH=${{ secrets.BOIII_MASTER_SSH_PATH_DEV }}" >> $GITHUB_ENV
- name: Download Release binaries
uses: actions/download-artifact@v3.0.2
with:
@ -97,7 +89,7 @@ jobs:
path: data
- name: Install SSH key
uses: shimataro/ssh-key-action@v2.5.1
uses: shimataro/ssh-key-action@v2.6.1
with:
key: ${{ secrets.BOIII_MASTER_SSH_PRIVATE_KEY }}
known_hosts: "just-a-placeholder-so-we-dont-get-errors"
@ -121,7 +113,7 @@ jobs:
run: echo "" > boiii.exe
- name: Cleanup
uses: actions/upload-artifact@v3.1.2
uses: actions/upload-artifact@v3.1.3
with:
name: Release Binary
retention-days: 1

View File

@ -1,17 +0,0 @@
name: Notify Discord
on:
push:
branches:
- "*"
issues:
jobs:
notify:
runs-on: ubuntu-latest
if: github.repository_owner == 'momo5502'
steps:
- name: Send notification to Discord
uses: Ilshidur/action-discord@master
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_CI_BOT_WEBHOOK }}

7
.gitmodules vendored
View File

@ -22,12 +22,13 @@
[submodule "deps/udis86"]
path = deps/udis86
url = https://github.com/vmt/udis86.git
[submodule "deps/discord-rpc"]
path = deps/discord-rpc
url = https://github.com/momo5502/discord-rpc.git
[submodule "deps/stb"]
path = deps/stb
url = https://github.com/nothings/stb.git
[submodule "deps/curl"]
path = deps/curl
branch = curl-8_4_0
url = https://github.com/curl/curl.git
[submodule "deps/discord-rpc"]
path = deps/discord-rpc
url = https://github.com/discord/discord-rpc.git

View File

@ -1,16 +1,8 @@
[![build](https://img.shields.io/github/actions/workflow/status/momo5502/boiii/build.yml?branch=main&label=Build&logo=github)](https://github.com/momo5502/boiii/actions)
[![bugs](https://img.shields.io/github/issues/momo5502/boiii/bug?label=Bugs)](https://github.com/momo5502/boiii/issues?q=is%3Aissue+is%3Aopen+label%3Abug)
[![github](https://img.shields.io/badge/GitHub-support-c96198.svg?logo=github)](https://github.com/sponsors/momo5502)
[![patreon](https://img.shields.io/badge/Patreon-support-red.svg?logo=patreon)](https://www.patreon.com/xlabsproject)
# What is BOIII ☄️
BOIII is a game modification for Call of Duty: Black Ops 3.
The Steam version of Black Ops 3 is required to be owned and installed for BOIII to work. You can get it from <a href="https://store.steampowered.com/app/311210/Call_of_Duty_Black_Ops_III/">here</a>.
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQeSXYzQITJrcjiifN1nqX1fsVE7VwLZ3vl2g&usqp=CAU">
## Writeups & Articles
- <a href="https://momo5502.com/posts/2022-11-17-reverse-engineering-integrity-checks-in-black-ops-3/">Reverse engineering integrity checks in Black Ops 3</a>

2
deps/curl vendored

@ -1 +1 @@
Subproject commit a64d7de61af5fb94b70972cd0981020e729c1499
Subproject commit 586e3c19cd408379d9bca72e86393154661e34c3

2
deps/minhook vendored

@ -1 +1 @@
Subproject commit 0f25a2449b3cf878bcbdbf91b693c38149ecf029
Subproject commit f5485b8454544c2f034c78f8f127c1d03dea3636

2
deps/rapidjson vendored

@ -1 +1 @@
Subproject commit 973dc9c06dcd3d035ebd039cfb9ea457721ec213
Subproject commit f9d53419e912910fd8fa57d5705fa41425428c35

View File

@ -77,11 +77,6 @@ newoption {
description = "Enable development builds of the client."
}
newoption {
trigger = "no-check",
description = "Disable ownership checks."
}
newaction {
trigger = "version",
@ -244,15 +239,11 @@ workspace "boiii"
staticruntime "On"
editandcontinue "Off"
warnings "Extra"
characterset "ASCII"
characterset "ASCII"
if _OPTIONS["dev-build"] then
defines {"DEV_BUILD"}
end
if _OPTIONS["no-check"] then
defines {"NO_CHECK"}
end
if os.getenv("CI") then
defines {"CI"}

View File

@ -214,6 +214,26 @@ namespace auth
distribute_player_xuid(target, player_index, xuid);
}
bool is_invalid_char(const int c)
{
if (c == '%')
{
return true;
}
if (c == '~')
{
return true;
}
if (c < 32 || c > 126)
{
return true;
}
return false;
}
void dispatch_connect_packet(const game::netadr_t& target, const std::string& data)
{
utils::byte_buffer buffer(data);
@ -255,6 +275,22 @@ namespace auth
return;
}
const auto name = info_string.get("name");
const auto is_name_invalid = [&name]() -> bool
{
return std::ranges::any_of(name, [](const auto c)
{
return is_invalid_char(c);
});
};
if (name.empty() || is_name_invalid())
{
network::send(target, "error", "Bad name");
return;
}
profile_infos::add_and_distribute_profile_info(target, xuid, info);
game::SV_DirectConnect(target);

View File

@ -58,7 +58,7 @@ namespace chat
void send_chat_message(int client_num, const std::string& text)
{
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE_0, utils::string::va("v \"%Iu %d %d %s\"", -1, 0, 0, text.data()));
game::SV_GameSendServerCommand(client_num, game::SV_CMD_CAN_IGNORE_0, utils::string::va("v \"%Iu %d %d %s\"", -1, 0, 0, text.data()));
}
// This function has probably a different name

View File

@ -1,9 +1,9 @@
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "game/game.hpp"
#include <utils/hook.hpp>
#include <utils/string.hpp>
namespace dedicated_patches
{
@ -77,6 +77,16 @@ namespace dedicated_patches
return clients[client_num].xuid;
}
void info_set_value_for_key_stub(char* s, const char* key, [[maybe_unused]] const char* value)
{
game::Info_SetValueForKey(s, key, "Unknown Soldier");
}
const char* va_stub([[maybe_unused]] const char* fmt, const char* name, [[maybe_unused]] const int client_num)
{
return utils::string::va("%s", name);
}
}
struct component final : server_component
@ -106,6 +116,20 @@ namespace dedicated_patches
// Stop executing default_dedicated.cfg & language_settings.cfg
utils::hook::set<uint8_t>(0x1405063C0_g, 0xC3);
// change 32 character max name limit to 15
// SV_UserinfoChanged
utils::hook::set<uint8_t>(0x14053136A_g, 15);
// G_ClientSessionInfoChanged
utils::hook::set<uint8_t>(0x1402799E9_g, 15);
utils::hook::set<uint8_t>(0x140279A04_g, 15);
utils::hook::set<uint8_t>(0x140279A21_g, 15);
utils::hook::set<uint8_t>(0x140279A85_g, 15);
// Disable Unknown Soldier with a number
utils::hook::call(0x140531311_g, info_set_value_for_key_stub);
utils::hook::call(0x1405311E0_g, va_stub);
utils::hook::call(0x140531227_g, va_stub);
}
};
}

View File

@ -19,7 +19,6 @@ namespace discord
ZeroMemory(&discord_presence, sizeof(discord_presence));
discord_presence.instance = 1;
//discord_presence.state = "BOIII";
discord_presence.partySize = 0;
discord_presence.partyMax = 0;
@ -48,7 +47,7 @@ namespace discord
handlers.spectateGame = nullptr;
handlers.joinRequest = nullptr;
Discord_Initialize("1047539933922988112", &handlers, 1, nullptr);
Discord_Initialize("1180599439862272060", &handlers, 1, nullptr);
this->initialized_ = true;

View File

@ -1,17 +1,17 @@
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "scheduler.hpp"
#include "game/game.hpp"
#include "game/fragment_handler.hpp"
#include "command.hpp"
#include "network.hpp"
#include "party.hpp"
#include "scheduler.hpp"
#include <utils/hook.hpp>
#include <utils/string.hpp>
#include <utils/finally.hpp>
#include "network.hpp"
#include "game/fragment_handler.hpp"
namespace network
{
namespace
@ -24,7 +24,7 @@ namespace network
return callbacks;
}
uint64_t handle_command(const game::netadr_t* address, const char* command, const game::msg_t* message)
int64_t handle_command(const game::netadr_t* address, const char* command, const game::msg_t* message)
{
const auto cmd_string = utils::string::to_lower(command);
auto& callbacks = get_callbacks();
@ -32,7 +32,7 @@ namespace network
const auto offset = cmd_string.size() + 5;
if (message->cursize < 0 || static_cast<size_t>(message->cursize) < offset || handler == callbacks.end())
{
return 1;
return TRUE;
}
const std::basic_string_view data(message->data + offset, message->cursize - offset);
@ -49,18 +49,24 @@ namespace network
{
}
return 0;
return FALSE;
}
bool cl_dispatch_connectionless_packet_stub([[maybe_unused]] int local_client_num, game::netadr_t from, game::msg_t* msg, [[maybe_unused]] int time)
{
const command::params params;
const auto* c = params.get(0);
return handle_command(&from, c, msg) == TRUE;
}
void handle_command_stub(utils::hook::assembler& a)
{
const auto sv = game::is_server();
a.pushad64();
a.mov(rdx, rcx); // command
a.mov(r8, sv ? r15 : r12); // msg
a.mov(rcx, sv ? r14 : r15); // address
a.mov(r8, r12); // msg
a.mov(rcx, r15); // address
a.call_aligned(handle_command);
@ -108,9 +114,7 @@ namespace network
{
server_addr.sin_port = htons(port++);
if (++retries > 10) return;
}
while (bind(s, reinterpret_cast<sockaddr*>(&server_addr), sizeof(server_addr)) ==
SOCKET_ERROR);
} while (bind(s, reinterpret_cast<sockaddr*>(&server_addr), sizeof(server_addr)) == SOCKET_ERROR);
}
bool& socket_byte_missing()
@ -142,15 +146,15 @@ namespace network
}
void con_restricted_execute_buf_stub(int local_client_num, game::ControllerIndex_t controller_index,
const char* buffer)
const char* buffer)
{
game::Cbuf_ExecuteBuffer(local_client_num, controller_index, buffer);
}
uint64_t handle_packet_internal_stub(const game::ControllerIndex_t controller_index,
const game::netadr_t from_adr, const game::XUID from_xuid,
const game::LobbyType lobby_type, const uint64_t dest_module,
game::msg_t* msg)
const game::netadr_t from_adr, const game::XUID from_xuid,
const game::LobbyType lobby_type, const uint64_t dest_module,
game::msg_t* msg)
{
if (from_adr.type != game::NA_LOOPBACK)
{
@ -158,9 +162,9 @@ namespace network
}
return handle_packet_internal_hook.invoke<bool>(controller_index, from_adr, from_xuid, lobby_type,
dest_module, msg)
? 1
: 0;
dest_module, msg)
? 1
: 0;
}
uint64_t ret2()
@ -322,9 +326,6 @@ namespace network
// set initial connection state to challenging
utils::hook::set<uint32_t>(game::select(0x14134C6E0, 0x14018E574), 4);
// intercept command handling
utils::hook::call(game::select(0x14134D146, 0x14018EED0), utils::hook::assemble(handle_command_stub));
// don't kick clients without dw handle
utils::hook::set<uint8_t>(game::select(0x14224DEAD, 0x1405315F9), 0xEB);
@ -334,21 +335,23 @@ namespace network
// NA_IP -> NA_RAWIP in NetAdr_ToString
utils::hook::set<uint8_t>(game::select(0x142172ED4, 0x140515864), game::NA_RAWIP);
// Kill 'echo' OOB handler
utils::hook::set<uint8_t>(game::select(0x14134D0FB, 0x14018EE82), 0xEB);
if (game::is_server())
{
// Remove restrictions for rcon commands
utils::hook::call(0x140538D5C_g, con_restricted_execute_buf_stub); // SVC_RemoteCommand
// Kill 'error' OOB handler on the dedi
utils::hook::nop(0x14018EF8B_g, 5);
// intercept command handling
utils::hook::call(0x14018E698_g, cl_dispatch_connectionless_packet_stub);
}
else
{
// Truncate error string to make sure there are no buffer overruns later
utils::hook::call(0x14134D206_g, com_error_oob_stub);
// intercept command handling
utils::hook::call(0x14134D146_g, utils::hook::assemble(handle_command_stub));
utils::hook::set<uint8_t>(0x14134D0FB_g, 0xEB);
}
// TODO: Fix that

View File

@ -68,7 +68,7 @@ namespace patches
// don't make script errors fatal error
utils::hook::call(game::select(0x1412CAC4D, 0x140158EB2), script_errors_stub);
// change 4 character name limit to 3 characters
// change 4 character min name limit to 3 characters
utils::hook::set<uint8_t>(game::select(0x14224DA53, 0x140531143), 3);
utils::hook::set<uint8_t>(game::select(0x14224DBB4, 0x1405312A8), 3);
utils::hook::set<uint8_t>(game::select(0x14224DF8C, 0x1405316DC), 3);

View File

@ -138,7 +138,7 @@ namespace server_list
bool get_master_server(game::netadr_t& address)
{
address = network::address_from_string("server.boiii.re:20810");
address = network::address_from_string("server.alterware.dev:20810");
return address.type != game::NA_BAD;
}

View File

@ -40,6 +40,9 @@ namespace status
"num score ping xuid name address qport \n");
utils::hook::copy_string(game::select(0x1430504E0, 0x140E85A80),
"--- ----- ---- ---------------- ---------------- ------------------------ ------ \n");
utils::hook::copy_string(game::select(0x1430417C0, 0x140E76D50),
"%i.%i.%i.%i:%i");
}
};
}

View File

@ -194,7 +194,7 @@ namespace steam_proxy
void evaluate_ownership_state(const ownership_state state)
{
#if defined(DEV_BUILD) || defined(NO_CHECK)
#if defined(DEV_BUILD)
(void)state;
#else
switch (state)
@ -222,7 +222,7 @@ namespace steam_proxy
void post_unpack() override
{
const auto res = start_mod("\xE2\x98\x84\xEF\xB8\x8F" " BOIII"s, steam::SteamUtils()->GetAppID());
const auto res = start_mod("\xF0\x9F\x92\x8E" " BOIII"s, steam::SteamUtils()->GetAppID());
evaluate_ownership_state(res);
clean_up_on_error();
}

View File

@ -97,7 +97,7 @@ namespace game
// Info
WEAK symbol<const char*(const char*, const char* key)> Info_ValueForKey{0x1422E87B0};
WEAK symbol<void(char* s, const char* key, const char* value)> Info_SetValueForKey{0x1422E8410};
WEAK symbol<void(char* s, const char* key, const char* value)> Info_SetValueForKey{0x1422E8410, 0x1405802D0};
// MSG
WEAK symbol<uint8_t(msg_t* msg)> MSG_ReadByte{0x142155450, 0x14050D1B0};
@ -248,7 +248,7 @@ namespace game
// Utils
WEAK symbol<const char*(char* str)> I_CleanStr{0x1422E9050, 0x140580E80};
WEAK symbol<int(const char* s0, const char* s1)> I_stricmp{0x1422E9530};
WEAK symbol<int(const char* s0, const char* s1)> I_stricmp{0x1422E9530, 0x140581300};
WEAK symbol<void(char* dest, size_t destsize, const char* src)> I_strcpy{
0x1422E9410, 0x1405811E0
};

View File

@ -65,8 +65,9 @@
#endif
#include <cassert>
#include <cstring>
#include <cctype>
#include <climits>
#include <cstring>
#include <array>
#include <atomic>
@ -89,10 +90,10 @@
#include <variant>
#include <vector>
#include <udis86.h>
#include <MinHook.h>
#include <asmjit/core/jitruntime.h>
#include <asmjit/x86/x86assembler.h>
#include <MinHook.h>
#include <udis86.h>
#define RAPIDJSON_NOEXCEPT
#define RAPIDJSON_ASSERT(cond) if (cond); else throw std::runtime_error("rapidjson assert fail");