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. 加法替换

image-20220709211305441

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. 减法替换

image-20220709211846015

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. 与替换

image-20220709212107850

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