More fixes

This commit is contained in:
momo5502 2019-09-24 11:46:47 +02:00
parent 91aa9cc0b8
commit 84cba76ae3
37 changed files with 3327 additions and 3280 deletions

View File

@ -1,51 +1,52 @@
libtommath = { libtommath = {
source = path.join(dependencies.basePath, "libtommath"), source = path.join(dependencies.basePath, "libtommath"),
} }
function libtommath.import() function libtommath.import()
links { links {
"libtommath" "libtommath"
} }
libtommath.includes() libtommath.includes()
end end
function libtommath.includes() function libtommath.includes()
includedirs { includedirs {
libtommath.source libtommath.source
} }
defines { defines {
"LTM_DESC", "LTM_DESC",
"__STDC_IEC_559__", "__STDC_IEC_559__",
} "MP_NO_DEV_URANDOM",
end }
end
function libtommath.project()
project "libtommath" function libtommath.project()
language "C" project "libtommath"
language "C"
libtommath.includes()
libtommath.includes()
files {
path.join(libtommath.source, "*.c"), files {
} path.join(libtommath.source, "*.c"),
}
defines {
"_LIB" defines {
} "_LIB"
}
removedefines {
"_DLL", removedefines {
"_USRDLL" "_DLL",
} "_USRDLL"
}
linkoptions {
"-IGNORE:4221" linkoptions {
} "-IGNORE:4221"
}
warnings "Off"
kind "StaticLib" warnings "Off"
end kind "StaticLib"
end
table.insert(dependencies, libtommath)
table.insert(dependencies, libtommath)

View File

@ -1,182 +1,182 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "bit_buffer.hpp" #include "bit_buffer.hpp"
namespace demonware namespace demonware
{ {
bool bit_buffer::read_bytes(const unsigned int bytes, unsigned char* output) bool bit_buffer::read_bytes(const unsigned int bytes, unsigned char* output)
{ {
return this->read(bytes * 8, output); return this->read(bytes * 8, output);
} }
bool bit_buffer::read_bool(bool* output) bool bit_buffer::read_bool(bool* output)
{ {
if (!this->read_data_type(1)) if (!this->read_data_type(1))
{ {
return false; return false;
} }
return this->read(1, output); return this->read(1, output);
} }
bool bit_buffer::read_uint32(unsigned int* output) bool bit_buffer::read_uint32(unsigned int* output)
{ {
if (!this->read_data_type(8)) if (!this->read_data_type(8))
{ {
return false; return false;
} }
return this->read(32, output); return this->read(32, output);
} }
bool bit_buffer::read_data_type(const char expected) bool bit_buffer::read_data_type(const char expected)
{ {
char data_type = 0; char data_type = 0;
if (!this->use_data_types_) return true; if (!this->use_data_types_) return true;
if (this->read(5, &data_type)) if (this->read(5, &data_type))
{ {
return (data_type == expected); return (data_type == expected);
} }
return false; return false;
} }
bool bit_buffer::write_bytes(const unsigned int bytes, const char* data) bool bit_buffer::write_bytes(const unsigned int bytes, const char* data)
{ {
return this->write_bytes(bytes, reinterpret_cast<const unsigned char*>(data)); return this->write_bytes(bytes, reinterpret_cast<const unsigned char*>(data));
} }
bool bit_buffer::write_bytes(unsigned int bytes, const unsigned char* data) bool bit_buffer::write_bytes(const unsigned int bytes, const unsigned char* data)
{ {
return this->write(bytes * 8, data); return this->write(bytes * 8, data);
} }
bool bit_buffer::write_bool(bool data) bool bit_buffer::write_bool(bool data)
{ {
if (this->write_data_type(1)) if (this->write_data_type(1))
{ {
return this->write(1, &data); return this->write(1, &data);
} }
return false; return false;
} }
bool bit_buffer::write_int32(int data) bool bit_buffer::write_int32(int data)
{ {
if (this->write_data_type(7)) if (this->write_data_type(7))
{ {
return this->write(32, &data); return this->write(32, &data);
} }
return false; return false;
} }
bool bit_buffer::write_uint32(unsigned int data) bool bit_buffer::write_uint32(unsigned int data)
{ {
if (this->write_data_type(8)) if (this->write_data_type(8))
{ {
return this->write(32, &data); return this->write(32, &data);
} }
return false; return false;
} }
bool bit_buffer::write_data_type(char data) bool bit_buffer::write_data_type(char data)
{ {
if (!this->use_data_types_) if (!this->use_data_types_)
{ {
return true; return true;
} }
return this->write(5, &data); return this->write(5, &data);
} }
bool bit_buffer::read(unsigned int bits, void* output) bool bit_buffer::read(unsigned int bits, void* output)
{ {
if (bits == 0) return false; if (bits == 0) return false;
if ((this->current_bit_ + bits) > (this->buffer_.size() * 8)) return false; if ((this->current_bit_ + bits) > (this->buffer_.size() * 8)) return false;
int cur_byte = this->current_bit_ >> 3; int cur_byte = this->current_bit_ >> 3;
auto cur_out = 0; auto cur_out = 0;
const char* bytes = this->buffer_.data(); const char* bytes = this->buffer_.data();
const auto output_bytes = reinterpret_cast<unsigned char*>(output); const auto output_bytes = reinterpret_cast<unsigned char*>(output);
while (bits > 0) while (bits > 0)
{ {
const int min_bit = (bits < 8) ? bits : 8; const int min_bit = (bits < 8) ? bits : 8;
const auto this_byte = bytes[cur_byte++] & 0xFF; const auto this_byte = bytes[cur_byte++] & 0xFF;
const int remain = this->current_bit_ & 7; const int remain = this->current_bit_ & 7;
if ((min_bit + remain) <= 8) if ((min_bit + remain) <= 8)
{ {
output_bytes[cur_out] = BYTE((0xFF >> (8 - min_bit)) & (this_byte >> remain)); output_bytes[cur_out] = BYTE((0xFF >> (8 - min_bit)) & (this_byte >> remain));
} }
else else
{ {
output_bytes[cur_out] = BYTE( output_bytes[cur_out] = BYTE(
(0xFF >> (8 - min_bit)) & (bytes[cur_byte] << (8 - remain)) | (this_byte >> remain)); (0xFF >> (8 - min_bit)) & (bytes[cur_byte] << (8 - remain)) | (this_byte >> remain));
} }
cur_out++; cur_out++;
this->current_bit_ += min_bit; this->current_bit_ += min_bit;
bits -= min_bit; bits -= min_bit;
} }
return true; return true;
} }
bool bit_buffer::write(const unsigned int bits, const void* data) bool bit_buffer::write(const unsigned int bits, const void* data)
{ {
if (bits == 0) return false; if (bits == 0) return false;
this->buffer_.resize(this->buffer_.size() + (bits >> 3) + 1); this->buffer_.resize(this->buffer_.size() + (bits >> 3) + 1);
int bit = bits; int bit = bits;
const auto bytes = const_cast<char*>(this->buffer_.data()); const auto bytes = const_cast<char*>(this->buffer_.data());
const auto* input_bytes = reinterpret_cast<const unsigned char*>(data); const auto* input_bytes = reinterpret_cast<const unsigned char*>(data);
while (bit > 0) while (bit > 0)
{ {
const int bit_pos = this->current_bit_ & 7; const int bit_pos = this->current_bit_ & 7;
auto rem_bit = 8 - bit_pos; auto rem_bit = 8 - bit_pos;
const auto this_write = (bit < rem_bit) ? bit : rem_bit; const auto this_write = (bit < rem_bit) ? bit : rem_bit;
const BYTE mask = ((0xFF >> rem_bit) | (0xFF << (bit_pos + this_write))); const BYTE mask = ((0xFF >> rem_bit) | (0xFF << (bit_pos + this_write)));
const int byte_pos = this->current_bit_ >> 3; const int byte_pos = this->current_bit_ >> 3;
const BYTE temp_byte = (mask & bytes[byte_pos]); const BYTE temp_byte = (mask & bytes[byte_pos]);
const BYTE this_bit = ((bits - bit) & 7); const BYTE this_bit = ((bits - bit) & 7);
const auto this_byte = (bits - bit) >> 3; const auto this_byte = (bits - bit) >> 3;
auto this_data = input_bytes[this_byte]; auto this_data = input_bytes[this_byte];
const auto next_byte = (((bits - 1) >> 3) > this_byte) ? input_bytes[this_byte + 1] : 0; const auto next_byte = (((bits - 1) >> 3) > this_byte) ? input_bytes[this_byte + 1] : 0;
this_data = BYTE((next_byte << (8 - this_bit)) | (this_data >> this_bit)); this_data = BYTE((next_byte << (8 - this_bit)) | (this_data >> this_bit));
const BYTE out_byte = (~mask & (this_data << bit_pos) | temp_byte); const BYTE out_byte = (~mask & (this_data << bit_pos) | temp_byte);
bytes[byte_pos] = out_byte; bytes[byte_pos] = out_byte;
this->current_bit_ += this_write; this->current_bit_ += this_write;
bit -= this_write; bit -= this_write;
} }
return true; return true;
} }
void bit_buffer::set_use_data_types(const bool use_data_types) void bit_buffer::set_use_data_types(const bool use_data_types)
{ {
this->use_data_types_ = use_data_types; this->use_data_types_ = use_data_types;
} }
unsigned int bit_buffer::size() const unsigned int bit_buffer::size() const
{ {
return this->current_bit_ / 8 + (this->current_bit_ % 8 ? 1 : 0); return this->current_bit_ / 8 + (this->current_bit_ % 8 ? 1 : 0);
} }
std::string& bit_buffer::get_buffer() std::string& bit_buffer::get_buffer()
{ {
this->buffer_.resize(this->size()); this->buffer_.resize(this->size());
return this->buffer_; return this->buffer_;
} }
} }

View File

@ -1,308 +1,308 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "byte_buffer.hpp" #include "byte_buffer.hpp"
namespace demonware namespace demonware
{ {
bool byte_buffer::read_byte(unsigned char* output) bool byte_buffer::read_byte(unsigned char* output)
{ {
if (!this->read_data_type(3)) return false; if (!this->read_data_type(3)) return false;
return this->read(1, output); return this->read(1, output);
} }
bool byte_buffer::read_bool(bool* output) bool byte_buffer::read_bool(bool* output)
{ {
if (!this->read_data_type(1)) return false; if (!this->read_data_type(1)) return false;
return this->read(1, output); return this->read(1, output);
} }
bool byte_buffer::read_int16(short* output) bool byte_buffer::read_int16(short* output)
{ {
if (!this->read_data_type(5)) return false; if (!this->read_data_type(5)) return false;
return this->read(2, output); return this->read(2, output);
} }
bool byte_buffer::read_uint16(unsigned short* output) bool byte_buffer::read_uint16(unsigned short* output)
{ {
if (!this->read_data_type(6)) return false; if (!this->read_data_type(6)) return false;
return this->read(2, output); return this->read(2, output);
} }
bool byte_buffer::read_int32(int* output) bool byte_buffer::read_int32(int* output)
{ {
if (!this->read_data_type(7)) return false; if (!this->read_data_type(7)) return false;
return this->read(4, output); return this->read(4, output);
} }
bool byte_buffer::read_uint32(unsigned int* output) bool byte_buffer::read_uint32(unsigned int* output)
{ {
if (!this->read_data_type(8)) return false; if (!this->read_data_type(8)) return false;
return this->read(4, output); return this->read(4, output);
} }
bool byte_buffer::read_int64(__int64* output) bool byte_buffer::read_int64(__int64* output)
{ {
if (!this->read_data_type(9)) return false; if (!this->read_data_type(9)) return false;
return this->read(8, output); return this->read(8, output);
} }
bool byte_buffer::read_uint64(unsigned __int64* output) bool byte_buffer::read_uint64(unsigned __int64* output)
{ {
if (!this->read_data_type(10)) return false; if (!this->read_data_type(10)) return false;
return this->read(8, output); return this->read(8, output);
} }
bool byte_buffer::read_float(float* output) bool byte_buffer::read_float(float* output)
{ {
if (!this->read_data_type(13)) return false; if (!this->read_data_type(13)) return false;
return this->read(4, output); return this->read(4, output);
} }
bool byte_buffer::read_string(std::string* output) bool byte_buffer::read_string(std::string* output)
{ {
char* out_data; char* out_data;
if (this->read_string(&out_data)) if (this->read_string(&out_data))
{ {
output->clear(); output->clear();
output->append(out_data); output->append(out_data);
return true; return true;
} }
return false; return false;
} }
bool byte_buffer::read_string(char** output) bool byte_buffer::read_string(char** output)
{ {
if (!this->read_data_type(16)) return false; if (!this->read_data_type(16)) return false;
*output = const_cast<char*>(this->buffer_.data()) + this->current_byte_; *output = const_cast<char*>(this->buffer_.data()) + this->current_byte_;
this->current_byte_ += strlen(*output) + 1; this->current_byte_ += strlen(*output) + 1;
return true; return true;
} }
bool byte_buffer::read_string(char* output, const int length) bool byte_buffer::read_string(char* output, const int length)
{ {
if (!this->read_data_type(16)) return false; if (!this->read_data_type(16)) return false;
strcpy_s(output, length, const_cast<char*>(this->buffer_.data()) + this->current_byte_); strcpy_s(output, length, const_cast<char*>(this->buffer_.data()) + this->current_byte_);
this->current_byte_ += strlen(output) + 1; this->current_byte_ += strlen(output) + 1;
return true; return true;
} }
bool byte_buffer::read_blob(std::string* output) bool byte_buffer::read_blob(std::string* output)
{ {
char* out_data; char* out_data;
int length; int length;
if (this->read_blob(&out_data, &length)) if (this->read_blob(&out_data, &length))
{ {
output->clear(); output->clear();
output->append(out_data, length); output->append(out_data, length);
return true; return true;
} }
return false; return false;
} }
bool byte_buffer::read_blob(char** output, int* length) bool byte_buffer::read_blob(char** output, int* length)
{ {
if (!this->read_data_type(0x13)) if (!this->read_data_type(0x13))
{ {
return false; return false;
} }
unsigned int size; unsigned int size;
this->read_uint32(&size); this->read_uint32(&size);
*output = const_cast<char*>(this->buffer_.data()) + this->current_byte_; *output = const_cast<char*>(this->buffer_.data()) + this->current_byte_;
*length = static_cast<int>(size); *length = static_cast<int>(size);
this->current_byte_ += size; this->current_byte_ += size;
return true; return true;
} }
bool byte_buffer::read_data_type(const char expected) bool byte_buffer::read_data_type(const char expected)
{ {
if (!this->use_data_types_) return true; if (!this->use_data_types_) return true;
char type; char type;
this->read(1, &type); this->read(1, &type);
return type == expected; return type == expected;
} }
bool byte_buffer::read_array_header(const unsigned char expected, unsigned int* element_count, bool byte_buffer::read_array_header(const unsigned char expected, unsigned int* element_count,
unsigned int* element_size) unsigned int* element_size)
{ {
if (element_count) *element_count = 0; if (element_count) *element_count = 0;
if (element_size) *element_size = 0; if (element_size) *element_size = 0;
if (!this->read_data_type(expected + 100)) return false; if (!this->read_data_type(expected + 100)) return false;
uint32_t array_size, el_count; uint32_t array_size, el_count;
if (!this->read_uint32(&array_size)) return false; if (!this->read_uint32(&array_size)) return false;
this->set_use_data_types(false); this->set_use_data_types(false);
this->read_uint32(&el_count); this->read_uint32(&el_count);
this->set_use_data_types(true); this->set_use_data_types(true);
if (element_count) *element_count = el_count; if (element_count) *element_count = el_count;
if (element_size) *element_size = array_size / el_count; if (element_size) *element_size = array_size / el_count;
return true; return true;
} }
bool byte_buffer::write_byte(char data) bool byte_buffer::write_byte(char data)
{ {
this->write_data_type(3); this->write_data_type(3);
return this->write(1, &data); return this->write(1, &data);
} }
bool byte_buffer::write_bool(bool data) bool byte_buffer::write_bool(bool data)
{ {
this->write_data_type(1); this->write_data_type(1);
return this->write(1, &data); return this->write(1, &data);
} }
bool byte_buffer::write_int16(short data) bool byte_buffer::write_int16(short data)
{ {
this->write_data_type(5); this->write_data_type(5);
return this->write(2, &data); return this->write(2, &data);
} }
bool byte_buffer::write_uint16(unsigned short data) bool byte_buffer::write_uint16(unsigned short data)
{ {
this->write_data_type(6); this->write_data_type(6);
return this->write(2, &data); return this->write(2, &data);
} }
bool byte_buffer::write_int32(int data) bool byte_buffer::write_int32(int data)
{ {
this->write_data_type(7); this->write_data_type(7);
return this->write(4, &data); return this->write(4, &data);
} }
bool byte_buffer::write_uint32(unsigned int data) bool byte_buffer::write_uint32(unsigned int data)
{ {
this->write_data_type(8); this->write_data_type(8);
return this->write(4, &data); return this->write(4, &data);
} }
bool byte_buffer::write_int64(__int64 data) bool byte_buffer::write_int64(__int64 data)
{ {
this->write_data_type(9); this->write_data_type(9);
return this->write(8, &data); return this->write(8, &data);
} }
bool byte_buffer::write_uint64(unsigned __int64 data) bool byte_buffer::write_uint64(unsigned __int64 data)
{ {
this->write_data_type(10); this->write_data_type(10);
return this->write(8, &data); return this->write(8, &data);
} }
bool byte_buffer::write_data_type(char data) bool byte_buffer::write_data_type(char data)
{ {
if (!this->use_data_types_) return true; if (!this->use_data_types_) return true;
return this->write(1, &data); return this->write(1, &data);
} }
bool byte_buffer::write_float(float data) bool byte_buffer::write_float(float data)
{ {
this->write_data_type(13); this->write_data_type(13);
return this->write(4, &data); return this->write(4, &data);
} }
bool byte_buffer::write_string(const std::string& data) bool byte_buffer::write_string(const std::string& data)
{ {
return this->write_string(data.data()); return this->write_string(data.data());
} }
bool byte_buffer::write_string(const char* data) bool byte_buffer::write_string(const char* data)
{ {
this->write_data_type(16); this->write_data_type(16);
return this->write(static_cast<int>(strlen(data)) + 1, data); return this->write(static_cast<int>(strlen(data)) + 1, data);
} }
bool byte_buffer::write_blob(const std::string& data) bool byte_buffer::write_blob(const std::string& data)
{ {
return this->write_blob(data.data(), INT(data.size())); return this->write_blob(data.data(), INT(data.size()));
} }
bool byte_buffer::write_blob(const char* data, const int length) bool byte_buffer::write_blob(const char* data, const int length)
{ {
this->write_data_type(0x13); this->write_data_type(0x13);
this->write_uint32(length); this->write_uint32(length);
return this->write(length, data); return this->write(length, data);
} }
bool byte_buffer::write_array_header(const unsigned char type, const unsigned int element_count, bool byte_buffer::write_array_header(const unsigned char type, const unsigned int element_count,
const unsigned int element_size) const unsigned int element_size)
{ {
const auto using_types = this->is_using_data_types(); const auto using_types = this->is_using_data_types();
this->set_use_data_types(false); this->set_use_data_types(false);
auto result = this->write_byte(type + 100); auto result = this->write_byte(type + 100);
this->set_use_data_types(true); this->set_use_data_types(true);
result &= this->write_uint32(element_count * element_size); result &= this->write_uint32(element_count * element_size);
this->set_use_data_types(false); this->set_use_data_types(false);
result &= this->write_uint32(element_count); result &= this->write_uint32(element_count);
this->set_use_data_types(using_types); this->set_use_data_types(using_types);
return result; return result;
} }
bool byte_buffer::read(int bytes, void* output) bool byte_buffer::read(const int bytes, void* output)
{ {
if (bytes + this->current_byte_ > this->buffer_.size()) return false; if (bytes + this->current_byte_ > this->buffer_.size()) return false;
std::memmove(output, this->buffer_.data() + this->current_byte_, bytes); std::memmove(output, this->buffer_.data() + this->current_byte_, bytes);
this->current_byte_ += bytes; this->current_byte_ += bytes;
return true; return true;
} }
bool byte_buffer::write(const int bytes, const void* data) bool byte_buffer::write(const int bytes, const void* data)
{ {
this->buffer_.append(reinterpret_cast<const char*>(data), bytes); this->buffer_.append(reinterpret_cast<const char*>(data), bytes);
this->current_byte_ += bytes; this->current_byte_ += bytes;
return true; return true;
} }
bool byte_buffer::write(const std::string& data) bool byte_buffer::write(const std::string& data)
{ {
return this->write(data.size(), data.data()); return this->write(data.size(), data.data());
} }
void byte_buffer::set_use_data_types(bool _useDataTypes) void byte_buffer::set_use_data_types(const bool use_data_types)
{ {
this->use_data_types_ = _useDataTypes; this->use_data_types_ = use_data_types;
} }
size_t byte_buffer::size() const size_t byte_buffer::size() const
{ {
return this->buffer_.size(); return this->buffer_.size();
} }
bool byte_buffer::is_using_data_types() const bool byte_buffer::is_using_data_types() const
{ {
return use_data_types_; return use_data_types_;
} }
std::string& byte_buffer::get_buffer() std::string& byte_buffer::get_buffer()
{ {
return this->buffer_; return this->buffer_;
} }
std::string byte_buffer::get_remaining() std::string byte_buffer::get_remaining()
{ {
return std::string(this->buffer_.begin() + this->current_byte_, this->buffer_.end()); return std::string(this->buffer_.begin() + this->current_byte_, this->buffer_.end());
} }
bool byte_buffer::has_more_data() const bool byte_buffer::has_more_data() const
{ {
return this->buffer_.size() > this->current_byte_; return this->buffer_.size() > this->current_byte_;
} }
} }

