Skip to content

Commit 8b74153

Browse files
committed
Added String and Symbol Obfuscation
1 parent f8bbb21 commit 8b74153

File tree

6 files changed

+199
-0
lines changed

6 files changed

+199
-0
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
cmake_minimum_required(VERSION 3.13)
2+
project(MLIROBF LANGUAGES CXX C)
3+
4+
# Use C++17
5+
set(CMAKE_CXX_STANDARD 17)
6+
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
7+
8+
9+
find_package(MLIR REQUIRED CONFIG) # What this does is that it tells the code that I want to use MLIR. Go find it and link to it.
10+
11+
12+
message(STATUS "Found MLIR: ${MLIR_PACKAGE_PREFIX}")
13+
14+
15+
include_directories(${PROJECT_SOURCE_DIR}/include) # THis helps it find include/Obfuscator/Passes.h
16+
17+
18+
add_subdirectory(lib) # This tells the CMake to build the code in mlir-obfuscator/lib/
19+
20+
21+
mlir_print_global_pass_registry() # Optional: Thjis is just to print MLIR passes for debugging
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#pragma once
2+
3+
#include "mlir/Pass/Pass.h"
4+
5+
namespace mlir {
6+
7+
// Creates the String Encryption Pass
8+
std::unique_ptr<Pass> createStringEncryptPass(llvm::StringRef key = "");
9+
10+
// Creates the Symbol Obfuscation / Renaming Pass
11+
std::unique_ptr<Pass> createSymbolObfuscatePass(llvm::StringRef key = "");
12+
13+
} // namespace mlir

mlir/mlir-obfuscator/lib/CMakeLists.txt

