diff --git a/.github/scripts/s3-deploy.py b/.github/scripts/s3-deploy.py
index 64b1e733..be77dec1 100755
--- a/.github/scripts/s3-deploy.py
+++ b/.github/scripts/s3-deploy.py
@@ -1,4 +1,9 @@
#!/usr/bin/env python3
+
+#
+# This file is distributed under the Apache License v2.0. See LICENSE for details.
+#
+
import sys
import os
import logging
diff --git a/README.md b/README.md
index 2df3fdb4..d4ca4005 100644
--- a/README.md
+++ b/README.md
@@ -28,10 +28,10 @@
# O-MVLL
O-MVLL (in reference to [O-LLVM](https://github.com/obfuscator-llvm/obfuscator)) is a LLVM-based obfuscator
-driven by a Python API and by new LLVM pass manager:
+driven by Python and the LLVM pass manager. It can be run as follows:
```bash
-clang++ -fpass-plugin=omvll.so main.cpp -o main
+clang++ -fpass-plugin=libOMVLL.dylib main.cpp -o main
```
```python
@@ -51,7 +51,7 @@ class MyConfig(omvll.ObfuscationConfig):
O-MVLL can be used with the Android NDK and an iOS toolchain but **it only supports the AArch64 architecture**.
-For the details, you can checkout the documentation: [obfuscator.re/omvll](https://obfuscator.re/omvll)
+For more details, please check out the documentation at [obfuscator.re/omvll](https://obfuscator.re/omvll).
### Download
@@ -60,7 +60,7 @@ For the details, you can checkout the documentation: [obfuscator.re/omvll](https
### Contact
-You can reach out by email at this address: `ping@obfuscator.re`
+Feel free to reach out at `ping@obfuscator.re` for any doubt, issue, bug you may encounter.
#### Maintainers
@@ -68,7 +68,7 @@ You can reach out by email at this address: `ping@obfuscator.re`
#### Author
-- [Romain Thomas](https://www.romainthomas.fr): [@rh0main](https://twitter.com/rh0main) - `me@romainthomas.fr`
+- [Romain Thomas](https://www.romainthomas.fr): [@rh0main](https://twitter.com/rh0main) (`me@romainthomas.fr`)
#### Credits
@@ -80,7 +80,9 @@ You can reach out by email at this address: `ping@obfuscator.re`
### License
-O-MVLL is released under the same License as LLVM: [Apache License, Version 2.0](./LICENSE)
+O-MVLL is released under the same License as LLVM: [Apache License, Version 2.0](./LICENSE).
+
+This project is partly funded by the EU and the European Cybersecurity Competence Center.
diff --git a/doc/conf.py b/doc/conf.py
index 8afe619e..2078c8bb 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -1,3 +1,7 @@
+#
+# This file is distributed under the Apache License v2.0. See LICENSE for details.
+#
+
import os
import sphinx
import sys
diff --git a/scripts/deps/common/compile_cpython310.sh b/scripts/deps/common/compile_cpython310.sh
index 1878fc49..3db57b9e 100755
--- a/scripts/deps/common/compile_cpython310.sh
+++ b/scripts/deps/common/compile_cpython310.sh
@@ -1,5 +1,11 @@
#!/usr/bin/env bash
+
+#
+# This file is distributed under the Apache License v2.0. See LICENSE for details.
+#
+
# This script is used to compile cpython
+
set -e
curl -LO https://www.python.org/ftp/python/3.10.7/Python-3.10.7.tgz
diff --git a/scripts/deps/common/compile_pybind11.sh b/scripts/deps/common/compile_pybind11.sh
index 58b0d61b..3de4c641 100755
--- a/scripts/deps/common/compile_pybind11.sh
+++ b/scripts/deps/common/compile_pybind11.sh
@@ -1,5 +1,11 @@
#!/usr/bin/env bash
+
+#
+# This file is distributed under the Apache License v2.0. See LICENSE for details.
+#
+
# This script is used to compile pybind11
+
set -e
curl -LO https://github.com/pybind/pybind11/archive/refs/tags/v2.10.3.tar.gz
diff --git a/scripts/deps/common/compile_spdlog.sh b/scripts/deps/common/compile_spdlog.sh
index 4a758b36..ab60d167 100755
--- a/scripts/deps/common/compile_spdlog.sh
+++ b/scripts/deps/common/compile_spdlog.sh
@@ -1,5 +1,11 @@
#!/usr/bin/env bash
+
+#
+# This file is distributed under the Apache License v2.0. See LICENSE for details.
+#
+
# This script is used to compile cpython
+
set -e
curl -LO https://github.com/gabime/spdlog/archive/refs/tags/v1.10.0.tar.gz
diff --git a/scripts/deps/generate_deps.sh b/scripts/deps/generate_deps.sh
index baee36b3..217c4d26 100755
--- a/scripts/deps/generate_deps.sh
+++ b/scripts/deps/generate_deps.sh
@@ -1,4 +1,9 @@
#!/usr/bin/env bash
+
+#
+# This file is distributed under the Apache License v2.0. See LICENSE for details.
+#
+
set -e
SCRIPT_PATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
diff --git a/scripts/deps/ndk/compile_llvm_r26d.sh b/scripts/deps/ndk/compile_llvm_r26d.sh
index 47ab3ac5..c35a2d3e 100755
--- a/scripts/deps/ndk/compile_llvm_r26d.sh
+++ b/scripts/deps/ndk/compile_llvm_r26d.sh
@@ -1,5 +1,11 @@
#!/usr/bin/env bash
+
+#
+# This file is distributed under the Apache License v2.0. See LICENSE for details.
+#
+
# This script is used to compile the Android NDK r26d LLVM toolchain
+
set -e
host=$(uname)
diff --git a/scripts/docker/doc.sh b/scripts/docker/doc.sh
index 983677c0..b1194cf0 100755
--- a/scripts/docker/doc.sh
+++ b/scripts/docker/doc.sh
@@ -1,4 +1,9 @@
#!/usr/bin/sh
+
+#
+# This file is distributed under the Apache License v2.0. See LICENSE for details.
+#
+
set -ex
mkdir -p /deps && cd /deps
diff --git a/scripts/docker/ndk_r26_compile.sh b/scripts/docker/ndk_r26_compile.sh
index c468e739..9602e1cb 100755
--- a/scripts/docker/ndk_r26_compile.sh
+++ b/scripts/docker/ndk_r26_compile.sh
@@ -1,6 +1,10 @@
#!/usr/bin/sh
-set -ex
+#
+# This file is distributed under the Apache License v2.0. See LICENSE for details.
+#
+
+set -ex
mkdir -p /data && cd /data
cp /third-party/omvll-deps-ndk-*/android-llvm-toolchain-r26d.tar.gz .
@@ -16,7 +20,6 @@ tar xzvf Python-slim.tar.gz
tar xzvf pybind11.tar.gz
tar xzvf spdlog-1.10.0-Linux.tar.gz
-
# Android NDK is bootstrapped in a so-called 2-stage process. To avoid ABI incompatibilities,
# we build our plugin with the same toolchain used to build the NDK itself (stage-1). Then,
# we link the plugin against stage-2 build artifacts.
diff --git a/scripts/docker/xcode_15_compile.sh b/scripts/docker/xcode_15_compile.sh
index 610efa92..b27c28c4 100755
--- a/scripts/docker/xcode_15_compile.sh
+++ b/scripts/docker/xcode_15_compile.sh
@@ -1,5 +1,11 @@
#!/usr/bin/sh
+
+#
+# This file is distributed under the Apache License v2.0. See LICENSE for details.
+#
+
set -ex
+
mkdir -p /deps && cd /deps
cp /third-party/omvll-deps-xcode-*/LLVM-16.0.0git-arm64-Darwin.tar.gz .
diff --git a/scripts/package.py b/scripts/package.py
index 7e9ee913..75a9e6e1 100644
--- a/scripts/package.py
+++ b/scripts/package.py
@@ -1,3 +1,7 @@
+#
+# This file is distributed under the Apache License v2.0. See LICENSE for details.
+#
+
import argparse
import sys
from pathlib import Path
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index ee98a103..aa2007f5 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -75,7 +75,6 @@ else()
set(OMVLL_DEBUG 1)
endif()
-
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/include/omvll/config.hpp.in"
"${CMAKE_CURRENT_BINARY_DIR}/include/omvll/config.hpp")
@@ -133,7 +132,6 @@ endif()
target_link_options(OMVLL PUBLIC ${OMVLL_LINK_OPT})
-
target_link_libraries(OMVLL
PRIVATE
spdlog::spdlog pybind11::headers
@@ -147,7 +145,6 @@ if(NOT APPLE)
)
endif()
-
set(LLVM_LIBS_DEP
demangle
OrcJIT
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 9d78d410..5a9fb1a4 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -1,10 +1,9 @@
-
target_sources(OMVLL PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/omvll_config.cpp
${CMAKE_CURRENT_SOURCE_DIR}/log.cpp
${CMAKE_CURRENT_SOURCE_DIR}/plugin.cpp
${CMAKE_CURRENT_SOURCE_DIR}/utils.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/Jitter.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/jitter.cpp
)
add_subdirectory("python")
diff --git a/src/core/Jitter.cpp b/src/core/Jitter.cpp
deleted file mode 100644
index e98dba48..00000000
--- a/src/core/Jitter.cpp
+++ /dev/null
@@ -1,154 +0,0 @@
-#include "omvll/Jitter.hpp"
-
-#include "omvll/utils.hpp"
-#include "omvll/log.hpp"
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-using namespace llvm;
-
-namespace omvll {
-
-Jitter::Jitter(const std::string &Triple)
- : Triple_{Triple}, Ctx_{new LLVMContext{}} {
- InitializeNativeTarget();
- InitializeNativeTargetAsmParser();
- InitializeNativeTargetAsmPrinter();
-}
-
-std::unique_ptr Jitter::compile(llvm::Module& M) {
- static ExitOnError ExitOnErr;
- auto JITB = ExitOnErr(orc::LLJITBuilder().create());
-
- std::unique_ptr Mod = CloneModule(M);
-
- auto Context = std::make_unique();
- ExitOnErr(JITB->addIRModule(llvm::orc::ThreadSafeModule(std::move(Mod), std::move(Context))));
- return JITB;
-}
-
-size_t Jitter::getFunctionSize(llvm::object::ObjectFile& Obj, llvm::StringRef Name) {
- if (auto* ELF = dyn_cast(&Obj)) {
- for (const object::ELFSymbolRef& Sym : ELF->symbols()) {
- if (Sym.getELFType() != ELF::STT_FUNC) {
- continue;
- }
- if (auto Str = Sym.getName()) {
- if (*Str == Name) {
- return Sym.getSize();
- }
- }
- }
- fatalError("jitAsm: Unable to find symbol '" + Name.str() + "'");
- }
- //if (auto* MachO = dyn_cast(&Obj)) {
- // for (const object::SymbolRef Sym : MachO->symbols()) {
- // object::DataRefImpl Impl = Sym.getRawDataRefImpl();
- // if (auto SName = MachO->getSymbolName(Impl)) {
- // if (*SName != Name) {
- // continue;
- // }
- // if (auto ItSec = MachO->getSymbolSection(Impl)) {
- // uint64_t size = (*ItSec)->getSize();
- // }
- // //return
- // }
- // }
- // fatalError("jitAsm: Unable to find symbol '" + Name.str() + "'");
- //}
- fatalError("jitAsm: Unsupported file format");
-}
-
-std::unique_ptr Jitter::jitAsm(const std::string& Asm, size_t Size) {
- static constexpr const char FNAME[] = "__omvll_asm_func";
-
- static ExitOnError ExitOnErr;
-
- auto Context = std::make_unique();
- auto M = std::make_unique("__omvll_asm_jit", *Context);
-
- Function *F = Function::Create(llvm::FunctionType::get(llvm::Type::getVoidTy(*Context), {}, false),
- Function::ExternalLinkage, FNAME, M.get());
-
- llvm::BasicBlock *BB = llvm::BasicBlock::Create(*Context, "EntryBlock", F);
- IRBuilder<> builder(BB);
-
- auto* FType = llvm::FunctionType::get(builder.getVoidTy(), false);
- InlineAsm* rawAsm = InlineAsm::get(FType, Asm, "",
- /* hasSideEffects */ true,
- /* isStackAligned */ true
- );
-
- builder.CreateCall(FType, rawAsm);
- builder.CreateRetVoid();
-
-
- orc::LLJITBuilder Builder;
- std::string TT = Triple_;
- orc::JITTargetMachineBuilder JTMB{llvm::Triple(TT)};
- JTMB.setRelocationModel(Reloc::Model::PIC_);
- JTMB.setCodeModel(CodeModel::Large);
- JTMB.setCodeGenOptLevel(CodeGenOpt::Level::None);
-
- Builder
- .setPlatformSetUp(orc::setUpInactivePlatform) // /!\Only for iOS???
- .setJITTargetMachineBuilder(JTMB);
-
- Builder
- .setJITTargetMachineBuilder(std::move(JTMB));
-
- std::unique_ptr JITB = ExitOnErr(Builder.create());
-
- if (!JITB) {
- fatalError("JITB is null");
- }
-
- M->setDataLayout(JITB->getDataLayout());
-
- auto& IRC = JITB->getIRCompileLayer();
- orc::IRCompileLayer::IRCompiler& Compiler = IRC.getCompiler();
- if (auto Res = Compiler(*M)) {
- std::unique_ptr Buff = std::move(*Res);
- size_t FunSize = Size * /* Sizeof AArch64 inst=*/ 4;
-
- //if (auto E = object::ObjectFile::createObjectFile(*Buff)) {
- // std::unique_ptr Obj = std::move(E.get());
- // FunSize = getFunctionSize(*Obj, FNAME);
- //}
-
- if (FunSize == 0) {
- fatalError("Can't get the function size");
- }
-
- ExitOnErr(JITB->addObjectFile(std::move(Buff)));
-
- if (auto L = JITB->lookup(FNAME)) {
- auto *ptr = reinterpret_cast(L->getValue());
- return MemoryBuffer::getMemBufferCopy({ptr, FunSize});
- }
- }
- fatalError("Can't compile: " + Asm);
-}
-
-}
diff --git a/src/core/jitter.cpp b/src/core/jitter.cpp
new file mode 100644
index 00000000..dad7db17
--- /dev/null
+++ b/src/core/jitter.cpp
@@ -0,0 +1,152 @@
+//
+// This file is distributed under the Apache License v2.0. See LICENSE for
+// details.
+//
+
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/Orc/LLJIT.h"
+#include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InlineAsm.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IRReader/IRReader.h"
+#include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Passes/PassBuilder.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Transforms/Utils/Cloning.h"
+
+#include "omvll/jitter.hpp"
+#include "omvll/utils.hpp"
+
+using namespace llvm;
+
+static constexpr auto AsmFunctionName = "__omvll_asm_func";
+
+namespace llvm {
+namespace object {
+class MachOObjectFile;
+} // end namespace object
+} // end namespace llvm
+
+namespace omvll {
+
+Jitter::Jitter(const std::string &Triple)
+ : Triple{Triple}, Ctx{new LLVMContext{}} {
+ InitializeNativeTarget();
+ InitializeNativeTargetAsmParser();
+ InitializeNativeTargetAsmPrinter();
+}
+
+std::unique_ptr Jitter::compile(Module &M) {
+ static ExitOnError ExitOnErr;
+ auto JITB = ExitOnErr(orc::LLJITBuilder().create());
+ std::unique_ptr ClonedM = CloneModule(M);
+ auto Context = std::make_unique();
+
+ ExitOnErr(JITB->addIRModule(
+ orc::ThreadSafeModule(std::move(ClonedM), std::move(Context))));
+ return JITB;
+}
+
+size_t Jitter::getFunctionSize(object::ObjectFile &Obj, StringRef Name) {
+ if (auto *ELF = dyn_cast(&Obj)) {
+ for (const object::ELFSymbolRef &Sym : ELF->symbols()) {
+ if (Sym.getELFType() != ELF::STT_FUNC)
+ continue;
+ if (auto Str = Sym.getName())
+ if (*Str == Name)
+ return Sym.getSize();
+ }
+ fatalError("jitAsm: Unable to find symbol " + Name.str());
+ }
+
+#if 0
+ if (auto *MachO = dyn_cast(&Obj)) {
+ for (const object::SymbolRef Sym : MachO->symbols()) {
+ object::DataRefImpl Impl = Sym.getRawDataRefImpl();
+ if (auto SName = MachO->getSymbolName(Impl)) {
+ if (*SName != Name)
+ continue;
+ }
+ if (auto ItSec = MachO->getSymbolSection(Impl)) {
+ uint64_t Size = (*ItSec)->getSize();
+ return Size;
+ }
+ }
+ fatalError("jitAsm: Unable to find symbol '" + Name.str() + "'");
+ }
+#endif
+
+ fatalError("jitAsm: Unsupported file format");
+}
+
+std::unique_ptr Jitter::jitAsm(const std::string &Asm,
+ size_t Size) {
+ static ExitOnError ExitOnErr;
+
+ auto Context = std::make_unique();
+ auto M = std::make_unique("__omvll_asm_jit", *Context);
+
+ Function *F =
+ Function::Create(FunctionType::get(Type::getVoidTy(*Context), {}, false),
+ Function::ExternalLinkage, AsmFunctionName, M.get());
+
+ BasicBlock *BB = BasicBlock::Create(*Context, "EntryBlock", F);
+ IRBuilder<> IRB(BB);
+
+ auto *FType = FunctionType::get(IRB.getVoidTy(), false);
+ InlineAsm *RawAsm = InlineAsm::get(FType, Asm, "", /* hasSideEffects */ true,
+ /* isStackAligned */ true);
+ IRB.CreateCall(FType, RawAsm);
+ IRB.CreateRetVoid();
+
+ orc::LLJITBuilder Builder;
+ std::string TT = Triple;
+ orc::JITTargetMachineBuilder JTMB{llvm::Triple(TT)};
+ JTMB.setRelocationModel(Reloc::Model::PIC_);
+ JTMB.setCodeModel(CodeModel::Large);
+ JTMB.setCodeGenOptLevel(CodeGenOpt::Level::None);
+
+ Builder.setPlatformSetUp(orc::setUpInactivePlatform)
+ .setJITTargetMachineBuilder(JTMB);
+ Builder.setJITTargetMachineBuilder(std::move(JTMB));
+
+ std::unique_ptr JITB = ExitOnErr(Builder.create());
+ if (!JITB)
+ fatalError("JITB is null");
+
+ M->setDataLayout(JITB->getDataLayout());
+
+ auto &IRC = JITB->getIRCompileLayer();
+ orc::IRCompileLayer::IRCompiler &Compiler = IRC.getCompiler();
+ if (auto Res = Compiler(*M)) {
+ std::unique_ptr Buff = std::move(*Res);
+ size_t FunSize = Size * /* Sizeof AArch64 inst=*/4;
+
+#if 0
+ if (auto E = object::ObjectFile::createObjectFile(*Buff)) {
+ std::unique_ptr Obj = std::move(E.get());
+ FunSize = getFunctionSize(*Obj, AsmFunctionName);
+ }
+#endif
+
+ if (FunSize == 0)
+ fatalError("Cannot retrieve function size");
+
+ ExitOnErr(JITB->addObjectFile(std::move(Buff)));
+ if (auto L = JITB->lookup(AsmFunctionName)) {
+ auto *Ptr = reinterpret_cast(L->getValue());
+ return MemoryBuffer::getMemBufferCopy({Ptr, FunSize});
+ }
+ }
+
+ fatalError("Cannot compile " + Asm);
+}
+
+} // end namespace omvll
diff --git a/src/core/log.cpp b/src/core/log.cpp
index b027b91f..43b8fe38 100644
--- a/src/core/log.cpp
+++ b/src/core/log.cpp
@@ -1,61 +1,74 @@
-#include "omvll/log.hpp"
+//
+// This file is distributed under the Apache License v2.0. See LICENSE for
+// details.
+//
#include "spdlog/spdlog.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/android_sink.h"
-Logger::Logger(Logger&&) = default;
-Logger& Logger::operator=(Logger&&) = default;
+#include "omvll/log.hpp"
+
+static constexpr auto EnvLogName = "OMVLL_TRUNCATE_LOG";
+static constexpr auto LogFileName = "omvll.log";
+static constexpr auto LogName = "omvll";
+
+Logger::Logger(Logger &&) = default;
+Logger &Logger::operator=(Logger &&) = default;
Logger::~Logger() = default;
Logger::Logger() {
- bool truncate = false;
- if (getenv("OMVLL_TRUNCATE_LOG"))
- truncate = true;
-
- sink_ = spdlog::basic_logger_mt("omvll", "omvll.log", truncate);
- //sink_ = spdlog::stdout_color_mt("omvll");
- sink_->set_pattern("%v");
- sink_->set_level(spdlog::level::debug);
- sink_->flush_on(spdlog::level::debug);
+ bool Truncate = false;
+ if (getenv(EnvLogName))
+ Truncate = true;
+
+ Sink = spdlog::basic_logger_mt(LogName, LogFileName, Truncate);
+ Sink->set_pattern("%v");
+ Sink->set_level(spdlog::level::debug);
+ Sink->flush_on(spdlog::level::debug);
}
-Logger& Logger::instance() {
- if (instance_ == nullptr) {
- instance_ = new Logger{};
+Logger &Logger::instance() {
+ if (!Instance) {
+ Instance = new Logger{};
std::atexit(destroy);
}
- return *instance_;
+ return *Instance;
}
-
-void Logger::destroy() {
- delete instance_;
-}
+void Logger::destroy() { delete Instance; }
void Logger::disable() {
- Logger::instance().sink_->set_level(spdlog::level::off);
+ Logger::instance().Sink->set_level(spdlog::level::off);
}
void Logger::enable() {
- Logger::instance().sink_->set_level(spdlog::level::warn);
+ Logger::instance().Sink->set_level(spdlog::level::warn);
}
-void Logger::set_level(spdlog::level::level_enum lvl) {
- Logger& instance = Logger::instance();
- instance.sink_->set_level(lvl);
- instance.sink_->flush_on(lvl);
+void Logger::set_level(spdlog::level::level_enum Level) {
+ Logger &Instance = Logger::instance();
+ Instance.Sink->set_level(Level);
+ Instance.Sink->flush_on(Level);
}
-void Logger::set_level(LOG_LEVEL lvl) {
- switch (lvl) {
- case LOG_LEVEL::DEBUG: Logger::set_level(spdlog::level::debug); return;
- case LOG_LEVEL::TRACE: Logger::set_level(spdlog::level::trace); return;
- case LOG_LEVEL::INFO: Logger::set_level(spdlog::level::info); return;
- case LOG_LEVEL::WARN: Logger::set_level(spdlog::level::warn); return;
- case LOG_LEVEL::ERR: Logger::set_level(spdlog::level::err); return;
+void Logger::set_level(LogLevel Level) {
+ switch (Level) {
+ case LogLevel::Debug:
+ Logger::set_level(spdlog::level::debug);
+ return;
+ case LogLevel::Trace:
+ Logger::set_level(spdlog::level::trace);
+ return;
+ case LogLevel::Info:
+ Logger::set_level(spdlog::level::info);
+ return;
+ case LogLevel::Warn:
+ Logger::set_level(spdlog::level::warn);
+ return;
+ case LogLevel::Err:
+ Logger::set_level(spdlog::level::err);
+ return;
}
}
-
-
diff --git a/src/core/omvll_config.cpp b/src/core/omvll_config.cpp
index 763db84c..894be4db 100644
--- a/src/core/omvll_config.cpp
+++ b/src/core/omvll_config.cpp
@@ -1,28 +1,34 @@
+//
+// This file is distributed under the Apache License v2.0. See LICENSE for
+// details.
+//
+
#include "omvll/omvll_config.hpp"
#include "omvll/passes.hpp"
namespace omvll {
-config_t config;
-void init_default_config() {
- config.passes = {
- AntiHook::name().str(),
- StringEncoding::name().str(),
- OpaqueFieldAccess::name().str(),
- ControlFlowFlattening::name().str(),
- BreakControlFlow::name().str(),
+OMVLLConfig Config;
+
+void initDefaultConfig() {
+ Config.Passes = {
+ AntiHook::name().str(),
+ StringEncoding::name().str(),
+
+ OpaqueFieldAccess::name().str(),
+ ControlFlowFlattening::name().str(),
+ BreakControlFlow::name().str(),
- OpaqueConstants::name().str(),
- Arithmetic::name().str(),
+ OpaqueConstants::name().str(),
+ Arithmetic::name().str(),
- // Last pass
- Cleaning::name().str(),
+ // Last pass.
+ Cleaning::name().str(),
};
- config.cleaning = true;
- config.inline_jni_wrappers = true;
- config.shuffle_functions = true;
+ Config.Cleaning = true;
+ Config.InlineJniWrappers = true;
+ Config.ShuffleFunctions = true;
}
-}
-
+} // end namespace omvll
diff --git a/src/core/plugin.cpp b/src/core/plugin.cpp
index f004f1c9..b62f61e8 100644
--- a/src/core/plugin.cpp
+++ b/src/core/plugin.cpp
@@ -1,157 +1,145 @@
-#include "omvll/passes.hpp"
+//
+// This file is distributed under the Apache License v2.0. See LICENSE for
+// details.
+//
+
+#include
+
+#include "llvm/Passes/PassBuilder.h"
+#include "llvm/Passes/PassPlugin.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/YAMLParser.h"
+#include "llvm/Support/YAMLTraits.h"
+
#include "omvll/PyConfig.hpp"
+#include "omvll/jitter.hpp"
#include "omvll/log.hpp"
+#include "omvll/passes.hpp"
#include "omvll/utils.hpp"
-#include "omvll/Jitter.hpp"
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
using namespace llvm;
-#define REGISTER_PASS(X) \
- do { \
- if (pass == X::name()) { \
- SDEBUG("Registering {}", pass); \
- MPM.addPass(X()); \
- continue; \
- } \
- } while (0)
-
-template <>
-struct yaml::MappingTraits {
- static void mapping(IO& io, omvll::yaml_config_t& config) {
- io.mapOptional("OMVLL_PYTHONPATH", config.PYTHONPATH, "");
- io.mapOptional("OMVLL_CONFIG", config.OMVLL_CONFIG, "");
- }
+template <> struct yaml::MappingTraits {
+ static void mapping(IO &IO, omvll::YamlConfig &Config) {
+ IO.mapOptional("OMVLL_PYTHONPATH", Config.PythonPath, "");
+ IO.mapOptional("OMVLL_CONFIG", Config.OMVLLConfig, "");
+ }
};
-std::string expand_abs_path(StringRef path, StringRef base) {
- if (sys::path::is_absolute(path)) {
- if (!sys::fs::exists(path))
- SWARN("Absolute path from doesn't exist!");
- return path.str();
+static std::string expandAbsPath(StringRef Path, StringRef Base) {
+ if (sys::path::is_absolute(Path)) {
+ if (!sys::fs::exists(Path))
+ SWARN("Absolute path from does not exist");
+ return Path.str();
}
- SmallString<256> YConfigAbs = base;
- sys::path::append(YConfigAbs, path);
+ SmallString<256> YConfigAbs = Base;
+ sys::path::append(YConfigAbs, Path);
if (!sys::fs::exists(YConfigAbs))
- SWARN("Relative path doesn't exist!");
+ SWARN("Relative path does not exist");
+
return YConfigAbs.str().str();
}
-bool load_yamlconfig(StringRef dir, StringRef filename) {
- SmallString<256> YConfig = dir;
- sys::path::append(YConfig, filename);
+static bool loadYamlConfig(StringRef Dir, StringRef FileName) {
+ SmallString<256> YConfig = Dir;
+ sys::path::append(YConfig, FileName);
if (!sys::fs::exists(YConfig))
return false;
SINFO("Loading omvll.yml from {}", YConfig.str());
auto Buffer = MemoryBuffer::getFile(YConfig);
if (!Buffer) {
- SERR("Can't read '{}': {}", YConfig.str(), Buffer.getError().message());
+ SERR("Cannot read '{}': {}", YConfig.str(), Buffer.getError().message());
return false;
}
- yaml::Input yin(**Buffer);
- omvll::yaml_config_t yconfig;
- yin >> yconfig;
- SINFO("OMVLL_PYTHONPATH = {}", yconfig.PYTHONPATH);
- yconfig.PYTHONPATH = expand_abs_path(yconfig.PYTHONPATH, dir);
+ yaml::Input Input(**Buffer);
+ omvll::YamlConfig Config;
+ Input >> Config;
+
+ SINFO("OMVLL_PYTHONPATH = {}", Config.PythonPath);
+ Config.PythonPath = expandAbsPath(Config.PythonPath, Dir);
- SINFO("OMVLL_CONFIG = {}", yconfig.OMVLL_CONFIG);
- yconfig.OMVLL_CONFIG = expand_abs_path(yconfig.OMVLL_CONFIG, dir);
+ SINFO("OMVLL_CONFIG = {}", Config.OMVLLConfig);
+ Config.OMVLLConfig = expandAbsPath(Config.OMVLLConfig, Dir);
- omvll::PyConfig::yconfig = yconfig;
+ omvll::PyConfig::YConfig = Config;
return true;
}
-bool find_yamlconfig(std::string dir) {
+static bool findYamlConfig(std::string Dir) {
while (true) {
- SINFO("Looking for omvll.yml in {}", dir);
- if (load_yamlconfig(dir, omvll::PyConfig::YAML_FILE))
+ SINFO("Looking for omvll.yml in {}", Dir);
+ if (loadYamlConfig(Dir, omvll::PyConfig::YamlFile))
return true;
- if (sys::path::has_parent_path(dir)) {
- dir = sys::path::parent_path(dir);
+ if (sys::path::has_parent_path(Dir)) {
+ Dir = sys::path::parent_path(Dir);
} else {
return false;
}
}
}
-void omvll::init_yamlconfig() {
- SmallString<256> cwd;
- if (auto err = sys::fs::current_path(cwd)) {
- SERR("Can't determine the current path: '{}''", err.message());
+void omvll::initYamlConfig() {
+ SmallString<256> CurrentPath;
+ if (auto Err = sys::fs::current_path(CurrentPath)) {
+ SERR("Cannot determine the current path: '{}'", Err.message());
} else {
- if (find_yamlconfig(cwd.str().str()))
+ if (findYamlConfig(CurrentPath.str().str()))
return;
}
- Dl_info info;
- if (!dladdr((void*)find_yamlconfig, &info)) {
- SERR("Can't determine plugin file path");
+ Dl_info Info;
+ if (!dladdr((void *)findYamlConfig, &Info)) {
+ SERR("Cannot determine plugin file path");
} else {
- SmallString<256> PluginDir = StringRef(info.dli_fname);
+ SmallString<256> PluginDir = StringRef(Info.dli_fname);
sys::path::remove_filename(PluginDir);
- if (find_yamlconfig(PluginDir.str().str()))
+ if (findYamlConfig(PluginDir.str().str()))
return;
}
- SINFO("Didn't find omvll.yml");
+ SINFO("Could not find omvll.yml");
}
-
PassPluginLibraryInfo getOMVLLPluginInfo() {
- static std::atomic ONCE_FLAG = false;
+ static std::atomic Once = false;
Logger::set_level(spdlog::level::level_enum::debug);
- omvll::init_yamlconfig();
- omvll::init_pythonpath();
- return {LLVM_PLUGIN_API_VERSION, "OMVLL", "0.0.1",
- [](PassBuilder &PB) {
+ omvll::initYamlConfig();
+ omvll::initPythonpath();
+ return {LLVM_PLUGIN_API_VERSION, "OMVLL", "1.1.0", [](PassBuilder &PB) {
try {
- auto& instance = omvll::PyConfig::instance();
- SDEBUG("OMVLL Path: {}", instance.config_path());
+ auto &Instance = omvll::PyConfig::instance();
+ SDEBUG("Found OMVLL at: {}", Instance.configPath());
PB.registerPipelineEarlySimplificationEPCallback(
- [&] (ModulePassManager &MPM, OptimizationLevel opt) {
- if (ONCE_FLAG) {
- return true;
- }
- for (const std::string& pass : instance.get_passes()) {
- REGISTER_PASS(omvll::AntiHook);
- REGISTER_PASS(omvll::StringEncoding);
-
- REGISTER_PASS(omvll::OpaqueFieldAccess);
- REGISTER_PASS(omvll::ControlFlowFlattening);
- REGISTER_PASS(omvll::BreakControlFlow);
-
- REGISTER_PASS(omvll::OpaqueConstants);
- REGISTER_PASS(omvll::Arithmetic);
-
+ [&](ModulePassManager &MPM, OptimizationLevel Opt) {
+ if (Once)
+ return true;
+
+ MPM.addPass(omvll::AntiHook());
+ MPM.addPass(omvll::StringEncoding());
+ MPM.addPass(omvll::OpaqueFieldAccess());
+ MPM.addPass(omvll::ControlFlowFlattening());
+ MPM.addPass(omvll::BreakControlFlow());
+ MPM.addPass(omvll::OpaqueConstants());
+ MPM.addPass(omvll::Arithmetic());
#ifdef OMVLL_EXPERIMENTAL
- /* ObjCleaner must be the last pass as function's name could be
- * changed, which can be confusing of the user
- */
- REGISTER_PASS(omvll::ObjCleaner);
+ // ObjCleaner must be the last pass as function's name could
+ // be changed, which can be confusing for the user.
+ MPM.addPass(omvll::ObjCleaner());
#endif
- REGISTER_PASS(omvll::Cleaning);
- }
- ONCE_FLAG = true;
- return true;
- }
- );
- } catch (const std::exception& e) {
- omvll::fatalError(e.what());
+ MPM.addPass(omvll::Cleaning());
+
+ Once = true;
+ return true;
+ });
+ } catch (const std::exception &Exc) {
+ omvll::fatalError(Exc.what());
}
}};
}
@@ -161,5 +149,3 @@ extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo
llvmGetPassPluginInfo() {
return getOMVLLPluginInfo();
}
-
-
diff --git a/src/core/python/PyConfig.cpp b/src/core/python/PyConfig.cpp
index 74ff4c22..05b30823 100644
--- a/src/core/python/PyConfig.cpp
+++ b/src/core/python/PyConfig.cpp
@@ -1,73 +1,76 @@
-#include "omvll/PyConfig.hpp"
-#include "omvll/passes.hpp"
-#include "omvll/utils.hpp"
-#include "omvll/log.hpp"
-#include "omvll/versioning.hpp"
-#include "omvll/omvll_config.hpp"
+//
+// This file is distributed under the Apache License v2.0. See LICENSE for
+// details.
+//
-#include "PyObfuscationConfig.hpp"
-#include "init.hpp"
+#include
+#include
#include
#include
-#include
-#include
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Module.h"
-#include
-#include
-#include
+#include "omvll/PyConfig.hpp"
+#include "omvll/omvll_config.hpp"
+#include "omvll/utils.hpp"
+#include "omvll/versioning.hpp"
+
+#include "PyObfuscationConfig.hpp"
+#include "init.hpp"
namespace py = pybind11;
-namespace omvll {
+using namespace pybind11::literals;
+namespace omvll {
-void init_pythonpath() {
- if (char* config = getenv(PyConfig::PYENV_KEY)) {
- Py_SetPath(Py_DecodeLocale(config, nullptr));
- setenv("PYTHONHOME", config, true);
+void initPythonpath() {
+ if (char *Config = getenv(PyConfig::PyEnv_Key)) {
+ Py_SetPath(Py_DecodeLocale(Config, nullptr));
+ setenv("PYTHONHOME", Config, true);
return;
}
- if (!PyConfig::yconfig.PYTHONPATH.empty()) {
- Py_SetPath(Py_DecodeLocale(PyConfig::yconfig.PYTHONPATH.c_str(), nullptr));
- setenv("PYTHONHOME", PyConfig::yconfig.PYTHONPATH.c_str(), true);
+ if (!PyConfig::YConfig.PythonPath.empty()) {
+ Py_SetPath(Py_DecodeLocale(PyConfig::YConfig.PythonPath.c_str(), nullptr));
+ setenv("PYTHONHOME", PyConfig::YConfig.PythonPath.c_str(), true);
return;
}
- #if defined(__linux__)
- if (auto* hdl = dlopen("libpython3.10.so", RTLD_LAZY)) {
- char PATH[400];
- int ret = dlinfo(hdl, RTLD_DI_ORIGIN, PATH);
- if (ret != 0) {
- return;
- }
- std::string PythonPath = PATH;
- PythonPath.append("/python3.10");
- Py_SetPath(Py_DecodeLocale(PythonPath.c_str(), nullptr));
- setenv("PYTHONHOME", PythonPath.c_str(), true);
+
+#if defined(__linux__)
+ if (auto *Hdl = dlopen("libpython3.10.so", RTLD_LAZY)) {
+ char Path[400];
+ int Ret = dlinfo(Hdl, RTLD_DI_ORIGIN, Path);
+ if (Ret != 0)
return;
- }
- #endif
+
+ std::string PythonPath = Path;
+ PythonPath.append("/python3.10");
+ Py_SetPath(Py_DecodeLocale(PythonPath.c_str(), nullptr));
+ setenv("PYTHONHOME", PythonPath.c_str(), true);
+ return;
+ }
+#endif
}
-void omvll_ctor(py::module_& m) {
- init_default_config();
+void OMVLLCtor(py::module_ &m) {
+ initDefaultConfig();
m.attr("LLVM_VERSION") = OMVLL_LLVM_VERSION_STRING;
m.attr("OMVLL_VERSION") = OMVLL_VERSION;
m.attr("OMVLL_VERSION_FULL") = "OMVLL Version: " OMVLL_VERSION " / " OMVLL_LLVM_VERSION_STRING
" (" OMVLL_LLVM_VERSION ")";
- py::class_(m, "config_t",
- R"delim(
+ py::class_(m, "OMVLLConfig",
+ R"delim(
This class is used to configure the global behavior of O-MVLL.
It can be accessed through the global :attr:`omvll.config` attribute
)delim")
- .def_readwrite("passes",
- &config_t::passes,
- R"delim(
+ .def_readwrite("passes", &OMVLLConfig::Passes,
+ R"delim(
This **ordered** list contains the sequence of the obfuscation passes
that must be used.
It should not be modified unless you know what you do.
@@ -78,9 +81,8 @@ void omvll_ctor(py::module_& m) {
)delim")
- .def_readwrite("inline_jni_wrappers",
- &config_t::inline_jni_wrappers,
- R"delim(
+ .def_readwrite("inline_jni_wrappers", &OMVLLConfig::InlineJniWrappers,
+ R"delim(
This boolean attribute is used to force inlining JNI C++ wrapper.
For instance ``GetStringChars``:
@@ -92,9 +94,8 @@ void omvll_ctor(py::module_& m) {
The default value is ``True``.
)delim")
- .def_readwrite("shuffle_functions",
- &config_t::shuffle_functions,
- R"delim(
+ .def_readwrite("shuffle_functions", &OMVLLConfig::ShuffleFunctions,
+ R"delim(
Whether the postition of Module's functions should be shuffled.
This randomization is used to avoid the same (relative) position of the functions
@@ -119,22 +120,21 @@ void omvll_ctor(py::module_& m) {
If this value is set to ``True`` (which is the default value), the sequence is randomized.
)delim");
- m.attr("config") = &config;
+ m.attr("config") = &Config;
py_init_obf_opt(m);
py_init_llvm_bindings(m);
py_init_log(m);
py::class_(m, "ObfuscationConfig",
- R"delim(
+ R"delim(
This class must be inherited by the user to define where and how the obfuscation
passes must be enabled.
)delim")
- .def(py::init<>())
+ .def(py::init<>())
- .def("obfuscate_string",
- &ObfuscationConfig::obfuscate_string,
- R"delim(
+ .def("obfuscate_string", &ObfuscationConfig::obfuscateString,
+ R"delim(
The default user-callback used to configure strings obfuscation.
In addition to the associated class options, O-MVLL interprets these return values as follows:
@@ -154,11 +154,11 @@ void omvll_ctor(py::module_& m) {
+--------------+-------------------------------------+
See the :omvll:`strings-encoding` documentation.
- )delim", "module"_a, "function"_a, "string"_a)
+ )delim",
+ "module"_a, "function"_a, "string"_a)
- .def("break_control_flow",
- &ObfuscationConfig::break_control_flow,
- R"delim(
+ .def("break_control_flow", &ObfuscationConfig::breakControlFlow,
+ R"delim(
The default user-callback for the pass that breaks
the control flow.
@@ -175,11 +175,11 @@ void omvll_ctor(py::module_& m) {
+--------------+-------------------------------------------------+
See the :omvll:`control-flow-breaking` documentation.
- )delim", "module"_a, "function"_a)
+ )delim",
+ "module"_a, "function"_a)
- .def("flatten_cfg",
- &ObfuscationConfig::flatten_cfg,
- R"delim(
+ .def("flatten_cfg", &ObfuscationConfig::controlFlowGraphFlattening,
+ R"delim(
The default user-callback used to configure the
control-flow flattening pass.
@@ -196,11 +196,11 @@ void omvll_ctor(py::module_& m) {
+--------------+------------------------------------------------------+
See the :omvll:`control-flow-flattening` documentation.
- )delim", "module"_a, "function"_a)
+ )delim",
+ "module"_a, "function"_a)
- .def("obfuscate_struct_access",
- &ObfuscationConfig::obfuscate_struct_access,
- R"delim(
+ .def("obfuscate_struct_access", &ObfuscationConfig::obfuscateStructAccess,
+ R"delim(
The default user-callback when obfuscating structures accesses.
In addition to the associated class options, O-MVLL interprets these return values as follows:
@@ -216,11 +216,12 @@ void omvll_ctor(py::module_& m) {
+--------------+---------------------------------------------+
See the :omvll:`opaque-fields-access` documentation.
- )delim", "module"_a, "function"_a, "struct"_a)
+ )delim",
+ "module"_a, "function"_a, "struct"_a)
- .def("obfuscate_variable_access",
- &ObfuscationConfig::obfuscate_variable_access,
- R"delim(
+ .def("obfuscate_variable_access",
+ &ObfuscationConfig::obfuscateVariableAccess,
+ R"delim(
The default user-callback when obfuscating global variables access.
In addition to the associated class options, O-MVLL interprets these return values as follows:
@@ -236,11 +237,11 @@ void omvll_ctor(py::module_& m) {
+--------------+------------------------------------------+
See the :omvll:`opaque-fields-access` documentation.
- )delim", "module"_a, "function"_a, "variable"_a)
+ )delim",
+ "module"_a, "function"_a, "variable"_a)
- .def("obfuscate_constants",
- &ObfuscationConfig::obfuscate_constants,
- R"delim(
+ .def("obfuscate_constants", &ObfuscationConfig::obfuscateConstants,
+ R"delim(
The default user-callback to obfuscate constants.
In addition to the associated class options, O-MVLL interprets these return values as follows:
@@ -258,11 +259,11 @@ void omvll_ctor(py::module_& m) {
+-------------------+--------------------------------------------------------+
See the :omvll:`opaque-constants` documentation.
- )delim", "module"_a, "function"_a)
+ )delim",
+ "module"_a, "function"_a)
- .def("obfuscate_arithmetic",
- &ObfuscationConfig::obfuscate_arithmetic,
- R"delim(
+ .def("obfuscate_arithmetic", &ObfuscationConfig::obfuscateArithmetics,
+ R"delim(
The default user-callback when obfuscating arithmetic operations.
In addition to the associated class options, O-MVLL interprets these return values as follows:
@@ -278,11 +279,11 @@ void omvll_ctor(py::module_& m) {
+--------------+-------------------------------------------+
See the :omvll:`arithmetic` documentation.
- )delim", "module"_a, "function"_a)
+ )delim",
+ "module"_a, "function"_a)
- .def("anti_hooking",
- &ObfuscationConfig::anti_hooking,
- R"delim(
+ .def("anti_hooking", &ObfuscationConfig::antiHooking,
+ R"delim(
The default user-callback to enable hooking protection.
In addition to the associated class options, O-MVLL interprets these return values as follows:
@@ -298,101 +299,91 @@ void omvll_ctor(py::module_& m) {
+--------------+-----------------------------------------+
See the :omvll:`anti-hook` documentation.
- )delim", "module"_a, "function"_a)
+ )delim",
+ "module"_a, "function"_a)
- .def("report_diff",
- &ObfuscationConfig::report_diff,
- R"delim(
+ .def("report_diff", &ObfuscationConfig::reportDiff,
+ R"delim(
User-callback to monitor IR-level changes from individual obfuscation passes.
- )delim", "pass_name"_a, "original"_a, "obfuscated"_a);
-
+ )delim",
+ "pass_name"_a, "original"_a, "obfuscated"_a);
}
-std::unique_ptr init_omvll_core(py::dict modules) {
- auto m = std::make_unique(py::module_::create_extension_module("omvll", "", new PyModuleDef()));
- omvll_ctor(*m);
- modules["omvll"] = *m;
- return m;
+std::unique_ptr initOMVLLCore(py::dict Modules) {
+ auto M = std::make_unique(
+ py::module_::create_extension_module("omvll", "", new PyModuleDef()));
+ OMVLLCtor(*M);
+ Modules["omvll"] = *M;
+ return M;
}
-
PyConfig::~PyConfig() = default;
-PyConfig& PyConfig::instance() {
- if (instance_ == nullptr) {
- instance_ = new PyConfig{};
+PyConfig &PyConfig::instance() {
+ if (!Instance) {
+ Instance = new PyConfig{};
std::atexit(destroy);
}
- return *instance_;
+ return *Instance;
}
-ObfuscationConfig* PyConfig::getUserConfig() {
+ObfuscationConfig *PyConfig::getUserConfig() {
try {
llvm::LLVMContext Ctx;
- if (!py::hasattr(*mod_, "omvll_get_config")) {
+ if (!py::hasattr(*Mod, "omvll_get_config"))
fatalError("Missing omvll_get_config");
- }
- auto py_user_config = mod_->attr("omvll_get_config");
- if (py_user_config.is_none()) {
- fatalError("Missing omvll_get_config");
- }
- py::object result = py_user_config();
- auto* conf = result.cast();
- return conf;
- } catch (const std::exception& e) {
- fatalError(e.what());
- }
-}
+ auto PyUserConfig = Mod->attr("omvll_get_config");
+ if (PyUserConfig.is_none())
+ fatalError("Missing omvll_get_config");
-const std::vector& PyConfig::get_passes() {
- return config.passes;
+ py::object Result = PyUserConfig();
+ return Result.cast();
+ } catch (const std::exception &Exc) {
+ fatalError(Exc.what());
+ }
}
PyConfig::PyConfig() {
py::initialize_interpreter();
- py::module_ sys_mod = py::module_::import("sys");
- py::module_ pathlib = py::module_::import("pathlib");
-
- py::dict modules = sys_mod.attr("modules");
- core_mod_ = init_omvll_core(modules);
-
- llvm::StringRef configpath;
-
- if (char* config = getenv(ENV_KEY)) {
- configpath = config;
- } else if (!PyConfig::yconfig.OMVLL_CONFIG.empty()) {
- configpath = PyConfig::yconfig.OMVLL_CONFIG;
- }
- std::string modname = DEFAULT_FILE_NAME;
- if (!configpath.empty()) {
- std::string config = configpath.str();
-
- auto pypath = pathlib.attr("Path")(config);
- py::list path = sys_mod.attr("path");
- path.insert(0, pypath.attr("parent").attr("as_posix")());
- std::string name = pypath.attr("stem").cast();
- modname = name;
+ py::module_ SysMod = py::module_::import("sys");
+ py::module_ PathLib = py::module_::import("pathlib");
+ py::dict Modules = SysMod.attr("modules");
+
+ CoreMod = initOMVLLCore(Modules);
+
+ llvm::StringRef ConfigPath;
+ if (char *Config = getenv(EnvKey))
+ ConfigPath = Config;
+ else if (!PyConfig::YConfig.OMVLLConfig.empty())
+ ConfigPath = PyConfig::YConfig.OMVLLConfig;
+
+ std::string ModName = DefaultFileName;
+ if (!ConfigPath.empty()) {
+ std::string Config = ConfigPath.str();
+ auto PyPath = PathLib.attr("Path")(Config);
+ py::list Path = SysMod.attr("path");
+ Path.insert(0, PyPath.attr("parent").attr("as_posix")());
+ std::string Name = PyPath.attr("stem").cast();
+ ModName = Name;
}
try {
- mod_ = std::make_unique(py::module_::import(modname.c_str()));
- } catch (const std::exception& e) {
- fatalError(e.what());
+ Mod = std::make_unique(py::module_::import(ModName.c_str()));
+ } catch (const std::exception &Exc) {
+ fatalError(Exc.what());
}
}
-std::string PyConfig::config_path() {
- return mod_->attr("__file__").cast();
+std::string PyConfig::configPath() {
+ return Mod->attr("__file__").cast();
}
void PyConfig::destroy() {
- delete instance_;
+ delete Instance;
py::finalize_interpreter();
}
-}
+} // end namespace omvll
-PYBIND11_MODULE(omvll, m) {
- omvll::omvll_ctor(m);
-}
+PYBIND11_MODULE(omvll, m) { omvll::OMVLLCtor(m); }
diff --git a/src/core/python/PyObfuscationConfig.cpp b/src/core/python/PyObfuscationConfig.cpp
index 49998629..5be4377e 100644
--- a/src/core/python/PyObfuscationConfig.cpp
+++ b/src/core/python/PyObfuscationConfig.cpp
@@ -1,269 +1,295 @@
-#include "PyObfuscationConfig.hpp"
-#include "omvll/utils.hpp"
-#include "omvll/log.hpp"
-
-#include
+//
+// This file is distributed under the Apache License v2.0. See LICENSE for
+// details.
+//
#include
#include
#include
-#include
-#include
-#include
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Module.h"
+
+#include "omvll/utils.hpp"
+
+#include "PyObfuscationConfig.hpp"
namespace py = pybind11;
+namespace detail = py::detail;
+
using namespace std::string_literals;
namespace omvll {
-StringEncodingOpt PyObfuscationConfig::obfuscate_string(llvm::Module* mod, llvm::Function* func,
- const std::string& str)
-{
+StringEncodingOpt PyObfuscationConfig::obfuscateString(llvm::Module *M,
+ llvm::Function *F,
+ const std::string &Str) {
py::gil_scoped_acquire gil;
- py::function override = py::get_override(static_cast(this), "obfuscate_string");
+ const auto *Base = static_cast(this);
+ py::function override = py::get_override(Base, "obfuscate_string");
if (override) {
try {
- py::bytes bytes_str(str);
- py::object out = override(mod, func, bytes_str);
- if (out.is_none()) {
+ py::bytes bytes_str(Str);
+ py::object out = override(M, F, bytes_str);
+ if (out.is_none())
return StringEncOptSkip();
- }
+
if (py::isinstance(out)) {
- bool val = out.cast();
- if (!val) {
+ bool Value = out.cast();
+ if (!Value)
return StringEncOptSkip();
- } else {
+ else
return StringEncOptDefault();
- }
}
if (py::isinstance(out)) {
- auto val = out.cast();
- return StringEncOptReplace(std::move(val));
+ auto Value = out.cast();
+ return StringEncOptReplace(std::move(Value));
}
if (py::isinstance(out)) {
- auto val = out.cast();
- return StringEncOptReplace(std::move(val));
+ auto Value = out.cast();
+ return StringEncOptReplace(std::move(Value));
}
- if (py::detail::cast_is_temporary_value_reference::value) {
- static pybind11::detail::override_caster_t caster;
- return pybind11::detail::cast_ref(std::move(out), caster);
+ bool is_temp =
+ detail::cast_is_temporary_value_reference::value;
+ if (is_temp) {
+ static detail::override_caster_t caster;
+ return detail::cast_ref(std::move(out), caster);
}
- return pybind11::detail::cast_safe(std::move(out));
- } catch (const std::exception& e) {
- fatalError("Error in 'obfuscate_string': '"s + e.what() + "'");
+
+ return detail::cast_safe(std::move(out));
+ } catch (const std::exception &Exc) {
+ fatalError("Error in obfuscate_string: '"s + Exc.what() + "'");
}
}
-
return StringEncOptSkip();
}
-BreakControlFlowOpt PyObfuscationConfig::break_control_flow(llvm::Module* mod, llvm::Function* func) {
+BreakControlFlowOpt PyObfuscationConfig::breakControlFlow(llvm::Module *M,
+ llvm::Function *F) {
py::gil_scoped_acquire gil;
- py::function override = py::get_override(static_cast(this), "break_control_flow");
+ const auto *Base = static_cast(this);
+ py::function override = py::get_override(Base, "break_control_flow");
if (override) {
try {
- py::object out = override(mod, func);
- if (out.is_none()) {
+ py::object out = override(M, F);
+ if (out.is_none())
return false;
- }
+
if (py::isinstance(out)) {
- bool val = out.cast();
- return val;
+ bool Value = out.cast();
+ return Value;
}
- if (py::detail::cast_is_temporary_value_reference::value) {
- static pybind11::detail::override_caster_t caster;
- return pybind11::detail::cast_ref(std::move(out), caster);
+
+ bool is_temp =
+ detail::cast_is_temporary_value_reference::value;
+ if (is_temp) {
+ static detail::override_caster_t caster;
+ return detail::cast_ref(std::move(out), caster);
}
- return pybind11::detail::cast_safe(std::move(out));
- } catch (const std::exception& e) {
- fatalError("Error in 'break_control_flow': '"s + e.what() + "'");
+
+ return detail::cast_safe(std::move(out));
+ } catch (const std::exception &Exc) {
+ fatalError("Error in break_control_flow: '"s + Exc.what() + "'");
}
}
return false;
}
-ControlFlowFlatteningOpt PyObfuscationConfig::flatten_cfg(llvm::Module* mod, llvm::Function* func) {
+ControlFlowFlatteningOpt
+PyObfuscationConfig::controlFlowGraphFlattening(llvm::Module *M,
+ llvm::Function *F) {
py::gil_scoped_acquire gil;
- py::function override = py::get_override(static_cast(this), "flatten_cfg");
+ const auto *Base = static_cast(this);
+ py::function override = py::get_override(Base, "flatten_cfg");
if (override) {
try {
- py::object out = override(mod, func);
- if (out.is_none()) {
+ py::object out = override(M, F);
+ if (out.is_none())
return false;
- }
+
if (py::isinstance(out)) {
- bool val = out.cast();
- return val;
+ bool Value = out.cast();
+ return Value;
}
- if (py::detail::cast_is_temporary_value_reference::value) {
- static pybind11::detail::override_caster_t caster;
- return pybind11::detail::cast_ref(std::move(out), caster);
+
+ bool is_temp = detail::cast_is_temporary_value_reference<
+ ControlFlowFlatteningOpt>::value;
+ if (is_temp) {
+ static detail::override_caster_t caster;
+ return detail::cast_ref(std::move(out),
+ caster);
}
- return pybind11::detail::cast_safe(std::move(out));
- } catch (const std::exception& e) {
- fatalError("Error in 'flatten_cfg': '"s + e.what() + "'");
+
+ return detail::cast_safe(std::move(out));
+ } catch (const std::exception &Exc) {
+ fatalError("Error in flatten_cfg: '"s + Exc.what() + "'");
}
}
return false;
}
-StructAccessOpt PyObfuscationConfig::obfuscate_struct_access(llvm::Module* mod, llvm::Function* func,
- llvm::StructType* S)
-{
+StructAccessOpt
+PyObfuscationConfig::obfuscateStructAccess(llvm::Module *M, llvm::Function *F,
+ llvm::StructType *S) {
py::gil_scoped_acquire gil;
- py::function override = py::get_override(static_cast(this), "obfuscate_struct_access");
+ const auto *Base = static_cast(this);
+ py::function override = py::get_override(Base, "obfuscate_struct_access");
if (override) {
try {
- py::object out = override(mod, func, S);
-
- if (out.is_none()) {
+ py::object out = override(M, F, S);
+ if (out.is_none())
return false;
- }
if (py::isinstance(out)) {
- bool val = out.cast();
- return val;
+ bool Value = out.cast();
+ return Value;
}
- if (py::detail::cast_is_temporary_value_reference::value) {
- static pybind11::detail::override_caster_t caster;
- return pybind11::detail::cast_ref(std::move(out), caster);
+ bool is_temp =
+ detail::cast_is_temporary_value_reference::value;
+ if (is_temp) {
+ static detail::override_caster_t caster;
+ return detail::cast_ref(std::move(out), caster);
}
- return pybind11::detail::cast_safe(std::move(out));
- } catch (const std::exception& e) {
- fatalError("Error in 'obfuscate_struct_access': '"s + e.what() + "'");
+
+ return detail::cast_safe(std::move(out));
+ } catch (const std::exception &Exc) {
+ fatalError("Error in obfuscate_struct_access: '"s + Exc.what() + "'");
}
}
return false;
}
-VarAccessOpt PyObfuscationConfig::obfuscate_variable_access(llvm::Module* mod, llvm::Function* func,
- llvm::GlobalVariable* GV)
-{
+VarAccessOpt
+PyObfuscationConfig::obfuscateVariableAccess(llvm::Module *M, llvm::Function *F,
+ llvm::GlobalVariable *GV) {
py::gil_scoped_acquire gil;
- py::function override = py::get_override(static_cast(this), "obfuscate_variable_access");
+ const auto *Base = static_cast(this);
+ py::function override = py::get_override(Base, "obfuscate_variable_access");
if (override) {
try {
- py::object out = override(mod, func, GV);
-
- if (out.is_none()) {
+ py::object out = override(M, F, GV);
+ if (out.is_none())
return false;
- }
if (py::isinstance(out)) {
bool val = out.cast();
return val;
}
- if (py::detail::cast_is_temporary_value_reference::value) {
- static pybind11::detail::override_caster_t caster;
- return pybind11::detail::cast_ref(std::move(out), caster);
+ if (detail::cast_is_temporary_value_reference::value) {
+ static detail::override_caster_t caster;
+ return detail::cast_ref(std::move(out), caster);
}
- return pybind11::detail::cast_safe(std::move(out));
- } catch (const std::exception& e) {
- fatalError("Error in 'obfuscate_variable_access': '"s + e.what() + "'");
+
+ return detail::cast_safe(std::move(out));
+ } catch (const std::exception &Exc) {
+ fatalError("Error in obfuscate_variable_access: '"s + Exc.what() + "'");
}
}
return false;
}
-AntiHookOpt PyObfuscationConfig::anti_hooking(llvm::Module* mod, llvm::Function* func)
-{
+AntiHookOpt PyObfuscationConfig::antiHooking(llvm::Module *M,
+ llvm::Function *F) {
py::gil_scoped_acquire gil;
- py::function override = py::get_override(static_cast(this), "anti_hooking");
+ const auto *Base = static_cast(this);
+ py::function override = py::get_override(Base, "anti_hooking");
if (override) {
try {
- py::object out = override(mod, func);
- if (out.is_none()) {
+ py::object out = override(M, F);
+ if (out.is_none())
return false;
- }
if (py::isinstance(out)) {
- bool res = out.cast();
- return res;
+ bool Res = out.cast();
+ return Res;
}
- if (py::detail::cast_is_temporary_value_reference::value) {
- static pybind11::detail::override_caster_t caster;
- return pybind11::detail::cast_ref(std::move(out), caster);
+
+ if (detail::cast_is_temporary_value_reference::value) {
+ static detail::override_caster_t caster;
+ return detail::cast_ref(std::move(out), caster);
}
- return pybind11::detail::cast_safe(std::move(out));
- } catch (const std::exception& e) {
- fatalError("Error in 'anti_hooking': '"s + e.what() + "'");
+
+ return detail::cast_safe(std::move(out));
+ } catch (const std::exception &Exc) {
+ fatalError("Error in anti_hooking: '"s + Exc.what() + "'");
}
}
return false;
}
-bool PyObfuscationConfig::has_report_diff_override() {
- std::call_once(overrides_report_diff_checked_, [this]() {
- const auto *base = static_cast(this);
- overrides_report_diff_ =
- static_cast(py::get_override(base, "report_diff"));
+bool PyObfuscationConfig::hasReportDiffOverride() {
+ std::call_once(OverridesReportDiffChecked, [this]() {
+ const auto *Base = static_cast(this);
+ OverridesReportDiff =
+ static_cast(py::get_override(Base, "report_diff"));
});
- return overrides_report_diff_;
+ return OverridesReportDiff;
}
-void PyObfuscationConfig::report_diff(const std::string &pass,
- const std::string &original,
- const std::string &obfuscated) {
- if (has_report_diff_override()) {
+void PyObfuscationConfig::reportDiff(const std::string &Pass,
+ const std::string &Original,
+ const std::string &Obfuscated) {
+ if (hasReportDiffOverride()) {
py::gil_scoped_acquire gil;
- py::function override = py::get_override(
- static_cast(this), "report_diff");
+ const auto *Base = static_cast(this);
+ py::function override = py::get_override(Base, "report_diff");
assert(override && "Checked once in ctor");
try {
- override(pass, original, obfuscated);
- } catch (const std::exception &e) {
- fatalError("Error in 'report_diff': '"s + e.what() + "'");
+ override(Pass, Original, Obfuscated);
+ } catch (const std::exception &Exc) {
+ fatalError("Error in report_diff: '"s + Exc.what() + "'");
}
}
}
-ArithmeticOpt PyObfuscationConfig::obfuscate_arithmetic(llvm::Module* mod, llvm::Function* func)
-{
+ArithmeticOpt PyObfuscationConfig::obfuscateArithmetics(llvm::Module *M,
+ llvm::Function *F) {
py::gil_scoped_acquire gil;
- py::function override = py::get_override(static_cast(this), "obfuscate_arithmetic");
+ const auto *Base = static_cast(this);
+ py::function override = py::get_override(Base, "obfuscate_arithmetic");
if (override) {
try {
- py::object out = override(mod, func);
- if (out.is_none()) {
+ py::object out = override(M, F);
+ if (out.is_none())
return false;
- }
if (py::isinstance(out)) {
bool res = out.cast();
return res;
}
- if (py::detail::cast_is_temporary_value_reference::value) {
- static pybind11::detail::override_caster_t caster;
- return pybind11::detail::cast_ref(std::move(out), caster);
+
+ if (detail::cast_is_temporary_value_reference::value) {
+ static detail::override_caster_t caster;
+ return detail::cast_ref(std::move(out), caster);
}
- return pybind11::detail::cast_safe(std::move(out));
- } catch (const std::exception& e) {
- fatalError("Error in 'obfuscate_arithmetic': '"s + e.what() + "'");
+
+ return detail::cast_safe(std::move(out));
+ } catch (const std::exception &Exc) {
+ fatalError("Error in obfuscate_arithmetic: '"s + Exc.what() + "'");
}
}
return false;
}
-OpaqueConstantsOpt PyObfuscationConfig::obfuscate_constants(llvm::Module* mod, llvm::Function* func)
-{
+OpaqueConstantsOpt PyObfuscationConfig::obfuscateConstants(llvm::Module *M,
+ llvm::Function *F) {
py::gil_scoped_acquire gil;
- py::function override = py::get_override(static_cast(this), "obfuscate_constants");
+ const auto *Base = static_cast(this);
+ py::function override = py::get_override(Base, "obfuscate_constants");
if (override) {
try {
- py::object out = override(mod, func);
- if (out.is_none()) {
+ py::object out = override(M, F);
+ if (out.is_none())
return OpaqueConstantsSkip();
- }
if (py::isinstance(out)) {
- bool res = out.cast();
- return OpaqueConstantsBool(res);
+ bool Res = out.cast();
+ return OpaqueConstantsBool(Res);
}
if (py::isinstance(out)) {
@@ -276,18 +302,19 @@ OpaqueConstantsOpt PyObfuscationConfig::obfuscate_constants(llvm::Module* mod, l
return OpaqueConstantsSet(std::move(values));
}
- if (py::detail::cast_is_temporary_value_reference::value) {
- static pybind11::detail::override_caster_t caster;
- return pybind11::detail::cast_ref(std::move(out), caster);
+ bool is_temp =
+ detail::cast_is_temporary_value_reference::value;
+ if (is_temp) {
+ static detail::override_caster_t caster;
+ return detail::cast_ref(std::move(out), caster);
}
- return pybind11::detail::cast_safe(std::move(out));
- } catch (const std::exception& e) {
- fatalError("Error in 'obfuscate_constants': '"s + e.what() + "'");
+
+ return detail::cast_safe(std::move(out));
+ } catch (const std::exception &Exc) {
+ fatalError("Error in obfuscate_constants: '"s + Exc.what() + "'");
}
}
return OpaqueConstantsSkip();
}
-}
-
-
+} // end namespace omvll
diff --git a/src/core/python/PyObfuscationConfig.hpp b/src/core/python/PyObfuscationConfig.hpp
index 4a37a3a6..9d65be42 100644
--- a/src/core/python/PyObfuscationConfig.hpp
+++ b/src/core/python/PyObfuscationConfig.hpp
@@ -1,33 +1,49 @@
-#ifndef OMVLL_PY_OBFUSCATION_CONFIG_H
-#define OMVLL_PY_OBFUSCATION_CONFIG_H
-#include "omvll/ObfuscationConfig.hpp"
+#pragma once
+
+//
+// This file is distributed under the Apache License v2.0. See LICENSE for
+// details.
+//
+
#include
+#include "omvll/ObfuscationConfig.hpp"
+
namespace omvll {
class PyObfuscationConfig : public ObfuscationConfig {
using ObfuscationConfig::ObfuscationConfig;
- StringEncodingOpt obfuscate_string(llvm::Module* mod, llvm::Function* func,
- const std::string& str) override;
- BreakControlFlowOpt break_control_flow(llvm::Module* mod, llvm::Function* func) override;
- ControlFlowFlatteningOpt flatten_cfg(llvm::Module* mod, llvm::Function* func) override;
+ StringEncodingOpt obfuscateString(llvm::Module *M, llvm::Function *F,
+ const std::string &Str) override;
+
+ BreakControlFlowOpt breakControlFlow(llvm::Module *M,
+ llvm::Function *F) override;
- StructAccessOpt obfuscate_struct_access(llvm::Module* mod, llvm::Function* func,
- llvm::StructType* S) override;
- VarAccessOpt obfuscate_variable_access(llvm::Module* mod, llvm::Function* func,
- llvm::GlobalVariable* S) override;
- AntiHookOpt anti_hooking(llvm::Module* mod, llvm::Function* func) override;
- ArithmeticOpt obfuscate_arithmetic(llvm::Module* mod, llvm::Function* func) override;
- OpaqueConstantsOpt obfuscate_constants(llvm::Module* mod, llvm::Function* func) override;
+ ControlFlowFlatteningOpt
+ controlFlowGraphFlattening(llvm::Module *M, llvm::Function *F) override;
- bool has_report_diff_override() override;
- void report_diff(const std::string &pass, const std::string &original,
- const std::string &obfuscated) override;
+ StructAccessOpt obfuscateStructAccess(llvm::Module *M, llvm::Function *F,
+ llvm::StructType *S) override;
+
+ VarAccessOpt obfuscateVariableAccess(llvm::Module *M, llvm::Function *F,
+ llvm::GlobalVariable *S) override;
+
+ AntiHookOpt antiHooking(llvm::Module *M, llvm::Function *F) override;
+
+ ArithmeticOpt obfuscateArithmetics(llvm::Module *M,
+ llvm::Function *F) override;
+
+ OpaqueConstantsOpt obfuscateConstants(llvm::Module *M,
+ llvm::Function *F) override;
+
+ bool hasReportDiffOverride() override;
+ void reportDiff(const std::string &Pass, const std::string &Original,
+ const std::string &Obfuscated) override;
private:
- bool overrides_report_diff_ = false;
- std::once_flag overrides_report_diff_checked_;
+ bool OverridesReportDiff = false;
+ std::once_flag OverridesReportDiffChecked;
};
-}
-#endif
+
+} // end namespace omvll
diff --git a/src/core/python/init.hpp b/src/core/python/init.hpp
index ca049dc5..c7f3f38f 100644
--- a/src/core/python/init.hpp
+++ b/src/core/python/init.hpp
@@ -1,16 +1,18 @@
-#ifndef OMVLL_PY_INIT_H
-#define OMVLL_PY_INIT_H
+#pragma once
+
+//
+// This file is distributed under the Apache License v2.0. See LICENSE for
+// details.
+//
+
#include
#include
#include
-namespace py = pybind11;
-using namespace pybind11::literals;
-
namespace omvll {
-py::module_& py_init_log(py::module_& m);
-py::module_& py_init_llvm_bindings(py::module_& m);
-py::module_& py_init_obf_opt(py::module_& m);
-}
-#endif
+pybind11::module_ &py_init_log(pybind11::module_ &M);
+pybind11::module_ &py_init_llvm_bindings(pybind11::module_ &M);
+pybind11::module_ &py_init_obf_opt(pybind11::module_ &M);
+
+} // end namespace omvll
diff --git a/src/core/python/pyllvm.cpp b/src/core/python/pyllvm.cpp
index 7492ef8e..9aaf5b5e 100644
--- a/src/core/python/pyllvm.cpp
+++ b/src/core/python/pyllvm.cpp
@@ -1,18 +1,28 @@
-#include
-#include
-#include
+//
+// This file is distributed under the Apache License v2.0. See LICENSE for
+// details.
+//
+
+#include "llvm/Demangle/Demangle.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Module.h"
#include "omvll/utils.hpp"
#include "init.hpp"
+namespace py = pybind11;
+
+using namespace pybind11::literals;
+
namespace omvll {
-py::module_& py_init_llvm_bindings(py::module_& m) {
- py::class_(m, "Struct", "This class mirrors ``llvm::StructType``")
- .def_property_readonly("name",
- [] (const llvm::StructType& S) { return S.getName().str(); },
- R"delim(
+py::module_ &py_init_llvm_bindings(py::module_ &m) {
+ py::class_(m, "Struct",
+ "This class mirrors ``llvm::StructType``")
+ .def_property_readonly(
+ "name", [](const llvm::StructType &S) { return S.getName().str(); },
+ R"delim(
The name of the structure or the class.
For instance:
@@ -24,60 +34,63 @@ py::module_& py_init_llvm_bindings(py::module_& m) {
)delim");
py::class_(m, "Module", "This class mirrors ``llvm::Module``")
- .def_property_readonly("identifier", &llvm::Module::getModuleIdentifier)
+ .def_property_readonly("identifier", &llvm::Module::getModuleIdentifier)
- .def_property_readonly("instruction_count",
- &llvm::Module::getInstructionCount,
- R"delim(
+ .def_property_readonly("instruction_count",
+ &llvm::Module::getInstructionCount,
+ R"delim(
The number of non-debug IR instructions in the module.
)delim")
- .def_property_readonly("source_filename",
- &llvm::Module::getSourceFileName,
- R"delim(
+ .def_property_readonly("source_filename",
+ &llvm::Module::getSourceFileName,
+ R"delim(
The source filename of the module
)delim")
- .def_property_readonly("name",
- [] (const llvm::Module& module) { return module.getName().str(); },
- R"delim(
+ .def_property_readonly(
+ "name",
+ [](const llvm::Module &Module) { return Module.getName().str(); },
+ R"delim(
The short "name" of this module
)delim")
- .def_property_readonly("data_layout",
- &llvm::Module::getDataLayoutStr,
- R"delim(
+ .def_property_readonly("data_layout", &llvm::Module::getDataLayoutStr,
+ R"delim(
Get the data layout string for the module's target platform.
)delim")
- .def("dump", [] (llvm::Module& self, const std::string& path) {
- dump(self, path);
- },
- R"delim(
+ .def(
+ "dump",
+ [](llvm::Module &Self, const std::string &Path) { dump(Self, Path); },
+ R"delim(
This function dumps the IR instructions of the current module in the
file provided in the second parameter.
- )delim", "file"_a);
-
-
- py::class_(m, "Function", "This class mirrors ``llvm::Function``")
- .def_property_readonly("nb_instructions",
- &llvm::Function::getInstructionCount,
- R"delim(
+ )delim",
+ "file"_a);
+
+ py::class_(m, "Function",
+ "This class mirrors ``llvm::Function``")
+ .def_property_readonly("nb_instructions",
+ &llvm::Function::getInstructionCount,
+ R"delim(
Return the number of IR instructions.
)delim")
- .def_property_readonly("name",
- [] (const llvm::Function& func) {
- return func.getName().str();
- }, R"delim(
+ .def_property_readonly(
+ "name",
+ [](const llvm::Function &Func) { return Func.getName().str(); },
+ R"delim(
The (mangled) name of the function.
For instance:
- ``_ZN7_JNIEnv12NewStringUTFEPKc``
- ``main``
)delim")
- .def_property_readonly("demangled_name",
- [] (const llvm::Function& func) {
- return llvm::demangle(func.getName().str());
- }, R"delim(
+ .def_property_readonly(
+ "demangled_name",
+ [](const llvm::Function &Func) {
+ return llvm::demangle(Func.getName().str());
+ },
+ R"delim(
The demangled name of the function.
For instance:
@@ -85,21 +98,24 @@ py::module_& py_init_llvm_bindings(py::module_& m) {
- ``main``
)delim");
- py::class_(m, "GlobalVariable", "This class mirrors ``llvm::GlobalVariable``")
- .def_property_readonly("name",
- [] (const llvm::GlobalVariable& GV) {
- return GV.getName().str();
- }, R"delim(
+ py::class_(
+ m, "GlobalVariable", "This class mirrors ``llvm::GlobalVariable``")
+ .def_property_readonly(
+ "name",
+ [](const llvm::GlobalVariable &GV) { return GV.getName().str(); },
+ R"delim(
The mangled name of the global variable.
)delim")
- .def_property_readonly("demangled_name",
- [] (const llvm::GlobalVariable& GV) {
- return llvm::demangle(GV.getName().str());
- }, R"delim(
+ .def_property_readonly(
+ "demangled_name",
+ [](const llvm::GlobalVariable &GV) {
+ return llvm::demangle(GV.getName().str());
+ },
+ R"delim(
The demangled name of the global variable.
)delim");
return m;
}
-}
+} // end namespace omvll
diff --git a/src/core/python/pylog.cpp b/src/core/python/pylog.cpp
index 241b610b..9655fed3 100644
--- a/src/core/python/pylog.cpp
+++ b/src/core/python/pylog.cpp
@@ -1,19 +1,26 @@
+//
+// This file is distributed under the Apache License v2.0. See LICENSE for
+// details.
+//
+
#include "omvll/log.hpp"
+
#include "init.hpp"
-namespace omvll {
+namespace py = pybind11;
-py::module_& py_init_log(py::module_& m) {
+namespace omvll {
- py::enum_(m, "LOG_LEVEL")
- .value("DEBUG", LOG_LEVEL::DEBUG)
- .value("TRACE", LOG_LEVEL::TRACE)
- .value("INFO", LOG_LEVEL::INFO)
- .value("WARN", LOG_LEVEL::WARN)
- .value("ERR", LOG_LEVEL::ERR);
+py::module_ &py_init_log(py::module_ &m) {
+ py::enum_(m, "LogLevel")
+ .value("DEBUG", LogLevel::Debug)
+ .value("TRACE", LogLevel::Trace)
+ .value("INFO", LogLevel::Info)
+ .value("WARN", LogLevel::Warn)
+ .value("ERR", LogLevel::Err);
- m.def("set_log_level", py::overload_cast(&Logger::set_level));
+ m.def("set_log_level", py::overload_cast(&Logger::set_level));
return m;
}
-}
+} // end namespace omvll
diff --git a/src/core/python/pyobf_opt.cpp b/src/core/python/pyobf_opt.cpp
index 0a57f387..bba804db 100644
--- a/src/core/python/pyobf_opt.cpp
+++ b/src/core/python/pyobf_opt.cpp
@@ -1,9 +1,19 @@
-#include "init.hpp"
+//
+// This file is distributed under the Apache License v2.0. See LICENSE for
+// details.
+//
+
#include "omvll/passes/ObfuscationOpt.hpp"
+#include "init.hpp"
+
+namespace py = pybind11;
+
+using namespace pybind11::literals;
+
namespace omvll {
-py::module_& py_init_obf_opt(py::module_& m) {
+py::module_ &py_init_obf_opt(py::module_ &m) {
// Strings Encoding
py::class_(m, "StringEncOptSkip",
R"delim(
@@ -153,4 +163,4 @@ py::module_& py_init_obf_opt(py::module_& m) {
return m;
}
-}
+} // end namespace omvll
diff --git a/src/core/utils.cpp b/src/core/utils.cpp
index 5c7f5803..f79bda04 100644
--- a/src/core/utils.cpp
+++ b/src/core/utils.cpp
@@ -1,28 +1,33 @@
-#include "omvll/utils.hpp"
+//
+// This file is distributed under the Apache License v2.0. See LICENSE for
+// details.
+//
+
+#include
+
+#include "llvm/ADT/Hashing.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IRReader/IRReader.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Program.h"
+#include "llvm/Support/RandomNumberGenerator.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include "llvm/Transforms/Utils/Local.h"
+
#include "omvll/ObfuscationConfig.hpp"
#include "omvll/PyConfig.hpp"
#include "omvll/log.hpp"
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
+#include "omvll/utils.hpp"
using namespace llvm;
@@ -97,7 +102,7 @@ runClangExecutable(StringRef Code, StringRef Dashx, const Triple &Triple,
for (const auto &Arg : ExtraArgs)
Args.push_back(Arg);
- // Create the input C file and choose macthing output file name
+ // Create the input C file and choose macthing output file name.
int InFileFD;
SmallString<128> InFileName;
std::string Prefix = "omvll-" + Triple.getTriple();
@@ -110,16 +115,16 @@ runClangExecutable(StringRef Code, StringRef Dashx, const Triple &Triple,
Args.push_back(OutFileName);
Args.push_back(InFileName);
- // Write the given C code to the input file
+ // Write the given C code to the input file.
{
std::error_code EC;
- raw_fd_ostream inFileOS(InFileName, EC);
+ raw_fd_ostream OS(InFileName, EC);
if (EC)
return errorCodeToError(EC);
- inFileOS << Code;
+ OS << Code;
}
- // TODO: Write to omvll debug log instead of stderr
+ // TODO: Write to omvll debug log instead of stderr.
for (StringRef Entry : Args)
errs() << Entry << " ";
errs() << "\n";
@@ -131,7 +136,7 @@ runClangExecutable(StringRef Code, StringRef Dashx, const Triple &Triple,
return OutFileName;
}
-static Error createSMDiagnosticError(llvm::SMDiagnostic &Diag) {
+static Error createSMDiagnosticError(SMDiagnostic &Diag) {
std::string Msg;
{
raw_string_ostream OS(Msg);
@@ -140,8 +145,8 @@ static Error createSMDiagnosticError(llvm::SMDiagnostic &Diag) {
return make_error(std::move(Msg), inconvertibleErrorCode());
}
-static Expected> loadModule(StringRef Path,
- LLVMContext &Ctx) {
+static Expected> loadModule(StringRef Path,
+ LLVMContext &Ctx) {
SMDiagnostic Err;
auto M = parseIRFile(Path, Err, Ctx);
if (!M)
@@ -149,54 +154,53 @@ static Expected> loadModule(StringRef Path,
return M;
}
-} // namespace detail
+} // end namespace detail
namespace omvll {
-std::string ToString(const Module& M) {
- std::error_code ec;
- std::string out;
- raw_string_ostream os(out);
- M.print(os, nullptr);
- return out;
+std::string ToString(const Module &M) {
+ std::error_code EC;
+ std::string Out;
+ raw_string_ostream OS(Out);
+ M.print(OS, nullptr);
+ return Out;
}
-std::string ToString(const Instruction& I) {
- std::string out;
- raw_string_ostream(out) << I;
- return out;
+std::string ToString(const Instruction &I) {
+ std::string Out;
+ raw_string_ostream(Out) << I;
+ return Out;
}
-std::string ToString(const BasicBlock& BB) {
- std::string out;
- raw_string_ostream os(out);
- BB.printAsOperand(os, true);
- return out;
+std::string ToString(const BasicBlock &BB) {
+ std::string Out;
+ raw_string_ostream OS(Out);
+ BB.printAsOperand(OS, true);
+ return Out;
}
-std::string ToString(const Type& Ty) {
- std::string out;
- raw_string_ostream os(out);
- os << TypeIDStr(Ty) << ": " << Ty;
- return out;
+std::string ToString(const Type &Ty) {
+ std::string Out;
+ raw_string_ostream OS(Out);
+ OS << TypeIDStr(Ty) << ": " << Ty;
+ return Out;
}
-std::string ToString(const Value& V) {
- std::string out;
- raw_string_ostream os(out);
- os << ValueIDStr(V) << ": " << V;
- return out;
+std::string ToString(const Value &V) {
+ std::string Out;
+ raw_string_ostream OS(Out);
+ OS << ValueIDStr(V) << ": " << V;
+ return Out;
}
-
-std::string ToString(const MDNode& N) {
- std::string out;
- raw_string_ostream os(out);
- N.printTree(os);
- return out;
+std::string ToString(const MDNode &N) {
+ std::string Out;
+ raw_string_ostream OS(Out);
+ N.printTree(OS);
+ return Out;
}
-std::string TypeIDStr(const Type& Ty) {
+std::string TypeIDStr(const Type &Ty) {
switch (Ty.getTypeID()) {
case Type::TypeID::HalfTyID: return "HalfTyID";
case Type::TypeID::BFloatTyID: return "BFloatTyID";
@@ -225,8 +229,7 @@ std::string TypeIDStr(const Type& Ty) {
}
}
-std::string ValueIDStr(const Value& V) {
-
+std::string ValueIDStr(const Value &V) {
#define HANDLE_VALUE(ValueName) case Value::ValueTy::ValueName ## Val: return #ValueName;
//#define HANDLE_INSTRUCTION(Name) /* nothing */
@@ -241,40 +244,38 @@ std::string ValueIDStr(const Value& V) {
return std::to_string(V.getValueID());
}
-void dump(Module& M, const std::string& file) {
- std::error_code ec;
- raw_fd_ostream fd(file, ec);
- M.print(fd, nullptr);
+void dump(Module &M, const std::string &File) {
+ std::error_code EC;
+ raw_fd_ostream FD(File, EC);
+ M.print(FD, nullptr);
}
-void dump(Function& F, const std::string& file) {
- std::error_code ec;
- raw_fd_ostream fd(file, ec);
- F.print(fd, nullptr);
+void dump(Function &F, const std::string &File) {
+ std::error_code EC;
+ raw_fd_ostream FD(File, EC);
+ F.print(FD, nullptr);
}
-void dump(const MemoryBuffer& MB, const std::string& file) {
- std::error_code ec;
- raw_fd_ostream fd(file, ec);
- fd << MB.getBuffer();
+void dump(const MemoryBuffer &MB, const std::string &File) {
+ std::error_code EC;
+ raw_fd_ostream FD(File, EC);
+ FD << MB.getBuffer();
}
-size_t demotePHINode(Function& F) {
- size_t count = 0;
- std::vector phiNodes;
+size_t demotePHINode(Function &F) {
+ size_t Count = 0;
+ std::vector PhiNodes;
do {
- phiNodes.clear();
- for (auto& BB : F) {
- for (auto& I : BB.phis()) {
- phiNodes.push_back(&I);
- }
- }
- count += phiNodes.size();
- for (PHINode* phi : phiNodes) {
- DemotePHIToStack(phi, F.begin()->getTerminator());
- }
- } while (!phiNodes.empty());
- return count;
+ PhiNodes.clear();
+ for (auto &BB : F)
+ for (auto &I : BB.phis())
+ PhiNodes.push_back(&I);
+
+ Count += PhiNodes.size();
+ for (PHINode *Phi : PhiNodes)
+ DemotePHIToStack(Phi, F.begin()->getTerminator());
+ } while (!PhiNodes.empty());
+ return Count;
}
static bool valueEscapes(const Instruction &Inst) {
@@ -287,28 +288,26 @@ static bool valueEscapes(const Instruction &Inst) {
return false;
}
-size_t demoteRegs(Function& F) {
- size_t count = 0;
- std::list WorkList;
- BasicBlock* BBEntry = &F.getEntryBlock();
+size_t demoteRegs(Function &F) {
+ size_t Count = 0;
+ std::list WorkList;
+ BasicBlock *BBEntry = &F.getEntryBlock();
do {
WorkList.clear();
- for (BasicBlock& BB : F) {
- for (Instruction& I : BB) {
- if (!(isa