forked from 61bcdefg/Hikari-LLVM15-Core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
SplitBasicBlocks.cpp
126 lines (105 loc) · 4.05 KB
/
SplitBasicBlocks.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// For open-source license, please refer to
// [License](https://github.com/HikariObfuscator/Hikari/wiki/License).
//===----------------------------------------------------------------------===//
#include "llvm/IR/Instructions.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Transforms/Obfuscation/CryptoUtils.h"
#include "llvm/Transforms/Obfuscation/Split.h"
#include "llvm/Transforms/Obfuscation/Utils.h"
using namespace llvm;
static cl::opt<size_t>
s_user_split_num("split_num", cl::init(2),
cl::desc("Split <split_num> time each BB"));
namespace {
struct SplitBasicBlock : public FunctionPass {
static char ID; // Pass identification, replacement for typeid
bool flag;
SplitBasicBlock() : FunctionPass(ID) { this->flag = true; }
SplitBasicBlock(bool flag) : FunctionPass(ID) { this->flag = flag; }
bool runOnFunction(Function &F) override {
// Check if the number of applications is correct
if (!((s_user_split_num > 1) && (s_user_split_num <= 10))) {
errs()
<< "Split application basic block percentage -split_num=x must be 1 "
"< x <= 10";
return false;
}
// Do we obfuscate
if (toObfuscate(flag, &F, "split")) {
errs() << "Running BasicBlockSplit On " << F.getName() << "\n";
split(&F);
}
return true;
}
void split(Function *F) {
std::vector<BasicBlock *> origBB;
size_t split_ctr = 0;
// Save all basic blocks
for (BasicBlock &BB : *F)
origBB.emplace_back(&BB);
for (BasicBlock *currBB : origBB) {
if (currBB->size() < 2 || containsPHI(currBB) ||
containsSwiftError(currBB))
continue;
if (s_user_split_num > currBB->size() - 1)
split_ctr = currBB->size() - 1;
else
split_ctr = s_user_split_num;
// Generate splits point (count number of the LLVM instructions in the
// current BB)
std::vector<size_t> llvm_inst_ord;
for (size_t i = 1; i < currBB->size(); ++i)
llvm_inst_ord.emplace_back(i);
// Shuffle
split_point_shuffle(llvm_inst_ord);
std::sort(llvm_inst_ord.begin(), llvm_inst_ord.begin() + split_ctr);
// Split
size_t llvm_inst_prev_offset = 0;
BasicBlock::iterator curr_bb_it = currBB->begin();
BasicBlock *curr_bb_offset = currBB;
for (size_t i = 0; i < split_ctr; ++i) {
for (size_t j = 0; j < llvm_inst_ord[i] - llvm_inst_prev_offset; ++j)
++curr_bb_it;
llvm_inst_prev_offset = llvm_inst_ord[i];
// https://github.com/eshard/obfuscator-llvm/commit/fff24c7a1555aa3ae7160056b06ba1e0b3d109db
/* TODO: find a real fix or try with the probe-stack inline-asm when its
* ready. See https://github.com/Rust-for-Linux/linux/issues/355.
* Sometimes moving an alloca from the entry block to the second block
* causes a segfault when using the "probe-stack" attribute (observed
* with with Rust programs). To avoid this issue we just split the entry
* block after the allocas in this case.
*/
if (F->hasFnAttribute("probe-stack") && currBB->isEntryBlock() &&
isa<AllocaInst>(curr_bb_it))
continue;
curr_bb_offset = curr_bb_offset->splitBasicBlock(
curr_bb_it, curr_bb_offset->getName() + ".split");
}
}
}
bool containsPHI(BasicBlock *BB) {
for (Instruction &I : *BB)
if (isa<PHINode>(&I))
return true;
return false;
}
bool containsSwiftError(BasicBlock *BB) {
for (Instruction &I : *BB)
if (AllocaInst *AI = dyn_cast<AllocaInst>(&I))
if (AI->isSwiftError())
return true;
return false;
}
void split_point_shuffle(std::vector<size_t> &vec) {
int n = vec.size();
for (int i = n - 1; i > 0; --i)
std::swap(vec[i], vec[cryptoutils->get_range(i + 1)]);
}
};
} // namespace
char SplitBasicBlock::ID = 0;
INITIALIZE_PASS(SplitBasicBlock, "splitobf", "Enable BasicBlockSpliting.",
false, false)
FunctionPass *llvm::createSplitBasicBlockPass(bool flag) {
return new SplitBasicBlock(flag);
}