Stuff
Co-Authored-By: fed <58637860+fedddddd@users.noreply.github.com>
This commit is contained in:
parent
4f15287255
commit
1382280bfd
@ -1,14 +1,10 @@
|
||||
#include <std_include.hpp>
|
||||
#include "console.hpp"
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "game/game.hpp"
|
||||
#include "command.hpp"
|
||||
|
||||
#include <utils/thread.hpp>
|
||||
#include <utils/flags.hpp>
|
||||
#include <utils/concurrency.hpp>
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
namespace game_console
|
||||
{
|
||||
void print(int type, const std::string& data);
|
||||
@ -18,271 +14,50 @@ namespace console
|
||||
{
|
||||
namespace
|
||||
{
|
||||
using message_queue = std::queue<std::string>;
|
||||
utils::concurrency::container<message_queue> messages;
|
||||
|
||||
bool native_console()
|
||||
DWORD WINAPI console(LPVOID)
|
||||
{
|
||||
static const auto flag = utils::flags::has_flag("nativeconsole");
|
||||
return flag;
|
||||
}
|
||||
FreeConsole();
|
||||
AllocConsole();
|
||||
AttachConsole(GetCurrentProcessId());
|
||||
|
||||
void hide_console()
|
||||
{
|
||||
auto* const con_window = GetConsoleWindow();
|
||||
(void)freopen("CONIN$", "r", stdin);
|
||||
(void)freopen("CONOUT$", "w", stdout);
|
||||
|
||||
DWORD process;
|
||||
GetWindowThreadProcessId(con_window, &process);
|
||||
|
||||
if (!native_console() && (process == GetCurrentProcessId() || IsDebuggerPresent()))
|
||||
{
|
||||
ShowWindow(con_window, SW_HIDE);
|
||||
}
|
||||
}
|
||||
|
||||
std::string format(va_list* ap, const char* message)
|
||||
{
|
||||
static thread_local char buffer[0x1000];
|
||||
|
||||
const auto count = _vsnprintf_s(buffer, sizeof(buffer), sizeof(buffer), message, *ap);
|
||||
|
||||
if (count < 0) return {};
|
||||
return {buffer, static_cast<size_t>(count)};
|
||||
}
|
||||
|
||||
void dispatch_message(const int type, const std::string& message)
|
||||
{
|
||||
if (native_console())
|
||||
{
|
||||
printf("%s\n", message.data());
|
||||
return;
|
||||
}
|
||||
|
||||
game_console::print(type, message);
|
||||
messages.access([&message](message_queue& msgs)
|
||||
{
|
||||
msgs.emplace(message);
|
||||
});
|
||||
}
|
||||
|
||||
void append_text(const char* text)
|
||||
{
|
||||
dispatch_message(con_type_info, text);
|
||||
}
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
component()
|
||||
{
|
||||
hide_console();
|
||||
|
||||
if (native_console())
|
||||
{
|
||||
setvbuf(stdout, nullptr, _IONBF, 0);
|
||||
setvbuf(stderr, nullptr, _IONBF, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)_pipe(this->handles_, 1024, _O_TEXT);
|
||||
(void)_dup2(this->handles_[1], 1);
|
||||
(void)_dup2(this->handles_[1], 2);
|
||||
}
|
||||
}
|
||||
|
||||
void post_start() override
|
||||
{
|
||||
this->terminate_runner_ = false;
|
||||
|
||||
this->console_runner_ = utils::thread::create_named_thread("Console IO", [this]
|
||||
{
|
||||
if (native_console())
|
||||
{
|
||||
this->native_input();
|
||||
}
|
||||
else
|
||||
{
|
||||
this->runner();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void pre_destroy() override
|
||||
{
|
||||
this->terminate_runner_ = true;
|
||||
|
||||
printf("\r\n");
|
||||
_flushall();
|
||||
|
||||
if (this->console_runner_.joinable())
|
||||
{
|
||||
this->console_runner_.join();
|
||||
}
|
||||
|
||||
if (this->console_thread_.joinable())
|
||||
{
|
||||
this->console_thread_.join();
|
||||
}
|
||||
|
||||
#ifndef NATIVE_CONSOLE
|
||||
_close(this->handles_[0]);
|
||||
_close(this->handles_[1]);
|
||||
#endif
|
||||
|
||||
messages.access([&](message_queue& msgs)
|
||||
{
|
||||
msgs = {};
|
||||
});
|
||||
}
|
||||
|
||||
void post_unpack() override
|
||||
{
|
||||
// Redirect input (]command)
|
||||
utils::hook::jump(SELECT_VALUE(0x1403E34C0, 0x1405141E0), append_text); // H1(1.4)
|
||||
|
||||
this->initialize();
|
||||
}
|
||||
|
||||
private:
|
||||
volatile bool console_initialized_ = false;
|
||||
volatile bool terminate_runner_ = false;
|
||||
|
||||
std::thread console_runner_;
|
||||
std::thread console_thread_;
|
||||
|
||||
int handles_[2]{};
|
||||
|
||||
void initialize()
|
||||
{
|
||||
this->console_thread_ = utils::thread::create_named_thread("Console", [this]()
|
||||
{
|
||||
if (!native_console() && (game::environment::is_dedi() || !utils::flags::has_flag("noconsole")))
|
||||
{
|
||||
game::Sys_ShowConsole();
|
||||
}
|
||||
|
||||
if (!game::environment::is_dedi())
|
||||
{
|
||||
// Hide that shit
|
||||
ShowWindow(console::get_window(), SW_MINIMIZE);
|
||||
}
|
||||
|
||||
{
|
||||
messages.access([&](message_queue&)
|
||||
{
|
||||
this->console_initialized_ = true;
|
||||
});
|
||||
}
|
||||
|
||||
MSG msg;
|
||||
while (!this->terminate_runner_)
|
||||
{
|
||||
if (PeekMessageA(&msg, nullptr, NULL, NULL, PM_REMOVE))
|
||||
{
|
||||
if (msg.message == WM_QUIT)
|
||||
{
|
||||
command::execute("quit", false);
|
||||
break;
|
||||
}
|
||||
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->log_messages();
|
||||
std::this_thread::sleep_for(1ms);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void log_messages()
|
||||
{
|
||||
/*while*/
|
||||
if (this->console_initialized_ && !messages.get_raw().empty())
|
||||
{
|
||||
std::queue<std::string> message_queue_copy;
|
||||
|
||||
{
|
||||
messages.access([&](message_queue& msgs)
|
||||
{
|
||||
message_queue_copy = std::move(msgs);
|
||||
msgs = {};
|
||||
});
|
||||
}
|
||||
|
||||
while (!message_queue_copy.empty())
|
||||
{
|
||||
log_message(message_queue_copy.front());
|
||||
message_queue_copy.pop();
|
||||
}
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
static void log_message(const std::string& message)
|
||||
{
|
||||
OutputDebugStringA(message.data());
|
||||
game::Conbuf_AppendText(message.data());
|
||||
}
|
||||
|
||||
void runner()
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
while (!this->terminate_runner_ && this->handles_[0])
|
||||
{
|
||||
const auto len = _read(this->handles_[0], buffer, sizeof(buffer));
|
||||
if (len > 0)
|
||||
{
|
||||
dispatch_message(con_type_info, std::string(buffer, len));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::this_thread::sleep_for(1ms);
|
||||
}
|
||||
}
|
||||
|
||||
std::this_thread::yield();
|
||||
}
|
||||
|
||||
void native_input()
|
||||
{
|
||||
std::string cmd;
|
||||
|
||||
while (!this->terminate_runner_)
|
||||
while (true)
|
||||
{
|
||||
std::getline(std::cin, cmd);
|
||||
command::execute(cmd);
|
||||
|
||||
}
|
||||
|
||||
std::this_thread::yield();
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
HWND get_window()
|
||||
{
|
||||
return *reinterpret_cast<HWND*>((SELECT_VALUE(0x14CF56C00, 0x14DDFC2D0))); // H1(1.4)
|
||||
}
|
||||
|
||||
void set_title(std::string title)
|
||||
std::string format(va_list* ap, const char* message)
|
||||
{
|
||||
SetWindowText(get_window(), title.data());
|
||||
static thread_local char buffer[0x1000];
|
||||
|
||||
const auto count = _vsnprintf_s(buffer, sizeof(buffer), sizeof(buffer), message, *ap);
|
||||
|
||||
if (count < 0) return {};
|
||||
return { buffer, static_cast<size_t>(count) };
|
||||
}
|
||||
|
||||
void set_size(const int width, const int height)
|
||||
void dispatch_message(const int type, const std::string& message)
|
||||
{
|
||||
RECT rect;
|
||||
GetWindowRect(get_window(), &rect);
|
||||
//if (native_console())
|
||||
//{
|
||||
printf("%s\n", message.data());
|
||||
// return;
|
||||
//}
|
||||
|
||||
SetWindowPos(get_window(), nullptr, rect.left, rect.top, width, height, 0);
|
||||
|
||||
auto* const logo_window = *reinterpret_cast<HWND*>(SELECT_VALUE(0x14CF56C10, 0x14DDFC2E0)); // H1(1.4)
|
||||
SetWindowPos(logo_window, nullptr, 5, 5, width - 25, 60, 0);
|
||||
//game_console::print(type, message);
|
||||
//messages.access([&message](message_queue& msgs)
|
||||
// {
|
||||
// msgs.emplace(message);
|
||||
// });
|
||||
}
|
||||
|
||||
void print(const int type, const char* fmt, ...)
|
||||
@ -294,6 +69,15 @@ namespace console
|
||||
|
||||
dispatch_message(type, result);
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
void post_start() override
|
||||
{
|
||||
CreateThread(0, 0, console, 0, 0, 0);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//REGISTER_COMPONENT(console::component)
|
||||
REGISTER_COMPONENT(console::component)
|
||||
|
@ -297,7 +297,7 @@ namespace demonware
|
||||
|
||||
if (server)
|
||||
{
|
||||
server->handle_input(buf, len, {s, to, tolen});
|
||||
server->handle_input(buf, len, { s, to, tolen });
|
||||
return len;
|
||||
}
|
||||
|
||||
@ -425,9 +425,9 @@ namespace demonware
|
||||
}
|
||||
}
|
||||
|
||||
void bd_logger_stub(char* a1, void* a2, void* a3, void* a4, const char* function, ...)
|
||||
void bd_logger_stub()
|
||||
{
|
||||
|
||||
//printf("logged\n");
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -481,6 +481,32 @@ namespace demonware
|
||||
printf("bdAuth: Unknown error\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
utils::hook::detour kekw_hook;
|
||||
bool kekw_stub(__int64 a1, __int64 a2, __int64* a3)
|
||||
{
|
||||
// Checks X-Signature header or something
|
||||
utils::hook::set(0x7D4AB0_b, 0xC301B0);
|
||||
// Checks extended_data and extra_data in json object
|
||||
utils::hook::set(0x7D55C0_b, 0xC301B0);
|
||||
return kekw_hook.invoke<bool>(a1, a2, a3);
|
||||
}
|
||||
|
||||
void* allocate_somewhere_near(uint8_t* base_address)
|
||||
{
|
||||
const size_t PAGE_SIZE = 0x1000;
|
||||
size_t offset = 0;
|
||||
while (true)
|
||||
{
|
||||
offset += PAGE_SIZE;
|
||||
auto res = VirtualAlloc(base_address - offset, PAGE_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
||||
if (res)
|
||||
{
|
||||
std::memset(res, 0, PAGE_SIZE);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
@ -537,52 +563,69 @@ namespace demonware
|
||||
|
||||
void post_unpack() override
|
||||
{
|
||||
utils::hook::jump(SELECT_VALUE(0x140610320, 0x1407400B0), bd_logger_stub);
|
||||
/*
|
||||
mwr has upgraded some networking methods and the gethostbyname import from winsock library is no longer used
|
||||
gethostbyname has been replaced with getaddrinfo
|
||||
btw, still you can't get online..
|
||||
*/
|
||||
//utils::hook::jump(SELECT_VALUE(0, 0x7EBC20_b), bd_logger_stub);
|
||||
|
||||
if (game::environment::is_sp())
|
||||
{
|
||||
utils::hook::set<uint8_t>(0x1405FCA00, 0xC3); // bdAuthSteam
|
||||
utils::hook::set<uint8_t>(0x140333A00, 0xC3); // dwNet
|
||||
// utils::hook::set<uint8_t>(0x1405FCA00, 0xC3); // bdAuthSteam H1(1.4)
|
||||
// utils::hook::set<uint8_t>(0x140333A00, 0xC3); // dwNet H1(1.4)
|
||||
return;
|
||||
}
|
||||
|
||||
utils::hook::set<uint8_t>(0x140715039, 0x0); // CURLOPT_SSL_VERIFYPEER
|
||||
utils::hook::set<uint8_t>(0x140715025, 0xAF); // CURLOPT_SSL_VERIFYHOST
|
||||
utils::hook::set<uint8_t>(0x14095433C, 0x0); // HTTPS -> HTTP
|
||||
utils::hook::set<uint8_t>(0x7C0AD9_b, 0x0); // CURLOPT_SSL_VERIFYPEER H1MP64(1.15)
|
||||
utils::hook::set<uint8_t>(0x7C0AC5_b, 0xAF); // CURLOPT_SSL_VERIFYHOST H1MP64(1.15)
|
||||
utils::hook::set<uint8_t>(0xA1327C_b, 0x0); // HTTPS -> HTTP [MWR OK][S1X: 0x14088D0E8]
|
||||
|
||||
//HTTPS -> HTTP
|
||||
utils::hook::inject(0x14006DDA9, "http://prod.umbrella.demonware.net/v1.0/");
|
||||
utils::hook::inject(0x14006E11C, "http://prod.umbrella.demonware.net/v1.0/");
|
||||
utils::hook::inject(0x14006E2FB, "http://prod.umbrella.demonware.net/v1.0/");
|
||||
utils::hook::inject(0x14006E9A9, "http://prod.uno.demonware.net/v1.0/");
|
||||
utils::hook::inject(0x14006ED49, "http://prod.uno.demonware.net/v1.0/");
|
||||
utils::hook::inject(0x140728170, "http://%s:%d/auth/");
|
||||
char* umbrella = (char*)allocate_somewhere_near((uint8_t*)game::base_address);
|
||||
std::memcpy(umbrella, "http://prod.umbrella.demonware.net/v1.0/", sizeof("http://prod.umbrella.demonware.net/v1.0/"));
|
||||
|
||||
utils::hook::set<uint8_t>(0x14047F290, 0xC3); // SV_SendMatchData
|
||||
utils::hook::set<uint8_t>(0x140598990, 0xC3); // Live_CheckForFullDisconnect
|
||||
utils::hook::inject(0x8615F_b, umbrella);
|
||||
utils::hook::inject(0x8638C_b, umbrella);
|
||||
|
||||
#ifdef DEBUG
|
||||
// yes
|
||||
utils::hook::call(0x140727BEB, l);
|
||||
utils::hook::call(0x140727AFC, i);
|
||||
utils::hook::call(0x140727E49, h);
|
||||
utils::hook::call(0x140727E30, g);
|
||||
utils::hook::call(0x140727E37, f);
|
||||
utils::hook::call(0x140727DF2, e);
|
||||
utils::hook::call(0x140727DF9, d);
|
||||
utils::hook::call(0x140727CFC, c);
|
||||
utils::hook::call(0x140727C82, b);
|
||||
utils::hook::call(0x140727E6A, a);
|
||||
#endif
|
||||
char* uno = (char*)allocate_somewhere_near((uint8_t*)game::base_address);
|
||||
std::memcpy(uno, "http://prod.uno.demonware.net/v1.0/", sizeof("http://prod.uno.demonware.net/v1.0/"));
|
||||
|
||||
utils::hook::inject(0x86C56_b, uno);
|
||||
utils::hook::inject(0x86F96_b, uno);
|
||||
|
||||
BYTE bytes[] = { 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x25, 0x73, 0x3A, 0x25, 0x64, 0x2F, 0x61, 0x75, 0x74, 0x68, 0x2F, 0x0 }; // KEKW
|
||||
std::memcpy((void*)0x9EDB08_b, bytes, sizeof(bytes)); //utils::hook::inject(0x140728170, "http://%s:%d/auth/"); :DDD
|
||||
|
||||
//utils::hook::set<uint8_t>(0x14047F290, 0xC3); // SV_SendMatchData H1MP64(1.4)
|
||||
//utils::hook::set<uint8_t>(0x140598990, 0xC3); // Live_CheckForFullDisconnect H1MP64(1.4)
|
||||
|
||||
//#ifdef DEBUG
|
||||
// // yes
|
||||
// utils::hook::call(0x140727BEB, l);
|
||||
// utils::hook::call(0x140727AFC, i);
|
||||
// utils::hook::call(0x140727E49, h);
|
||||
// utils::hook::call(0x140727E30, g);
|
||||
// utils::hook::call(0x140727E37, f);
|
||||
// utils::hook::call(0x140727DF2, e);
|
||||
// utils::hook::call(0x140727DF9, d);
|
||||
// utils::hook::call(0x140727CFC, c);
|
||||
// utils::hook::call(0x140727C82, b);
|
||||
// utils::hook::call(0x140727E6A, a);
|
||||
//#endif
|
||||
// Checks X-Signature header or something
|
||||
utils::hook::set(0x140728380, 0xC301B0);
|
||||
//utils::hook::set(0x7D4AB0_b, 0xC301B0);
|
||||
// Checks extended_data and extra_data in json object
|
||||
utils::hook::set(0x140728E90, 0xC301B0);
|
||||
//utils::hook::set(0x7D55C0_b, 0xC301B0);
|
||||
// Update check
|
||||
utils::hook::set(0x1403A5390, 0xC301B0);
|
||||
|
||||
//utils::hook::set(0x1403A5390, 0xC301B0);
|
||||
|
||||
// Remove some while loop in demonware that freezes the rendering for a few secs at launch
|
||||
utils::hook::nop(0x14057DBC5, 5);
|
||||
//utils::hook::nop(0x14057DBC5, 5);
|
||||
|
||||
MessageBoxA(0, "TEST", "", 0);
|
||||
kekw_hook.create(0x7AC600_b, kekw_stub);
|
||||
MessageBoxA(0, "TEST2", "", 0);
|
||||
}
|
||||
|
||||
void pre_destroy() override
|
||||
@ -596,4 +639,4 @@ namespace demonware
|
||||
};
|
||||
}
|
||||
|
||||
//REGISTER_COMPONENT(demonware::component)
|
||||
REGISTER_COMPONENT(demonware::component)
|
||||
|
@ -170,4 +170,41 @@ namespace demonware
|
||||
buffer->read_blob(&this->data);
|
||||
}
|
||||
};
|
||||
|
||||
class bdFile2 final : public bdTaskResult
|
||||
{
|
||||
public:
|
||||
uint32_t unk1;
|
||||
uint32_t unk2;
|
||||
uint32_t unk3;
|
||||
bool priv;
|
||||
uint64_t owner_id;
|
||||
std::string platform;
|
||||
std::string filename;
|
||||
std::string data;
|
||||
|
||||
void serialize(byte_buffer* buffer) override
|
||||
{
|
||||
buffer->write_uint32(this->unk1);
|
||||
buffer->write_uint32(this->unk2);
|
||||
buffer->write_uint32(this->unk3);
|
||||
buffer->write_bool(this->priv);
|
||||
buffer->write_uint64(this->owner_id);
|
||||
buffer->write_string(this->platform);
|
||||
buffer->write_string(this->filename);
|
||||
buffer->write_blob(this->data);
|
||||
}
|
||||
|
||||
void deserialize(byte_buffer* buffer) override
|
||||
{
|
||||
buffer->read_uint32(&this->unk1);
|
||||
buffer->read_uint32(&this->unk2);
|
||||
buffer->read_uint32(&this->unk3);
|
||||
buffer->read_bool(&this->priv);
|
||||
buffer->read_uint64(&this->owner_id);
|
||||
buffer->read_string(&this->platform);
|
||||
buffer->read_string(&this->filename);
|
||||
buffer->read_blob(&this->data);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -172,15 +172,45 @@ namespace demonware
|
||||
const auto path = get_user_file_path(filename);
|
||||
utils::io::write_file(path, data);
|
||||
|
||||
auto* info = new bdFileInfo;
|
||||
auto* info = new bdFile2;
|
||||
|
||||
info->file_id = *reinterpret_cast<const uint64_t*>(utils::cryptography::sha1::compute(filename).data());
|
||||
// int
|
||||
// int
|
||||
// int
|
||||
// byte (priv)
|
||||
// int64 (owner)
|
||||
// string (platform)
|
||||
// string (file)
|
||||
// blob
|
||||
// size
|
||||
// data
|
||||
// int
|
||||
// int
|
||||
// int
|
||||
// byte
|
||||
// int64
|
||||
// string (platform)
|
||||
// string (file)
|
||||
// blob
|
||||
// size
|
||||
// data
|
||||
|
||||
info->unk1 = 0;
|
||||
info->unk2 = 0;
|
||||
info->unk3 = 0;
|
||||
info->priv = false;
|
||||
info->owner_id = owner;
|
||||
info->platform = platform;
|
||||
info->filename = filename;
|
||||
info->data = data;
|
||||
|
||||
/*info->file_id = *reinterpret_cast<const uint64_t*>(utils::cryptography::sha1::compute(filename).data());
|
||||
info->filename = filename;
|
||||
info->create_time = uint32_t(time(nullptr));
|
||||
info->modified_time = info->create_time;
|
||||
info->file_size = uint32_t(data.size());
|
||||
info->owner_id = uint64_t(owner);
|
||||
info->priv = priv;
|
||||
info->priv = priv;*/
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("[DW]: [bdStorage]: set user file: %s\n", filename.data());
|
||||
@ -213,6 +243,8 @@ namespace demonware
|
||||
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
|
||||
printf("%i\n", numfiles);
|
||||
|
||||
for (uint32_t i = 0; i < numfiles; i++)
|
||||
{
|
||||
std::string filename, data;
|
||||
@ -221,6 +253,9 @@ namespace demonware
|
||||
const auto path = get_user_file_path(filename);
|
||||
if (!utils::io::read_file(path, &data))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("[DW]: [bdStorage]: get user file: missing file: %s, %s, %s\n", game.data(), filename.data(), platform.data());
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user