004 Change Instructions (obfuscation)
본 튜토리얼에서는 프로그램 분석 기법을 LLVM을 통해 구현해보는 것이 목적이기 때문에 모든 이론적 지식을 자세하게 다루지는 않을 것이다.
Learning Objectives
- learn a definition of obfuscation
- learn obfuscation technuques
- learn how to change instructions
What is obfuscation?
How can we change instructions?
implementation
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Instruction.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/IR/IRBuilder.h"
using namespace llvm;
namespace{
struct YJ008MbaAdd : public FunctionPass{
static char ID;
YJ008MbaAdd() : FunctionPass(ID){};
bool runOnFunction(Function& F) override {
bool isModified = false;
for(auto& BB: F){
for(auto I = BB.begin(); I != BB.end(); ++I){
auto *op = dyn_cast<BinaryOperator>(I);
if (!op) continue;
if (op->getOpcode() != Instruction::Add || !op->getType()->isIntegerTy())
continue;
IRBuilder<> Builder(op);
//a + b == (((a ^ b) + 2 * (a & b)) * 39 + 23) * 151 + 111
Instruction* v = BinaryOperator::CreateAdd(Builder.CreateMul(
Builder.CreateAdd(Builder.CreateXor(op->getOperand(0), op->getOperand(1)),
Builder.CreateAdd(Builder.CreateMul(ConstantInt::get(op->getType(), 2),
Builder.CreateMul(Builder.CreateAnd(op->getOperand(0), op->getOperand(1)),
ConstantInt::get(op->getType(), 39))),
ConstantInt::get(op->getType(), 23))),
ConstantInt::get(op->getType(), 151)),
ConstantInt::get(op->getType(), 111));
ReplaceInstWithInst(op->getParent()->getInstList(), I, v);
isModified = true;
}
}
return isModified;
}
};
}
char YJ008MbaAdd::ID = 0;
static RegisterPass<YJ008MbaAdd>X ("MbaAdd", "Replace add with MBA add", false, true);
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
namespace{
struct YJ008MbaSub : public FunctionPass{
static char ID;
YJ008MbaSub() : FunctionPass(ID){}
bool runOnFunction(Function& F) override {
bool isModified = false;
for(auto& BB : F){
for(auto I = BB.begin(); I != BB.end(); ++I){
// errs() << I << '\n';
auto *op = dyn_cast<BinaryOperator>(I);
if(!op) continue;
// skip inst if opcode is not Sub or of Integer type
unsigned opcode = op->getOpcode();
if (opcode != Instruction::Sub || !op->getType()->isIntegerTy()) continue;
IRBuilder<> Builder(op);
// create inst: (a + ~b) + 1
Instruction *v = BinaryOperator::CreateAdd(
Builder.CreateAdd(op->getOperand(0), Builder.CreateNot(op->getOperand(1))),
ConstantInt::get(op->getType(), 1));
errs() << op << '\n';
// replace inst sub -> (a + ~b) + 1
ReplaceInstWithInst(op->getParent()->getInstList(), I, v);
// errs() << "HI";
isModified = true;
}
}
return isModified;
}
};
}
char YJ008MbaSub::ID = 0;
static RegisterPass<YJ008MbaSub>X("MbaSub", "replace Sub with Mab", false, true);
Pass | Type |
---|---|
Writing HelloLLVM Pass | analysis |
Iterating over Module, Function, Basic block | analysis |
Count the number of insts, func calls | analysis |
Insert func call | transformation |
Change Insts (obfuscation) | transformation |
Control flow graph | transformation |
Reference
[1] Andrzej Warzyński. llvm-tutor. github
[2] Adrian Sampson. LLVM for Grad Students. blog
[3] Keshav Pingali. CS 380C: Advanced Topics in Compilers. blog
[4] Arthur Eubanks. The New Pass Manager. blog
Enjoy Reading This Article?
Here are some more articles you might like to read next: