From 8937333a2ba0d111a280ebcfd634498785465cc0 Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Sat, 3 Sep 2022 21:03:55 -0700 Subject: [PATCH] support early BB login command in multi-key detector crypt --- src/PSOEncryption.cc | 6 +++--- src/PSOEncryption.hh | 4 ++-- src/ProxyCommands.cc | 3 +-- src/ProxyServer.cc | 5 +---- src/SendCommands.cc | 8 +++++++- src/SendCommands.hh | 1 + 6 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/PSOEncryption.cc b/src/PSOEncryption.cc index 54b1d15f..c8b4254d 100644 --- a/src/PSOEncryption.cc +++ b/src/PSOEncryption.cc @@ -756,7 +756,7 @@ PSOEncryption::Type PSOBBEncryption::type() const { PSOBBMultiKeyDetectorEncryption::PSOBBMultiKeyDetectorEncryption( const vector>& possible_keys, - const string& expected_first_data, + const unordered_set& expected_first_data, const void* seed, size_t seed_size) : possible_keys(possible_keys), @@ -772,7 +772,7 @@ void PSOBBMultiKeyDetectorEncryption::encrypt(void* data, size_t size, bool adva void PSOBBMultiKeyDetectorEncryption::decrypt(void* data, size_t size, bool advance) { if (!this->active_crypt.get()) { - if (size != this->expected_first_data.size()) { + if (size != 8) { throw logic_error("initial decryption size does not match expected first data size"); } @@ -782,7 +782,7 @@ void PSOBBMultiKeyDetectorEncryption::decrypt(void* data, size_t size, bool adva *this->active_key, this->seed.data(), this->seed.size())); string test_data(reinterpret_cast(data), size); this->active_crypt->decrypt(test_data.data(), test_data.size(), false); - if (test_data == this->expected_first_data) { + if (this->expected_first_data.count(test_data)) { break; } this->active_key.reset(); diff --git a/src/PSOEncryption.hh b/src/PSOEncryption.hh index f60c9bcb..275eee96 100644 --- a/src/PSOEncryption.hh +++ b/src/PSOEncryption.hh @@ -169,7 +169,7 @@ class PSOBBMultiKeyDetectorEncryption : public PSOEncryption { public: PSOBBMultiKeyDetectorEncryption( const std::vector>& possible_keys, - const std::string& expected_first_data, + const std::unordered_set& expected_first_data, const void* seed, size_t seed_size); @@ -189,7 +189,7 @@ protected: std::vector> possible_keys; std::shared_ptr active_key; std::shared_ptr active_crypt; - std::string expected_first_data; + const std::unordered_set& expected_first_data; std::string seed; }; diff --git a/src/ProxyCommands.cc b/src/ProxyCommands.cc index aaed4060..788d3dba 100644 --- a/src/ProxyCommands.cc +++ b/src/ProxyCommands.cc @@ -372,9 +372,8 @@ static HandlerResult on_server_bb_03(shared_ptr s, // client receives the unencrypted data session.client_channel.send(0x03, 0x00, data); - static const string expected_first_data("\xB4\x00\x93\x00\x00\x00\x00\x00", 8); session.detector_crypt.reset(new PSOBBMultiKeyDetectorEncryption( - s->bb_private_keys, expected_first_data, cmd.client_key.data(), sizeof(cmd.client_key))); + s->bb_private_keys, bb_crypt_initial_client_commands, cmd.client_key.data(), sizeof(cmd.client_key))); session.client_channel.crypt_in = session.detector_crypt; session.client_channel.crypt_out.reset(new PSOBBMultiKeyImitatorEncryption( session.detector_crypt, cmd.server_key.data(), sizeof(cmd.server_key), true)); diff --git a/src/ProxyServer.cc b/src/ProxyServer.cc index 69282137..da76a7b8 100644 --- a/src/ProxyServer.cc +++ b/src/ProxyServer.cc @@ -214,11 +214,8 @@ void ProxyServer::on_client_connect( random_data(client_key.data(), client_key.bytes()); auto cmd = prepare_server_init_contents_bb(server_key, client_key, 0); session->channel.send(0x03, 0x00, &cmd, sizeof(cmd)); - // TODO: Is this actually needed? - // bufferevent_flush(session->bev.get(), EV_READ | EV_WRITE, BEV_FLUSH); - static const string expected_first_data("\xB4\x00\x93\x00\x00\x00\x00\x00", 8); session->detector_crypt.reset(new PSOBBMultiKeyDetectorEncryption( - this->state->bb_private_keys, expected_first_data, cmd.client_key.data(), sizeof(cmd.client_key))); + this->state->bb_private_keys, bb_crypt_initial_client_commands, cmd.client_key.data(), sizeof(cmd.client_key))); session->channel.crypt_in = session->detector_crypt; session->channel.crypt_out.reset(new PSOBBMultiKeyImitatorEncryption( session->detector_crypt, cmd.server_key.data(), sizeof(cmd.server_key), true)); diff --git a/src/SendCommands.cc b/src/SendCommands.cc index aada8d72..60502e69 100644 --- a/src/SendCommands.cc +++ b/src/SendCommands.cc @@ -49,6 +49,12 @@ const unordered_set v3_crypt_initial_client_commands({ 0x0194019E, // (02) XB extended login (UDP off) }); +const unordered_set bb_crypt_initial_client_commands({ + string("\xB4\x00\x93\x00\x00\x00\x00\x00", 8), + string("\xAC\x00\x93\x00\x00\x00\x00\x00", 8), + string("\xDC\x00\xDB\x00\x00\x00\x00\x00", 8), +}); + void send_command(shared_ptr c, uint16_t command, uint32_t flag, @@ -180,7 +186,7 @@ void send_server_init_bb(shared_ptr s, shared_ptr c, static const string secondary_expected_first_data("\xDC\x00\xDB\x00\x00\x00\x00\x00", 8); shared_ptr detector_crypt(new PSOBBMultiKeyDetectorEncryption( s->bb_private_keys, - use_secondary_message ? secondary_expected_first_data : primary_expected_first_data, + bb_crypt_initial_client_commands, cmd.client_key.data(), sizeof(cmd.client_key))); c->channel.crypt_in = detector_crypt; diff --git a/src/SendCommands.hh b/src/SendCommands.hh index 85018d55..5e1d0ac1 100644 --- a/src/SendCommands.hh +++ b/src/SendCommands.hh @@ -21,6 +21,7 @@ extern const std::unordered_set v2_crypt_initial_client_commands; extern const std::unordered_set v3_crypt_initial_client_commands; +extern const std::unordered_set bb_crypt_initial_client_commands; // TODO: Many of these functions should take a Channel& instead of a // shared_ptr. Refactor functions appropriately.