Whitespace-only changes.
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#include "Obfuscator/Passes.h"
2+
3+
#include "mlir/IR/Attributes.h"
4+
#include "mlir/IR/BuiltinOps.h"
5+
#include "mlir/IR/Operation.h"
6+
#include "mlir/Pass/Pass.h"
7+
#include "mlir/IR/MLIRContext.h"
8+
9+
#include <string>
10+
11+
using namespace mlir;
12+
13+
namespace {
14+
15+
/// Simple XOR encryption for demonstration
16+
static std::string xorEncrypt(const std::string &input, const std::string &key) {
17+
std::string out = input;
18+
for (size_t i = 0; i < input.size(); i++) {
19+
out[i] = input[i] ^ key[i % key.size()];
20+
}
21+
return out;
22+
}
23+
24+
/// String Encryption Pass
25+
struct StringEncryptPass
26+
: public PassWrapper<StringEncryptPass, OperationPass<ModuleOp>> { // This lines makes a skeleton for the pass
27+
28+
StringEncryptPass() = default;
29+
StringEncryptPass(const std::string &k) : key(k) {}
30+
31+
void runOnOperation() override {
32+
ModuleOp module = getOperation();
33+
MLIRContext *ctx = module.getContext();
34+
35+
module.walk([&](Operation *op) { // Walk visits every operation in the IR, including the nested ones
36+
bool changed = false;
37+
SmallVector<NamedAttribute> newAttrs;
38+
39+
for (auto &attr : op->getAttrs()) {
40+
// Only encrypt string attributes
41+
if (auto strAttr = attr.getValue().dyn_cast<StringAttr>()) {
42+
std::string original = strAttr.getValue().str();
43+
std::string encrypted = xorEncrypt(original, key);
44+
45+
auto newValue = StringAttr::get(ctx, encrypted);
46+
newAttrs.emplace_back(attr.getName(), newValue);
47+
changed = true;
48+
} else {
49+
newAttrs.push_back(attr);
50+
}
51+
}
52+
53+
// Replace attribute dictionary if something changed
54+
if (changed) {
55+
op->setAttrDictionary(DictionaryAttr::get(ctx, newAttrs));
56+
}
57+
});
58+
}
59+
60+
std::string key = "default_key";
61+
};
62+
63+
} // namespace
64+
65+
/// Factory function exposed to the outside world
66+
std::unique_ptr<Pass> mlir::createStringEncryptPass(llvm::StringRef key) {
67+
return std::make_unique<StringEncryptPass>(key.str());
68+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#include "Obfuscator/Passes.h"
2+
3+
#include "mlir/IR/BuiltinOps.h"
4+
#include "mlir/IR/SymbolTable.h"
5+
#include "mlir/Pass/Pass.h"
6+
#include "mlir/IR/MLIRContext.h"
7+
#include "mlir/Dialect/Func/IR/FuncOps.h"
8+
9+
#include <random>
10+
11+
using namespace mlir;
12+
13+
namespace {
14+
15+
/// Utility: generate random obfuscated names (hex-based)
16+
static std::string generateObfuscatedName(std::mt19937 &rng) {
17+
std::uniform_int_distribution<uint32_t> dist(0, 0xFFFFFFFF);
18+
uint32_t num = dist(rng);
19+
20+
// format as hex string: f_a1b2c3d4
21+
char buffer[16];
22+
snprintf(buffer, sizeof(buffer), "f_%08x", num);
23+
return std::string(buffer);
24+
}
25+
26+
/// Symbol Obfuscation Pass
27+
struct SymbolObfuscatePass
28+
: public PassWrapper<SymbolObfuscatePass, OperationPass<ModuleOp>> {
29+
30+
SymbolObfuscatePass() = default;
31+
SymbolObfuscatePass(const std::string &k) : key(k) {}
32+
33+
void runOnOperation() override {
34+
ModuleOp module = getOperation();
35+
MLIRContext *ctx = module.getContext();
36+
SymbolTable symbolTable(module);
37+
38+
// initialize RNG with deterministic seed (from key)
39+
std::seed_seq seq(key.begin(), key.end());
40+
std::mt19937 rng(seq);
41+
42+
// Mapping: oldName -> newName
43+
llvm::StringMap<std::string> renameMap;
44+
45+
// Step 1: Rename symbol definitions (functions)
46+
module.walk([&](func::FuncOp func) {
47+
StringRef oldName = func.getName();
48+
std::string newName = generateObfuscatedName(rng);
49+
50+
renameMap[oldName] = newName;
51+
symbolTable.setSymbolName(func, newName);
52+
});
53+
54+
// Step 2: Update symbol references everywhere
55+
module.walk([&](Operation *op) {
56+
SmallVector<NamedAttribute> updatedAttrs;
57+
bool changed = false;
58+
59+
for (auto &attr : op->getAttrs()) {
60+
if (auto symAttr = attr.getValue().dyn_cast<SymbolRefAttr>()) {
61+
StringRef old = symAttr.getRootReference();
62+
if (renameMap.count(old)) {
63+
auto newRef = SymbolRefAttr::get(ctx, renameMap[old]);
64+
updatedAttrs.emplace_back(attr.getName(), newRef);
65+
changed = true;
66+
continue;
67+
}
68+
}
69+
// no change -> keep original
70+
updatedAttrs.push_back(attr);
71+
}
72+
73+
if (changed) {
74+
op->setAttrDictionary(DictionaryAttr::get(ctx, updatedAttrs));
75+
}
76+
});
77+
}
78+
79+
std::string key = "seed";
80+
};
81+
82+
} // namespace
83+
84+
/// Public factory
85+
std::unique_ptr<Pass> mlir::createSymbolObfuscatePass(llvm::StringRef key) {
86+
return std::make_unique<SymbolObfuscatePass>(key.str());
87+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// String test
2+
func.func @hello() attributes { msg = "HELLO WORLD" } {
3+
return
4+
}
5+
6+
// Symbol test
7+
func.func @main() {
8+
%0 = func.call @hello() : () -> ()
9+
return
10+
}

0 commit comments

Comments
 (0)