From 91d05c5de64cebc1412a9639b77249169dec10e0 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Thu, 4 Feb 2021 00:21:53 +0100 Subject: [PATCH] Added AES decryption node --- .../source/content/data_processor_nodes.cpp | 153 +++++++++++++++++- .../libimhex/include/hex/helpers/crypto.hpp | 19 ++- plugins/libimhex/source/helpers/crypto.cpp | 44 ++++- 3 files changed, 206 insertions(+), 10 deletions(-) diff --git a/plugins/builtin/source/content/data_processor_nodes.cpp b/plugins/builtin/source/content/data_processor_nodes.cpp index 2651651a9..eb2bb3681 100644 --- a/plugins/builtin/source/content/data_processor_nodes.cpp +++ b/plugins/builtin/source/content/data_processor_nodes.cpp @@ -1,14 +1,51 @@ #include -#include "math_evaluator.hpp" - #include +#include + namespace hex::plugin::builtin { + class NodeNullptr : public dp::Node { + public: + NodeNullptr() : Node("Nullptr", { dp::Attribute(dp::Attribute::IOType::Out, dp::Attribute::Type::Buffer, "") }) {} + + void process() override { + this->setBufferOnOutput(0, { }); + } + + private: + u64 m_value = 0; + }; + + class NodeString : public dp::Node { + public: + NodeString() : Node("String", { dp::Attribute(dp::Attribute::IOType::Out, dp::Attribute::Type::Buffer, "") }) { + this->m_value.resize(0xFFF, 0x00); + } + + void drawNode() override { + ImGui::PushItemWidth(100); + ImGui::InputText("##string", reinterpret_cast(this->m_value.data()), this->m_value.size() - 1); + ImGui::PopItemWidth(); + } + + void process() override { + std::vector output(std::strlen(this->m_value.c_str()) + 1, 0x00); + std::strcpy(reinterpret_cast(output.data()), this->m_value.c_str()); + + output.pop_back(); + + this->setBufferOnOutput(0, output); + } + + private: + std::string m_value; + }; + class NodeInteger : public dp::Node { public: - NodeInteger() : Node("Integer", { dp::Attribute(dp::Attribute::IOType::Out, dp::Attribute::Type::Integer, "Value") }) {} + NodeInteger() : Node("Integer", { dp::Attribute(dp::Attribute::IOType::Out, dp::Attribute::Type::Integer, "") }) {} void drawNode() override { ImGui::TextUnformatted("0x"); ImGui::SameLine(0, 0); @@ -30,7 +67,7 @@ namespace hex::plugin::builtin { class NodeFloat : public dp::Node { public: - NodeFloat() : Node("Float", { dp::Attribute(dp::Attribute::IOType::Out, dp::Attribute::Type::Float, "Value") }) {} + NodeFloat() : Node("Float", { dp::Attribute(dp::Attribute::IOType::Out, dp::Attribute::Type::Float, "") }) {} void drawNode() override { ImGui::PushItemWidth(100); @@ -406,9 +443,112 @@ namespace hex::plugin::builtin { } }; + class NodeCryptoAESDecrypt : public dp::Node { + public: + NodeCryptoAESDecrypt() : Node("Decrypt AES", { dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Buffer, "Key"), + dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Buffer, "IV"), + dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Buffer, "Nonce"), + dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Buffer, "Input"), + dp::Attribute(dp::Attribute::IOType::Out, dp::Attribute::Type::Buffer, "Output") }) {} + + void drawNode() override { + ImGui::PushItemWidth(100); + ImGui::Combo("Mode", &this->m_mode, "ECB\0CBC\0CFB128\0CTR\0GCM\0CCM\0OFB\0"); + ImGui::Combo("Key Length", &this->m_keyLength, "128 Bits\000192 Bits\000256 Bits\000"); + ImGui::PopItemWidth(); + } + + void process() override { + auto key = this->getBufferOnInput(0); + auto iv = this->getBufferOnInput(1); + auto nonce = this->getBufferOnInput(2); + auto input = this->getBufferOnInput(3); + + if (!key.has_value() || !iv.has_value() || !nonce.has_value() || !input.has_value()) + return; + + if (key->empty() || input->empty()) + return; + + std::array ivData = { 0 }, nonceData = { 0 }; + + std::copy(iv->begin(), iv->end(), ivData.begin()); + std::copy(nonce->begin(), nonce->end(), nonceData.begin()); + + auto output = crypt::aesDecrypt(static_cast(this->m_mode), static_cast(this->m_keyLength), key.value(), nonceData, ivData, input.value()); + + this->setBufferOnOutput(4, output); + } + + private: + int m_mode = 0; + int m_keyLength = 0; + }; + + class NodeDecodingBase64 : public dp::Node { + public: + NodeDecodingBase64() : Node("Base64 Decoder", { + dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Buffer, "In"), + dp::Attribute(dp::Attribute::IOType::Out, dp::Attribute::Type::Buffer, "Out") }) {} + + void process() override { + auto input = this->getBufferOnInput(0); + + if (!input.has_value()) + return; + + auto output = crypt::decode64(input.value()); + + this->setBufferOnOutput(1, output); + } + }; + + class NodeDecodingHex : public dp::Node { + public: + NodeDecodingHex() : Node("Hexadecimal Decoder", { + dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Buffer, "In"), + dp::Attribute(dp::Attribute::IOType::Out, dp::Attribute::Type::Buffer, "Out") }) {} + + void process() override { + auto input = this->getBufferOnInput(0); + + if (!input.has_value()) + return; + + if (input->size() % 2 != 0) + return; + + std::vector output; + for (u32 i = 0; i < input->size(); i += 2) { + char c1 = tolower(input->at(i)); + char c2 = tolower(input->at(i + 1)); + + if (!std::isxdigit(c1) || !isxdigit(c2)) + return; + + u8 value; + if (std::isdigit(c1)) + value = (c1 - '0') << 4; + else + value = ((c1 - 'a') + 0x0A) << 4; + + if (std::isdigit(c2)) + value |= c2 - '0'; + else + value |= (c2 - 'a') + 0x0A; + + output.push_back(value); + } + + this->setBufferOnOutput(1, output); + } + }; + void registerDataProcessorNodes() { ContentRegistry::DataProcessorNode::add("Constants", "Integer"); ContentRegistry::DataProcessorNode::add("Constants", "Float"); + ContentRegistry::DataProcessorNode::add("Constants", "Nullptr"); + ContentRegistry::DataProcessorNode::add("Constants", "String"); ContentRegistry::DataProcessorNode::add("Constants", "RGBA8 Color"); ContentRegistry::DataProcessorNode::add("Display", "Integer"); @@ -432,6 +572,11 @@ namespace hex::plugin::builtin { ContentRegistry::DataProcessorNode::add("Bitwise Operations", "OR"); ContentRegistry::DataProcessorNode::add("Bitwise Operations", "XOR"); ContentRegistry::DataProcessorNode::add("Bitwise Operations", "NOT"); + + ContentRegistry::DataProcessorNode::add("Decoding", "Base64"); + ContentRegistry::DataProcessorNode::add("Decoding", "Hexadecimal"); + + ContentRegistry::DataProcessorNode::add("Crypto", "AES"); } } \ No newline at end of file diff --git a/plugins/libimhex/include/hex/helpers/crypto.hpp b/plugins/libimhex/include/hex/helpers/crypto.hpp index 8438a3934..2698312aa 100644 --- a/plugins/libimhex/include/hex/helpers/crypto.hpp +++ b/plugins/libimhex/include/hex/helpers/crypto.hpp @@ -27,5 +27,22 @@ namespace hex::crypt { std::vector decode64(const std::vector &input); std::vector encode64(const std::vector &input); - std::vector aesCtrDecrypt(const std::vector &key, std::array nonce, std::array iv, const std::vector &input); + enum class AESMode : u8 { + ECB = 0, + CBC = 1, + CFB128 = 2, + CTR = 3, + GCM = 4, + CCM = 5, + OFB = 6, + XTS = 7 + }; + + enum class KeyLength : u8 { + Key128Bits = 0, + Key192Bits = 1, + Key256Bits = 2 + }; + + std::vector aesDecrypt(AESMode mode, KeyLength keyLength, const std::vector &key, std::array nonce, std::array iv, const std::vector &input); } \ No newline at end of file diff --git a/plugins/libimhex/source/helpers/crypto.cpp b/plugins/libimhex/source/helpers/crypto.cpp index 6531b6445..59bad05f7 100644 --- a/plugins/libimhex/source/helpers/crypto.cpp +++ b/plugins/libimhex/source/helpers/crypto.cpp @@ -241,24 +241,58 @@ namespace hex::crypt { return output; } - std::vector aesCtrDecrypt(const std::vector &key, std::array nonce, std::array iv, const std::vector &input) { - std::vector output(input.size()); + static std::vector aes(mbedtls_cipher_type_t type, mbedtls_operation_t operation, const std::vector &key, std::array nonce, std::array iv, const std::vector &input) { + std::vector output; + + if (input.empty()) + return { }; + mbedtls_cipher_context_t ctx; + auto cipherInfo = mbedtls_cipher_info_from_type(type); - mbedtls_cipher_setup(&ctx, mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_CTR)); - mbedtls_cipher_setkey(&ctx, key.data(), key.size() * 8, MBEDTLS_DECRYPT); + mbedtls_cipher_setup(&ctx, cipherInfo); + mbedtls_cipher_setkey(&ctx, key.data(), key.size() * 8, operation); std::array nonceCounter = { 0 }; std::copy(nonce.begin(), nonce.end(), nonceCounter.begin()); std::copy(iv.begin(), iv.end(), nonceCounter.begin() + 8); - size_t outputSize = output.size(); + size_t outputSize = input.size() + cipherInfo->block_size; + output.resize(outputSize, 0x00); mbedtls_cipher_crypt(&ctx, nonceCounter.data(), nonceCounter.size(), input.data(), input.size(), output.data(), &outputSize); mbedtls_cipher_free(&ctx); + output.resize(input.size()); + return output; } + std::vector aesDecrypt(AESMode mode, KeyLength keyLength, const std::vector &key, std::array nonce, std::array iv, const std::vector &input) { + switch (keyLength) { + case KeyLength::Key128Bits: if (key.size() != 128 / 8) return { }; break; + case KeyLength::Key192Bits: if (key.size() != 192 / 8) return { }; break; + case KeyLength::Key256Bits: if (key.size() != 256 / 8) return { }; break; + default: return { }; + } + + mbedtls_cipher_type_t type; + switch (mode) { + case AESMode::ECB: type = MBEDTLS_CIPHER_AES_128_ECB; break; + case AESMode::CBC: type = MBEDTLS_CIPHER_AES_128_CBC; break; + case AESMode::CFB128: type = MBEDTLS_CIPHER_AES_128_CFB128; break; + case AESMode::CTR: type = MBEDTLS_CIPHER_AES_128_CTR; break; + case AESMode::GCM: type = MBEDTLS_CIPHER_AES_128_GCM; break; + case AESMode::CCM: type = MBEDTLS_CIPHER_AES_128_CCM; break; + case AESMode::OFB: type = MBEDTLS_CIPHER_AES_128_OFB; break; + case AESMode::XTS: type = MBEDTLS_CIPHER_AES_128_XTS; break; + default: return { }; + } + + type = mbedtls_cipher_type_t(type + u8(keyLength)); + + return aes(type, MBEDTLS_DECRYPT, key, nonce, iv, input); + } + } \ No newline at end of file