View File

@ -1,182 +1,201 @@
#pragma once #pragma once
#include "bit_buffer.hpp" #include "bit_buffer.hpp"
#include "byte_buffer.hpp" #include "byte_buffer.hpp"
namespace demonware namespace demonware
{ {
class reply class reply
{ {
public: public:
virtual ~reply() = default; virtual ~reply() = default;
virtual std::string get_data() = 0; virtual std::string get_data() = 0;
}; };
class raw_reply : public reply class raw_reply : public reply
{ {
public: public:
raw_reply() = default; raw_reply() = default;
explicit raw_reply(std::string data) : buffer_(std::move(data)) {}
explicit raw_reply(std::string data) : buffer_(std::move(data))
virtual std::string get_data() override {
{ }
return this->buffer_;
} virtual std::string get_data() override
{
protected: return this->buffer_;
std::string buffer_; }
};
protected:
class typed_reply : public raw_reply std::string buffer_;
{ };
public:
typed_reply(uint8_t _type) : type_(_type) {} class typed_reply : public raw_reply
{
protected: public:
uint8_t get_type() const { return this->type_; } typed_reply(uint8_t _type) : type_(_type)
{
private: }
uint8_t type_;
}; protected:
uint8_t get_type() const { return this->type_; }
class encrypted_reply final : public typed_reply
{ private:
public: uint8_t type_;
encrypted_reply(const uint8_t type, bit_buffer* bbuffer) : typed_reply(type) };
{
this->buffer_.append(bbuffer->get_buffer()); class encrypted_reply final : public typed_reply
} {
encrypted_reply(const uint8_t type, byte_buffer* bbuffer) : typed_reply(type) public:
{ encrypted_reply(const uint8_t type, bit_buffer* bbuffer) : typed_reply(type)
this->buffer_.append(bbuffer->get_buffer()); {
} this->buffer_.append(bbuffer->get_buffer());
}
virtual std::string get_data() override;
}; encrypted_reply(const uint8_t type, byte_buffer* bbuffer) : typed_reply(type)
{
class unencrypted_reply final : public typed_reply this->buffer_.append(bbuffer->get_buffer());
{ }
public:
unencrypted_reply(uint8_t _type, bit_buffer* bbuffer) : typed_reply(_type) virtual std::string get_data() override;
{ };
this->buffer_.append(bbuffer->get_buffer());
} class unencrypted_reply final : public typed_reply
unencrypted_reply(uint8_t _type, byte_buffer* bbuffer) : typed_reply(_type) {
{ public:
this->buffer_.append(bbuffer->get_buffer()); unencrypted_reply(uint8_t _type, bit_buffer* bbuffer) : typed_reply(_type)
} {
this->buffer_.append(bbuffer->get_buffer());
virtual std::string get_data() override; }
};
unencrypted_reply(uint8_t _type, byte_buffer* bbuffer) : typed_reply(_type)
class remote_reply; {
class service_reply; this->buffer_.append(bbuffer->get_buffer());
}
class i_server
{ virtual std::string get_data() override;
public: };
virtual ~i_server() = default;
virtual int send(const char* buf, int len) = 0; class remote_reply;
virtual int recv(char* buf, int len) = 0; class service_reply;
virtual void send_reply(reply* reply) = 0; class i_server
{
virtual std::shared_ptr<remote_reply> create_message(uint8_t type) public:
{ virtual ~i_server() = default;
auto reply = std::make_shared<remote_reply>(this, type); virtual int send(const char* buf, int len) = 0;
return reply; virtual int recv(char* buf, int len) = 0;
}
virtual void send_reply(reply* reply) = 0;
virtual std::shared_ptr<service_reply> create_reply(uint8_t type, uint32_t error = 0 /*Game::bdLobbyErrorCode::BD_NO_ERROR*/)
{ virtual std::shared_ptr<remote_reply> create_message(uint8_t type)
auto reply = std::make_shared<service_reply>(this, type, error); {
return reply; auto reply = std::make_shared<remote_reply>(this, type);
} return reply;
}; }
class remote_reply final virtual std::shared_ptr<service_reply> create_reply(uint8_t type,
{ uint32_t error = 0 /*Game::bdLobbyErrorCode::BD_NO_ERROR*/)
public: {
remote_reply(i_server* server, uint8_t _type) : type_(_type), server_(server) {} auto reply = std::make_shared<service_reply>(this, type, error);
return reply;
template <typename BufferType> }
void send(BufferType* buffer, const bool encrypted) };
{
std::unique_ptr<typed_reply> reply; class remote_reply final
{
if (encrypted) reply = std::make_unique<encrypted_reply>(this->type_, buffer); public:
else reply = std::make_unique<unencrypted_reply>(this->type_, buffer); remote_reply(i_server* server, uint8_t _type) : type_(_type), server_(server)
this->server_->send_reply(reply.get()); {
} }
uint8_t get_type() const { return this->type_; } template <typename BufferType>
void send(BufferType* buffer, const bool encrypted)
private: {
uint8_t type_; std::unique_ptr<typed_reply> reply;
i_server* server_;
}; if (encrypted) reply = std::make_unique<encrypted_reply>(this->type_, buffer);
else reply = std::make_unique<unencrypted_reply>(this->type_, buffer);
class i_serializable this->server_->send_reply(reply.get());
{ }
public:
virtual ~i_serializable() = default; uint8_t get_type() const { return this->type_; }
virtual void serialize(byte_buffer* /*buffer*/) {}
virtual void deserialize(byte_buffer* /*buffer*/) {} private:
}; uint8_t type_;
i_server* server_;
class service_reply final };
{
public: class i_serializable
service_reply(i_server* _server, uint8_t _type, uint32_t _error) : type_(_type), error_(_error), reply_(_server, 1) {} {
public:
uint64_t send() virtual ~i_serializable() = default;
{
static uint64_t id = 0x8000000000000001; virtual void serialize(byte_buffer* /*buffer*/)
const auto transaction_id = ++id; {
}
byte_buffer buffer;
buffer.write_uint64(transaction_id); virtual void deserialize(byte_buffer* /*buffer*/)
buffer.write_uint32(this->error_); {
buffer.write_byte(this->type_); }
};
if (!this->error_)
{ class service_reply final
buffer.write_uint32(uint32_t(this->objects_.size())); {
if (!this->objects_.empty()) public:
{ service_reply(i_server* _server, uint8_t _type, uint32_t _error) : type_(_type), error_(_error),
buffer.write_uint32(uint32_t(this->objects_.size())); reply_(_server, 1)
{
for (auto& object : this->objects_) }
{
object->serialize(&buffer); uint64_t send()
} {
static uint64_t id = 0x8000000000000001;
this->objects_.clear(); const auto transaction_id = ++id;
}
} byte_buffer buffer;
else buffer.write_uint64(transaction_id);
{ buffer.write_uint32(this->error_);
buffer.write_uint64(transaction_id); buffer.write_byte(this->type_);
}
if (!this->error_)
this->reply_.send(&buffer, true); {
return transaction_id; buffer.write_uint32(uint32_t(this->objects_.size()));
} if (!this->objects_.empty())
{
void add(const std::shared_ptr<i_serializable>& object) buffer.write_uint32(uint32_t(this->objects_.size()));
{
this->objects_.push_back(object); for (auto& object : this->objects_)
} {
object->serialize(&buffer);
void add(i_serializable* object) }
{
this->add(std::shared_ptr<i_serializable>(object)); this->objects_.clear();
} }
}
private: else
uint8_t type_; {
uint32_t error_; buffer.write_uint64(transaction_id);
remote_reply reply_; }
std::vector<std::shared_ptr<i_serializable>> objects_; this->reply_.send(&buffer, true);
}; return transaction_id;
} }
void add(const std::shared_ptr<i_serializable>& object)
{
this->objects_.push_back(object);
}
void add(i_serializable* object)
{
this->add(std::shared_ptr<i_serializable>(object));
}
private:
uint8_t type_;
uint32_t error_;
remote_reply reply_;
std::vector<std::shared_ptr<i_serializable>> objects_;
};
}

View File

@ -1,75 +1,75 @@
#include <std_include.hpp> #include <std_include.hpp>
#include <utility> #include <utility>
#include "module/dw.hpp" #include "module/dw.hpp"
#include "utils/cryptography.hpp" #include "utils/cryptography.hpp"
#include "byte_buffer.hpp" #include "byte_buffer.hpp"
namespace demonware namespace demonware
{ {
stun_server::stun_server(std::string _name) : name_(std::move(_name)) stun_server::stun_server(std::string _name) : name_(std::move(_name))
{ {
this->address_ = utils::cryptography::jenkins_one_at_a_time::compute(this->name_); this->address_ = utils::cryptography::jenkins_one_at_a_time::compute(this->name_);
} }
unsigned long stun_server::get_address() const unsigned long stun_server::get_address() const
{ {
return this->address_; return this->address_;
} }
void stun_server::ip_discovery(SOCKET s, const sockaddr* to, int tolen) const void stun_server::ip_discovery(SOCKET s, const sockaddr* to, const int tolen) const
{ {
const uint32_t ip = 0x0100007f; const uint32_t ip = 0x0100007f;
byte_buffer buffer; byte_buffer buffer;
buffer.set_use_data_types(false); buffer.set_use_data_types(false);
buffer.write_byte(31); // type buffer.write_byte(31); // type
buffer.write_byte(2); // version buffer.write_byte(2); // version
buffer.write_byte(0); // version buffer.write_byte(0); // version
buffer.write_uint32(ip); // external ip buffer.write_uint32(ip); // external ip
buffer.write_uint16(3074); // port buffer.write_uint16(3074); // port
dw::send_datagram_packet(s, buffer.get_buffer(), to, tolen); dw::send_datagram_packet(s, buffer.get_buffer(), to, tolen);
} }
void stun_server::nat_discovery(SOCKET s, const sockaddr* to, int tolen) const void stun_server::nat_discovery(SOCKET s, const sockaddr* to, const int tolen) const
{ {
const uint32_t ip = 0x0100007f; const uint32_t ip = 0x0100007f;
byte_buffer buffer; byte_buffer buffer;
buffer.set_use_data_types(false); buffer.set_use_data_types(false);
buffer.write_byte(21); // type buffer.write_byte(21); // type
buffer.write_byte(2); // version buffer.write_byte(2); // version
buffer.write_byte(0); // version buffer.write_byte(0); // version
buffer.write_uint32(ip); // external ip buffer.write_uint32(ip); // external ip
buffer.write_uint16(3074); // port buffer.write_uint16(3074); // port
buffer.write_uint32(this->get_address()); // server ip buffer.write_uint32(this->get_address()); // server ip
buffer.write_uint16(3074); // server port buffer.write_uint16(3074); // server port
dw::send_datagram_packet(s, buffer.get_buffer(), to, tolen); dw::send_datagram_packet(s, buffer.get_buffer(), to, tolen);
} }
int stun_server::send(const SOCKET s, const char* buf, int len, const sockaddr* to, int tolen) const int stun_server::send(const SOCKET s, const char* buf, const int len, const sockaddr* to, const int tolen) const
{ {
uint8_t type, version, padding; uint8_t type, version, padding;
byte_buffer buffer(std::string(buf, len)); byte_buffer buffer(std::string(buf, len));
buffer.set_use_data_types(false); buffer.set_use_data_types(false);
buffer.read_byte(&type); buffer.read_byte(&type);
buffer.read_byte(&version); buffer.read_byte(&version);
buffer.read_byte(&padding); buffer.read_byte(&padding);
switch (type) switch (type)
{ {
case 30: case 30:
this->ip_discovery(s, to, tolen); this->ip_discovery(s, to, tolen);
break; break;
case 20: case 20:
this->nat_discovery(s, to, tolen); this->nat_discovery(s, to, tolen);
break; break;
default: default:
break; break;
} }
return len; return len;
} }
} }

View File

@ -1,21 +1,21 @@
#pragma once #pragma once
namespace demonware namespace demonware
{ {
class stun_server final class stun_server final
{ {
public: public:
explicit stun_server(std::string name); explicit stun_server(std::string name);
unsigned long get_address() const; unsigned long get_address() const;
int send(SOCKET s, const char* buf, int len, const sockaddr* to, int tolen) const; int send(SOCKET s, const char* buf, int len, const sockaddr* to, int tolen) const;
private: private:
std::string name_; std::string name_;
unsigned long address_; unsigned long address_;
void ip_discovery(SOCKET s, const sockaddr* to, int tolen) const; void ip_discovery(SOCKET s, const sockaddr* to, int tolen) const;
void nat_discovery(SOCKET s, const sockaddr* to, int tolen) const; void nat_discovery(SOCKET s, const sockaddr* to, int tolen) const;
}; };
} }

View File

