diff options
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | examples/bid64_constant/CMakeLists.txt | 30 | ||||
| -rwxr-xr-x | examples/bid64_constant/sample_binary | bin | 0 -> 374912 bytes | |||
| -rw-r--r-- | examples/bid64_constant/src/bid64_constant.cpp | 144 |
4 files changed, 175 insertions, 0 deletions
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 3e1bedce..1e8d5373 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,5 +1,6 @@ # Personal+ edition (free edition doesn't get plugins due to no API access) add_subdirectory(background_task) +add_subdirectory(bid64_constant) add_subdirectory(breakpoint) add_subdirectory(encoded_strings) add_subdirectory(x86_extension) diff --git a/examples/bid64_constant/CMakeLists.txt b/examples/bid64_constant/CMakeLists.txt new file mode 100644 index 00000000..4dc29cb0 --- /dev/null +++ b/examples/bid64_constant/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 3.15 FATAL_ERROR) + +project(bid64_constant CXX C) + +add_library(${PROJECT_NAME} SHARED + src/bid64_constant.cpp) + +if(NOT BN_API_BUILD_EXAMPLES AND NOT BN_INTERNAL_BUILD) + # Out-of-tree build + find_path( + BN_API_PATH + NAMES binaryninjaapi.h + HINTS ../.. binaryninjaapi $ENV{BN_API_PATH} + REQUIRED + ) + add_subdirectory(${BN_API_PATH} api) +endif() + +target_link_libraries(${PROJECT_NAME} + binaryninjaapi) + +set_target_properties(${PROJECT_NAME} PROPERTIES + CXX_STANDARD 20 + CXX_VISIBILITY_PRESET hidden + CXX_STANDARD_REQUIRED ON + VISIBILITY_INLINES_HIDDEN ON + POSITION_INDEPENDENT_CODE ON + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/out/bin) + +bn_install_plugin(${PROJECT_NAME}) diff --git a/examples/bid64_constant/sample_binary b/examples/bid64_constant/sample_binary Binary files differnew file mode 100755 index 00000000..53aef608 --- /dev/null +++ b/examples/bid64_constant/sample_binary diff --git a/examples/bid64_constant/src/bid64_constant.cpp b/examples/bid64_constant/src/bid64_constant.cpp new file mode 100644 index 00000000..f2c91ea4 --- /dev/null +++ b/examples/bid64_constant/src/bid64_constant.cpp @@ -0,0 +1,144 @@ +// This plugin renders 64-bit binary integer decimal floating point constants directly in the +// decompilation. See the sample binary at `examples/bid64_constant/sample_binary` for an +// example of a binary that uses this unusual format. + +#define _CRT_SECURE_NO_WARNINGS +#include <cinttypes> +#include <cstdio> +#include <cstring> +#include <map> +#include <functional> +#include <vector> +#include "binaryninjaapi.h" + +using namespace BinaryNinja; +using namespace std; + + +static string Bid64ToString(bool sign, uint64_t magnitude, int exponent) +{ + if (magnitude == 0) + exponent = 0; + + string digits = to_string(magnitude); + int intPartDigits = digits.length() + exponent; + + int displayedExponent = 0; + if (intPartDigits > 10 || intPartDigits < -4) + { + int newExponent = 1 - (int)digits.length(); + displayedExponent = exponent - newExponent; + intPartDigits = digits.length() + newExponent; + } + + string fracDigits; + if (intPartDigits < 0) + fracDigits = digits; + else if (intPartDigits <= (int)digits.length()) + fracDigits = digits.substr(intPartDigits); + + int trailingZeros = 0; + for (size_t i = 0; i < fracDigits.length(); i++) + { + if (fracDigits[(fracDigits.length() - 1) - i] != '0') + break; + trailingZeros++; + } + + int nonzeroFracDigits = (int)fracDigits.length() - trailingZeros; + fracDigits = fracDigits.substr(0, nonzeroFracDigits); + + string result; + if (sign) + result = "-"; + if (intPartDigits > 0) + { + for (size_t i = 0; i < intPartDigits; i++) + { + if (i >= digits.length()) + result += "0"; + else + result += string(1, digits[i]); + } + } + else + { + result += "0"; + } + + if (intPartDigits < 0 && fracDigits.length() > 0) + { + result += "."; + for (size_t i = 0; i < -intPartDigits; i++) + result += "0"; + result += fracDigits; + } + else if (fracDigits.length() > 0) + { + result += "."; + result += fracDigits; + } + + if (displayedExponent > 0) + result += "E+" + to_string(displayedExponent); + else if (displayedExponent < 0) + result += "E" + to_string(displayedExponent); + + return result; +} + + +class Bid64ConstantRenderer : public ConstantRenderer +{ +public: + Bid64ConstantRenderer() : ConstantRenderer("bid64_constant") + { + } + + bool RenderConstant(const HighLevelILInstruction&, Type* type, int64_t val, HighLevelILTokenEmitter& tokens, + DisassemblySettings* settings, BNOperatorPrecedence) override + { + // Typedefs have the final type, so make sure it is a 64 bit integer. The registered name + // should be the typedef "BID_UINT64". + if (!type || type->GetClass() != IntegerTypeClass) + return false; + if (type->GetWidth() != 8) + return false; + auto name = type->GetRegisteredName(); + if (!name || name->GetName().GetString() != "BID_UINT64") + return false; + + // Get sign bit and raw exponent + bool sign = (val & (1LL << 63)) != 0; + int rawExponent = (int)((val >> 53) & 0x3ff); + if (rawExponent >= 0x300) + { + // Don't try and render NaN or infinity + return false; + } + + // Get magnitude and actual exponent + constexpr uint64_t BIAS = 398; + int exponent = rawExponent - BIAS; + uint64_t magnitude = val & ((1LL << 53) - 1); + + tokens.Append(FloatingPointToken, Bid64ToString(sign, magnitude, exponent) + "_bid"); + return true; + } +}; + + +extern "C" +{ + BN_DECLARE_CORE_ABI_VERSION + + BINARYNINJAPLUGIN void CorePluginDependencies() + { + } + + BINARYNINJAPLUGIN bool CorePluginInit() + { + ConstantRenderer::Register(new Bid64ConstantRenderer()); + return true; + } +} |
