OLLVM混淆学习(3)——指令替换(SUB)
0x01 指令替换基本介绍
指令替换就是将正常的二元运算指令(如加法、减法、异或等等),替换为等效而更复杂的指令序列,以达到混淆计算过程的目的。它仅支持整数运算的替换,因为替换浮点指令会造成舍入的错误和误差。
最近这四篇LLVM混淆的文章都是来自看雪“LLVM与代码混淆技术”这门课,推荐大家可以去看一下绝对物超所值,感谢34r7hm4n的倾情讲解。
例如:
a = b + c
===> a = b - (-c)
===> a = -(-b + (-c))
该混淆唯一的难点就在于找到和原指令等效的复杂指令,并将所有的原指令替换成复杂指令即可,其他都是重复操作没啥特别的。
0x02 实现方法
实现复杂指令替换过程中主要注意要将创建的每条指令插到BI(当前原指令,这种只是物理上的插入并不是逻辑上的,所以对原来的指令没有影响)前面,后续利用replaceAllUsesWith函数将新创建的复杂指令把原指令在物理上替换掉就行。
保存原指令块,switch-case判断进入对应混淆
bool Substitution::runOnFunction(Function &F){
for(int i = 0;i < ObfuTime;i ++){
for(BasicBlock &BB : F){
vector<Instruction*> origInst;
for(Instruction &I : BB){
origInst.push_back(&I);
}
for(Instruction *I : origInst){
if(isa<BinaryOperator>(I)){
BinaryOperator *BI = cast<BinaryOperator>(I);
substitute(BI);
}
}
}
}
}
void Substitution::substitute(BinaryOperator *BI){
bool flag = true;
switch (BI->getOpcode()) {
case BinaryOperator::Add:
substituteAdd(BI);
break;
case BinaryOperator::Sub:
substituteSub(BI);
break;
case BinaryOperator::And:
substituteAnd(BI);
break;
case BinaryOperator::Or:
substituteOr(BI);
break;
case BinaryOperator::Xor:
substituteXor(BI);
break;
default:
flag = false;
break;
}
if(flag){
// 是否删去不影响执行结果,此时已经替换掉BI了,原BI没有地方执行了
BI->eraseFromParent();
}
}
1. 加法替换
void Substitution::substituteAdd(BinaryOperator *BI){
int choice = rand() % NUMBER_ADD_SUBST;
switch (choice) {
case 0:
addNeg(BI);
break;
case 1:
addDoubleNeg(BI);
break;
case 2:
addRand(BI);
break;
case 3:
addRand2(BI);
break;
default:
break;
}
}
void Substitution::addNeg(BinaryOperator *BI){
BinaryOperator *op;
op = BinaryOperator::CreateNeg(BI->getOperand(1), "", BI);
op = BinaryOperator::CreateSub(BI->getOperand(0), op, "", BI);
BI->replaceAllUsesWith(op);
}
void Substitution::addDoubleNeg(BinaryOperator *BI){
BinaryOperator *op, *op1, *op2;
op1 = BinaryOperator::CreateNeg(BI->getOperand(0), "", BI);
op2 = BinaryOperator::CreateNeg(BI->getOperand(1), "", BI);
op = BinaryOperator::CreateAdd(op1, op2, "", BI);
op = BinaryOperator::CreateNeg(op, "", BI);
BI->replaceAllUsesWith(op);
}
void Substitution::addRand(BinaryOperator *BI){
ConstantInt *r = (ConstantInt*)CONST(BI->getType(), rand());
BinaryOperator *op, *op1, *op2;
op = BinaryOperator::CreateAdd(BI->getOperand(0), r, "", BI);
op = BinaryOperator::CreateAdd(op, BI->getOperand(1), "", BI);
op = BinaryOperator::CreateSub(op, r, "", BI);
BI->replaceAllUsesWith(op);
}
void Substitution::addRand2(BinaryOperator *BI){
ConstantInt *r = (ConstantInt*)CONST(BI->getType(), rand());
BinaryOperator *op, *op1, *op2;
op = BinaryOperator::CreateSub(BI->getOperand(0), r, "", BI);
op = BinaryOperator::CreateAdd(op, BI->getOperand(1), "", BI);
op = BinaryOperator::CreateAdd(op, r, "", BI);
BI->replaceAllUsesWith(op);
}
2. 减法替换
void Substitution::substituteSub(BinaryOperator *BI){
int choice = rand() % NUMBER_SUB_SUBST;
switch (choice) {
case 0:
subNeg(BI);
break;
case 1:
subRand(BI);
break;
case 2:
subRand2(BI);
break;
default:
break;
}
}
void Substitution::subNeg(BinaryOperator *BI){
BinaryOperator *op;
op = BinaryOperator::CreateNeg(BI->getOperand(1), "", BI);
op = BinaryOperator::CreateAdd(BI->getOperand(0), op, "", BI);
BI->replaceAllUsesWith(op);
}
void Substitution::subRand(BinaryOperator *BI){
ConstantInt *r = (ConstantInt*)CONST(BI->getType(), rand());
BinaryOperator *op, *op1, *op2;
op = BinaryOperator::CreateAdd(BI->getOperand(0), r, "", BI);
op = BinaryOperator::CreateSub(op, BI->getOperand(1), "", BI);
op = BinaryOperator::CreateSub(op, r, "", BI);
BI->replaceAllUsesWith(op);
}
void Substitution::subRand2(BinaryOperator *BI){
ConstantInt *r = (ConstantInt*)CONST(BI->getType(), rand());
BinaryOperator *op, *op1, *op2;
op = BinaryOperator::CreateSub(BI->getOperand(0), r, "", BI);
op = BinaryOperator::CreateSub(op, BI->getOperand(1), "", BI);
op = BinaryOperator::CreateAdd(op, r, "", BI);
BI->replaceAllUsesWith(op);
}
3. 与替换
void Substitution::substituteAnd(BinaryOperator *BI){
int choice = rand() % NUMBER_AND_SUBST;
switch (choice) {
case 0:
andSubstitute(BI);
break;
case 1:
andSubstituteRand(BI);
break;
default:
break;
}
}
void Substitution::andSubstitute(BinaryOperator *BI){
BinaryOperator *op;
op = BinaryOperator::CreateNot(BI->getOperand(1), "", BI);
op = BinaryOperator::CreateXor(BI->getOperand(0), op, "", BI);
op = BinaryOperator::CreateAnd(op, BI->getOperand(0), "", BI);
BI->replaceAllUsesWith(op);
}
void Substitution::andSubstituteRand(BinaryOperator *BI){
ConstantInt *r = (ConstantInt*)CONST(BI->getType(), rand());
BinaryOperator *op, *op1;
op = BinaryOperator::CreateNot(BI->getOperand(0), "", BI);
op1 = BinaryOperator::CreateNot(BI->getOperand(1), "", BI);
op = BinaryOperator::CreateOr(op, op1, "", BI);
op = BinaryOperator::CreateNot(op, "", BI);
op1 = BinaryOperator::CreateNot(r, "", BI);
op1 = BinaryOperator::CreateOr(r, op1, "", BI);
op = BinaryOperator::CreateAnd(op, op1, "", BI);
BI->replaceAllUsesWith(op);
}
4. 或替换
void Substitution::substituteOr(BinaryOperator *BI){
int choice = rand() % NUMBER_OR_SUBST;
switch (choice) {
case 0:
orSubstitute(BI);
break;
case 1:
orSubstituteRand(BI);
break;
default:
break;
}
}
void Substitution::orSubstitute(BinaryOperator *BI){
BinaryOperator *op, *op1;
op = BinaryOperator::CreateAnd(BI->getOperand(0), BI->getOperand(1), "", BI);
op1 = BinaryOperator::CreateXor(BI->getOperand(0), BI->getOperand(1), "", BI);
op = BinaryOperator::CreateOr(op, op1, "", BI);
BI->replaceAllUsesWith(op);
}
void Substitution::orSubstituteRand(BinaryOperator *BI){
ConstantInt *r = (ConstantInt*)CONST(BI->getType(), rand());
BinaryOperator *op, *op1;
op = BinaryOperator::CreateNot(BI->getOperand(0), "", BI);
op1 = BinaryOperator::CreateNot(BI->getOperand(1), "", BI);
op = BinaryOperator::CreateAnd(op, op1, "", BI);
op = BinaryOperator::CreateNot(op, "", BI);
op1 = BinaryOperator::CreateNot(r, "", BI);
op1 = BinaryOperator::CreateOr(r, op1, "", BI);
op = BinaryOperator::CreateAnd(op, op1, "", BI);
BI->replaceAllUsesWith(op);
}
5. 异或替换
void Substitution::substituteXor(BinaryOperator *BI){
int choice = rand() % NUMBER_XOR_SUBST;
switch (choice) {
case 0:
xorSubstitute(BI);
break;
case 1:
xorSubstituteRand(BI);
break;
default:
break;
}
}
void Substitution::xorSubstitute(BinaryOperator *BI){
BinaryOperator *op, *op1, *op2, *op3;
op1 = BinaryOperator::CreateNot(BI->getOperand(0), "", BI);
op1 = BinaryOperator::CreateAnd(op1, BI->getOperand(1), "", BI);
op2 = BinaryOperator::CreateNot(BI->getOperand(1), "", BI);
op2 = BinaryOperator::CreateAnd(BI->getOperand(0), op2, "", BI);
op = BinaryOperator::CreateOr(op1, op2, "", BI);
BI->replaceAllUsesWith(op);
}
void Substitution::xorSubstituteRand(BinaryOperator *BI){
ConstantInt *r = (ConstantInt*)CONST(BI->getType(), rand());
BinaryOperator *op, *op1, *op2, *op3;
op1 = BinaryOperator::CreateNot(BI->getOperand(0), "", BI);
op1 = BinaryOperator::CreateAnd(op1, r, "", BI);
op2 = BinaryOperator::CreateNot(r, "", BI);
op2 = BinaryOperator::CreateAnd(BI->getOperand(0), op2, "", BI);
op = BinaryOperator::CreateOr(op1, op2, "", BI);
op1 = BinaryOperator::CreateNot(BI->getOperand(1), "", BI);
op1 = BinaryOperator::CreateAnd(op1, r, "", BI);
op2 = BinaryOperator::CreateNot(r, "", BI);
op2 = BinaryOperator::CreateAnd(BI->getOperand(1), op2, "", BI);
op3 = BinaryOperator::CreateOr(op1, op2, "", BI);
op = BinaryOperator::CreateXor(op, op3, "", BI);
BI->replaceAllUsesWith(op);
}
0x03 参考链接
https://www.kanxue.com/book-88-2113.htm
https://github.com/bluesadi/Pluto-Obfuscator/blob/kanxue/Transforms/src/Substitution.cpp
这篇文章写得深入浅出,让我这个小白也看懂了!