@ -85,7 +85,7 @@ namespace game
void Conbuf_AppendText(const char* message) void Conbuf_AppendText(const char* message)
{ {
if(is_dedi()) if (is_dedi())
{ {
conbuf_append_text_dedicated(message); conbuf_append_text_dedicated(message);
} }
@ -247,7 +247,8 @@ namespace game
} }
else else
{ {
return reinterpret_cast<void(*)(unsigned int, unsigned int, unsigned int)>(0x4EFAA0)(id, stringValue, paramcount); return reinterpret_cast<void(*)(unsigned int, unsigned int, unsigned int)>(0x4EFAA0)(
id, stringValue, paramcount);
} }
} }
@ -297,7 +298,7 @@ namespace game
launcher::mode get_mode() launcher::mode get_mode()
{ {
if(mode == launcher::mode::none) if (mode == launcher::mode::none)
{ {
throw std::runtime_error("Launcher mode not valid. Something must be wrong."); throw std::runtime_error("Launcher mode not valid. Something must be wrong.");
} }
@ -330,7 +331,8 @@ namespace game
native::DB_LoadXAssets = native::DB_LoadXAssets_t(SELECT_VALUE(0x48A8E0, 0x4CD020, 0x44F770)); native::DB_LoadXAssets = native::DB_LoadXAssets_t(SELECT_VALUE(0x48A8E0, 0x4CD020, 0x44F770));
native::Dvar_SetFromStringByName = native::Dvar_SetFromStringByName_t(SELECT_VALUE(0x4DD090, 0x5BF740, 0x518DF0)); native::Dvar_SetFromStringByName = native::Dvar_SetFromStringByName_t(
SELECT_VALUE(0x4DD090, 0x5BF740, 0x518DF0));
native::G_RunFrame = native::G_RunFrame_t(SELECT_VALUE(0x52EAA0, 0x50CB70, 0x48AD60)); native::G_RunFrame = native::G_RunFrame_t(SELECT_VALUE(0x52EAA0, 0x50CB70, 0x48AD60));
@ -358,11 +360,11 @@ namespace game
native::scr_VmPub = reinterpret_cast<native::scrVmPub_t*>(SELECT_VALUE(0x1BF2580, 0x20B4A80, 0x1F5B080)); native::scr_VmPub = reinterpret_cast<native::scrVmPub_t*>(SELECT_VALUE(0x1BF2580, 0x20B4A80, 0x1F5B080));
native::scr_instanceFunctions = reinterpret_cast<native::scr_call_t*>( SELECT_VALUE(0x184CDB0, 0x1D4F258, native::scr_instanceFunctions = reinterpret_cast<native::scr_call_t*>(SELECT_VALUE(0x184CDB0, 0x1D4F258,
0x1BF59C8)); 0x1BF59C8));
native::scr_globalFunctions = reinterpret_cast<native::scr_call_t*>( SELECT_VALUE(0x186C68C, 0x1D6EB34, native::scr_globalFunctions = reinterpret_cast<native::scr_call_t*>(SELECT_VALUE(0x186C68C, 0x1D6EB34,
0x1C152A4 0x1C152A4
)); ));
native::g_script_error_level = reinterpret_cast<int*>(SELECT_VALUE(0x1BEFCFC, 0x20B21FC, 0x1F5B058)); native::g_script_error_level = reinterpret_cast<int*>(SELECT_VALUE(0x1BEFCFC, 0x20B21FC, 0x1F5B058));
native::g_script_error = reinterpret_cast<jmp_buf*>(SELECT_VALUE(0x1BF1D18, 0x20B4218, 0x1F5A818)); native::g_script_error = reinterpret_cast<jmp_buf*>(SELECT_VALUE(0x1BF1D18, 0x20B4218, 0x1F5A818));

View File

@ -20,7 +20,7 @@ namespace game
typedef void (*DB_LoadXAssets_t)(XZoneInfo* zoneInfo, unsigned int zoneCount, int sync); typedef void (*DB_LoadXAssets_t)(XZoneInfo* zoneInfo, unsigned int zoneCount, int sync);
extern DB_LoadXAssets_t DB_LoadXAssets; extern DB_LoadXAssets_t DB_LoadXAssets;
typedef void (*Dvar_SetFromStringByName_t)(const char *dvarName, const char *string); typedef void (*Dvar_SetFromStringByName_t)(const char* dvarName, const char* string);
extern Dvar_SetFromStringByName_t Dvar_SetFromStringByName; extern Dvar_SetFromStringByName_t Dvar_SetFromStringByName;
typedef int (*G_RunFrame_t)(int, int); typedef int (*G_RunFrame_t)(int, int);

View File

@ -1,134 +1,134 @@
#include "std_include.hpp" #include "std_include.hpp"
#include "context.hpp" #include "context.hpp"
namespace game namespace game
{ {
namespace scripting namespace scripting
{ {
entity::entity() : entity(nullptr, 0) entity::entity() : entity(nullptr, 0)
{ {
} }
entity::entity(const entity& other) : entity(other.context_, other.entity_id_) entity::entity(const entity& other) : entity(other.context_, other.entity_id_)
{ {
} }
entity::entity(entity&& other) noexcept entity::entity(entity&& other) noexcept
{ {
if (&other == this) return; if (&other == this) return;
this->context_ = other.context_; this->context_ = other.context_;
this->entity_id_ = other.entity_id_; this->entity_id_ = other.entity_id_;
other.context_ = nullptr; other.context_ = nullptr;
other.entity_id_ = 0; other.entity_id_ = 0;
} }
entity::entity(context* context, const unsigned int entity_id) : context_(context), entity_id_(entity_id) entity::entity(context* context, const unsigned int entity_id) : context_(context), entity_id_(entity_id)
{ {
this->add(); this->add();
} }
entity::~entity() entity::~entity()
{ {
this->release(); this->release();
} }
entity& entity::operator=(const entity& other) entity& entity::operator=(const entity& other)
{ {
if (&other != this) if (&other != this)
{ {
this->release(); this->release();
this->context_ = other.context_; this->context_ = other.context_;
this->entity_id_ = other.entity_id_; this->entity_id_ = other.entity_id_;
this->add(); this->add();
} }
return *this; return *this;
} }
entity& entity::operator=(entity&& other) noexcept entity& entity::operator=(entity&& other) noexcept
{ {
if (&other != this) if (&other != this)
{ {
this->release(); this->release();
this->context_ = other.context_; this->context_ = other.context_;
this->entity_id_ = other.entity_id_; this->entity_id_ = other.entity_id_;
other.context_ = nullptr; other.context_ = nullptr;
other.entity_id_ = 0; other.entity_id_ = 0;
} }
return *this; return *this;
} }
event_listener_handle entity::on_notify(const std::string& event, event_listener_handle entity::on_notify(const std::string& event,
const std::function<void(std::vector<chaiscript::Boxed_Value>)>& const std::function<void(std::vector<chaiscript::Boxed_Value>)>&
callback, callback,
const bool is_volatile) const bool is_volatile)
const const
{ {
event_listener listener; event_listener listener;
listener.event = event; listener.event = event;
listener.callback = callback; listener.callback = callback;
listener.entity_id = this->entity_id_; listener.entity_id = this->entity_id_;
listener.is_volatile = is_volatile; listener.is_volatile = is_volatile;
return this->context_->get_event_handler()->add_event_listener(listener); return this->context_->get_event_handler()->add_event_listener(listener);
} }
unsigned int entity::get_entity_id() const unsigned int entity::get_entity_id() const
{ {
return this->entity_id_; return this->entity_id_;
} }
native::scr_entref_t entity::get_entity_reference() const native::scr_entref_t entity::get_entity_reference() const
{ {
return game::native::Scr_GetEntityIdRef(this->get_entity_id()); return game::native::Scr_GetEntityIdRef(this->get_entity_id());
} }
chaiscript::Boxed_Value entity::call(const std::string& function, chaiscript::Boxed_Value entity::call(const std::string& function,
const std::vector<chaiscript::Boxed_Value>& arguments) const const std::vector<chaiscript::Boxed_Value>& arguments) const
{ {
return this->context_->get_executer()->call(function, this->get_entity_id(), arguments); return this->context_->get_executer()->call(function, this->get_entity_id(), arguments);
} }
void entity::notify(const std::string& event, void entity::notify(const std::string& event,
const std::vector<chaiscript::Boxed_Value>& arguments) const const std::vector<chaiscript::Boxed_Value>& arguments) const
{ {
this->context_->get_executer()->notify(event, this->get_entity_id(), arguments); this->context_->get_executer()->notify(event, this->get_entity_id(), arguments);
} }
void entity::set(const std::string& field, const chaiscript::Boxed_Value& value) const void entity::set(const std::string& field, const chaiscript::Boxed_Value& value) const
{ {
this->context_->get_executer()->set_entity_field(field, this->get_entity_id(), value); this->context_->get_executer()->set_entity_field(field, this->get_entity_id(), value);
} }
chaiscript::Boxed_Value entity::get(const std::string& field) const chaiscript::Boxed_Value entity::get(const std::string& field) const
{ {
return this->context_->get_executer()->get_entity_field(field, this->get_entity_id()); return this->context_->get_executer()->get_entity_field(field, this->get_entity_id());
} }
void entity::add() const void entity::add() const
{ {
if (this->entity_id_) if (this->entity_id_)
{ {
native::VariableValue value{}; native::VariableValue value;
value.type = native::SCRIPT_OBJECT; value.type = native::SCRIPT_OBJECT;
value.u.entityId = this->entity_id_; value.u.entityId = this->entity_id_;
native::AddRefToValue(&value); native::AddRefToValue(&value);
} }
} }
void entity::release() const void entity::release() const
{ {
if (this->entity_id_) if (this->entity_id_)
{ {
native::RemoveRefToValue(native::SCRIPT_OBJECT, {static_cast<int>(this->entity_id_)}); native::RemoveRefToValue(native::SCRIPT_OBJECT, {static_cast<int>(this->entity_id_)});
} }
} }
} }
} }

View File

@ -1,124 +1,124 @@
#include "std_include.hpp" #include "std_include.hpp"
#include "context.hpp" #include "context.hpp"
namespace game namespace game
{ {
namespace scripting namespace scripting
{ {
event_handler::event_handler(context* context) : context_(context) event_handler::event_handler(context* context) : context_(context)
{ {
const auto chai = this->context_->get_chai(); const auto chai = this->context_->get_chai();
chai->add(chaiscript::user_type<event_listener_handle>(), "_event_listener_handle"); chai->add(chaiscript::user_type<event_listener_handle>(), "_event_listener_handle");
chai->add(chaiscript::constructor<event_listener_handle()>(), "_event_listener_handle"); chai->add(chaiscript::constructor<event_listener_handle()>(), "_event_listener_handle");
chai->add(chaiscript::constructor<event_listener_handle(const event_listener_handle&)>(), chai->add(chaiscript::constructor<event_listener_handle(const event_listener_handle&)>(),
"_event_listener_handle"); "_event_listener_handle");
chai->add(chaiscript::fun( chai->add(chaiscript::fun(
[](event_listener_handle& lhs, const event_listener_handle& rhs) -> event_listener_handle& [](event_listener_handle& lhs, const event_listener_handle& rhs) -> event_listener_handle&
{ {
return lhs = rhs; return lhs = rhs;
}), "="); }), "=");
chai->add(chaiscript::fun([this](const event_listener_handle& handle) chai->add(chaiscript::fun([this](const event_listener_handle& handle)
{ {
this->remove(handle); this->remove(handle);
}), "clear"); }), "clear");
} }
void event_handler::dispatch(event* event) void event_handler::dispatch(event* event)
{ {
try try
{ {
std::vector<chaiscript::Boxed_Value> arguments; std::vector<chaiscript::Boxed_Value> arguments;
for (auto argument : event->arguments) for (auto argument : event->arguments)
{ {
arguments.push_back(this->context_->get_parameters()->load(argument)); arguments.push_back(this->context_->get_parameters()->load(argument));
} }
this->dispatch_to_specific_listeners(event, arguments); this->dispatch_to_specific_listeners(event, arguments);
this->dispatch_to_generic_listeners(event, arguments); this->dispatch_to_generic_listeners(event, arguments);
} }
catch (chaiscript::exception::eval_error& e) catch (chaiscript::exception::eval_error& e)
{ {
throw std::runtime_error(e.pretty_print()); throw std::runtime_error(e.pretty_print());
} }
} }
void event_handler::dispatch_to_specific_listeners(event* event, void event_handler::dispatch_to_specific_listeners(event* event,
const std::vector<chaiscript::Boxed_Value>& arguments) const std::vector<chaiscript::Boxed_Value>& arguments)
{ {
for (auto listener : this->event_listeners_) for (auto listener : this->event_listeners_)
{ {
if (listener->event == event->name && listener->entity_id == event->entity_id) if (listener->event == event->name && listener->entity_id == event->entity_id)
{ {
if (listener->is_volatile) if (listener->is_volatile)
{ {
this->event_listeners_.remove(listener); this->event_listeners_.remove(listener);
} }
listener->callback(arguments); listener->callback(arguments);
} }
} }
} }
void event_handler::dispatch_to_generic_listeners(event* event, void event_handler::dispatch_to_generic_listeners(event* event,
const std::vector<chaiscript::Boxed_Value>& arguments) const std::vector<chaiscript::Boxed_Value>& arguments)
{ {
for (auto listener : this->generic_event_listeners_) for (auto listener : this->generic_event_listeners_)
{ {
if (listener->event == event->name) if (listener->event == event->name)
{ {
if (listener->is_volatile) if (listener->is_volatile)
{ {
this->generic_event_listeners_.remove(listener); this->generic_event_listeners_.remove(listener);
} }
listener->callback(entity(this->context_, event->entity_id), arguments); listener->callback(entity(this->context_, event->entity_id), arguments);
} }
} }
} }
event_listener_handle event_handler::add_event_listener(event_listener listener) event_listener_handle event_handler::add_event_listener(event_listener listener)
{ {
listener.id = ++this->current_listener_id_; listener.id = ++this->current_listener_id_;
this->event_listeners_.add(listener); this->event_listeners_.add(listener);
return {listener.id}; return {listener.id};
} }
event_listener_handle event_handler::add_event_listener(generic_event_listener listener) event_listener_handle event_handler::add_event_listener(generic_event_listener listener)
{ {
listener.id = ++this->current_listener_id_; listener.id = ++this->current_listener_id_;
this->generic_event_listeners_.add(listener); this->generic_event_listeners_.add(listener);
return {listener.id}; return {listener.id};
} }
void event_handler::clear() void event_handler::clear()
{ {
this->event_listeners_.clear(); this->event_listeners_.clear();
this->generic_event_listeners_.clear(); this->generic_event_listeners_.clear();
} }
void event_handler::remove(const event_listener_handle& handle) void event_handler::remove(const event_listener_handle& handle)
{ {
for (auto task : this->event_listeners_) for (const auto task : this->event_listeners_)
{ {
if (task->id == handle.id) if (task->id == handle.id)
{ {
this->event_listeners_.remove(task); this->event_listeners_.remove(task);
return; return;
} }
} }
for (auto task : this->generic_event_listeners_) for (const auto task : this->generic_event_listeners_)
{ {
if (task->id == handle.id) if (task->id == handle.id)
{ {
this->generic_event_listeners_.remove(task); this->generic_event_listeners_.remove(task);
return; return;
} }
} }
} }
} }
} }

View File

@ -1,172 +1,172 @@
#include "std_include.hpp" #include "std_include.hpp"
#include "game/game.hpp" #include "game/game.hpp"
#include "utils/string.hpp" #include "utils/string.hpp"
#include "functions.hpp" #include "functions.hpp"
#include "stack_isolation.hpp" #include "stack_isolation.hpp"
#include "safe_executer.hpp" #include "safe_executer.hpp"
#include "context.hpp" #include "context.hpp"
namespace game namespace game
{ {
namespace scripting namespace scripting
{ {
executer::executer(context* context) : context_(context) executer::executer(context* context) : context_(context)
{ {
} }
int executer::get_field_id(const int classnum, const std::string& field) const int executer::get_field_id(const int classnum, const std::string& field) const
{ {
const auto field_name = utils::string::to_lower(field); const auto field_name = utils::string::to_lower(field);
const auto class_id = native::g_classMap[classnum].id; const auto class_id = native::g_classMap[classnum].id;
const auto field_str = native::SL_GetString(field_name.data(), 1); const auto field_str = native::SL_GetString(field_name.data(), 1);
const auto _ = gsl::finally([field_str]() const auto _ = gsl::finally([field_str]()
{ {
native::RemoveRefToValue(native::SCRIPT_STRING, {int(field_str)}); native::RemoveRefToValue(native::SCRIPT_STRING, {int(field_str)});
}); });
const auto offset = native::FindVariable(class_id, field_str); const auto offset = native::FindVariable(class_id, field_str);
if (offset) if (offset)
{ {
const auto index = 4 * (offset + 0xC800 * (class_id & 1)); const auto index = 4 * (offset + 0xC800 * (class_id & 1));
return PINT(SELECT_VALUE(0x1A3BC80, 0x1EFE180, 0x1DC8800))[index]; return PINT(SELECT_VALUE(0x1A3BC80, 0x1EFE180, 0x1DC8800))[index];
} }
return -1; return -1;
} }
void executer::set_entity_field(const std::string& field, const unsigned int entity_id, void executer::set_entity_field(const std::string& field, const unsigned int entity_id,
const chaiscript::Boxed_Value& value) const chaiscript::Boxed_Value& value)
{ {
const auto entref = native::Scr_GetEntityIdRef(entity_id); const auto entref = native::Scr_GetEntityIdRef(entity_id);
const int id = get_field_id(entref.raw.classnum, field); const int id = get_field_id(entref.raw.classnum, field);
if (id != -1) if (id != -1)
{ {
stack_isolation _; stack_isolation _;
this->context_->get_parameters()->push(value); this->context_->get_parameters()->push(value);
native::scr_VmPub->outparamcount = native::scr_VmPub->inparamcount; native::scr_VmPub->outparamcount = native::scr_VmPub->inparamcount;
native::scr_VmPub->inparamcount = 0; native::scr_VmPub->inparamcount = 0;
if (!safe_executer::set_entity_field(entref, id)) if (!safe_executer::set_entity_field(entref, id))
{ {
throw std::runtime_error("Failed to set value for field '" + field + "'"); throw std::runtime_error("Failed to set value for field '" + field + "'");
} }
} }
else else
{ {
this->entity_fields_[entity_id][field] = value; this->entity_fields_[entity_id][field] = value;
} }
} }
chaiscript::Boxed_Value executer::get_entity_field(const std::string& field, const unsigned int entity_id) chaiscript::Boxed_Value executer::get_entity_field(const std::string& field, const unsigned int entity_id)
{ {
const auto entref = native::Scr_GetEntityIdRef(entity_id); const auto entref = native::Scr_GetEntityIdRef(entity_id);
const auto id = this->get_field_id(entref.raw.classnum, field); const auto id = this->get_field_id(entref.raw.classnum, field);
if (id != -1) if (id != -1)
{ {
stack_isolation _; stack_isolation _;
native::VariableValue value{}; native::VariableValue value{};
if (!safe_executer::get_entity_field(entref, id, &value)) if (!safe_executer::get_entity_field(entref, id, &value))
{ {
throw std::runtime_error("Failed to get value for field '" + field + "'"); throw std::runtime_error("Failed to get value for field '" + field + "'");
} }
const auto $ = gsl::finally([value]() const auto $ = gsl::finally([value]()
{ {
native::RemoveRefToValue(value.type, value.u); native::RemoveRefToValue(value.type, value.u);
}); });
return this->context_->get_parameters()->load(value); return this->context_->get_parameters()->load(value);
} }
else else
{ {
const auto& map = this->entity_fields_[entity_id]; const auto& map = this->entity_fields_[entity_id];
const auto value = map.find(field); const auto value = map.find(field);
if (value != map.end()) if (value != map.end())
{ {
return value->second; return value->second;
} }
} }
return {}; return {};
} }
void executer::notify(const std::string& event, const unsigned int entity_id, void executer::notify(const std::string& event, const unsigned int entity_id,
std::vector<chaiscript::Boxed_Value> arguments) const std::vector<chaiscript::Boxed_Value> arguments) const
{ {
stack_isolation _; stack_isolation _;
std::reverse(arguments.begin(), arguments.end()); std::reverse(arguments.begin(), arguments.end());
for (auto argument : arguments) for (auto argument : arguments)
{ {
this->context_->get_parameters()->push(argument); this->context_->get_parameters()->push(argument);
} }
const auto event_id = native::SL_GetString(event.data(), 0); const auto event_id = native::SL_GetString(event.data(), 0);
native::Scr_NotifyId(entity_id, event_id, native::scr_VmPub->inparamcount); native::Scr_NotifyId(entity_id, event_id, native::scr_VmPub->inparamcount);
} }
chaiscript::Boxed_Value executer::call(const std::string& function, const unsigned int entity_id, chaiscript::Boxed_Value executer::call(const std::string& function, const unsigned int entity_id,
std::vector<chaiscript::Boxed_Value> arguments) const std::vector<chaiscript::Boxed_Value> arguments) const
{ {
const auto function_index = find_function_index(function, entity_id == 0); const auto function_index = find_function_index(function, entity_id == 0);
if (function_index < 0) if (function_index < 0)
{ {
throw std::runtime_error("No function found for name '" + function + "'"); throw std::runtime_error("No function found for name '" + function + "'");
} }
const auto entity = function_index > 0x1C7 const auto entity = function_index > 0x1C7
? native::Scr_GetEntityIdRef(entity_id) ? native::Scr_GetEntityIdRef(entity_id)
: native::scr_entref_t{~0u}; : native::scr_entref_t{~0u};
const auto function_ptr = native::Scr_GetFunc(function_index); const auto function_ptr = native::Scr_GetFunc(function_index);
stack_isolation _; stack_isolation _;
std::reverse(arguments.begin(), arguments.end()); std::reverse(arguments.begin(), arguments.end());
for (const auto& argument : arguments) for (const auto& argument : arguments)
{ {
this->context_->get_parameters()->push(argument); this->context_->get_parameters()->push(argument);
} }
native::scr_VmPub->outparamcount = native::scr_VmPub->inparamcount; native::scr_VmPub->outparamcount = native::scr_VmPub->inparamcount;
native::scr_VmPub->inparamcount = 0; native::scr_VmPub->inparamcount = 0;
if (!safe_executer::call(function_ptr, entity)) if (!safe_executer::call(function_ptr, entity))
{ {
throw std::runtime_error("Error executing function '" + function + "'"); throw std::runtime_error("Error executing function '" + function + "'");
} }
return this->context_->get_parameters()->get_return_value(); return this->context_->get_parameters()->get_return_value();
} }
int executer::find_function_index(const std::string& function, const bool prefer_global) int executer::find_function_index(const std::string& function, const bool prefer_global)
{ {
const auto target = utils::string::to_lower(function); const auto target = utils::string::to_lower(function);
const auto primary_map = prefer_global const auto primary_map = prefer_global
? &global_function_map ? &global_function_map
: &instance_function_map; : &instance_function_map;
const auto secondary_map = !prefer_global const auto secondary_map = !prefer_global
? &global_function_map ? &global_function_map
: &instance_function_map; : &instance_function_map;
auto function_entry = primary_map->find(target); auto function_entry = primary_map->find(target);
if (function_entry != primary_map->end()) if (function_entry != primary_map->end())
{ {
return function_entry->second; return function_entry->second;
} }
function_entry = secondary_map->find(target); function_entry = secondary_map->find(target);
if (function_entry != secondary_map->end()) if (function_entry != secondary_map->end())
{ {
return function_entry->second; return function_entry->second;
} }
return -1; return -1;
} }
} }
} }

View File

@ -1,3 +1,5 @@
#pragma once
namespace game namespace game
{ {
namespace scripting namespace scripting

View File

@ -1,152 +1,153 @@
#include "std_include.hpp" #include "std_include.hpp"
#include "context.hpp" #include "context.hpp"
namespace game namespace game
{ {
namespace scripting namespace scripting
{ {
parameters::parameters(context* context) : context_(context) parameters::parameters(context* context) : context_(context)
{ {
} }
chaiscript::Boxed_Value parameters::load(const native::VariableValue value) const chaiscript::Boxed_Value parameters::load(const native::VariableValue value) const
{ {
if (value.type == native::SCRIPT_STRING) if (value.type == native::SCRIPT_STRING)
{ {
const std::string string = native::SL_ConvertToString(value.u.stringValue); const std::string string = native::SL_ConvertToString(value.u.stringValue);
return chaiscript::var(string); return chaiscript::var(string);
} }
else if (value.type == native::SCRIPT_FLOAT) else if (value.type == native::SCRIPT_FLOAT)
{ {
return chaiscript::var(value.u.floatValue); return chaiscript::var(value.u.floatValue);
} }
else if (value.type == native::SCRIPT_INTEGER) else if (value.type == native::SCRIPT_INTEGER)
{ {
return chaiscript::var(value.u.intValue); return chaiscript::var(value.u.intValue);
} }
else if (value.type == native::SCRIPT_OBJECT) else if (value.type == native::SCRIPT_OBJECT)
{ {
return chaiscript::var(entity(this->context_, value.u.entityId)); return chaiscript::var(entity(this->context_, value.u.entityId));
} }
else if (value.type == native::SCRIPT_VECTOR) else if (value.type == native::SCRIPT_VECTOR)
{ {
std::vector<chaiscript::Boxed_Value> values; std::vector<chaiscript::Boxed_Value> values;
values.push_back(chaiscript::var(value.u.vectorValue[0])); values.push_back(chaiscript::var(value.u.vectorValue[0]));
values.push_back(chaiscript::var(value.u.vectorValue[1])); values.push_back(chaiscript::var(value.u.vectorValue[1]));
values.push_back(chaiscript::var(value.u.vectorValue[2])); values.push_back(chaiscript::var(value.u.vectorValue[2]));
return chaiscript::var(values); return chaiscript::var(values);
} }
return {}; return {};
} }
void parameters::push(const chaiscript::Boxed_Value& value) const void parameters::push(const chaiscript::Boxed_Value& value) const
{ {
if (native::scr_VmPub->outparamcount) if (native::scr_VmPub->outparamcount)
{ {
native::Scr_ClearOutParams(); native::Scr_ClearOutParams();
} }
if (native::scr_VmPub->top == native::scr_VmPub->maxstack) if (native::scr_VmPub->top == native::scr_VmPub->maxstack)
{ {
throw std::runtime_error("Internal script stack overflow"); throw std::runtime_error("Internal script stack overflow");
} }
native::VariableValue* value_ptr = ++native::scr_VmPub->top; native::VariableValue* value_ptr = ++native::scr_VmPub->top;
++native::scr_VmPub->inparamcount; ++native::scr_VmPub->inparamcount;
value_ptr->type = native::SCRIPT_NONE; value_ptr->type = native::SCRIPT_NONE;
value_ptr->u.intValue = 0; value_ptr->u.intValue = 0;
if (value.get_type_info() == typeid(float)) if (value.get_type_info() == typeid(float))
{ {
const auto real_value = this->context_->get_chai()->boxed_cast<float>(value); const auto real_value = this->context_->get_chai()->boxed_cast<float>(value);
value_ptr->type = native::SCRIPT_FLOAT; value_ptr->type = native::SCRIPT_FLOAT;
value_ptr->u.floatValue = real_value; value_ptr->u.floatValue = real_value;
} }
else if (value.get_type_info() == typeid(double)) else if (value.get_type_info() == typeid(double))
{ {
const auto real_value = this->context_->get_chai()->boxed_cast<double>(value); const auto real_value = this->context_->get_chai()->boxed_cast<double>(value);
value_ptr->type = native::SCRIPT_FLOAT; value_ptr->type = native::SCRIPT_FLOAT;
value_ptr->u.floatValue = static_cast<float>(real_value); value_ptr->u.floatValue = static_cast<float>(real_value);
} }
else if (value.get_type_info() == typeid(int)) else if (value.get_type_info() == typeid(int))
{ {
const auto real_value = this->context_->get_chai()->boxed_cast<int>(value); const auto real_value = this->context_->get_chai()->boxed_cast<int>(value);
value_ptr->type = native::SCRIPT_INTEGER; value_ptr->type = native::SCRIPT_INTEGER;
value_ptr->u.intValue = real_value; value_ptr->u.intValue = real_value;
} }
else if (value.get_type_info() == typeid(bool)) else if (value.get_type_info() == typeid(bool))
{ {
const auto real_value = this->context_->get_chai()->boxed_cast<bool>(value); const auto real_value = this->context_->get_chai()->boxed_cast<bool>(value);
value_ptr->type = native::SCRIPT_INTEGER; value_ptr->type = native::SCRIPT_INTEGER;
value_ptr->u.intValue = real_value; value_ptr->u.intValue = real_value;
} }
else if (value.get_type_info() == typeid(entity)) else if (value.get_type_info() == typeid(entity))
{ {
const auto real_value = this->context_->get_chai()->boxed_cast<entity>(value); const auto real_value = this->context_->get_chai()->boxed_cast<entity>(value);
value_ptr->type = native::SCRIPT_OBJECT; value_ptr->type = native::SCRIPT_OBJECT;
value_ptr->u.entityId = real_value.get_entity_id(); value_ptr->u.entityId = real_value.get_entity_id();
game::native::AddRefToValue(value_ptr); game::native::AddRefToValue(value_ptr);
} }
else if (value.get_type_info() == typeid(std::string)) else if (value.get_type_info() == typeid(std::string))
{ {
const auto real_value = this->context_->get_chai()->boxed_cast<std::string>(value); const auto real_value = this->context_->get_chai()->boxed_cast<std::string>(value);
value_ptr->type = native::SCRIPT_STRING; value_ptr->type = native::SCRIPT_STRING;
value_ptr->u.stringValue = game::native::SL_GetString(real_value.data(), 0); value_ptr->u.stringValue = game::native::SL_GetString(real_value.data(), 0);
} }
else if (value.get_type_info() == typeid(std::vector<chaiscript::Boxed_Value>)) else if (value.get_type_info() == typeid(std::vector<chaiscript::Boxed_Value>))
{ {
float values[3]; float values[3];
const auto real_value = this->context_->get_chai()->boxed_cast<std::vector<chaiscript::Boxed_Value>>(value); const auto real_value = this->context_->get_chai()->boxed_cast<std::vector<chaiscript::Boxed_Value>
if (real_value.size() != 3) >(value);
{ if (real_value.size() != 3)
throw std::runtime_error("Invalid vector length. Size must be exactly 3"); {
} throw std::runtime_error("Invalid vector length. Size must be exactly 3");
}
const auto unbox_float = [&real_value, this](const size_t index) -> float
{ const auto unbox_float = [&real_value, this](const size_t index) -> float
const auto value = real_value[index]; {
if (value.get_type_info() == typeid(float)) const auto value = real_value[index];
{ if (value.get_type_info() == typeid(float))
return this->context_->get_chai()->boxed_cast<float>(value); {
} return this->context_->get_chai()->boxed_cast<float>(value);
if (value.get_type_info() == typeid(double)) }
{ if (value.get_type_info() == typeid(double))
return float(this->context_->get_chai()->boxed_cast<double>(value)); {
} return float(this->context_->get_chai()->boxed_cast<double>(value));
if (value.get_type_info() == typeid(int)) }
{ if (value.get_type_info() == typeid(int))
return float(this->context_->get_chai()->boxed_cast<int>(value)); {
} return float(this->context_->get_chai()->boxed_cast<int>(value));
}
throw std::runtime_error("Vector element at index " + std::to_string(index) + " is not a number");
}; throw std::runtime_error("Vector element at index " + std::to_string(index) + " is not a number");
};
values[0] = unbox_float(0);
values[1] = unbox_float(1); values[0] = unbox_float(0);
values[2] = unbox_float(2); values[1] = unbox_float(1);
values[2] = unbox_float(2);
value_ptr->type = native::SCRIPT_VECTOR;
value_ptr->u.vectorValue = native::Scr_AllocVector(values); value_ptr->type = native::SCRIPT_VECTOR;
} value_ptr->u.vectorValue = native::Scr_AllocVector(values);
else }
{ else
throw std::runtime_error("Unable to unbox value of type '" + value.get_type_info().bare_name() + "'"); {
} throw std::runtime_error("Unable to unbox value of type '" + value.get_type_info().bare_name() + "'");
} }
}
chaiscript::Boxed_Value parameters::get_return_value() const
{ chaiscript::Boxed_Value parameters::get_return_value() const
if (native::scr_VmPub->inparamcount == 0) return {}; {
if (native::scr_VmPub->inparamcount == 0) return {};
native::Scr_ClearOutParams();
native::scr_VmPub->outparamcount = native::scr_VmPub->inparamcount; native::Scr_ClearOutParams();
native::scr_VmPub->inparamcount = 0; native::scr_VmPub->outparamcount = native::scr_VmPub->inparamcount;
native::scr_VmPub->inparamcount = 0;
return this->load(native::scr_VmPub->top[1 - native::scr_VmPub->outparamcount]);
} return this->load(native::scr_VmPub->top[1 - native::scr_VmPub->outparamcount]);
} }
} }
}

View File

@ -1,97 +1,99 @@
#include "std_include.hpp" #include "std_include.hpp"
#include "context.hpp" #include "context.hpp"
namespace game namespace game
{ {
namespace scripting namespace scripting
{ {
scheduler::scheduler(context* context) : context_(context) scheduler::scheduler(context* context) : context_(context)
{ {
const auto chai = this->context_->get_chai(); const auto chai = this->context_->get_chai();
chai->add(chaiscript::user_type<task_handle>(), "_task_handle"); chai->add(chaiscript::user_type<task_handle>(), "_task_handle");
chai->add(chaiscript::constructor<task_handle()>(), "_task_handle"); chai->add(chaiscript::constructor<task_handle()>(), "_task_handle");
chai->add(chaiscript::constructor<task_handle(const task_handle&)>(), "_task_handle"); chai->add(chaiscript::constructor<task_handle(const task_handle&)>(), "_task_handle");
chai->add(chaiscript::fun([](task_handle& lhs, const task_handle& rhs) -> task_handle& chai->add(chaiscript::fun([](task_handle& lhs, const task_handle& rhs) -> task_handle&
{ {
return lhs = rhs; return lhs = rhs;
}), "="); }), "=");
chai->add(chaiscript::fun([this](const std::function<void()>& callback, const long long milliseconds) -> task_handle chai->add(chaiscript::fun(
{ [this](const std::function<void()>& callback, const long long milliseconds) -> task_handle
return this->add(callback, milliseconds, true); {
}), "setTimeout"); return this->add(callback, milliseconds, true);
}), "setTimeout");
chai->add(chaiscript::fun([this](const std::function<void()>& callback, const long long milliseconds) -> task_handle
{ chai->add(chaiscript::fun(
return this->add(callback, milliseconds, false); [this](const std::function<void()>& callback, const long long milliseconds) -> task_handle
}), "setInterval"); {
return this->add(callback, milliseconds, false);
const auto clear = [this](const task_handle& handle) }), "setInterval");
{
this->remove(handle); const auto clear = [this](const task_handle& handle)
}; {
this->remove(handle);
chai->add(chaiscript::fun(clear), "clear"); };
chai->add(chaiscript::fun(clear), "clearTimeout");
chai->add(chaiscript::fun(clear), "clearInterval"); chai->add(chaiscript::fun(clear), "clear");
} chai->add(chaiscript::fun(clear), "clearTimeout");
chai->add(chaiscript::fun(clear), "clearInterval");
void scheduler::run_frame() }
{
for (auto task : this->tasks_) void scheduler::run_frame()
{ {
const auto now = std::chrono::steady_clock::now(); for (auto task : this->tasks_)
if ((now - task->last_execution) > task->delay) {
{ const auto now = std::chrono::steady_clock::now();
task->last_execution = now; if ((now - task->last_execution) > task->delay)
if (task->is_volatile) {
{ task->last_execution = now;
this->tasks_.remove(task); if (task->is_volatile)
} {
this->tasks_.remove(task);
task->callback(); }
}
} task->callback();
} }
}
void scheduler::clear() }
{
this->tasks_.clear(); void scheduler::clear()
} {
this->tasks_.clear();
task_handle scheduler::add(const std::function<void()>& callback, const long long milliseconds, }
const bool is_volatile)
{ task_handle scheduler::add(const std::function<void()>& callback, const long long milliseconds,
return this->add(callback, std::chrono::milliseconds(milliseconds), is_volatile); const bool is_volatile)
} {
return this->add(callback, std::chrono::milliseconds(milliseconds), is_volatile);
task_handle scheduler::add(const std::function<void()>& callback, const std::chrono::milliseconds delay, }
const bool is_volatile)
{ task_handle scheduler::add(const std::function<void()>& callback, const std::chrono::milliseconds delay,
task task; const bool is_volatile)
task.is_volatile = is_volatile; {
task.callback = callback; task task;
task.delay = delay; task.is_volatile = is_volatile;
task.last_execution = std::chrono::steady_clock::now(); task.callback = callback;
task.id = ++this->current_task_id_; task.delay = delay;
task.last_execution = std::chrono::steady_clock::now();
this->tasks_.add(task); task.id = ++this->current_task_id_;
return { task.id }; this->tasks_.add(task);
}
return {task.id};
void scheduler::remove(const task_handle& handle) }
{
for (auto task : this->tasks_) void scheduler::remove(const task_handle& handle)
{ {
if(task->id == handle.id) for (auto task : this->tasks_)
{ {
this->tasks_.remove(task); if (task->id == handle.id)
break; {
} this->tasks_.remove(task);
} break;
} }
} }
} }
}
}

View File

@ -43,6 +43,6 @@ int html_argument::get_number() const
bool html_argument::get_bool() const bool html_argument::get_bool() const
{ {
if(!this->is_bool()) return false; if (!this->is_bool()) return false;
return this->value_->boolVal != FALSE; return this->value_->boolVal != FALSE;
} }

View File

@ -12,7 +12,7 @@ FARPROC loader::load(const utils::nt::module& module) const
const auto buffer = binary_loader::load(this->mode_); const auto buffer = binary_loader::load(this->mode_);
if (buffer.empty()) return nullptr; if (buffer.empty()) return nullptr;
utils::nt::module source(HMODULE(buffer.data())); const utils::nt::module source(HMODULE(buffer.data()));
if (!source) return nullptr; if (!source) return nullptr;
this->load_sections(module, source); this->load_sections(module, source);
@ -58,8 +58,8 @@ FARPROC loader::load(const utils::nt::module& module) const
.get_optional_header()->DataDirectory[ .get_optional_header()->DataDirectory[
IMAGE_DIRECTORY_ENTRY_IMPORT]; IMAGE_DIRECTORY_ENTRY_IMPORT];
std::memmove(module.get_nt_headers(), source.get_nt_headers(), std::memmove(module.get_nt_headers(), source.get_nt_headers(),
sizeof(IMAGE_NT_HEADERS) + (source.get_nt_headers()->FileHeader.NumberOfSections * (sizeof( sizeof(IMAGE_NT_HEADERS) + source.get_nt_headers()->FileHeader.NumberOfSections * sizeof(
IMAGE_SECTION_HEADER)))); IMAGE_SECTION_HEADER));
return FARPROC(module.get_ptr() + source.get_relative_entry_point()); return FARPROC(module.get_ptr() + source.get_relative_entry_point());
} }

View File

@ -1,26 +1,26 @@
#pragma once #pragma once
class module class module
{ {
public: public:
virtual ~module() virtual ~module()
{ {
} }
virtual void post_start() virtual void post_start()
{ {
} }
virtual void post_load() virtual void post_load()
{ {
} }
virtual void pre_destroy() virtual void pre_destroy()
{ {
} }
virtual void* load_import(const std::string& module, const std::string& function) virtual void* load_import(const std::string& module, const std::string& function)
{ {
return nullptr; return nullptr;
} }
}; };

View File

@ -27,7 +27,7 @@ bool module_loader::post_start()
module_->post_start(); module_->post_start();
} }
} }
catch(premature_shutdown_trigger&) catch (premature_shutdown_trigger&)
{ {
return false; return false;
} }
@ -75,7 +75,7 @@ void* module_loader::load_import(const std::string& module, const std::string& f
for (const auto& module_ : *modules_) for (const auto& module_ : *modules_)
{ {
const auto module_function_ptr = module_->load_import(module, function); const auto module_function_ptr = module_->load_import(module, function);
if(module_function_ptr) if (module_function_ptr)
{ {
function_ptr = module_function_ptr; function_ptr = module_function_ptr;
} }

View File

@ -1,61 +1,61 @@
#pragma once #pragma once
#include "module.hpp" #include "module.hpp"
class module_loader final class module_loader final
{ {
public: public:
class premature_shutdown_trigger final : public std::exception class premature_shutdown_trigger final : public std::exception
{ {
const char* what() const noexcept override const char* what() const noexcept override
{ {
return "Premature shutdown requested"; return "Premature shutdown requested";
} }
}; };
template <typename T> template <typename T>
class installer final class installer final
{ {
static_assert(std::is_base_of<module, T>::value, "Module has invalid base class"); static_assert(std::is_base_of<module, T>::value, "Module has invalid base class");
public: public:
installer() installer()
{ {
register_module(std::make_unique<T>()); register_module(std::make_unique<T>());
} }
}; };
template<typename T> template <typename T>
static T* get() static T* get()
{ {
for(const auto& module_ : *modules_) for (const auto& module_ : *modules_)
{ {
if(typeid(*module_.get()) == typeid(T)) if (typeid(*module_.get()) == typeid(T))
{ {
return reinterpret_cast<T*>(module_.get()); return reinterpret_cast<T*>(module_.get());
} }
} }
return nullptr; return nullptr;
} }
static void register_module(std::unique_ptr<module>&& module); static void register_module(std::unique_ptr<module>&& module);
static bool post_start(); static bool post_start();
static bool post_load(); static bool post_load();
static void pre_destroy(); static void pre_destroy();
static void* load_import(const std::string& module, const std::string& function); static void* load_import(const std::string& module, const std::string& function);
static void trigger_premature_shutdown(); static void trigger_premature_shutdown();
private: private:
static std::vector<std::unique_ptr<module>>* modules_; static std::vector<std::unique_ptr<module>>* modules_;
static void destroy_modules(); static void destroy_modules();
}; };
#define REGISTER_MODULE(name) \ #define REGISTER_MODULE(name) \
namespace \ namespace \
{ \ { \
static module_loader::installer<name> $_##name; \ static module_loader::installer<name> $_##name; \
} }

View File

@ -105,7 +105,7 @@ int main()
auto mode = detect_mode_from_arguments(); auto mode = detect_mode_from_arguments();
if (mode == launcher::mode::none) if (mode == launcher::mode::none)
{ {
launcher launcher; const launcher launcher;
mode = launcher.run(); mode = launcher.run();
if (mode == launcher::mode::none) return 0; if (mode == launcher::mode::none) return 0;
} }

View File

@ -1,102 +1,102 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "scheduler.hpp" #include "scheduler.hpp"
#include "utils/string.hpp" #include "utils/string.hpp"
#include "game/structs.hpp" #include "game/structs.hpp"
#include "game/game.hpp" #include "game/game.hpp"
#include "utils/hook.hpp" #include "utils/hook.hpp"
std::mutex scheduler::mutex_; std::mutex scheduler::mutex_;
std::queue<std::pair<std::string, int>> scheduler::errors_; std::queue<std::pair<std::string, int>> scheduler::errors_;
utils::concurrent_list<std::function<void()>> scheduler::callbacks_; utils::concurrent_list<std::function<void()>> scheduler::callbacks_;
utils::concurrent_list<std::function<void()>> scheduler::single_callbacks_; utils::concurrent_list<std::function<void()>> scheduler::single_callbacks_;
void scheduler::on_frame(const std::function<void()>& callback) void scheduler::on_frame(const std::function<void()>& callback)
{ {
std::lock_guard _(mutex_); std::lock_guard _(mutex_);
callbacks_.add(callback); callbacks_.add(callback);
} }
void scheduler::once(const std::function<void()>& callback) void scheduler::once(const std::function<void()>& callback)
{ {
std::lock_guard _(mutex_); std::lock_guard _(mutex_);
single_callbacks_.add(callback); single_callbacks_.add(callback);
} }
void scheduler::error(const std::string& message, int level) void scheduler::error(const std::string& message, int level)
{ {
std::lock_guard _(mutex_); std::lock_guard _(mutex_);
errors_.emplace(message, level); errors_.emplace(message, level);
} }
void scheduler::frame_stub() void scheduler::frame_stub()
{ {
execute(); execute();
reinterpret_cast<void(*)()>(SELECT_VALUE(0x458600, 0x556470, 0x4DB070))(); reinterpret_cast<void(*)()>(SELECT_VALUE(0x458600, 0x556470, 0x4DB070))();
} }
__declspec(naked) void scheduler::execute() __declspec(naked) void scheduler::execute()
{ {
__asm __asm
{ {
call execute_error call execute_error
call execute_safe call execute_safe
retn retn
} }
} }
void scheduler::execute_safe() void scheduler::execute_safe()
{ {
for (auto callback : callbacks_) for (auto callback : callbacks_)
{ {
(*callback)(); (*callback)();
} }
for (auto callback : single_callbacks_) for (auto callback : single_callbacks_)
{ {
single_callbacks_.remove(callback); single_callbacks_.remove(callback);
(*callback)(); (*callback)();
} }
} }
void scheduler::execute_error() void scheduler::execute_error()
{ {
const char* message; const char* message;
int level; int level;
if(get_next_error(&message, &level) && message) if (get_next_error(&message, &level) && message)
{ {
game::native::Com_Error(level, "%s", message); game::native::Com_Error(level, "%s", message);
} }
} }
bool scheduler::get_next_error(const char** error_message, int* error_level) bool scheduler::get_next_error(const char** error_message, int* error_level)
{ {
std::lock_guard _(mutex_); std::lock_guard _(mutex_);
if(errors_.empty()) if (errors_.empty())
{ {
*error_message = nullptr; *error_message = nullptr;
return false; return false;
} }
const auto error = errors_.front(); const auto error = errors_.front();
errors_.pop(); errors_.pop();
*error_level = error.second; *error_level = error.second;
*error_message = utils::string::va("%s", error.first.data()); *error_message = utils::string::va("%s", error.first.data());
return true; return true;
} }
void scheduler::post_load() void scheduler::post_load()
{ {
utils::hook(SELECT_VALUE(0x44C7DB, 0x55688E, 0x4DB324), frame_stub, HOOK_CALL).install()->quick(); utils::hook(SELECT_VALUE(0x44C7DB, 0x55688E, 0x4DB324), frame_stub, HOOK_CALL).install()->quick();
} }
void scheduler::pre_destroy() void scheduler::pre_destroy()
{ {
std::lock_guard _(mutex_); std::lock_guard _(mutex_);
callbacks_.clear(); callbacks_.clear();
single_callbacks_.clear(); single_callbacks_.clear();
} }
REGISTER_MODULE(scheduler); REGISTER_MODULE(scheduler);

View File

@ -19,7 +19,8 @@ public:
->quick(); ->quick();
utils::hook(SELECT_VALUE(0x4F9706, 0x5772A0, 0x4FAB88), &frame_stub, HOOK_CALL).install()->quick(); utils::hook(SELECT_VALUE(0x4F9706, 0x5772A0, 0x4FAB88), &frame_stub, HOOK_CALL).install()->quick();
utils::hook(SELECT_VALUE(0x4FFA48, 0x5774AB, 0x4FEFD7), &frame_stub, HOOK_CALL).install()->quick(); // Only relevant one? utils::hook(SELECT_VALUE(0x4FFA48, 0x5774AB, 0x4FEFD7), &frame_stub, HOOK_CALL).install()->quick();
// Only relevant one?
utils::hook(SELECT_VALUE(0x6109F3, 0x56B637, 0x4EDFF7), &vm_notify_stub, HOOK_CALL).install()->quick(); utils::hook(SELECT_VALUE(0x6109F3, 0x56B637, 0x4EDFF7), &vm_notify_stub, HOOK_CALL).install()->quick();
utils::hook(SELECT_VALUE(0x6128BE, 0x56D541, 0x4EFAF9), &vm_notify_stub, HOOK_CALL).install()->quick(); utils::hook(SELECT_VALUE(0x6128BE, 0x56D541, 0x4EFAF9), &vm_notify_stub, HOOK_CALL).install()->quick();
@ -149,7 +150,7 @@ private:
game::native::VM_Notify(notify_id, type, stack); game::native::VM_Notify(notify_id, type, stack);
} }
static int frame_stub(int a1, int a2) static int frame_stub(const int a1, const int a2)
{ {
module_loader::get<scripting>()->run_frame(); module_loader::get<scripting>()->run_frame();
return game::native::G_RunFrame(a1, a2); return game::native::G_RunFrame(a1, a2);

View File

@ -8,7 +8,7 @@ class security final : public module
public: public:
void post_load() override void post_load() override
{ {
if(game::is_mp()) if (game::is_mp())
{ {
utils::hook(0x4AECD4, read_p2p_auth_ticket_stub, HOOK_JUMP).install()->quick(); utils::hook(0x4AECD4, read_p2p_auth_ticket_stub, HOOK_JUMP).install()->quick();
} }

View File

@ -133,7 +133,7 @@ private:
this->client_utils_.invoke<void>("SetAppIDForCurrentPipe", app_id, false); this->client_utils_.invoke<void>("SetAppIDForCurrentPipe", app_id, false);
utils::nt::module self; const utils::nt::module self;
const auto path = self.get_path(); const auto path = self.get_path();
char our_directory[MAX_PATH] = {0}; char our_directory[MAX_PATH] = {0};

View File

@ -1,16 +1,38 @@
#include <std_include.hpp> #include <std_include.hpp>
#pragma comment(linker, "/merge:.data=.cld") #pragma comment(linker, "/merge:.data=.cld")
#pragma comment(linker, "/merge:.rdata=.clr") #pragma comment(linker, "/merge:.rdata=.clr")
#pragma comment(linker, "/merge:.cl=.main") #pragma comment(linker, "/merge:.cl=.main")
#pragma comment(linker, "/merge:.text=.main") #pragma comment(linker, "/merge:.text=.main")
#pragma comment(linker, "/section:.main,re") #pragma comment(linker, "/section:.main,re")
#pragma comment(linker, "/base:0x400000") #pragma comment(linker, "/base:0x400000")
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#pragma bss_seg(".payload") #pragma bss_seg(".payload")
char payload_data[BINARY_PAYLOAD_SIZE]; char payload_data[BINARY_PAYLOAD_SIZE];
#pragma data_seg(".main") #pragma data_seg(".main")
char main_data[200] = {1}; char main_data[200] = {1};
extern "C" {
int s_read_arc4random(void*, size_t)
{
return -1;
}
int s_read_getrandom(void*, size_t)
{
return -1;
}
int s_read_urandom(void*, size_t)
{
return -1;
}
int s_read_ltm_rng(void*, size_t)
{
return -1;
}
}

View File

@ -2,7 +2,6 @@
#include "interface.hpp" #include "interface.hpp"
#include "utils/memory.hpp" #include "utils/memory.hpp"
#include "utils/nt.hpp" #include "utils/nt.hpp"
#include <minwinbase.h>
namespace steam namespace steam
{ {

View File

@ -1,91 +1,91 @@
#pragma once #pragma once
#ifdef interface #ifdef interface
#undef interface #undef interface
#endif #endif
namespace steam namespace steam
{ {
template <size_t ...> template <size_t ...>
struct argument_size_calculator final : std::integral_constant<size_t, 0> struct argument_size_calculator final : std::integral_constant<size_t, 0>
{ {
}; };
template <size_t X, size_t ... Xs> template <size_t X, size_t ... Xs>
struct argument_size_calculator<X, Xs...> final : std::integral_constant< struct argument_size_calculator<X, Xs...> final : std::integral_constant<
size_t, X + ((argument_size_calculator<Xs...>::value + (sizeof(void*) - 1)) & ~(sizeof(void*) - 1))> size_t, X + ((argument_size_calculator<Xs...>::value + (sizeof(void*) - 1)) & ~(sizeof(void*) - 1))>
{ {
}; };
class interface final class interface final
{ {
public: public:
class method final class method final
{ {
public: public:
void* pointer = nullptr; void* pointer = nullptr;
size_t param_size = 0; size_t param_size = 0;
}; };
class method_result final class method_result final
{ {
public: public:
std::string name; std::string name;
size_t param_size = 0; size_t param_size = 0;
bool name_found = false; bool name_found = false;
bool param_size_found = false; bool param_size_found = false;
}; };
interface(); interface();
interface(void* interface_ptr); interface(void* interface_ptr);
operator bool() const; operator bool() const;
template <typename T, typename... Args> template <typename T, typename... Args>
T invoke(const std::string& method_name, Args ... args) T invoke(const std::string& method_name, Args ... args)
{ {
if (!this->interface_ptr_) if (!this->interface_ptr_)
{ {
throw std::runtime_error("Invalid interface pointer"); throw std::runtime_error("Invalid interface pointer");
} }
const auto method_result = this->find_method(method_name); const auto method_result = this->find_method(method_name);
if (!method_result.pointer) if (!method_result.pointer)
{ {
throw std::runtime_error("Unable to find desired method"); throw std::runtime_error("Unable to find desired method");
} }
constexpr size_t passed_argc = argument_size_calculator<sizeof(Args)...>::value; constexpr size_t passed_argc = argument_size_calculator<sizeof(Args)...>::value;
if (passed_argc != method_result.param_size) if (passed_argc != method_result.param_size)
{ {
throw std::runtime_error("Invalid argument count"); throw std::runtime_error("Invalid argument count");
} }
return reinterpret_cast<T(__thiscall*)(void*, Args ...)>(method_result.pointer)( return reinterpret_cast<T(__thiscall*)(void*, Args ...)>(method_result.pointer)(
this->interface_ptr_, args...); this->interface_ptr_, args...);
} }
template <typename T, typename... Args> template <typename T, typename... Args>
T invoke(const size_t table_entry, Args ... args) T invoke(const size_t table_entry, Args ... args)
{ {
if (!this->interface_ptr_) if (!this->interface_ptr_)
{ {
throw std::runtime_error("Invalid interface pointer"); throw std::runtime_error("Invalid interface pointer");
} }
return reinterpret_cast<T(__thiscall*)(void*, Args ...)>((*this->interface_ptr_)[table_entry])( return reinterpret_cast<T(__thiscall*)(void*, Args ...)>((*this->interface_ptr_)[table_entry])(
this->interface_ptr_, args...); this->interface_ptr_, args...);
} }
private: private:
void*** interface_ptr_; void*** interface_ptr_;
std::unordered_map<std::string, method> methods_; std::unordered_map<std::string, method> methods_;
method find_method(const std::string& name); method find_method(const std::string& name);
method search_method(const std::string& name); method search_method(const std::string& name);
method_result analyze_method(const void* method_ptr); method_result analyze_method(const void* method_ptr);
bool is_rdata(void* pointer); bool is_rdata(void* pointer);
}; };
} }

View File

@ -1,234 +1,232 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "steam/steam.hpp" #include "steam/steam.hpp"
#include "module/scheduler.hpp"
namespace steam
namespace steam {
{ ::utils::nt::module overlay(nullptr);
::utils::nt::module overlay(nullptr);
uint64_t callbacks::call_id_ = 0;
uint64_t callbacks::call_id_ = 0; std::recursive_mutex callbacks::mutex_;
std::recursive_mutex callbacks::mutex_; std::map<uint64_t, bool> callbacks::calls_;
std::map<uint64_t, bool> callbacks::calls_; std::map<uint64_t, callbacks::base*> callbacks::result_handlers_;
std::map<uint64_t, callbacks::base*> callbacks::result_handlers_; std::vector<callbacks::result> callbacks::results_;
std::vector<callbacks::result> callbacks::results_; std::vector<callbacks::base*> callbacks::callback_list_;
std::vector<callbacks::base*> callbacks::callback_list_;
uint64_t callbacks::register_call()
uint64_t callbacks::register_call() {
{ std::lock_guard _(mutex_);
std::lock_guard _(mutex_); calls_[++call_id_] = false;
calls_[++call_id_] = false; return call_id_;
return call_id_; }
}
void callbacks::register_callback(base* handler, const int callback)
void callbacks::register_callback(base* handler, const int callback) {
{ std::lock_guard _(mutex_);
std::lock_guard _(mutex_); handler->set_i_callback(callback);
handler->set_i_callback(callback); callback_list_.push_back(handler);
callback_list_.push_back(handler); }
}
void callbacks::register_call_result(const uint64_t call, base* result)
void callbacks::register_call_result(const uint64_t call, base* result) {
{ std::lock_guard _(mutex_);
std::lock_guard _(mutex_); result_handlers_[call] = result;
result_handlers_[call] = result; }
}
void callbacks::return_call(void* data, const int size, const int type, const uint64_t call)
void callbacks::return_call(void* data, const int size, const int type, const uint64_t call) {
{ std::lock_guard _(mutex_);
std::lock_guard _(mutex_);
result result;
result result{}; result.call = call;
result.data = data;
result.call = call; result.size = size;
result.data = data; result.type = type;
result.size = size;
result.type = type; calls_[call] = true;
calls_[call] = true; results_.push_back(result);
}
results_.push_back(result);
} void callbacks::run_callbacks()
{
void callbacks::run_callbacks() std::lock_guard _(mutex_);
{
std::lock_guard _(mutex_); for (const auto& result : results_)
{
for (const auto& result : results_) if (result_handlers_.find(result.call) != result_handlers_.end())
{ {
if (result_handlers_.find(result.call) != result_handlers_.end()) result_handlers_[result.call]->run(result.data, false, result.call);
{ }
result_handlers_[result.call]->run(result.data, false, result.call);
} for (const auto& callback : callback_list_)
{
for (const auto& callback : callback_list_) if (callback && callback->get_i_callback() == result.type)
{ {
if (callback && callback->get_i_callback() == result.type) callback->run(result.data, false, 0);
{ }
callback->run(result.data, false, 0); }
}
} if (result.data)
{
if (result.data) free(result.data);
{ }
free(result.data); }
}
} results_.clear();
}
results_.clear();
} std::string get_steam_install_directory()
{
std::string get_steam_install_directory() HKEY reg_key;
{ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Valve\\Steam", 0, KEY_QUERY_VALUE, &reg_key) ==
HKEY reg_key; ERROR_SUCCESS)
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Valve\\Steam", 0, KEY_QUERY_VALUE, &reg_key) == {
ERROR_SUCCESS) char path[MAX_PATH] = {0};
{ DWORD length = sizeof(path);
char path[MAX_PATH] = {0}; RegQueryValueExA(reg_key, "InstallPath", nullptr, nullptr, reinterpret_cast<BYTE*>(path),
DWORD length = sizeof(path); &length);
RegQueryValueExA(reg_key, "InstallPath", nullptr, nullptr, reinterpret_cast<BYTE*>(path), RegCloseKey(reg_key);
&length);
RegCloseKey(reg_key); std::string steam_path = path;
if (steam_path.back() != '\\' && steam_path.back() != '/')
std::string steam_path = path; {
if (steam_path.back() != '\\' && steam_path.back() != '/') steam_path.push_back('\\');
{ }
steam_path.push_back('\\');
} return steam_path;
}
return steam_path;
} return {};
}
return {};
} extern "C" {
bool SteamAPI_RestartAppIfNecessary()
extern "C" { {
bool SteamAPI_RestartAppIfNecessary() return false;
{ }
return false;
} bool SteamAPI_Init()
{
bool SteamAPI_Init() overlay = ::utils::nt::module("gameoverlayrenderer.dll");
{
overlay = ::utils::nt::module("gameoverlayrenderer.dll"); if (!overlay)
{
if (!overlay) const auto steam_path = get_steam_install_directory();
{ if (!steam_path.empty())
const auto steam_path = get_steam_install_directory(); {
if (!steam_path.empty()) overlay = ::utils::nt::module::load(steam_path + "gameoverlayrenderer.dll");
{ }
overlay = ::utils::nt::module::load(steam_path + "gameoverlayrenderer.dll"); }
}
} return true;
}
return true;
} void SteamAPI_RegisterCallResult(callbacks::base* result, uint64_t call)
{
void SteamAPI_RegisterCallResult(callbacks::base* result, uint64_t call) callbacks::register_call_result(call, result);
{ }
callbacks::register_call_result(call, result);
} void SteamAPI_RegisterCallback(callbacks::base* handler, int callback)
{
void SteamAPI_RegisterCallback(callbacks::base* handler, int callback) callbacks::register_callback(handler, callback);
{ }
callbacks::register_callback(handler, callback);
} void SteamAPI_RunCallbacks()
{
void SteamAPI_RunCallbacks() callbacks::run_callbacks();
{ }
callbacks::run_callbacks();
} void SteamAPI_Shutdown()
{
void SteamAPI_Shutdown() }
{
} void SteamAPI_UnregisterCallResult()
{
void SteamAPI_UnregisterCallResult() }
{
} void SteamAPI_UnregisterCallback()
{
void SteamAPI_UnregisterCallback() }
{
}
bool SteamGameServer_Init()
{
bool SteamGameServer_Init() return true;
{ }
return true;
} void SteamGameServer_RunCallbacks()
{
void SteamGameServer_RunCallbacks() }
{
} void SteamGameServer_Shutdown()
{
void SteamGameServer_Shutdown() }
{
}
friends* SteamFriends()
{
friends* SteamFriends() static friends friends;
{ return &friends;
static friends friends; }
return &friends;
} matchmaking* SteamMatchmaking()
{
matchmaking* SteamMatchmaking() static matchmaking matchmaking;
{ return &matchmaking;
static matchmaking matchmaking; }
return &matchmaking;
} matchmaking_servers* SteamMatchmakingServers()
{
matchmaking_servers* SteamMatchmakingServers() static matchmaking_servers matchmaking_servers;
{ return &matchmaking_servers;
static matchmaking_servers matchmaking_servers; }
return &matchmaking_servers;
} game_server* SteamGameServer()
{
game_server* SteamGameServer() static game_server game_server;
{ return &game_server;
static game_server game_server; }
return &game_server;
} master_server_updater* SteamMasterServerUpdater()
{
master_server_updater* SteamMasterServerUpdater() static master_server_updater master_server_updater;
{ return &master_server_updater;
static master_server_updater master_server_updater; }
return &master_server_updater;
} networking* SteamNetworking()
{
networking* SteamNetworking() static networking networking;
{ return &networking;
static networking networking; }
return &networking;
} remote_storage* SteamRemoteStorage()
{
remote_storage* SteamRemoteStorage() static remote_storage remote_storage;
{ return &remote_storage;
static remote_storage remote_storage; }
return &remote_storage;
} user* SteamUser()
{
user* SteamUser() static user user;
{ return &user;
static user user; }
return &user;
} utils* SteamUtils()
{
utils* SteamUtils() static utils utils;
{ return &utils;
static utils utils; }
return &utils;
} apps* SteamApps()
{
apps* SteamApps() static apps apps;
{ return &apps;
static apps apps; }
return &apps;
} user_stats* SteamUserStats()
{
user_stats* SteamUserStats() static user_stats user_stats;
{ return &user_stats;
static user_stats user_stats; }
return &user_stats; }
} }
}
}

View File

@ -1,130 +1,131 @@
#pragma once #pragma once
namespace utils namespace utils
{ {
template <typename T> template <typename T>
class concurrent_list final class concurrent_list final
{ {
public: public:
class element final class element final
{ {
public: public:
explicit element(std::recursive_mutex* mutex, std::shared_ptr<T> entry = {}, std::shared_ptr<element> next = {}) : explicit element(std::recursive_mutex* mutex, std::shared_ptr<T> entry = {},
mutex_(mutex), std::shared_ptr<element> next = {}) :
entry_(std::move(entry)), mutex_(mutex),
next_(std::move(next)) entry_(std::move(entry)),
{ next_(std::move(next))
} {
}
void remove(const std::shared_ptr<T>& element)
{ void remove(const std::shared_ptr<T>& element)
std::lock_guard _(*this->mutex_); {
if (!this->next_) return; std::lock_guard _(*this->mutex_);
if (!this->next_) return;
if (this->next_->entry_.get() == element.get())
{ if (this->next_->entry_.get() == element.get())
this->next_ = this->next_->next_; {
} this->next_ = this->next_->next_;
else }
{ else
this->next_->remove(element); {
} this->next_->remove(element);
} }
}
std::shared_ptr<element> get_next() const
{ std::shared_ptr<element> get_next() const
std::lock_guard _(*this->mutex_); {
return this->next_; std::lock_guard _(*this->mutex_);
} return this->next_;
}
std::shared_ptr<T> operator*() const
{ std::shared_ptr<T> operator*() const
std::lock_guard _(*this->mutex_); {
return this->entry_; std::lock_guard _(*this->mutex_);
} return this->entry_;
}
element& operator++()
{ element& operator++()
std::lock_guard _(*this->mutex_); {
*this = this->next_ ? *this->next_ : element(this->mutex_); std::lock_guard _(*this->mutex_);
return *this; *this = this->next_ ? *this->next_ : element(this->mutex_);
} return *this;
}
element operator++(int)
{ element operator++(int)
std::lock_guard _(*this->mutex_); {
auto result = *this; std::lock_guard _(*this->mutex_);
this->operator++(); auto result = *this;
return result; this->operator++();
} return result;
}
bool operator==(const element& other)
{ bool operator==(const element& other)
std::lock_guard _(*this->mutex_); {
return this->entry_.get() == other.entry_.get(); std::lock_guard _(*this->mutex_);
} return this->entry_.get() == other.entry_.get();
}
bool operator!=(const element& other)
{ bool operator!=(const element& other)
std::lock_guard _(*this->mutex_); {
return !(*this == other); std::lock_guard _(*this->mutex_);
} return !(*this == other);
}
private:
std::recursive_mutex* mutex_; private:
std::shared_ptr<T> entry_; std::recursive_mutex* mutex_;
std::shared_ptr<element> next_; std::shared_ptr<T> entry_;
}; std::shared_ptr<element> next_;
};
element begin()
{ element begin()
std::lock_guard _(this->mutex_); {
return this->entry_ ? *this->entry_ : this->end(); std::lock_guard _(this->mutex_);
} return this->entry_ ? *this->entry_ : this->end();
}
element end()
{ element end()
std::lock_guard _(this->mutex_); {
return element(&this->mutex_); std::lock_guard _(this->mutex_);
} return element(&this->mutex_);
}
void remove(const element& entry)
{ void remove(const element& entry)
std::lock_guard _(this->mutex_); {
this->remove(*entry); std::lock_guard _(this->mutex_);
} this->remove(*entry);
}
void remove(const std::shared_ptr<T>& element)
{ void remove(const std::shared_ptr<T>& element)
std::lock_guard _(this->mutex_); {
if (!this->entry_) return; std::lock_guard _(this->mutex_);
if (!this->entry_) return;
if ((**this->entry_).get() == element.get())
{ if ((**this->entry_).get() == element.get())
this->entry_ = this->entry_->get_next(); {
} this->entry_ = this->entry_->get_next();
else }
{ else
this->entry_->remove(element); {
} this->entry_->remove(element);
} }
}
void add(const T& object)
{ void add(const T& object)
std::lock_guard _(this->mutex_); {
std::lock_guard _(this->mutex_);
const auto object_ptr = std::make_shared<T>(object);
this->entry_ = std::make_shared<element>(&this->mutex_, object_ptr, this->entry_); const auto object_ptr = std::make_shared<T>(object);
} this->entry_ = std::make_shared<element>(&this->mutex_, object_ptr, this->entry_);
}
void clear()
{ void clear()
std::lock_guard _(this->mutex_); {
this->entry_ = {}; std::lock_guard _(this->mutex_);
} this->entry_ = {};
}
private:
std::recursive_mutex mutex_; private:
std::shared_ptr<element> entry_; std::recursive_mutex mutex_;
}; std::shared_ptr<element> entry_;
} };
}

View File

@ -1,325 +1,326 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "string.hpp" #include "string.hpp"
#include "cryptography.hpp" #include "cryptography.hpp"
/// http://www.opensource.apple.com/source/CommonCrypto/CommonCrypto-55010/Source/libtomcrypt/doc/libTomCryptDoc.pdf /// http://www.opensource.apple.com/source/CommonCrypto/CommonCrypto-55010/Source/libtomcrypt/doc/libTomCryptDoc.pdf
namespace utils namespace utils
{ {
namespace cryptography namespace cryptography
{ {
ecc::key::key() ecc::key::key()
{ {
ZeroMemory(&this->key_storage_, sizeof(this->key_storage_)); ZeroMemory(&this->key_storage_, sizeof(this->key_storage_));
} }
ecc::key::~key() ecc::key::~key()
{ {
this->free(); this->free();
} }
bool ecc::key::is_valid() const bool ecc::key::is_valid() const
{ {
return (!memory::is_set(&this->key_storage_, 0, sizeof(this->key_storage_))); return (!memory::is_set(&this->key_storage_, 0, sizeof(this->key_storage_)));
} }
ecc_key* ecc::key::get() ecc_key* ecc::key::get()
{ {
return &this->key_storage_; return &this->key_storage_;
} }
std::string ecc::key::get_public_key() const std::string ecc::key::get_public_key() const
{ {
uint8_t buffer[512] = {0}; uint8_t buffer[512] = {0};
DWORD length = sizeof(buffer); DWORD length = sizeof(buffer);
if (ecc_ansi_x963_export(&this->key_storage_, buffer, &length) == CRYPT_OK) if (ecc_ansi_x963_export(&this->key_storage_, buffer, &length) == CRYPT_OK)
{ {
return std::string(reinterpret_cast<char*>(buffer), length); return std::string(reinterpret_cast<char*>(buffer), length);
} }
return {}; return {};
} }
void ecc::key::set(const std::string& pub_key_buffer) void ecc::key::set(const std::string& pub_key_buffer)
{ {
this->free(); this->free();
if (ecc_ansi_x963_import(reinterpret_cast<const uint8_t*>(pub_key_buffer.data()), pub_key_buffer.size(), if (ecc_ansi_x963_import(reinterpret_cast<const uint8_t*>(pub_key_buffer.data()), pub_key_buffer.size(),
&this->key_storage_) != CRYPT_OK) &this->key_storage_) != CRYPT_OK)
{ {
ZeroMemory(&this->key_storage_, sizeof(this->key_storage_)); ZeroMemory(&this->key_storage_, sizeof(this->key_storage_));
} }
} }
void ecc::key::deserialize(const std::string& key) void ecc::key::deserialize(const std::string& key)
{ {
this->free(); this->free();
if (ecc_import(reinterpret_cast<const uint8_t*>(key.data()), key.size(), &this->key_storage_) != CRYPT_OK) if (ecc_import(reinterpret_cast<const uint8_t*>(key.data()), key.size(), &this->key_storage_) != CRYPT_OK)
{ {
ZeroMemory(&this->key_storage_, sizeof(this->key_storage_)); ZeroMemory(&this->key_storage_, sizeof(this->key_storage_));
} }
} }
std::string ecc::key::serialize(const int type) const std::string ecc::key::serialize(const int type) const
{ {
uint8_t buffer[4096] = {0}; uint8_t buffer[4096] = {0};
DWORD length = sizeof(buffer); DWORD length = sizeof(buffer);
if (ecc_export(buffer, &length, type, &this->key_storage_) == CRYPT_OK) if (ecc_export(buffer, &length, type, &this->key_storage_) == CRYPT_OK)
{ {
return std::string(reinterpret_cast<char*>(buffer), length); return std::string(reinterpret_cast<char*>(buffer), length);
} }
return ""; return "";
} }
void ecc::key::free() void ecc::key::free()
{ {
if (this->is_valid()) if (this->is_valid())
{ {
ecc_free(&this->key_storage_); ecc_free(&this->key_storage_);
} }
ZeroMemory(&this->key_storage_, sizeof(this->key_storage_)); ZeroMemory(&this->key_storage_, sizeof(this->key_storage_));
} }
bool ecc::key::operator==(key& key) const bool ecc::key::operator==(key& key) const
{ {
return (this->is_valid() && key.is_valid() && this->serialize(PK_PUBLIC) == key.serialize(PK_PUBLIC)); return (this->is_valid() && key.is_valid() && this->serialize(PK_PUBLIC) == key.serialize(PK_PUBLIC));
} }
ecc::key ecc::generate_key(const int bits) ecc::key ecc::generate_key(const int bits)
{ {
key key; key key;
ltc_mp = ltm_desc; ltc_mp = ltm_desc;
register_prng(&sprng_desc); register_prng(&sprng_desc);
ecc_make_key(nullptr, find_prng("sprng"), bits / 8, key.get()); ecc_make_key(nullptr, find_prng("sprng"), bits / 8, key.get());
return key; return key;
} }
std::string ecc::sign_message(key key, const std::string& message) std::string ecc::sign_message(key key, const std::string& message)
{ {
if (!key.is_valid()) return ""; if (!key.is_valid()) return "";
uint8_t buffer[512]; uint8_t buffer[512];
DWORD length = sizeof(buffer); DWORD length = sizeof(buffer);
ltc_mp = ltm_desc; ltc_mp = ltm_desc;
register_prng(&sprng_desc); register_prng(&sprng_desc);
ecc_sign_hash(reinterpret_cast<const uint8_t*>(message.data()), message.size(), buffer, &length, nullptr, ecc_sign_hash(reinterpret_cast<const uint8_t*>(message.data()), message.size(), buffer, &length, nullptr,
find_prng("sprng"), key.get()); find_prng("sprng"), key.get());
return std::string(reinterpret_cast<char*>(buffer), length); return std::string(reinterpret_cast<char*>(buffer), length);
} }
bool ecc::verify_message(key key, const std::string& message, const std::string& signature) bool ecc::verify_message(key key, const std::string& message, const std::string& signature)
{ {
if (!key.is_valid()) return false; if (!key.is_valid()) return false;
ltc_mp = ltm_desc; ltc_mp = ltm_desc;
auto result = 0; auto result = 0;
return ( ecc_verify_hash(reinterpret_cast<const uint8_t*>(signature.data()), signature.size(), return (ecc_verify_hash(reinterpret_cast<const uint8_t*>(signature.data()), signature.size(),
reinterpret_cast<const uint8_t*>(message.data()), message.size(), &result, key.get()) == CRYPT_OK && result != 0); reinterpret_cast<const uint8_t*>(message.data()), message.size(), &result,
} key.get()) == CRYPT_OK && result != 0);
}
std::string rsa::encrypt(const std::string& data, const std::string& hash, const std::string& key)
{ std::string rsa::encrypt(const std::string& data, const std::string& hash, const std::string& key)
initialize(); {
initialize();
const auto prng_id = find_prng("yarrow");
const auto prng_id = find_prng("yarrow");
rsa_key new_key;
rsa_import(PBYTE(key.data()), key.size(), &new_key); rsa_key new_key;
rsa_import(PBYTE(key.data()), key.size(), &new_key);
prng_state yarrow;
rng_make_prng(128, prng_id, &yarrow, nullptr); prng_state yarrow;
rng_make_prng(128, prng_id, &yarrow, nullptr);
unsigned char buffer[0x80];
unsigned long length = sizeof(buffer); unsigned char buffer[0x80];
unsigned long length = sizeof(buffer);
const auto rsa_result = rsa_encrypt_key( //
PBYTE(data.data()), // const auto rsa_result = rsa_encrypt_key( //
data.size(), // PBYTE(data.data()), //
buffer, // data.size(), //
&length, // buffer, //
PBYTE(hash.data()), // &length, //
hash.size(), // PBYTE(hash.data()), //
&yarrow, // hash.size(), //
prng_id, // &yarrow, //
find_hash("sha1"), // prng_id, //
&new_key); find_hash("sha1"), //
&new_key);
rsa_free(&new_key);
rsa_free(&new_key);
if (rsa_result == CRYPT_OK)
{ if (rsa_result == CRYPT_OK)
return std::string(PCHAR(buffer), length); {
} return std::string(PCHAR(buffer), length);
}
return {};
} return {};
}
void rsa::initialize()
{ void rsa::initialize()
static auto initialized = false; {
if (initialized) return; static auto initialized = false;
initialized = true; if (initialized) return;
initialized = true;
ltc_mp = ltm_desc;
register_hash(&sha1_desc); ltc_mp = ltm_desc;
register_prng(&yarrow_desc); register_hash(&sha1_desc);
} register_prng(&yarrow_desc);
}
std::string des3::encrypt(const std::string& data, const std::string& iv, const std::string& key)
{ std::string des3::encrypt(const std::string& data, const std::string& iv, const std::string& key)
initialize(); {
initialize();
std::string enc_data;
enc_data.resize(data.size()); std::string enc_data;
enc_data.resize(data.size());
symmetric_CBC cbc;
const auto des3 = find_cipher("3des"); symmetric_CBC cbc;
const auto des3 = find_cipher("3des");
cbc_start(des3, reinterpret_cast<const uint8_t*>(iv.data()), reinterpret_cast<const uint8_t*>(key.data()),
key.size(), 0, &cbc); cbc_start(des3, reinterpret_cast<const uint8_t*>(iv.data()), reinterpret_cast<const uint8_t*>(key.data()),
cbc_encrypt(reinterpret_cast<const uint8_t*>(data.data()), key.size(), 0, &cbc);
reinterpret_cast<uint8_t*>(const_cast<char*>(enc_data.data())), data.size(), &cbc); cbc_encrypt(reinterpret_cast<const uint8_t*>(data.data()),
cbc_done(&cbc); reinterpret_cast<uint8_t*>(const_cast<char*>(enc_data.data())), data.size(), &cbc);
cbc_done(&cbc);
return enc_data;
} return enc_data;
}
std::string des3::decrypt(const std::string& data, const std::string& iv, const std::string& key)
{ std::string des3::decrypt(const std::string& data, const std::string& iv, const std::string& key)
initialize(); {
initialize();
std::string dec_data;
dec_data.resize(data.size()); std::string dec_data;
dec_data.resize(data.size());
symmetric_CBC cbc;
const auto des3 = find_cipher("3des"); symmetric_CBC cbc;
const auto des3 = find_cipher("3des");
cbc_start(des3, reinterpret_cast<const uint8_t*>(iv.data()), reinterpret_cast<const uint8_t*>(key.data()),
key.size(), 0, &cbc); cbc_start(des3, reinterpret_cast<const uint8_t*>(iv.data()), reinterpret_cast<const uint8_t*>(key.data()),
cbc_decrypt(reinterpret_cast<const uint8_t*>(data.data()), key.size(), 0, &cbc);
reinterpret_cast<uint8_t*>(const_cast<char*>(dec_data.data())), data.size(), &cbc); cbc_decrypt(reinterpret_cast<const uint8_t*>(data.data()),
cbc_done(&cbc); reinterpret_cast<uint8_t*>(const_cast<char*>(dec_data.data())), data.size(), &cbc);
cbc_done(&cbc);
return dec_data;
} return dec_data;
}
void des3::initialize()
{ void des3::initialize()
static auto initialized = false; {
if (initialized) return; static auto initialized = false;
initialized = true; if (initialized) return;
initialized = true;
register_cipher(&des3_desc);
} register_cipher(&des3_desc);
}
std::string tiger::compute(const std::string& data, const bool hex)
{ std::string tiger::compute(const std::string& data, const bool hex)
return compute(reinterpret_cast<const uint8_t*>(data.data()), data.size(), hex); {
} return compute(reinterpret_cast<const uint8_t*>(data.data()), data.size(), hex);
}
std::string tiger::compute(const uint8_t* data, const size_t length, const bool hex)
{ std::string tiger::compute(const uint8_t* data, const size_t length, const bool hex)
uint8_t buffer[24] = {0}; {
uint8_t buffer[24] = {0};
hash_state state;
tiger_init(&state); hash_state state;
tiger_process(&state, data, length); tiger_init(&state);
tiger_done(&state, buffer); tiger_process(&state, data, length);
tiger_done(&state, buffer);
std::string hash(reinterpret_cast<char*>(buffer), sizeof(buffer));
if (!hex) return hash; std::string hash(reinterpret_cast<char*>(buffer), sizeof(buffer));
if (!hex) return hash;
return string::dump_hex(hash, "");
} return string::dump_hex(hash, "");
}
std::string sha1::compute(const std::string& data, const bool hex)
{ std::string sha1::compute(const std::string& data, const bool hex)
return compute(reinterpret_cast<const uint8_t*>(data.data()), data.size(), hex); {
} return compute(reinterpret_cast<const uint8_t*>(data.data()), data.size(), hex);
}
std::string sha1::compute(const uint8_t* data, size_t length, const bool hex)
{ std::string sha1::compute(const uint8_t* data, const size_t length, const bool hex)
uint8_t buffer[20] = {0}; {
uint8_t buffer[20] = {0};
hash_state state;
sha1_init(&state); hash_state state;
sha1_process(&state, data, length); sha1_init(&state);
sha1_done(&state, buffer); sha1_process(&state, data, length);
sha1_done(&state, buffer);
std::string hash(reinterpret_cast<char*>(buffer), sizeof(buffer));
if (!hex) return hash; std::string hash(reinterpret_cast<char*>(buffer), sizeof(buffer));
if (!hex) return hash;
return string::dump_hex(hash, "");
} return string::dump_hex(hash, "");
}
std::string sha256::compute(const std::string& data, bool hex)
{ std::string sha256::compute(const std::string& data, const bool hex)
return compute(reinterpret_cast<const uint8_t*>(data.data()), data.size(), hex); {
} return compute(reinterpret_cast<const uint8_t*>(data.data()), data.size(), hex);
}
std::string sha256::compute(const uint8_t* data, size_t length, bool hex)
{ std::string sha256::compute(const uint8_t* data, const size_t length, const bool hex)
uint8_t buffer[32] = {0}; {
uint8_t buffer[32] = {0};
hash_state state;
sha256_init(&state); hash_state state;
sha256_process(&state, data, length); sha256_init(&state);
sha256_done(&state, buffer); sha256_process(&state, data, length);
sha256_done(&state, buffer);
std::string hash(reinterpret_cast<char*>(buffer), sizeof(buffer));
if (!hex) return hash; std::string hash(reinterpret_cast<char*>(buffer), sizeof(buffer));
if (!hex) return hash;
return string::dump_hex(hash, "");
} return string::dump_hex(hash, "");
}
std::string sha512::compute(const std::string& data, bool hex)
{ std::string sha512::compute(const std::string& data, const bool hex)
return compute(reinterpret_cast<const uint8_t*>(data.data()), data.size(), hex); {
} return compute(reinterpret_cast<const uint8_t*>(data.data()), data.size(), hex);
}
std::string sha512::compute(const uint8_t* data, size_t length, bool hex)
{ std::string sha512::compute(const uint8_t* data, const size_t length, const bool hex)
uint8_t buffer[64] = {0}; {
uint8_t buffer[64] = {0};
hash_state state;
sha512_init(&state); hash_state state;
sha512_process(&state, data, length); sha512_init(&state);
sha512_done(&state, buffer); sha512_process(&state, data, length);
sha512_done(&state, buffer);
std::string hash(reinterpret_cast<char*>(buffer), sizeof(buffer));
if (!hex) return hash; std::string hash(reinterpret_cast<char*>(buffer), sizeof(buffer));
if (!hex) return hash;
return string::dump_hex(hash, "");
} return string::dump_hex(hash, "");
}
unsigned int jenkins_one_at_a_time::compute(const std::string& data)
{ unsigned int jenkins_one_at_a_time::compute(const std::string& data)
return compute(data.data(), data.size()); {
} return compute(data.data(), data.size());
}
unsigned int jenkins_one_at_a_time::compute(const char* key, const size_t len)
{ unsigned int jenkins_one_at_a_time::compute(const char* key, const size_t len)
unsigned int hash, i; {
for (hash = i = 0; i < len; ++i) unsigned int hash, i;
{ for (hash = i = 0; i < len; ++i)
hash += key[i]; {
hash += (hash << 10); hash += key[i];
hash ^= (hash >> 6); hash += (hash << 10);
} hash ^= (hash >> 6);
hash += (hash << 3); }
hash ^= (hash >> 11); hash += (hash << 3);
hash += (hash << 15); hash ^= (hash >> 11);
return hash; hash += (hash << 15);
} return hash;
} }
} }
}

View File

@ -1,96 +1,95 @@
#pragma once #pragma once
#include "memory.hpp"
namespace utils
namespace utils {
{ namespace cryptography
namespace cryptography {
{ class ecc final
class ecc final {
{ public:
public: class key final
class key final {
{ public:
public: key();
key(); ~key();
~key();
bool is_valid() const;
bool is_valid() const;
ecc_key* get();
ecc_key* get();
std::string get_public_key() const;
std::string get_public_key() const;
void set(const std::string& pub_key_buffer);
void set(const std::string& pub_key_buffer);
void deserialize(const std::string& key);
void deserialize(const std::string& key);
std::string serialize(int type = PK_PRIVATE) const;
std::string serialize(const int type = PK_PRIVATE) const;
void free();
void free();
bool operator==(key& key) const;
bool operator==(key& key) const;
private:
private: ecc_key key_storage_{};
ecc_key key_storage_{}; };
};
static key generate_key(int bits);
static key generate_key(int bits); static std::string sign_message(key key, const std::string& message);
static std::string sign_message(key key, const std::string& message); static bool verify_message(key key, const std::string& message, const std::string& signature);
static bool verify_message(key key, const std::string& message, const std::string& signature); };
};
class rsa final
class rsa final {
{ public:
public: static std::string encrypt(const std::string& data, const std::string& hash, const std::string& key);
static std::string encrypt(const std::string& data, const std::string& hash, const std::string& key);
private:
private: static void initialize();
static void initialize(); };
};
class des3 final
class des3 final {
{ public:
public: static std::string encrypt(const std::string& data, const std::string& iv, const std::string& key);
static std::string encrypt(const std::string& data, const std::string& iv, const std::string& key); static std::string decrypt(const std::string& data, const std::string& iv, const std::string& key);
static std::string decrypt(const std::string& data, const std::string& iv, const std::string& key);
private:
private: static void initialize();
static void initialize(); };
};
class tiger final
class tiger final {
{ public:
public: static std::string compute(const std::string& data, bool hex = false);
static std::string compute(const std::string& data, bool hex = false); static std::string compute(const uint8_t* data, size_t length, bool hex = false);
static std::string compute(const uint8_t* data, size_t length, bool hex = false); };
};
class sha1 final
class sha1 final {
{ public:
public: static std::string compute(const std::string& data, bool hex = false);
static std::string compute(const std::string& data, bool hex = false); static std::string compute(const uint8_t* data, size_t length, bool hex = false);
static std::string compute(const uint8_t* data, size_t length, bool hex = false); };
};
class sha256 final
class sha256 final {
{ public:
public: static std::string compute(const std::string& data, bool hex = false);
static std::string compute(const std::string& data, bool hex = false); static std::string compute(const uint8_t* data, size_t length, bool hex = false);
static std::string compute(const uint8_t* data, size_t length, bool hex = false); };
};
class sha512 final
class sha512 final {
{ public:
public: static std::string compute(const std::string& data, bool hex = false);
static std::string compute(const std::string& data, bool hex = false); static std::string compute(const uint8_t* data, size_t length, bool hex = false);
static std::string compute(const uint8_t* data, size_t length, bool hex = false); };
};
class jenkins_one_at_a_time final
class jenkins_one_at_a_time final {
{ public:
public: static unsigned int compute(const std::string& data);
static unsigned int compute(const std::string& data); static unsigned int compute(const char* key, size_t len);
static unsigned int compute(const char* key, size_t len); };
}; }
} }
}

View File

@ -1,52 +1,52 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "flags.hpp" #include "flags.hpp"
#include "string.hpp" #include "string.hpp"
namespace utils namespace utils
{ {
namespace flags namespace flags
{ {
void parse_flags(std::vector<std::string>& flags) void parse_flags(std::vector<std::string>& flags)
{ {
int num_args; int num_args;
const auto argv = CommandLineToArgvW(GetCommandLineW(), &num_args); const auto argv = CommandLineToArgvW(GetCommandLineW(), &num_args);
flags.clear(); flags.clear();
if (argv) if (argv)
{ {
for (auto i = 0; i < num_args; ++i) for (auto i = 0; i < num_args; ++i)
{ {
std::wstring wide_flag(argv[i]); std::wstring wide_flag(argv[i]);
if (wide_flag[0] == L'-') if (wide_flag[0] == L'-')
{ {
flags.emplace_back(wide_flag.begin() + 1, wide_flag.end()); flags.emplace_back(wide_flag.begin() + 1, wide_flag.end());
} }
} }
LocalFree(argv); LocalFree(argv);
} }
} }
bool has_flag(const std::string& flag) bool has_flag(const std::string& flag)
{ {
static auto parsed = false; static auto parsed = false;
static std::vector<std::string> enabled_flags; static std::vector<std::string> enabled_flags;
if (!parsed) if (!parsed)
{ {
parse_flags(enabled_flags); parse_flags(enabled_flags);
} }
for (const auto& entry : enabled_flags) for (const auto& entry : enabled_flags)
{ {
if (string::to_lower(entry) == string::to_lower(flag)) if (string::to_lower(entry) == string::to_lower(flag))
{ {
return true; return true;
} }
} }
return false; return false;
} }
} }
} }

View File

@ -1,10 +1,9 @@
#pragma once #pragma once
#include "memory.hpp"
namespace utils
namespace utils {
{ namespace flags
namespace flags {
{ bool has_flag(const std::string& flag);
bool has_flag(const std::string& flag); }
} }
}

View File

@ -1,179 +1,179 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "hook.hpp" #include "hook.hpp"
namespace utils namespace utils
{ {
void hook::signature::process() void hook::signature::process()
{ {
if (this->signatures_.empty()) return; if (this->signatures_.empty()) return;
const auto start = reinterpret_cast<char*>(this->start_); const auto start = reinterpret_cast<char*>(this->start_);
const unsigned int sig_count = this->signatures_.size(); const unsigned int sig_count = this->signatures_.size();
const auto containers = this->signatures_.data(); const auto containers = this->signatures_.data();
for (size_t i = 0; i < this->length_; ++i) for (size_t i = 0; i < this->length_; ++i)
{ {
const auto address = start + i; const auto address = start + i;
for (unsigned int k = 0; k < sig_count; ++k) for (unsigned int k = 0; k < sig_count; ++k)
{ {
const auto container = &containers[k]; const auto container = &containers[k];
unsigned int j; unsigned int j;
for (j = 0; j < strlen(container->mask); ++j) for (j = 0; j < strlen(container->mask); ++j)
{ {
if (container->mask[j] != '?' && container->signature[j] != address[j]) if (container->mask[j] != '?' && container->signature[j] != address[j])
{ {
break; break;
} }
} }
if (j == strlen(container->mask)) if (j == strlen(container->mask))
{ {
container->callback(address); container->callback(address);
} }
} }
} }
} }
void hook::signature::add(const container& container) void hook::signature::add(const container& container)
{ {
signatures_.push_back(container); signatures_.push_back(container);
} }
hook::~hook() hook::~hook()
{ {
if (this->initialized_) if (this->initialized_)
{ {
this->uninstall(); this->uninstall();
} }
} }
hook* hook::initialize(const DWORD place, void (*stub)(), const bool use_jump) hook* hook::initialize(const DWORD place, void (*stub)(), const bool use_jump)
{ {
return this->initialize(place, reinterpret_cast<void*>(stub), use_jump); return this->initialize(place, reinterpret_cast<void*>(stub), use_jump);
} }
hook* hook::initialize(const DWORD place, void* stub, const bool use_jump) hook* hook::initialize(const DWORD place, void* stub, const bool use_jump)
{ {
return this->initialize(reinterpret_cast<void*>(place), stub, use_jump); return this->initialize(reinterpret_cast<void*>(place), stub, use_jump);
} }
hook* hook::initialize(void* place, void* stub, const bool use_jump) hook* hook::initialize(void* place, void* stub, const bool use_jump)
{ {
if (this->initialized_) return this; if (this->initialized_) return this;
this->initialized_ = true; this->initialized_ = true;
this->use_jump_ = use_jump; this->use_jump_ = use_jump;
this->place_ = place; this->place_ = place;
this->stub_ = stub; this->stub_ = stub;
this->original_ = static_cast<char*>(this->place_) + 5 + *reinterpret_cast<DWORD*>((static_cast<char*>(this-> this->original_ = static_cast<char*>(this->place_) + 5 + *reinterpret_cast<DWORD*>((static_cast<char*>(this->
place_) + 1)); place_) + 1));
return this; return this;
} }
hook* hook::install(const bool unprotect, const bool keep_unprotected) hook* hook::install(const bool unprotect, const bool keep_unprotected)
{ {
std::lock_guard _(this->state_mutex_); std::lock_guard _(this->state_mutex_);
if (!this->initialized_ || this->installed_) if (!this->initialized_ || this->installed_)
{ {
return this; return this;
} }
this->installed_ = true; this->installed_ = true;
if (unprotect) VirtualProtect(this->place_, sizeof(this->buffer_), PAGE_EXECUTE_READWRITE, &this->protection_); if (unprotect) VirtualProtect(this->place_, sizeof(this->buffer_), PAGE_EXECUTE_READWRITE, &this->protection_);
std::memcpy(this->buffer_, this->place_, sizeof(this->buffer_)); std::memcpy(this->buffer_, this->place_, sizeof(this->buffer_));
const auto code = static_cast<char*>(this->place_); const auto code = static_cast<char*>(this->place_);
*code = static_cast<char>(this->use_jump_ ? 0xE9 : 0xE8); *code = static_cast<char>(this->use_jump_ ? 0xE9 : 0xE8);
*reinterpret_cast<size_t*>(code + 1) = reinterpret_cast<size_t>(this->stub_) - (reinterpret_cast<size_t>(this-> *reinterpret_cast<size_t*>(code + 1) = reinterpret_cast<size_t>(this->stub_) - (reinterpret_cast<size_t>(this->
place_) + 5); place_) + 5);
if (unprotect && !keep_unprotected) if (unprotect && !keep_unprotected)
VirtualProtect(this->place_, sizeof(this->buffer_), this->protection_, VirtualProtect(this->place_, sizeof(this->buffer_), this->protection_,
&this->protection_); &this->protection_);
FlushInstructionCache(GetCurrentProcess(), this->place_, sizeof(this->buffer_)); FlushInstructionCache(GetCurrentProcess(), this->place_, sizeof(this->buffer_));
return this; return this;
} }
void hook::quick() void hook::quick()
{ {
if (this->installed_) if (this->installed_)
{ {
this->installed_ = false; this->installed_ = false;
} }
} }
bool hook::iat(nt::module module, const std::string& target_module, const std::string& process, void* stub) bool hook::iat(const nt::module module, const std::string& target_module, const std::string& process, void* stub)
{ {
if (!module.is_valid()) return false; if (!module.is_valid()) return false;
auto ptr = module.get_iat_entry(target_module, process); auto ptr = module.get_iat_entry(target_module, process);
if (!ptr) return false; if (!ptr) return false;
DWORD protect; DWORD protect;
VirtualProtect(ptr, sizeof(*ptr), PAGE_EXECUTE_READWRITE, &protect); VirtualProtect(ptr, sizeof(*ptr), PAGE_EXECUTE_READWRITE, &protect);
*ptr = stub; *ptr = stub;
VirtualProtect(ptr, sizeof(*ptr), protect, &protect); VirtualProtect(ptr, sizeof(*ptr), protect, &protect);
return true; return true;
} }
hook* hook::uninstall(const bool unprotect) hook* hook::uninstall(const bool unprotect)
{ {
std::lock_guard _(this->state_mutex_); std::lock_guard _(this->state_mutex_);
if (!this->initialized_ || !this->installed_) if (!this->initialized_ || !this->installed_)
{ {
return this; return this;
} }
this->installed_ = false; this->installed_ = false;
if (unprotect) VirtualProtect(this->place_, sizeof(this->buffer_), PAGE_EXECUTE_READWRITE, &this->protection_); if (unprotect) VirtualProtect(this->place_, sizeof(this->buffer_), PAGE_EXECUTE_READWRITE, &this->protection_);
std::memcpy(this->place_, this->buffer_, sizeof(this->buffer_)); std::memcpy(this->place_, this->buffer_, sizeof(this->buffer_));
if (unprotect) VirtualProtect(this->place_, sizeof(this->buffer_), this->protection_, &this->protection_); if (unprotect) VirtualProtect(this->place_, sizeof(this->buffer_), this->protection_, &this->protection_);
FlushInstructionCache(GetCurrentProcess(), this->place_, sizeof(this->buffer_)); FlushInstructionCache(GetCurrentProcess(), this->place_, sizeof(this->buffer_));
return this; return this;
} }
void* hook::get_address() const void* hook::get_address() const
{ {
return this->place_; return this->place_;
} }
void* hook::get_original() const void* hook::get_original() const
{ {
return this->original_; return this->original_;
} }
void hook::nop(void* place, const size_t length) void hook::nop(void* place, const size_t length)
{ {
DWORD old_protect; DWORD old_protect;
VirtualProtect(place, length, PAGE_EXECUTE_READWRITE, &old_protect); VirtualProtect(place, length, PAGE_EXECUTE_READWRITE, &old_protect);
memset(place, 0x90, length); memset(place, 0x90, length);
VirtualProtect(place, length, old_protect, &old_protect); VirtualProtect(place, length, old_protect, &old_protect);
FlushInstructionCache(GetCurrentProcess(), place, length); FlushInstructionCache(GetCurrentProcess(), place, length);
} }
void hook::nop(const DWORD place, const size_t length) void hook::nop(const DWORD place, const size_t length)
{ {
nop(reinterpret_cast<void*>(place), length); nop(reinterpret_cast<void*>(place), length);
} }
} }

View File

@ -1,123 +1,123 @@
#pragma once #pragma once
#include "nt.hpp" #include "nt.hpp"
#define HOOK_JUMP true #define HOOK_JUMP true
#define HOOK_CALL false #define HOOK_CALL false
namespace utils namespace utils
{ {
class hook final class hook final
{ {
public: public:
class signature final class signature final
{ {
public: public:
struct container final struct container final
{ {
const char* signature; const char* signature;
const char* mask; const char* mask;
std::function<void(char*)> callback; std::function<void(char*)> callback;
}; };
signature(void* start, const size_t length) : start_(start), length_(length) signature(void* start, const size_t length) : start_(start), length_(length)
{ {
} }
signature(const DWORD start, const size_t length) : signature(reinterpret_cast<void*>(start), length) signature(const DWORD start, const size_t length) : signature(reinterpret_cast<void*>(start), length)
{ {
} }
signature() : signature(0x400000, 0x800000) signature() : signature(0x400000, 0x800000)
{ {
} }
void process(); void process();
void add(const container& container); void add(const container& container);
private: private:
void* start_; void* start_;
size_t length_; size_t length_;
std::vector<container> signatures_; std::vector<container> signatures_;
}; };
hook() : initialized_(false), installed_(false), place_(nullptr), stub_(nullptr), original_(nullptr), hook() : initialized_(false), installed_(false), place_(nullptr), stub_(nullptr), original_(nullptr),
use_jump_(false), protection_(0) use_jump_(false), protection_(0)
{ {
ZeroMemory(this->buffer_, sizeof(this->buffer_)); ZeroMemory(this->buffer_, sizeof(this->buffer_));
} }
hook(void* place, void* stub, const bool use_jump = true) : hook() { this->initialize(place, stub, use_jump); } hook(void* place, void* stub, const bool use_jump = true) : hook() { this->initialize(place, stub, use_jump); }
hook(void* place, void (*stub)(), const bool use_jump = true) : hook( hook(void* place, void (*stub)(), const bool use_jump = true) : hook(
place, reinterpret_cast<void*>(stub), use_jump) place, reinterpret_cast<void*>(stub), use_jump)
{ {
} }
hook(const DWORD place, void* stub, const bool use_jump = true) : hook( hook(const DWORD place, void* stub, const bool use_jump = true) : hook(
reinterpret_cast<void*>(place), stub, use_jump) reinterpret_cast<void*>(place), stub, use_jump)
{ {
} }
hook(const DWORD place, const DWORD stub, const bool use_jump = true) : hook( hook(const DWORD place, const DWORD stub, const bool use_jump = true) : hook(
reinterpret_cast<void*>(place), reinterpret_cast<void*>(stub), use_jump) reinterpret_cast<void*>(place), reinterpret_cast<void*>(stub), use_jump)
{ {
} }
hook(const DWORD place, void (*stub)(), const bool use_jump = true) : hook( hook(const DWORD place, void (*stub)(), const bool use_jump = true) : hook(
reinterpret_cast<void*>(place), reinterpret_cast<void*>(stub), use_jump) reinterpret_cast<void*>(place), reinterpret_cast<void*>(stub), use_jump)
{ {
} }
hook(const hook&) = delete; hook(const hook&) = delete;
hook(const hook&&) = delete; hook(const hook&&) = delete;
~hook(); ~hook();
hook* initialize(void* place, void* stub, bool use_jump = true); hook* initialize(void* place, void* stub, bool use_jump = true);
hook* initialize(DWORD place, void* stub, bool use_jump = true); hook* initialize(DWORD place, void* stub, bool use_jump = true);
hook* initialize(DWORD place, void (*stub)(), bool use_jump = true); // For lambdas hook* initialize(DWORD place, void (*stub)(), bool use_jump = true); // For lambdas
hook* install(bool unprotect = true, bool keep_unprotected = false); hook* install(bool unprotect = true, bool keep_unprotected = false);
hook* uninstall(bool unprotect = true); hook* uninstall(bool unprotect = true);
void* get_address() const; void* get_address() const;
void* get_original() const; void* get_original() const;
void quick(); void quick();
static bool iat(nt::module module, const std::string& target_module, const std::string& process, void* stub); static bool iat(nt::module module, const std::string& target_module, const std::string& process, void* stub);
static void nop(void* place, size_t length); static void nop(void* place, size_t length);
static void nop(DWORD place, size_t length); static void nop(DWORD place, size_t length);
template <typename T> template <typename T>
static void set(void* place, T value) static void set(void* place, T value)
{ {
DWORD old_protect; DWORD old_protect;
VirtualProtect(place, sizeof(T), PAGE_EXECUTE_READWRITE, &old_protect); VirtualProtect(place, sizeof(T), PAGE_EXECUTE_READWRITE, &old_protect);
*static_cast<T*>(place) = value; *static_cast<T*>(place) = value;
VirtualProtect(place, sizeof(T), old_protect, &old_protect); VirtualProtect(place, sizeof(T), old_protect, &old_protect);
FlushInstructionCache(GetCurrentProcess(), place, sizeof(T)); FlushInstructionCache(GetCurrentProcess(), place, sizeof(T));
} }
template <typename T> template <typename T>
static void set(const DWORD place, T value) static void set(const DWORD place, T value)
{ {
return set<T>(reinterpret_cast<void*>(place), value); return set<T>(reinterpret_cast<void*>(place), value);
} }
private: private:
bool initialized_; bool initialized_;
bool installed_; bool installed_;
void* place_; void* place_;
void* stub_; void* stub_;
void* original_; void* original_;
char buffer_[5]{}; char buffer_[5]{};
bool use_jump_; bool use_jump_;
DWORD protection_; DWORD protection_;
std::mutex state_mutex_; std::mutex state_mutex_;
}; };
} }

View File

@ -1,110 +1,110 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "io.hpp" #include "io.hpp"
namespace utils namespace utils
{ {
namespace io namespace io
{ {
bool file_exists(const std::string& file) bool file_exists(const std::string& file)
{ {
return std::ifstream(file).good(); return std::ifstream(file).good();
} }
bool write_file(const std::string& file, const std::string& data, const bool append) bool write_file(const std::string& file, const std::string& data, const bool append)
{ {
const auto pos = file.find_last_of("/\\"); const auto pos = file.find_last_of("/\\");
if (pos != std::string::npos) if (pos != std::string::npos)
{ {
create_directory(file.substr(0, pos)); create_directory(file.substr(0, pos));
} }
std::ofstream stream( std::ofstream stream(
file, std::ios::binary | std::ofstream::out | (append ? std::ofstream::app : std::ofstream::out)); file, std::ios::binary | std::ofstream::out | (append ? std::ofstream::app : std::ofstream::out));
if (stream.is_open()) if (stream.is_open())
{ {
stream.write(data.data(), data.size()); stream.write(data.data(), data.size());
stream.close(); stream.close();
return true; return true;
} }
return false; return false;
} }
std::string read_file(const std::string& file) std::string read_file(const std::string& file)
{ {
std::string data; std::string data;
read_file(file, &data); read_file(file, &data);
return data; return data;
} }
bool read_file(const std::string& file, std::string* data) bool read_file(const std::string& file, std::string* data)
{ {
if (!data) return false; if (!data) return false;
data->clear(); data->clear();
if (file_exists(file)) if (file_exists(file))
{ {
std::ifstream stream(file, std::ios::binary); std::ifstream stream(file, std::ios::binary);
if (!stream.is_open()) return false; if (!stream.is_open()) return false;
stream.seekg(0, std::ios::end); stream.seekg(0, std::ios::end);
const std::streamsize size = stream.tellg(); const std::streamsize size = stream.tellg();
stream.seekg(0, std::ios::beg); stream.seekg(0, std::ios::beg);
if (size > -1) if (size > -1)
{ {
data->resize(static_cast<uint32_t>(size)); data->resize(static_cast<uint32_t>(size));
stream.read(const_cast<char*>(data->data()), size); stream.read(const_cast<char*>(data->data()), size);
stream.close(); stream.close();
return true; return true;
} }
} }
return false; return false;
} }
size_t file_size(const std::string& file) size_t file_size(const std::string& file)
{ {
if (file_exists(file)) if (file_exists(file))
{ {
std::ifstream stream(file, std::ios::binary); std::ifstream stream(file, std::ios::binary);
if (stream.good()) if (stream.good())
{ {
stream.seekg(0, std::ios::end); stream.seekg(0, std::ios::end);
return static_cast<size_t>(stream.tellg()); return static_cast<size_t>(stream.tellg());
} }
} }
return 0; return 0;
} }
bool create_directory(const std::string& directory) bool create_directory(const std::string& directory)
{ {
return std::experimental::filesystem::create_directories(directory); return std::experimental::filesystem::create_directories(directory);
} }
bool directory_exists(const std::string& directory) bool directory_exists(const std::string& directory)
{ {
return std::experimental::filesystem::is_directory(directory); return std::experimental::filesystem::is_directory(directory);
} }
bool directory_is_empty(const std::string& directory) bool directory_is_empty(const std::string& directory)
{ {
return std::experimental::filesystem::is_empty(directory); return std::experimental::filesystem::is_empty(directory);
} }
std::vector<std::string> list_files(const std::string& directory) std::vector<std::string> list_files(const std::string& directory)
{ {
std::vector<std::string> files; std::vector<std::string> files;
for (auto& file : std::experimental::filesystem::directory_iterator(directory)) for (auto& file : std::experimental::filesystem::directory_iterator(directory))
{ {
files.push_back(file.path().generic_string()); files.push_back(file.path().generic_string());
} }
return files; return files;
} }
} }
} }

View File

@ -1,207 +1,207 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "nt.hpp" #include "nt.hpp"
namespace utils namespace utils
{ {
namespace nt namespace nt
{ {
module module::load(const std::string& name) module module::load(const std::string& name)
{ {
return module(LoadLibraryA(name.data())); return module(LoadLibraryA(name.data()));
} }
module module::get_by_address(void* address) module module::get_by_address(void* address)
{ {
HMODULE handle = nullptr; HMODULE handle = nullptr;
GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, reinterpret_cast<LPCSTR>(address), &handle); GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, reinterpret_cast<LPCSTR>(address), &handle);
return module(handle); return module(handle);
} }
module::module() module::module()
{ {
this->module_ = GetModuleHandleA(nullptr); this->module_ = GetModuleHandleA(nullptr);
} }
module::module(const std::string& name) module::module(const std::string& name)
{ {
this->module_ = GetModuleHandleA(name.data()); this->module_ = GetModuleHandleA(name.data());
} }
module::module(const HMODULE handle) module::module(const HMODULE handle)
{ {
this->module_ = handle; this->module_ = handle;
} }
bool module::operator==(const module& obj) const bool module::operator==(const module& obj) const
{ {
return this->module_ == obj.module_; return this->module_ == obj.module_;
} }
module::operator bool() const module::operator bool() const
{ {
return this->is_valid(); return this->is_valid();
} }
module::operator HMODULE() const module::operator HMODULE() const
{ {
return this->get_handle(); return this->get_handle();
} }
PIMAGE_NT_HEADERS module::get_nt_headers() const PIMAGE_NT_HEADERS module::get_nt_headers() const
{ {
if (!this->is_valid()) return nullptr; if (!this->is_valid()) return nullptr;
return reinterpret_cast<PIMAGE_NT_HEADERS>(this->get_ptr() + this->get_dos_header()->e_lfanew); return reinterpret_cast<PIMAGE_NT_HEADERS>(this->get_ptr() + this->get_dos_header()->e_lfanew);
} }
PIMAGE_DOS_HEADER module::get_dos_header() const PIMAGE_DOS_HEADER module::get_dos_header() const
{ {
return reinterpret_cast<PIMAGE_DOS_HEADER>(this->get_ptr()); return reinterpret_cast<PIMAGE_DOS_HEADER>(this->get_ptr());
} }
PIMAGE_OPTIONAL_HEADER module::get_optional_header() const PIMAGE_OPTIONAL_HEADER module::get_optional_header() const
{ {
if (!this->is_valid()) return nullptr; if (!this->is_valid()) return nullptr;
return &this->get_nt_headers()->OptionalHeader; return &this->get_nt_headers()->OptionalHeader;
} }
std::vector<PIMAGE_SECTION_HEADER> module::get_section_headers() const std::vector<PIMAGE_SECTION_HEADER> module::get_section_headers() const
{ {
std::vector<PIMAGE_SECTION_HEADER> headers; std::vector<PIMAGE_SECTION_HEADER> headers;
auto nt_headers = this->get_nt_headers(); auto nt_headers = this->get_nt_headers();
auto section = IMAGE_FIRST_SECTION(nt_headers); auto section = IMAGE_FIRST_SECTION(nt_headers);
for (uint16_t i = 0; i < nt_headers->FileHeader.NumberOfSections; ++i, ++section) for (uint16_t i = 0; i < nt_headers->FileHeader.NumberOfSections; ++i, ++section)
{ {
if (section) headers.push_back(section); if (section) headers.push_back(section);
else OutputDebugStringA("There was an invalid section :O"); else OutputDebugStringA("There was an invalid section :O");
} }
return headers; return headers;
} }
std::uint8_t* module::get_ptr() const std::uint8_t* module::get_ptr() const
{ {
return reinterpret_cast<std::uint8_t*>(this->module_); return reinterpret_cast<std::uint8_t*>(this->module_);
} }
void module::unprotect() const void module::unprotect() const
{ {
if (!this->is_valid()) return; if (!this->is_valid()) return;
DWORD protection; DWORD protection;
VirtualProtect(this->get_ptr(), this->get_optional_header()->SizeOfImage, PAGE_EXECUTE_READWRITE, VirtualProtect(this->get_ptr(), this->get_optional_header()->SizeOfImage, PAGE_EXECUTE_READWRITE,
&protection); &protection);
} }
size_t module::get_relative_entry_point() const size_t module::get_relative_entry_point() const
{ {
if (!this->is_valid()) return 0; if (!this->is_valid()) return 0;
return this->get_nt_headers()->OptionalHeader.AddressOfEntryPoint; return this->get_nt_headers()->OptionalHeader.AddressOfEntryPoint;
} }
void* module::get_entry_point() const void* module::get_entry_point() const
{ {
if (!this->is_valid()) return nullptr; if (!this->is_valid()) return nullptr;
return this->get_ptr() + this->get_relative_entry_point(); return this->get_ptr() + this->get_relative_entry_point();
} }
bool module::is_valid() const bool module::is_valid() const
{ {
return this->module_ != nullptr && this->get_dos_header()->e_magic == IMAGE_DOS_SIGNATURE; return this->module_ != nullptr && this->get_dos_header()->e_magic == IMAGE_DOS_SIGNATURE;
} }
std::string module::get_name() const std::string module::get_name() const
{ {
if (!this->is_valid()) return ""; if (!this->is_valid()) return "";
auto path = this->get_path(); auto path = this->get_path();
const auto pos = path.find_last_of("/\\"); const auto pos = path.find_last_of("/\\");
if (pos == std::string::npos) return path; if (pos == std::string::npos) return path;
return path.substr(pos + 1); return path.substr(pos + 1);
} }
std::string module::get_path() const std::string module::get_path() const
{ {
if (!this->is_valid()) return ""; if (!this->is_valid()) return "";
char name[MAX_PATH] = {0}; char name[MAX_PATH] = {0};
GetModuleFileNameA(this->module_, name, sizeof name); GetModuleFileNameA(this->module_, name, sizeof name);
return name; return name;
} }
void module::free() void module::free()
{ {
if (this->is_valid()) if (this->is_valid())
{ {
FreeLibrary(this->module_); FreeLibrary(this->module_);
this->module_ = nullptr; this->module_ = nullptr;
} }
} }
HMODULE module::get_handle() const HMODULE module::get_handle() const
{ {
return this->module_; return this->module_;
} }
void** module::get_iat_entry(const std::string& module_name, const std::string& proc_name) const void** module::get_iat_entry(const std::string& module_name, const std::string& proc_name) const
{ {
if (!this->is_valid()) return nullptr; if (!this->is_valid()) return nullptr;
module other_module(module_name); const module other_module(module_name);
if (!other_module.is_valid()) return nullptr; if (!other_module.is_valid()) return nullptr;
const auto target_function = other_module.get_proc<void*>(proc_name); const auto target_function = other_module.get_proc<void*>(proc_name);
if (!target_function) return nullptr; if (!target_function) return nullptr;
auto* header = this->get_optional_header(); auto* header = this->get_optional_header();
if (!header) return nullptr; if (!header) return nullptr;
auto* import_descriptor = reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>(this->get_ptr() + header->DataDirectory auto* import_descriptor = reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>(this->get_ptr() + header->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); [IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
while (import_descriptor->Name) while (import_descriptor->Name)
{ {
if (!_stricmp(reinterpret_cast<char*>(this->get_ptr() + import_descriptor->Name), module_name.data())) if (!_stricmp(reinterpret_cast<char*>(this->get_ptr() + import_descriptor->Name), module_name.data()))
{ {
auto* original_thunk_data = reinterpret_cast<PIMAGE_THUNK_DATA>(import_descriptor-> auto* original_thunk_data = reinterpret_cast<PIMAGE_THUNK_DATA>(import_descriptor->
OriginalFirstThunk + this->get_ptr()); OriginalFirstThunk + this->get_ptr());
auto* thunk_data = reinterpret_cast<PIMAGE_THUNK_DATA>(import_descriptor->FirstThunk + this-> auto* thunk_data = reinterpret_cast<PIMAGE_THUNK_DATA>(import_descriptor->FirstThunk + this->
get_ptr()); get_ptr());
while (original_thunk_data->u1.AddressOfData) while (original_thunk_data->u1.AddressOfData)
{ {
const size_t ordinal_number = original_thunk_data->u1.AddressOfData & 0xFFFFFFF; const size_t ordinal_number = original_thunk_data->u1.AddressOfData & 0xFFFFFFF;
if (ordinal_number > 0xFFFF) continue; if (ordinal_number > 0xFFFF) continue;
if (GetProcAddress(other_module.module_, reinterpret_cast<char*>(ordinal_number)) == if (GetProcAddress(other_module.module_, reinterpret_cast<char*>(ordinal_number)) ==
target_function) target_function)
{ {
return reinterpret_cast<void**>(&thunk_data->u1.Function); return reinterpret_cast<void**>(&thunk_data->u1.Function);
} }
++original_thunk_data; ++original_thunk_data;
++thunk_data; ++thunk_data;
} }
//break; //break;
} }
++import_descriptor; ++import_descriptor;
} }
return nullptr; return nullptr;
} }
void raise_hard_exception() void raise_hard_exception()
{ {
int data = false; int data = false;
utils::nt::module ntdll("ntdll.dll"); const module ntdll("ntdll.dll");
ntdll.invoke_pascal<void>("RtlAdjustPrivilege", 19, true, false, &data); ntdll.invoke_pascal<void>("RtlAdjustPrivilege", 19, true, false, &data);
ntdll.invoke_pascal<void>("NtRaiseHardError", 0xC000007B, 0, nullptr, nullptr, 6, &data); ntdll.invoke_pascal<void>("NtRaiseHardError", 0xC000007B, 0, nullptr, nullptr, 6, &data);
} }
} }
} }