From 17b2371910adc5d99cb776058e429dc1c8cee707 Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Fri, 8 Apr 2022 14:11:10 -0700 Subject: [PATCH] forgot to preserve flags before transformations... wrote tests now... --- include/obf/passes/next_inst_pass.hpp | 2 +- include/obf/transform/gen.hpp | 19 ++- src/tests/CMakeLists.txt | 10 ++ src/tests/cmake.toml | 3 +- src/tests/demolib2/CMakeLists.txt | 56 ++++++ src/tests/demolib2/cmake.toml | 7 + src/tests/demolib2/cmkr.cmake | 236 ++++++++++++++++++++++++++ src/tests/demolib2/obj1.cpp | 18 ++ src/tests/demolib2/obj2.cpp | 20 +++ 9 files changed, 368 insertions(+), 3 deletions(-) create mode 100644 src/tests/demolib2/CMakeLists.txt create mode 100644 src/tests/demolib2/cmake.toml create mode 100644 src/tests/demolib2/cmkr.cmake create mode 100644 src/tests/demolib2/obj1.cpp create mode 100644 src/tests/demolib2/obj2.cpp diff --git a/include/obf/passes/next_inst_pass.hpp b/include/obf/passes/next_inst_pass.hpp index 4e8228d..6fa7456 100644 --- a/include/obf/passes/next_inst_pass.hpp +++ b/include/obf/passes/next_inst_pass.hpp @@ -16,7 +16,7 @@ class next_inst_pass_t : public pass_t { private: std::optional has_next_inst_reloc(decomp::symbol_t*); xed_decoded_inst_t m_tmp_inst; - std::uint8_t m_type_inst_bytes[8] = {0x48, 0xC7, 0x04, 0x24, + std::uint8_t m_type_inst_bytes[9] = {0x48, 0xC7, 0x44, 0x24, 0x08, 0x44, 0x33, 0x22, 0x11}; }; } // namespace theo::obf \ No newline at end of file diff --git a/include/obf/transform/gen.hpp b/include/obf/transform/gen.hpp index 6093481..65b6e23 100644 --- a/include/obf/transform/gen.hpp +++ b/include/obf/transform/gen.hpp @@ -11,6 +11,17 @@ inline std::vector generate(xed_decoded_inst_t* inst, auto num_ops = transform::operations.size(); std::vector new_inst_bytes; + std::uint32_t inst_len = {}; + std::uint8_t inst_buff[XED_MAX_INSTRUCTION_BYTES]; + xed_encoder_request_t req; + + xed_state_t istate{XED_MACHINE_MODE_LONG_64, XED_ADDRESS_WIDTH_64b}; + xed_encoder_request_zero_set_mode(&req, &istate); + xed_encoder_request_set_effective_operand_width(&req, 64); + xed_encoder_request_set_iclass(&req, XED_ICLASS_PUSHFQ); + xed_encode(&req, inst_buff, sizeof(inst_buff), &inst_len); + new_inst_bytes.insert(new_inst_bytes.end(), inst_buff, inst_buff + inst_len); + for (auto cnt = 0u; cnt < num_transforms; ++cnt) { std::uint32_t imm = transform::operation_t::random( 0, std::numeric_limits::max()); @@ -25,9 +36,15 @@ inline std::vector generate(xed_decoded_inst_t* inst, {transform::operations[itr->second->inverse()]->get_transform(), imm}); } + xed_encoder_request_zero_set_mode(&req, &istate); + xed_encoder_request_set_effective_operand_width(&req, 64); + xed_encoder_request_set_iclass(&req, XED_ICLASS_POPFQ); + xed_encode(&req, inst_buff, sizeof(inst_buff), &inst_len); + new_inst_bytes.insert(new_inst_bytes.end(), inst_buff, inst_buff + inst_len); + // inverse the order in which the transformations are executed... // std::reverse(reloc->get_transforms().begin(), reloc->get_transforms().end()); return new_inst_bytes; } -} // namespace theo::obf \ No newline at end of file +} // namespace theo::obf::transform \ No newline at end of file diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 93f35ca..26a37b5 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -26,3 +26,13 @@ endif() add_subdirectory(demolib) set(CMAKE_FOLDER ${CMKR_CMAKE_FOLDER}) +# demolib2 +set(CMKR_CMAKE_FOLDER ${CMAKE_FOLDER}) +if(CMAKE_FOLDER) + set(CMAKE_FOLDER "${CMAKE_FOLDER}/demolib2") +else() + set(CMAKE_FOLDER demolib2) +endif() +add_subdirectory(demolib2) +set(CMAKE_FOLDER ${CMKR_CMAKE_FOLDER}) + diff --git a/src/tests/cmake.toml b/src/tests/cmake.toml index f73f334..b83951b 100644 --- a/src/tests/cmake.toml +++ b/src/tests/cmake.toml @@ -1,2 +1,3 @@ [subdir.demo] -[subdir.demolib] \ No newline at end of file +[subdir.demolib] +[subdir.demolib2] \ No newline at end of file diff --git a/src/tests/demolib2/CMakeLists.txt b/src/tests/demolib2/CMakeLists.txt new file mode 100644 index 0000000..81bdb8b --- /dev/null +++ b/src/tests/demolib2/CMakeLists.txt @@ -0,0 +1,56 @@ +# This file is automatically generated from cmake.toml - DO NOT EDIT +# See https://github.com/build-cpp/cmkr for more information + +cmake_minimum_required(VERSION 3.15) + +if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) + message(FATAL_ERROR "In-tree builds are not supported. Run CMake from a separate directory: cmake -B build") +endif() + +# Regenerate CMakeLists.txt automatically in the root project +set(CMKR_ROOT_PROJECT OFF) +if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) + set(CMKR_ROOT_PROJECT ON) + + # Bootstrap cmkr + include(cmkr.cmake OPTIONAL RESULT_VARIABLE CMKR_INCLUDE_RESULT) + if(CMKR_INCLUDE_RESULT) + cmkr() + endif() + + # Enable folder support + set_property(GLOBAL PROPERTY USE_FOLDERS ON) +endif() + +# Create a configure-time dependency on cmake.toml to improve IDE support +if(CMKR_ROOT_PROJECT) + configure_file(cmake.toml cmake.toml COPYONLY) +endif() + +project(demolib2) + +# Target demolib2 +set(CMKR_TARGET demolib2) +set(demolib2_SOURCES "") + +list(APPEND demolib2_SOURCES + obj1.cpp + obj2.cpp +) + +list(APPEND demolib2_SOURCES + cmake.toml +) + +set(CMKR_SOURCES ${demolib2_SOURCES}) +add_library(demolib2 STATIC) + +if(demolib2_SOURCES) + target_sources(demolib2 PRIVATE ${demolib2_SOURCES}) +endif() + +source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${demolib2_SOURCES}) + +unset(CMKR_TARGET) +unset(CMKR_SOURCES) + diff --git a/src/tests/demolib2/cmake.toml b/src/tests/demolib2/cmake.toml new file mode 100644 index 0000000..4869216 --- /dev/null +++ b/src/tests/demolib2/cmake.toml @@ -0,0 +1,7 @@ +[project] +name = "demolib2" + +[target.demolib2] +type = "static" + +sources = ["*.cpp"] \ No newline at end of file diff --git a/src/tests/demolib2/cmkr.cmake b/src/tests/demolib2/cmkr.cmake new file mode 100644 index 0000000..9af0802 --- /dev/null +++ b/src/tests/demolib2/cmkr.cmake @@ -0,0 +1,236 @@ +include_guard() + +# Change these defaults to point to your infrastructure if desired +set(CMKR_REPO "https://github.com/build-cpp/cmkr" CACHE STRING "cmkr git repository" FORCE) +set(CMKR_TAG "v0.2.12" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE) +set(CMKR_COMMIT_HASH "" CACHE STRING "cmkr git commit hash (optional)" FORCE) + +# To bootstrap/generate a cmkr project: cmake -P cmkr.cmake +if(CMAKE_SCRIPT_MODE_FILE) + set(CMAKE_BINARY_DIR "${CMAKE_BINARY_DIR}/build") + set(CMAKE_CURRENT_BINARY_DIR "${CMAKE_BINARY_DIR}") + file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}") +endif() + +# Set these from the command line to customize for development/debugging purposes +set(CMKR_EXECUTABLE "" CACHE FILEPATH "cmkr executable") +set(CMKR_SKIP_GENERATION OFF CACHE BOOL "skip automatic cmkr generation") +set(CMKR_BUILD_TYPE "Debug" CACHE STRING "cmkr build configuration") +mark_as_advanced(CMKR_REPO CMKR_TAG CMKR_COMMIT_HASH CMKR_EXECUTABLE CMKR_SKIP_GENERATION CMKR_BUILD_TYPE) + +# Disable cmkr if generation is disabled +if(DEFINED ENV{CI} OR CMKR_SKIP_GENERATION OR CMKR_BUILD_SKIP_GENERATION) + message(STATUS "[cmkr] Skipping automatic cmkr generation") + unset(CMKR_BUILD_SKIP_GENERATION CACHE) + macro(cmkr) + endmacro() + return() +endif() + +# Disable cmkr if no cmake.toml file is found +if(NOT CMAKE_SCRIPT_MODE_FILE AND NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake.toml") + message(AUTHOR_WARNING "[cmkr] Not found: ${CMAKE_CURRENT_SOURCE_DIR}/cmake.toml") + macro(cmkr) + endmacro() + return() +endif() + +# Convert a Windows native path to CMake path +if(CMKR_EXECUTABLE MATCHES "\\\\") + string(REPLACE "\\" "/" CMKR_EXECUTABLE_CMAKE "${CMKR_EXECUTABLE}") + set(CMKR_EXECUTABLE "${CMKR_EXECUTABLE_CMAKE}" CACHE FILEPATH "" FORCE) + unset(CMKR_EXECUTABLE_CMAKE) +endif() + +# Helper macro to execute a process (COMMAND_ERROR_IS_FATAL ANY is 3.19 and higher) +function(cmkr_exec) + execute_process(COMMAND ${ARGV} RESULT_VARIABLE CMKR_EXEC_RESULT) + if(NOT CMKR_EXEC_RESULT EQUAL 0) + message(FATAL_ERROR "cmkr_exec(${ARGV}) failed (exit code ${CMKR_EXEC_RESULT})") + endif() +endfunction() + +# Windows-specific hack (CMAKE_EXECUTABLE_PREFIX is not set at the moment) +if(WIN32) + set(CMKR_EXECUTABLE_NAME "cmkr.exe") +else() + set(CMKR_EXECUTABLE_NAME "cmkr") +endif() + +# Use cached cmkr if found +if(DEFINED ENV{CMKR_CACHE} AND EXISTS "$ENV{CMKR_CACHE}") + set(CMKR_DIRECTORY_PREFIX "$ENV{CMKR_CACHE}") + string(REPLACE "\\" "/" CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}") + if(NOT CMKR_DIRECTORY_PREFIX MATCHES "\\/$") + set(CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}/") + endif() + # Build in release mode for the cache + set(CMKR_BUILD_TYPE "Release") +else() + set(CMKR_DIRECTORY_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/_cmkr_") +endif() +set(CMKR_DIRECTORY "${CMKR_DIRECTORY_PREFIX}${CMKR_TAG}") +set(CMKR_CACHED_EXECUTABLE "${CMKR_DIRECTORY}/bin/${CMKR_EXECUTABLE_NAME}") + +# Handle upgrading logic +if(CMKR_EXECUTABLE AND NOT CMKR_CACHED_EXECUTABLE STREQUAL CMKR_EXECUTABLE) + if(CMKR_EXECUTABLE MATCHES "^${CMAKE_CURRENT_BINARY_DIR}/_cmkr") + if(DEFINED ENV{CMKR_CACHE} AND EXISTS "$ENV{CMKR_CACHE}") + message(AUTHOR_WARNING "[cmkr] Switching to cached cmkr: '${CMKR_CACHED_EXECUTABLE}'") + if(EXISTS "${CMKR_CACHED_EXECUTABLE}") + set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE) + else() + unset(CMKR_EXECUTABLE CACHE) + endif() + else() + message(AUTHOR_WARNING "[cmkr] Upgrading '${CMKR_EXECUTABLE}' to '${CMKR_CACHED_EXECUTABLE}'") + unset(CMKR_EXECUTABLE CACHE) + endif() + elseif(DEFINED ENV{CMKR_CACHE} AND EXISTS "$ENV{CMKR_CACHE}" AND CMKR_EXECUTABLE MATCHES "^${CMKR_DIRECTORY_PREFIX}") + message(AUTHOR_WARNING "[cmkr] Upgrading cached '${CMKR_EXECUTABLE}' to '${CMKR_CACHED_EXECUTABLE}'") + unset(CMKR_EXECUTABLE CACHE) + endif() +endif() + +if(CMKR_EXECUTABLE AND EXISTS "${CMKR_EXECUTABLE}") + message(VERBOSE "[cmkr] Found cmkr: '${CMKR_EXECUTABLE}'") +elseif(CMKR_EXECUTABLE AND NOT CMKR_EXECUTABLE STREQUAL CMKR_CACHED_EXECUTABLE) + message(FATAL_ERROR "[cmkr] '${CMKR_EXECUTABLE}' not found") +elseif(NOT CMKR_EXECUTABLE AND EXISTS "${CMKR_CACHED_EXECUTABLE}") + set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE) + message(STATUS "[cmkr] Found cached cmkr: '${CMKR_EXECUTABLE}'") +else() + set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE) + message(VERBOSE "[cmkr] Bootstrapping '${CMKR_EXECUTABLE}'") + + message(STATUS "[cmkr] Fetching cmkr...") + if(EXISTS "${CMKR_DIRECTORY}") + cmkr_exec("${CMAKE_COMMAND}" -E rm -rf "${CMKR_DIRECTORY}") + endif() + find_package(Git QUIET REQUIRED) + cmkr_exec("${GIT_EXECUTABLE}" + clone + --config advice.detachedHead=false + --branch ${CMKR_TAG} + --depth 1 + ${CMKR_REPO} + "${CMKR_DIRECTORY}" + ) + if(CMKR_COMMIT_HASH) + execute_process( + COMMAND "${GIT_EXECUTABLE}" checkout -q "${CMKR_COMMIT_HASH}" + RESULT_VARIABLE CMKR_EXEC_RESULT + WORKING_DIRECTORY "${CMKR_DIRECTORY}" + ) + if(NOT CMKR_EXEC_RESULT EQUAL 0) + message(FATAL_ERROR "Tag '${CMKR_TAG}' hash is not '${CMKR_COMMIT_HASH}'") + endif() + endif() + message(STATUS "[cmkr] Building cmkr (using system compiler)...") + cmkr_exec("${CMAKE_COMMAND}" + --no-warn-unused-cli + "${CMKR_DIRECTORY}" + "-B${CMKR_DIRECTORY}/build" + "-DCMAKE_BUILD_TYPE=${CMKR_BUILD_TYPE}" + "-DCMAKE_UNITY_BUILD=ON" + "-DCMAKE_INSTALL_PREFIX=${CMKR_DIRECTORY}" + "-DCMKR_GENERATE_DOCUMENTATION=OFF" + ) + cmkr_exec("${CMAKE_COMMAND}" + --build "${CMKR_DIRECTORY}/build" + --config "${CMKR_BUILD_TYPE}" + --parallel + ) + cmkr_exec("${CMAKE_COMMAND}" + --install "${CMKR_DIRECTORY}/build" + --config "${CMKR_BUILD_TYPE}" + --prefix "${CMKR_DIRECTORY}" + --component cmkr + ) + if(NOT EXISTS ${CMKR_EXECUTABLE}) + message(FATAL_ERROR "[cmkr] Failed to bootstrap '${CMKR_EXECUTABLE}'") + endif() + cmkr_exec("${CMKR_EXECUTABLE}" version) + message(STATUS "[cmkr] Bootstrapped ${CMKR_EXECUTABLE}") +endif() +execute_process(COMMAND "${CMKR_EXECUTABLE}" version + RESULT_VARIABLE CMKR_EXEC_RESULT +) +if(NOT CMKR_EXEC_RESULT EQUAL 0) + message(FATAL_ERROR "[cmkr] Failed to get version, try clearing the cache and rebuilding") +endif() + +# Use cmkr.cmake as a script +if(CMAKE_SCRIPT_MODE_FILE) + if(NOT EXISTS "${CMAKE_SOURCE_DIR}/cmake.toml") + execute_process(COMMAND "${CMKR_EXECUTABLE}" init + RESULT_VARIABLE CMKR_EXEC_RESULT + ) + if(NOT CMKR_EXEC_RESULT EQUAL 0) + message(FATAL_ERROR "[cmkr] Failed to bootstrap cmkr project. Please report an issue: https://github.com/build-cpp/cmkr/issues/new") + else() + message(STATUS "[cmkr] Modify cmake.toml and then configure using: cmake -B build") + endif() + else() + execute_process(COMMAND "${CMKR_EXECUTABLE}" gen + RESULT_VARIABLE CMKR_EXEC_RESULT + ) + if(NOT CMKR_EXEC_RESULT EQUAL 0) + message(FATAL_ERROR "[cmkr] Failed to generate project.") + else() + message(STATUS "[cmkr] Configure using: cmake -B build") + endif() + endif() +endif() + +# This is the macro that contains black magic +macro(cmkr) + # When this macro is called from the generated file, fake some internal CMake variables + get_source_file_property(CMKR_CURRENT_LIST_FILE "${CMAKE_CURRENT_LIST_FILE}" CMKR_CURRENT_LIST_FILE) + if(CMKR_CURRENT_LIST_FILE) + set(CMAKE_CURRENT_LIST_FILE "${CMKR_CURRENT_LIST_FILE}") + get_filename_component(CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY) + endif() + + # File-based include guard (include_guard is not documented to work) + get_source_file_property(CMKR_INCLUDE_GUARD "${CMAKE_CURRENT_LIST_FILE}" CMKR_INCLUDE_GUARD) + if(NOT CMKR_INCLUDE_GUARD) + set_source_files_properties("${CMAKE_CURRENT_LIST_FILE}" PROPERTIES CMKR_INCLUDE_GUARD TRUE) + + file(SHA256 "${CMAKE_CURRENT_LIST_FILE}" CMKR_LIST_FILE_SHA256_PRE) + + # Generate CMakeLists.txt + cmkr_exec("${CMKR_EXECUTABLE}" gen + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + ) + + file(SHA256 "${CMAKE_CURRENT_LIST_FILE}" CMKR_LIST_FILE_SHA256_POST) + + # Delete the temporary file if it was left for some reason + set(CMKR_TEMP_FILE "${CMAKE_CURRENT_SOURCE_DIR}/CMakerLists.txt") + if(EXISTS "${CMKR_TEMP_FILE}") + file(REMOVE "${CMKR_TEMP_FILE}") + endif() + + if(NOT CMKR_LIST_FILE_SHA256_PRE STREQUAL CMKR_LIST_FILE_SHA256_POST) + # Copy the now-generated CMakeLists.txt to CMakerLists.txt + # This is done because you cannot include() a file you are currently in + configure_file(CMakeLists.txt "${CMKR_TEMP_FILE}" COPYONLY) + + # Add the macro required for the hack at the start of the cmkr macro + set_source_files_properties("${CMKR_TEMP_FILE}" PROPERTIES + CMKR_CURRENT_LIST_FILE "${CMAKE_CURRENT_LIST_FILE}" + ) + + # 'Execute' the newly-generated CMakeLists.txt + include("${CMKR_TEMP_FILE}") + + # Delete the generated file + file(REMOVE "${CMKR_TEMP_FILE}") + + # Do not execute the rest of the original CMakeLists.txt + return() + endif() + # Resume executing the unmodified CMakeLists.txt + endif() +endmacro() diff --git a/src/tests/demolib2/obj1.cpp b/src/tests/demolib2/obj1.cpp new file mode 100644 index 0000000..0e3be5e --- /dev/null +++ b/src/tests/demolib2/obj1.cpp @@ -0,0 +1,18 @@ +extern "C" int MessageBoxA(void* hWnd, + char* lpText, + char* lpCaption, + void* uType); + +struct test_t { + char buff[0x2000]; +}; + +test_t t = {}; + +void AnotherFunc(); + +extern "C" void EntryPoint() { + t.buff[0] = 1; + t.buff[1] = 2; + AnotherFunc(); +} \ No newline at end of file diff --git a/src/tests/demolib2/obj2.cpp b/src/tests/demolib2/obj2.cpp new file mode 100644 index 0000000..5a31e9e --- /dev/null +++ b/src/tests/demolib2/obj2.cpp @@ -0,0 +1,20 @@ +#define OBF __declspec(code_seg(".obf")) + +extern "C" int MessageBoxA(void* hWnd, + char* lpText, + char* lpCaption, + void* uType); + +struct test_t { + char buff[0x2000]; +}; + +extern test_t t; + +OBF void AnotherFunc() { + if (t.buff[0]) + MessageBoxA(nullptr, "Hello World", "Hello World", nullptr); + + if (t.buff[1]) + MessageBoxA(nullptr, "Hello World 1", "Hello World 1", nullptr); +} \ No newline at end of file