Skip to content

GlobalsEncryption 在编译 protobuf 时由于 llvm.ctros 没有正确处理而 crash #55

@mrh929

Description

@mrh929

用 pluto-obfuscator -gle 选项编译 protobuf (https://github.com/protocolbuffers/protobuf/tree/79009d92375c4ba955ef37c810b84a6d047bb7ee) 的时候模块出现 crash

我的调试代码如下:

bool GlobalsEncryption::runOnModule(Module &M) {
    if (!enable) {
        return false;
    }
    INIT_CONTEXT(M);

    int gv_count;
    vector<GlobalVariable *> GVs;

    gv_count = M.getGlobalList().size();
    for (GlobalVariable &GV : M.getGlobalList()) {
        GVs.push_back(&GV);
    }
    for (int i = 0; i < ObfuTimes; i++) {
        for (GlobalVariable *GV : GVs) {

        // for (GlobalVariable &T : M.getGlobalList()) {
        // GlobalVariable *GV = &T;

        outs() << "original gv_count: " << gv_count << "  now: " << M.getGlobalList().size() << "\n";

        outs() << "debug: ===============\n";
        
        outs() << "isa<GlobalVariable>:" << isa<GlobalVariable>(GV) << "\n";

        outs() << "GV->classof(GV):" << GV->classof(GV) << "\n";
        
        GV->dump();
 
        // Only encrypt globals of integer and array
        if (!GV->getValueType()->isIntegerTy() &&
            !GV->getValueType()->isArrayTy()) {
            continue;
        }

        outs() << "-----------------------\n";

        if (GV->hasInitializer() && GV->getInitializer() &&
            (GV->getName().contains(".str") || !OnlyStr)
            // Do not encrypt globals having a section named "llvm.metadata"
            && !GV->getSection().equals("llvm.metadata")) {
            Constant *initializer = GV->getInitializer();
            ConstantInt *intData = dyn_cast<ConstantInt>(initializer);
            ConstantDataArray *arrData = dyn_cast<ConstantDataArray>(initializer);
            if (arrData) {
            uint32_t eleSize = arrData->getElementByteSize();
            uint32_t eleNum = arrData->getNumElements();
            uint32_t arrLen = eleNum * eleSize;
            char *data = const_cast<char *>(arrData->getRawDataValues().data());
            char *dataCopy = new char[arrLen];
            memcpy(dataCopy, data, arrLen);
            uint64_t key = cryptoutils->get_uint64_t();
            // A simple xor encryption
            for (uint32_t i = 0; i < arrLen; i++) {
                dataCopy[i] ^= ((char *)&key)[i % eleSize];
            }
            GV->setInitializer(ConstantDataArray::getRaw(
                StringRef(dataCopy, arrLen), eleNum, arrData->getElementType()));
            GV->setConstant(false);
            insertArrayDecryption(M, {GV, key, eleNum});
            } else if (intData) {
            uint64_t key = cryptoutils->get_uint64_t();
            ConstantInt *enc =
                CONST(intData->getType(), key ^ intData->getZExtValue());
            GV->setInitializer(enc);
            GV->setConstant(false);
            insertIntDecryption(M, {GV, key, 1LL});
            }
        }
        }
    }
    return true;
}

部分编译错误信息: 新建 文本文档.txt
复现代码: gmock-all-5d551a.zip

目前初步结论是 M.getGlobalList() 函数返回的列表中的某些元素在处理的过程中有发生改变。而这里我们的代码直接在一开始就把列表中的元素全部放入了 vector 内,等到 vector 取出该元素时,它已经不是一个合法的 GlobalVariable 了,导致 pass crash 掉。

还发现了几个其他的 bug,晚点我会申请 pr

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions