#include #include "module/dw.hpp" #include "utils/cryptography.hpp" namespace demonware { std::string unencrypted_reply::get_data() { byte_buffer result; result.set_use_data_types(false); result.write_int32(static_cast(this->buffer_.size()) + 2); result.write_bool(false); result.write_byte(this->get_type()); result.write(this->buffer_); return result.get_buffer(); } std::string encrypted_reply::get_data() { byte_buffer result; result.set_use_data_types(false); byte_buffer enc_buffer; enc_buffer.set_use_data_types(false); enc_buffer.write_int32(0xDEADBEEF); enc_buffer.write_byte(this->get_type()); enc_buffer.write(this->buffer_); auto data = enc_buffer.get_buffer(); auto size = enc_buffer.size(); size = ~7 & (size + 7); // 8 byte align data.resize(size); result.write_int32(static_cast(size) + 5); result.write_byte(true); auto seed = 0x13371337; result.write_int32(seed); const auto iv = utils::cryptography::tiger::compute(std::string(reinterpret_cast(&seed), 4)); const std::string key(reinterpret_cast(dw::get_key(true)), 24); result.write(utils::cryptography::des3::encrypt(data, iv, key)); return result.get_buffer(); } service_server::service_server(std::string _name) : name_(std::move(_name)) { this->address_ = utils::cryptography::jenkins_one_at_a_time::compute(this->name_); } unsigned long service_server::get_address() const { return this->address_; } int service_server::send(const char* buf, const int len) { if (len <= 3) return -1; std::lock_guard _(this->mutex_); this->incoming_queue_.push(std::string(buf, len)); return len; } int service_server::recv(char* buf, int len) { if (len > 0 && !this->outgoing_queue_.empty()) { std::lock_guard _(this->mutex_); len = std::min(len, static_cast(this->outgoing_queue_.size())); for (auto i = 0; i < len; ++i) { buf[i] = this->outgoing_queue_.front(); this->outgoing_queue_.pop(); } return len; } return SOCKET_ERROR; } void service_server::send_reply(reply* data) { if (!data) return; std::lock_guard _(this->mutex_); this->reply_sent_ = true; const auto buffer = data->get_data(); for (auto& byte : buffer) { this->outgoing_queue_.push(byte); } } void service_server::call_handler(const uint8_t type, const std::string& data) { if (this->services_.find(type) != this->services_.end()) { this->services_[type]->call_service(this, data); } else { printf("DW: Missing handler of type %d\n", type); } } void service_server::run_frame() { if (!this->incoming_queue_.empty()) { std::lock_guard _(this->mutex_); const auto packet = this->incoming_queue_.front(); this->incoming_queue_.pop(); this->parse_packet(packet); } } void service_server::parse_packet(const std::string& packet) { byte_buffer buffer(packet); buffer.set_use_data_types(false); try { while (buffer.has_more_data()) { int size; buffer.read_int32(&size); if (size <= 0) { const std::string zero("\x00\x00\x00\x00", 4); raw_reply reply(zero); this->send_reply(&reply); return; } else if (size == 200) // Connection id { byte_buffer bbufer; bbufer.write_uint64(0x00000000000000FD); auto reply = this->create_message(4); reply->send(&bbufer, false); return; } if (buffer.size() < size_t(size)) return; byte_buffer p_buffer; p_buffer.set_use_data_types(false); p_buffer.get_buffer().resize(size); buffer.read(size, p_buffer.get_buffer().data()); bool enc; p_buffer.read_bool(&enc); if (enc) { int iv; p_buffer.read_int32(&iv); auto iv_hash = utils::cryptography::tiger::compute(std::string(reinterpret_cast(&iv), 4)); const std::string key(reinterpret_cast(dw::get_key(false)), 24); p_buffer = byte_buffer{utils::cryptography::des3::decrypt(p_buffer.get_remaining(), iv_hash, key)}; p_buffer.set_use_data_types(false); int checksum; p_buffer.read_int32(&checksum); } uint8_t type; p_buffer.read_byte(&type); printf("DW: Handling message of type %d (encrypted: %d)\n", type, enc); this->reply_sent_ = false; this->call_handler(type, p_buffer.get_remaining()); if (!this->reply_sent_ && type != 7) { this->create_reply(type)->send(); } } } catch (...) { } } }