From c87bc6aebe52a34ceed5c0f914833e586fafd9de Mon Sep 17 00:00:00 2001 From: WerWolv Date: Wed, 11 Nov 2020 00:13:09 +0100 Subject: [PATCH] Implemented hash view with CRC16, CRC32 and MD5 support More to come --- CMakeLists.txt | 9 +-- include/utils.hpp | 9 ++- include/views/view_hashes.hpp | 26 ++++++ source/main.cpp | 2 + source/utils.cpp | 147 ++++++++++++++++++++++++++++++++++ source/views/view_hashes.cpp | 107 +++++++++++++++++++++++++ 6 files changed, 291 insertions(+), 9 deletions(-) create mode 100644 include/views/view_hashes.hpp create mode 100644 source/views/view_hashes.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3df06bcd2..dca81f177 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,10 +7,8 @@ find_library(GLFW REQUIRED glfw3) find_library(OPENGL REQUIRED OpenGL) include_directories(include ${GLFW_INCLUDE_DIRS} libs/ImGui/include libs/glad/include) - -SET(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} -mwindows) - -add_executable(ImHex WIN32 +SET(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -static-libstdc++ -static-libgcc -static") +add_executable(ImHex source/main.cpp source/window.cpp source/utils.cpp @@ -21,6 +19,7 @@ add_executable(ImHex WIN32 source/views/view_hexeditor.cpp source/views/view_pattern.cpp source/views/view_pattern_data.cpp + source/views/view_hashes.cpp libs/glad/source/glad.c @@ -34,6 +33,6 @@ add_executable(ImHex WIN32 res.rc ) -target_link_libraries(ImHex glfw3) +target_link_libraries(ImHex libglfw3.a libgcc.a libstdc++.a) diff --git a/include/utils.hpp b/include/utils.hpp index 4d056f60f..8070bb70c 100644 --- a/include/utils.hpp +++ b/include/utils.hpp @@ -1,10 +1,8 @@ #pragma once -#include -#include +#include -#include -#include +#include #include #include @@ -12,4 +10,7 @@ namespace hex { std::optional openFileDialog(); + u16 crc16(u8 *data, size_t size, u16 polynomial, u16 init); + u32 crc32(u8 *data, size_t size, u32 polynomial, u32 init); + std::array md5(u8 *data, size_t size); } \ No newline at end of file diff --git a/include/views/view_hashes.hpp b/include/views/view_hashes.hpp new file mode 100644 index 000000000..1d423b7af --- /dev/null +++ b/include/views/view_hashes.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include "views/view.hpp" + +#include + +namespace hex { + + class ViewHashes : public View { + public: + ViewHashes(FILE* &file); + virtual ~ViewHashes(); + + virtual void createView() override; + virtual void createMenu() override; + + private: + FILE* &m_file; + bool m_windowOpen = true; + + int m_currHashFunction = 0; + int m_hashStart = 0, m_hashEnd = 0; + static constexpr const char* HashFunctionNames[] = { "CRC16", "CRC32", "MD5", "SHA-1", "SHA-256" }; + }; + +} \ No newline at end of file diff --git a/source/main.cpp b/source/main.cpp index 6cfa41889..ad6099b5f 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -4,6 +4,7 @@ #include "views/view_hexeditor.hpp" #include "views/view_pattern.hpp" #include "views/view_pattern_data.hpp" +#include "views/view_hashes.hpp" #include #include @@ -19,6 +20,7 @@ int main() { window.addView(file, highlights); window.addView(highlights); window.addView(file, highlights); + window.addView(file); window.loop(); diff --git a/source/utils.cpp b/source/utils.cpp index e5f3d519a..fb135272f 100644 --- a/source/utils.cpp +++ b/source/utils.cpp @@ -1,5 +1,15 @@ #include "utils.hpp" +#include +#include + +#include +#include +#include +#include +#include +#include + namespace hex { std::optional openFileDialog() { @@ -40,4 +50,141 @@ namespace hex { return { }; } + u16 crc16(u8 *data, size_t size, u16 polynomial, u16 init) { + const auto table = [polynomial] { + std::array table; + + for (u16 i = 0; i < 256; i++) { + u16 crc = 0; + u16 c = i; + + for (u16 j = 0; j < 8; j++) { + if (((crc ^ c) & 0x0001U) != 0) + crc = (crc >> 1U) ^ polynomial; + else + crc >>= 1U; + + c >>= 1U; + } + + table[i] = crc; + } + + return table; + }(); + + u16 crc = init; + + for (size_t i = 0; i < size; i++) { + crc = (crc >> 8) ^ table[(crc ^ u16(*data++)) & 0x00FF]; + } + + return crc; + } + + u32 crc32(u8 *buffer, size_t size, u32 polynomial, u32 init) { + auto table = [polynomial] { + std::array table = {0}; + + for (uint32_t i = 0; i < 256; i++) { + uint32_t c = i; + for (size_t j = 0; j < 8; j++) { + if (c & 1) + c = polynomial ^ (c >> 1); + else + c >>= 1; + } + table[i] = c; + } + + return table; + }(); + + uint32_t c = init; + const uint8_t *u = static_cast(buffer); + + for (size_t i = 0; i < size; ++i) + c = table[(c ^ u[i]) & 0xFF] ^ (c >> 8); + + return ~c; + } + + std::array md5(u8 *data, size_t size) { + constexpr u32 r[] = { 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, + 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, + 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, + 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 + }; + + constexpr u32 k[] = { + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, + 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 + }; + + std::array h = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 }; + + u32 newSize = ((((size + 8) / 64) + 1) * 64) - 8; + + std::vector buffer(newSize + 64, 0x00); + std::memcpy(buffer.data(), data, size); + buffer[size] = 128; + + u32 numBits = 8 * size; + std::memcpy(buffer.data() + newSize, &numBits, 4); + + for (s32 offset = 0; offset < newSize; offset += (512/8)) { + u32 *w = reinterpret_cast(buffer.data() + offset); + + u32 a = h[0]; + u32 b = h[1]; + u32 c = h[2]; + u32 d = h[3]; + + for (u32 i = 0; i < 64; i++) { + u32 f, g; + + if (i < 16) { + f = (b & c) | ((~b) & d); + g = i; + } else if (i < 32) { + f = (d & b) | ((~d) & c); + g = (5 * i + 1) & 0x0F; + } else if (i < 48) { + f = b ^ c ^ d; + g = (3 * i + 5) & 0x0F; + } else { + f = c ^ (b | (~d)); + g = (7 * i) & 0x0F; + } + + u32 temp = d; + d = c; + c = b; + b = b + std::rotl(a + f + k[i] + w[g], r[i]); + a = temp; + } + + h[0] += a; + h[1] += b; + h[2] += c; + h[3] += d; + } + + return h; + } + } \ No newline at end of file diff --git a/source/views/view_hashes.cpp b/source/views/view_hashes.cpp new file mode 100644 index 000000000..e1ba944f4 --- /dev/null +++ b/source/views/view_hashes.cpp @@ -0,0 +1,107 @@ +#include "views/view_hashes.hpp" + +#include "utils.hpp" + +#include + +namespace hex { + + ViewHashes::ViewHashes(FILE* &file) : View(), m_file(file) { + + } + + ViewHashes::~ViewHashes() { + + } + + + void ViewHashes::createView() { + if (!this->m_windowOpen) + return; + + if (ImGui::Begin("Hashing", &this->m_windowOpen)) { + ImGui::BeginChild("##scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoNav); + + ImGui::NewLine(); + + ImGui::Combo("Hash Function", &this->m_currHashFunction, HashFunctionNames, sizeof(HashFunctionNames) / sizeof(const char*)); + + ImGui::NewLine(); + ImGui::Separator(); + ImGui::NewLine(); + + ImGui::InputInt("Begin", &this->m_hashStart, 0, 0, ImGuiInputTextFlags_CharsHexadecimal); + ImGui::InputInt("End", &this->m_hashEnd, 0, 0, ImGuiInputTextFlags_CharsHexadecimal); + + ImGui::NewLine(); + ImGui::Separator(); + ImGui::NewLine(); + + switch (this->m_currHashFunction) { + case 0: // CRC16 + { + if (this->m_file == nullptr) + break; + + std::vector buffer(this->m_hashEnd - this->m_hashStart + 1, 0x00); + fseek(this->m_file, this->m_hashStart, SEEK_SET); + fread(buffer.data(), 1, buffer.size(), this->m_file); + + static int polynomial = 0, init = 0; + + ImGui::InputInt("Initial Value", &init, 0, 0, ImGuiInputTextFlags_CharsHexadecimal); + ImGui::InputInt("Polynomial", &polynomial, 0, 0, ImGuiInputTextFlags_CharsHexadecimal); + ImGui::NewLine(); + ImGui::Separator(); + ImGui::NewLine(); + ImGui::LabelText("Result", "%X", crc16(buffer.data(), buffer.size(), polynomial, init)); + } + break; + case 1: // CRC32 + { + if (this->m_file == nullptr) + break; + + std::vector buffer(this->m_hashEnd - this->m_hashStart + 1, 0x00); + fseek(this->m_file, this->m_hashStart, SEEK_SET); + fread(buffer.data(), 1, buffer.size(), this->m_file); + + static int polynomial = 0, init = 0; + + ImGui::InputInt("Initial Value", &init, 0, 0, ImGuiInputTextFlags_CharsHexadecimal); + ImGui::InputInt("Polynomial", &polynomial, 0, 0, ImGuiInputTextFlags_CharsHexadecimal); + ImGui::NewLine(); + ImGui::Separator(); + ImGui::NewLine(); + ImGui::LabelText("Result", "%X", crc32(buffer.data(), buffer.size(), polynomial, init)); + } + break; + case 2: // MD5 + { + if (this->m_file == nullptr) + break; + + std::vector buffer(this->m_hashEnd - this->m_hashStart + 1, 0x00); + fseek(this->m_file, this->m_hashStart, SEEK_SET); + fread(buffer.data(), 1, buffer.size(), this->m_file); + + auto result = md5(buffer.data(), buffer.size()); + + ImGui::LabelText("Result", "%08X%08X%08X%08X", __builtin_bswap32(result[0]), __builtin_bswap32(result[1]), __builtin_bswap32(result[2]), __builtin_bswap32(result[3])); + } + break; + } + + ImGui::EndChild(); + ImGui::End(); + } + } + + void ViewHashes::createMenu() { + if (ImGui::BeginMenu("Window")) { + ImGui::MenuItem("Hash View", "", &this->m_windowOpen); + ImGui::EndMenu(); + } + } + +} \ No newline at end of file