support early BB login command in multi-key detector crypt
This commit is contained in:
@@ -756,7 +756,7 @@ PSOEncryption::Type PSOBBEncryption::type() const {
|
|||||||
|
|
||||||
PSOBBMultiKeyDetectorEncryption::PSOBBMultiKeyDetectorEncryption(
|
PSOBBMultiKeyDetectorEncryption::PSOBBMultiKeyDetectorEncryption(
|
||||||
const vector<shared_ptr<const PSOBBEncryption::KeyFile>>& possible_keys,
|
const vector<shared_ptr<const PSOBBEncryption::KeyFile>>& possible_keys,
|
||||||
const string& expected_first_data,
|
const unordered_set<string>& expected_first_data,
|
||||||
const void* seed,
|
const void* seed,
|
||||||
size_t seed_size)
|
size_t seed_size)
|
||||||
: possible_keys(possible_keys),
|
: 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) {
|
void PSOBBMultiKeyDetectorEncryption::decrypt(void* data, size_t size, bool advance) {
|
||||||
if (!this->active_crypt.get()) {
|
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");
|
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()));
|
*this->active_key, this->seed.data(), this->seed.size()));
|
||||||
string test_data(reinterpret_cast<const char*>(data), size);
|
string test_data(reinterpret_cast<const char*>(data), size);
|
||||||
this->active_crypt->decrypt(test_data.data(), test_data.size(), false);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
this->active_key.reset();
|
this->active_key.reset();
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ class PSOBBMultiKeyDetectorEncryption : public PSOEncryption {
|
|||||||
public:
|
public:
|
||||||
PSOBBMultiKeyDetectorEncryption(
|
PSOBBMultiKeyDetectorEncryption(
|
||||||
const std::vector<std::shared_ptr<const PSOBBEncryption::KeyFile>>& possible_keys,
|
const std::vector<std::shared_ptr<const PSOBBEncryption::KeyFile>>& possible_keys,
|
||||||
const std::string& expected_first_data,
|
const std::unordered_set<std::string>& expected_first_data,
|
||||||
const void* seed,
|
const void* seed,
|
||||||
size_t seed_size);
|
size_t seed_size);
|
||||||
|
|
||||||
@@ -189,7 +189,7 @@ protected:
|
|||||||
std::vector<std::shared_ptr<const PSOBBEncryption::KeyFile>> possible_keys;
|
std::vector<std::shared_ptr<const PSOBBEncryption::KeyFile>> possible_keys;
|
||||||
std::shared_ptr<const PSOBBEncryption::KeyFile> active_key;
|
std::shared_ptr<const PSOBBEncryption::KeyFile> active_key;
|
||||||
std::shared_ptr<PSOBBEncryption> active_crypt;
|
std::shared_ptr<PSOBBEncryption> active_crypt;
|
||||||
std::string expected_first_data;
|
const std::unordered_set<std::string>& expected_first_data;
|
||||||
std::string seed;
|
std::string seed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -372,9 +372,8 @@ static HandlerResult on_server_bb_03(shared_ptr<ServerState> s,
|
|||||||
// client receives the unencrypted data
|
// client receives the unencrypted data
|
||||||
session.client_channel.send(0x03, 0x00, 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(
|
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_in = session.detector_crypt;
|
||||||
session.client_channel.crypt_out.reset(new PSOBBMultiKeyImitatorEncryption(
|
session.client_channel.crypt_out.reset(new PSOBBMultiKeyImitatorEncryption(
|
||||||
session.detector_crypt, cmd.server_key.data(), sizeof(cmd.server_key), true));
|
session.detector_crypt, cmd.server_key.data(), sizeof(cmd.server_key), true));
|
||||||
|
|||||||
+1
-4
@@ -214,11 +214,8 @@ void ProxyServer::on_client_connect(
|
|||||||
random_data(client_key.data(), client_key.bytes());
|
random_data(client_key.data(), client_key.bytes());
|
||||||
auto cmd = prepare_server_init_contents_bb(server_key, client_key, 0);
|
auto cmd = prepare_server_init_contents_bb(server_key, client_key, 0);
|
||||||
session->channel.send(0x03, 0x00, &cmd, sizeof(cmd));
|
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(
|
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_in = session->detector_crypt;
|
||||||
session->channel.crypt_out.reset(new PSOBBMultiKeyImitatorEncryption(
|
session->channel.crypt_out.reset(new PSOBBMultiKeyImitatorEncryption(
|
||||||
session->detector_crypt, cmd.server_key.data(), sizeof(cmd.server_key), true));
|
session->detector_crypt, cmd.server_key.data(), sizeof(cmd.server_key), true));
|
||||||
|
|||||||
+7
-1
@@ -49,6 +49,12 @@ const unordered_set<uint32_t> v3_crypt_initial_client_commands({
|
|||||||
0x0194019E, // (02) XB extended login (UDP off)
|
0x0194019E, // (02) XB extended login (UDP off)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const unordered_set<string> 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<Client> c, uint16_t command, uint32_t flag,
|
void send_command(shared_ptr<Client> c, uint16_t command, uint32_t flag,
|
||||||
@@ -180,7 +186,7 @@ void send_server_init_bb(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
|||||||
static const string secondary_expected_first_data("\xDC\x00\xDB\x00\x00\x00\x00\x00", 8);
|
static const string secondary_expected_first_data("\xDC\x00\xDB\x00\x00\x00\x00\x00", 8);
|
||||||
shared_ptr<PSOBBMultiKeyDetectorEncryption> detector_crypt(new PSOBBMultiKeyDetectorEncryption(
|
shared_ptr<PSOBBMultiKeyDetectorEncryption> detector_crypt(new PSOBBMultiKeyDetectorEncryption(
|
||||||
s->bb_private_keys,
|
s->bb_private_keys,
|
||||||
use_secondary_message ? secondary_expected_first_data : primary_expected_first_data,
|
bb_crypt_initial_client_commands,
|
||||||
cmd.client_key.data(),
|
cmd.client_key.data(),
|
||||||
sizeof(cmd.client_key)));
|
sizeof(cmd.client_key)));
|
||||||
c->channel.crypt_in = detector_crypt;
|
c->channel.crypt_in = detector_crypt;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
extern const std::unordered_set<uint32_t> v2_crypt_initial_client_commands;
|
extern const std::unordered_set<uint32_t> v2_crypt_initial_client_commands;
|
||||||
extern const std::unordered_set<uint32_t> v3_crypt_initial_client_commands;
|
extern const std::unordered_set<uint32_t> v3_crypt_initial_client_commands;
|
||||||
|
extern const std::unordered_set<std::string> bb_crypt_initial_client_commands;
|
||||||
|
|
||||||
// TODO: Many of these functions should take a Channel& instead of a
|
// TODO: Many of these functions should take a Channel& instead of a
|
||||||
// shared_ptr<Client>. Refactor functions appropriately.
|
// shared_ptr<Client>. Refactor functions appropriately.
|
||||||
|
|||||||
Reference in New Issue
Block a user