From 8dee26a145994ea9a6b6f395ba4c63989d5c5957 Mon Sep 17 00:00:00 2001 From: Shane Slattery Date: Mon, 6 Mar 2023 15:21:42 +0000 Subject: [PATCH] Add ObfuscationPassManager (calls the obfuscation funcs based on attrs) --- main.cpp | 51 +++++++++--------------- source/BCF/BcfPass.cpp | 2 +- source/BCF/BcfPass.hpp | 2 +- source/CFF/CffPass.cpp | 2 +- source/CFF/CffPass.hpp | 2 +- source/FuncAttributeStore.cpp | 24 ++++++++--- source/FuncAttributeStore.hpp | 7 ++-- source/ISUB/iSubPass.cpp | 2 +- source/ISUB/iSubPass.hpp | 2 +- source/MBA/MbaPass.cpp | 4 +- source/MBA/MbaPass.hpp | 2 +- source/Passes/CMakeLists.txt | 4 +- source/Passes/FuncAnnotationsParser.cpp | 2 +- source/Passes/IObfuscationPass.hpp | 2 +- source/Passes/ObfuscationPassManager.cpp | 26 ++++++++++++ source/Passes/ObfuscationPassManager.hpp | 12 ++++++ 16 files changed, 93 insertions(+), 53 deletions(-) create mode 100644 source/Passes/ObfuscationPassManager.cpp create mode 100644 source/Passes/ObfuscationPassManager.hpp diff --git a/main.cpp b/main.cpp index f7d9f78..6a98e46 100644 --- a/main.cpp +++ b/main.cpp @@ -4,44 +4,29 @@ #include #include "common.hpp" #include "FuncAnnotationsParser.hpp" +#include "ObfuscationPassManager.hpp" -struct HelloWorld2 : llvm::PassInfoMixin { - // Takes IR unit to run the pass on Module and the corresponding manager - llvm::PreservedAnalyses run(llvm::Module& M, llvm::ModuleAnalysisManager &) { - for (auto&& F : M.getFunctionList()) { - llvm::outs() << "Hello from: "<< F.getName() << "\n"; - llvm::outs() << " number of arguments: " << F.arg_size() << "\n"; - llvm::outs() << " number of attributes: " << F.getAttributes().getNumAttrSets() << "\n"; - for (auto&& A : F.getAttributes()) { - llvm::outs() << A.getAsString() << "\n"; +namespace obfusc { + llvm::PassPluginLibraryInfo getObfuscPluginInfo() { + llvm::outs() << "ObfusC Version: " << OBFUSC_VERSION_STR << "\n"; + return {LLVM_PLUGIN_API_VERSION, "ObfusC", OBFUSC_VERSION_STR, + [](llvm::PassBuilder &PB) { + PB.registerPipelineEarlySimplificationEPCallback( + [=](llvm::ModulePassManager &MPM, llvm::OptimizationLevel Level) { + MPM.addPass(obfusc::FuncAnnotationsParser()); + } + ); + PB.registerOptimizerLastEPCallback( + [=](llvm::ModulePassManager &MPM, llvm::OptimizationLevel Level) { + MPM.addPass(obfusc::ObfuscationPassManager()); + } + ); } - } - return llvm::PreservedAnalyses::all(); + }; } - - // If false, pass is skipped for functions decorated with the optnone attribute (e.g. -O0). - static bool isRequired() { return true; } -}; - -llvm::PassPluginLibraryInfo getHelloWorldPluginInfo() { - llvm::outs() << "ObfusC Version: " << OBFUSC_VERSION_STR << "\n"; - return {LLVM_PLUGIN_API_VERSION, "ObfusC", OBFUSC_VERSION_STR, - [](llvm::PassBuilder &PB) { - PB.registerPipelineEarlySimplificationEPCallback( - [=](llvm::ModulePassManager &MPM, llvm::OptimizationLevel Level) { - MPM.addPass(obfusc::FuncAnnotationsParser()); - } - ); - PB.registerOptimizerLastEPCallback( - [=](llvm::ModulePassManager &MPM, llvm::OptimizationLevel Level) { - MPM.addPass(HelloWorld2()); - } - ); - } - }; } // Dynamic Library Entrypoint extern "C" LLVM_ATTRIBUTE_WEAK llvm::PassPluginLibraryInfo llvmGetPassPluginInfo() { - return getHelloWorldPluginInfo(); + return obfusc::getObfuscPluginInfo(); } diff --git a/source/BCF/BcfPass.cpp b/source/BCF/BcfPass.cpp index f78f3ca..9b53321 100644 --- a/source/BCF/BcfPass.cpp +++ b/source/BCF/BcfPass.cpp @@ -4,7 +4,7 @@ namespace obfusc { BcfPass::BcfPass() {} BcfPass::~BcfPass() {} - bool BcfPass::obfuscate(llvm::Module& mod) { + bool BcfPass::obfuscate(llvm::Module& mod, llvm::Function& func) { return true; } diff --git a/source/BCF/BcfPass.hpp b/source/BCF/BcfPass.hpp index 2547dbc..ef0f0b4 100644 --- a/source/BCF/BcfPass.hpp +++ b/source/BCF/BcfPass.hpp @@ -7,6 +7,6 @@ namespace obfusc { BcfPass(); ~BcfPass() override; - bool obfuscate(llvm::Module& mod) override; + bool obfuscate(llvm::Module& mod, llvm::Function& func) override; }; } \ No newline at end of file diff --git a/source/CFF/CffPass.cpp b/source/CFF/CffPass.cpp index ab5908e..c8f34c7 100644 --- a/source/CFF/CffPass.cpp +++ b/source/CFF/CffPass.cpp @@ -4,7 +4,7 @@ namespace obfusc { CffPass::CffPass() {} CffPass::~CffPass() {} - bool CffPass::obfuscate(llvm::Module& mod) { + bool CffPass::obfuscate(llvm::Module& mod, llvm::Function& func) { return true; } diff --git a/source/CFF/CffPass.hpp b/source/CFF/CffPass.hpp index eaf139b..a72d023 100644 --- a/source/CFF/CffPass.hpp +++ b/source/CFF/CffPass.hpp @@ -7,6 +7,6 @@ namespace obfusc { CffPass(); ~CffPass() override; - bool obfuscate(llvm::Module& mod) override; + bool obfuscate(llvm::Module& mod, llvm::Function& func) override; }; } \ No newline at end of file diff --git a/source/FuncAttributeStore.cpp b/source/FuncAttributeStore.cpp index 238e44f..5f676db 100644 --- a/source/FuncAttributeStore.cpp +++ b/source/FuncAttributeStore.cpp @@ -7,13 +7,19 @@ namespace obfusc { return x; } - bool FuncAttributeStore::IsAttrStored(const char* attr) { - if (!attr || strlen(attr) < 1) { + bool FuncAttributeStore::IsAttrStored(llvm::StringRef& attr) { + if (attr.size() < 2) { return false; } + const char* attrCStr = attr.data(); + + if (attr[0] == '\"') { + attrCStr = attr.substr(1, attr.size()-2).data(); + } + for (auto& info : m_info) { - if (strncasecmp(info.name, attr, info.size) == 0) { + if (strncasecmp(info.name, attrCStr, info.size) == 0) { return true; } } @@ -21,13 +27,19 @@ namespace obfusc { return false; } - IObfuscationPass* FuncAttributeStore::GetAttrPass(const char* attr) { - if (!attr || strlen(attr) < 1) { + IObfuscationPass* FuncAttributeStore::GetAttrPass(llvm::StringRef&& attr) { + if (attr.size() < 2) { return nullptr; } + const char* attrCStr = attr.data(); + + if (attr[0] == '\"') { + attrCStr = attr.substr(1, attr.size()-2).data(); + } + for (auto& info : m_info) { - if (strncasecmp(info.name, attr, info.size) == 0) { + if (strncasecmp(info.name, attrCStr, info.size) == 0) { return info.pass; } } diff --git a/source/FuncAttributeStore.hpp b/source/FuncAttributeStore.hpp index 659e9de..a2db6c1 100644 --- a/source/FuncAttributeStore.hpp +++ b/source/FuncAttributeStore.hpp @@ -1,17 +1,18 @@ #pragma once #include +#include #include "IObfuscationPass.hpp" namespace obfusc { class FuncAttributeStore { public: static FuncAttributeStore& GetInstance(); - bool IsAttrStored(const char* attr); - IObfuscationPass* GetAttrPass(const char* attr); + bool IsAttrStored(llvm::StringRef& attr); + IObfuscationPass* GetAttrPass(llvm::StringRef&& attr); void StoreAttributeInfo(const char* name, IObfuscationPass* pass); private: - FuncAttributeStore(); + FuncAttributeStore() {} struct AttrStoreInfo { const char* name; diff --git a/source/ISUB/iSubPass.cpp b/source/ISUB/iSubPass.cpp index 3435ec5..922bfd2 100644 --- a/source/ISUB/iSubPass.cpp +++ b/source/ISUB/iSubPass.cpp @@ -4,7 +4,7 @@ namespace obfusc { iSubPass::iSubPass() {} iSubPass::~iSubPass() {} - bool iSubPass::obfuscate(llvm::Module& mod) { + bool iSubPass::obfuscate(llvm::Module& mod, llvm::Function& func) { return true; } diff --git a/source/ISUB/iSubPass.hpp b/source/ISUB/iSubPass.hpp index 6be098e..67c9710 100644 --- a/source/ISUB/iSubPass.hpp +++ b/source/ISUB/iSubPass.hpp @@ -7,6 +7,6 @@ namespace obfusc { iSubPass(); ~iSubPass() override; - bool obfuscate(llvm::Module& mod) override; + bool obfuscate(llvm::Module& mod, llvm::Function& func) override; }; } \ No newline at end of file diff --git a/source/MBA/MbaPass.cpp b/source/MBA/MbaPass.cpp index 7a59592..8cd9aed 100644 --- a/source/MBA/MbaPass.cpp +++ b/source/MBA/MbaPass.cpp @@ -4,7 +4,9 @@ namespace obfusc { MbaPass::MbaPass() {} MbaPass::~MbaPass() {} - bool MbaPass::obfuscate(llvm::Module& mod) { + bool MbaPass::obfuscate(llvm::Module& mod, llvm::Function& func) { + llvm::outs() << "Hello from: "<< __PRETTY_FUNCTION__ << "\n"; + return true; } diff --git a/source/MBA/MbaPass.hpp b/source/MBA/MbaPass.hpp index 153511f..f6aecfb 100644 --- a/source/MBA/MbaPass.hpp +++ b/source/MBA/MbaPass.hpp @@ -7,6 +7,6 @@ namespace obfusc { MbaPass(); ~MbaPass() override; - bool obfuscate(llvm::Module& mod) override; + bool obfuscate(llvm::Module& mod, llvm::Function& func) override; }; } \ No newline at end of file diff --git a/source/Passes/CMakeLists.txt b/source/Passes/CMakeLists.txt index 6b96937..1a631c3 100644 --- a/source/Passes/CMakeLists.txt +++ b/source/Passes/CMakeLists.txt @@ -1,3 +1,5 @@ target_sources(ObfusC PRIVATE FuncAnnotationsParser.hpp) target_sources(ObfusC PRIVATE FuncAnnotationsParser.cpp) -target_sources(ObfusC PRIVATE IObfuscationPass.hpp) \ No newline at end of file +target_sources(ObfusC PRIVATE IObfuscationPass.hpp) +target_sources(ObfusC PRIVATE ObfuscationPassManager.hpp) +target_sources(ObfusC PRIVATE ObfuscationPassManager.cpp) \ No newline at end of file diff --git a/source/Passes/FuncAnnotationsParser.cpp b/source/Passes/FuncAnnotationsParser.cpp index a3cf79a..0bd525f 100644 --- a/source/Passes/FuncAnnotationsParser.cpp +++ b/source/Passes/FuncAnnotationsParser.cpp @@ -23,7 +23,7 @@ namespace obfusc { if (llvm::ConstantDataArray* strArray = llvm::dyn_cast(globalStrPtr->getOperand(0))) { //Get Annotation str llvm::StringRef str = strArray->getAsString(); - if (FuncAttributeStore::GetInstance().IsAttrStored(str.data())) { + if (FuncAttributeStore::GetInstance().IsAttrStored(str)) { func->addFnAttr(str); //add Annotation to function } } diff --git a/source/Passes/IObfuscationPass.hpp b/source/Passes/IObfuscationPass.hpp index feff56b..944228e 100644 --- a/source/Passes/IObfuscationPass.hpp +++ b/source/Passes/IObfuscationPass.hpp @@ -3,7 +3,7 @@ class IObfuscationPass { public: - virtual bool obfuscate(llvm::Module& mod) = 0; + virtual bool obfuscate(llvm::Module& mod, llvm::Function& func) = 0; protected: IObfuscationPass() {} virtual ~IObfuscationPass() {} diff --git a/source/Passes/ObfuscationPassManager.cpp b/source/Passes/ObfuscationPassManager.cpp new file mode 100644 index 0000000..b13224f --- /dev/null +++ b/source/Passes/ObfuscationPassManager.cpp @@ -0,0 +1,26 @@ +#include "ObfuscationPassManager.hpp" +#include "IObfuscationPass.hpp" +#include "FuncAttributeStore.hpp" + +namespace obfusc { + llvm::PreservedAnalyses ObfuscationPassManager::run(llvm::Module& mod, llvm::ModuleAnalysisManager&) { + bool changed = false; + for (auto& func : mod.getFunctionList()) { //Get all functions in module + for (auto& attrs : func.getAttributes()) { //Get each attribute lists attached to function + for (auto& attr : attrs) { //Get attributes one by one + if (attr.isStringAttribute()) { //If attribute is a string + IObfuscationPass* pass = FuncAttributeStore::GetInstance().GetAttrPass(llvm::StringRef(attr.getAsString().data())); //Check if attr is an obfuscation pass + if (pass) { + changed |= pass->obfuscate(mod, func); //Call obfuscate func + } + } + } + } + } + + if (changed) { + return llvm::PreservedAnalyses::none(); + } + return llvm::PreservedAnalyses::all(); + } +} \ No newline at end of file diff --git a/source/Passes/ObfuscationPassManager.hpp b/source/Passes/ObfuscationPassManager.hpp new file mode 100644 index 0000000..1cd9d8d --- /dev/null +++ b/source/Passes/ObfuscationPassManager.hpp @@ -0,0 +1,12 @@ +#pragma once +#include + +namespace obfusc { + struct ObfuscationPassManager : llvm::PassInfoMixin { + // Takes IR unit to run the pass on Module and the corresponding manager + llvm::PreservedAnalyses run(llvm::Module& mod, llvm::ModuleAnalysisManager&); + + // If false, pass is skipped for functions decorated with the optnone attribute (e.g. -O0). + static bool isRequired() { return true; } + }; +} \ No newline at end of file