Skip to content

Commit

Permalink
fix some serious problem
Browse files Browse the repository at this point in the history
  • Loading branch information
oubotong authored May 30, 2018
1 parent 8231475 commit 7507d66
Showing 1 changed file with 66 additions and 120 deletions.
186 changes: 66 additions & 120 deletions lib/Transforms/Obfuscation/StringObfuscation.cpp
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
#define DEBUG_TYPE "objdiv"
#include <string>
#include <strstream>
#include <sstream>

#include "llvm/ADT/Statistic.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Value.h"
#include "llvm/IR/CallSite.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/CryptoUtils.h"
#include "llvm/Transforms/Obfuscation/StringObfuscation.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"

using namespace llvm;

Expand All @@ -22,7 +23,7 @@ namespace llvm {
struct encVar {
public:
GlobalVariable *var;
char key;
uint8_t key;
};

class StringObfuscationPass: public llvm::ModulePass {
Expand Down Expand Up @@ -50,7 +51,13 @@ namespace llvm {
std::string section(gv->getSection());

// Let's encode the static ones
if (gv->isConstant() && gv->hasInitializer() && isa<ConstantDataSequential>(gv->getInitializer()) && section != "llvm.metadata" && section.find("__objc_methname") == std::string::npos) {
if (gv->getName().str().substr(0,4)==".str"&&
gv->isConstant() &&
gv->hasInitializer() &&
isa<ConstantDataSequential>(gv->getInitializer()) &&
section != "llvm.metadata" &&
section.find("__objc_methname") == std::string::npos
/*&&gv->getType()->getArrayElementType()->getArrayElementType()->isIntegerTy()*/) {
++GlobalsEncoded;
//errs() << " is constant";

Expand All @@ -65,23 +72,24 @@ namespace llvm {
// dynGV->copyAttributesFrom(gv);
dynGV->setInitializer(gv->getInitializer());

std::string tmp=gv->getName().str();
// errs()<<"GV: "<<*gv<<"\n";

Constant *initializer = gv->getInitializer();
ConstantDataSequential *cdata = dyn_cast<ConstantDataSequential>(initializer);
if (cdata) {
const char *orig = cdata->getRawDataValues().data();
unsigned int len = cdata->getNumElements()*cdata->getElementByteSize();
unsigned len = cdata->getNumElements()*cdata->getElementByteSize();

encVar *cur = new encVar();
cur->var = dynGV;
cur->key = llvm::cryptoutils->get_uint8_t();

// casting away const is undef. behavior in C++
// TODO a clean implementation would retrieve the data, generate a new constant
// set the correct type, and copy the data over.
//char *encr = new char[len];
//Constant *initnew = ConstantDataArray::getString(M.getContext(), encr, true);
char *encr = (char*)orig; // ugly but works for now

char *encr = const_cast<char *>(orig);
// Simple xor encoding
for (unsigned i = 0; i != len; ++i) {
encr[i] = orig[i]^cur->key;
Expand All @@ -93,7 +101,6 @@ namespace llvm {
// Prepare to add decode function for this variable
encGlob.push_back(cur);
} else {
// errs() << " undhandled!";
// just copying default initializer for now
dynGV->setInitializer(initializer);
}
Expand All @@ -109,149 +116,88 @@ namespace llvm {
for (unsigned i = 0, e = toDelConstGlob.size(); i != e; ++i)
toDelConstGlob[i]->eraseFromParent();


// create code to initialize global variables at runtime
addDecodeFunction(&M, &encGlob);


return true;
}

private:
void addDecodeFunction(Module *mod, std::vector<encVar*> *gvars) {
void addDecodeFunction(Module *mod, std::vector<encVar*> *gvars) {
// Declare and add the function definition
//errs()<<"Successful enter decode function"<<"\n";
std::vector<Type*>FuncTy_args;
FunctionType* FuncTy = FunctionType::get(
/*Result=*/Type::getVoidTy(mod->getContext()), // returning void
/*Params=*/FuncTy_args, // taking no args
/*isVarArg=*/false);
uint64_t StringObfDecodeRandomName = cryptoutils->get_uint64_t();
std::string random_str;
std::strstream random_stream;
std::stringstream random_stream;
random_stream << StringObfDecodeRandomName;
random_stream >> random_str;
StringObfDecodeRandomName++;
Constant* c = mod->getOrInsertFunction(".datadiv_decode" + random_str, FuncTy);
//errs() << "Function name is " << ".datadiv_decode" + random_str << "\n";
Function* fdecode = cast<Function>(c);
fdecode->setCallingConv(CallingConv::C);

// Declare some constants we'll use in the loop
ConstantInt* const_0 = ConstantInt::get(mod->getContext(), APInt(32, 0));
ConstantInt* const_1 = ConstantInt::get(mod->getContext(), APInt(32, 1));
BasicBlock* label_entry = BasicBlock::Create(mod->getContext(), "entry", fdecode);

BasicBlock* entry = BasicBlock::Create(mod->getContext(), "entry", fdecode);

IRBuilder<> builder(mod->getContext());
builder.SetInsertPoint(entry);


for (unsigned i = 0, e = gvars->size(); i != e; ++i) {
GlobalVariable *gvar = (*gvars)[i]->var;
char key = (*gvars)[i]->key;
//errs() << "Adding code for " << gvar->getName() << '\n';
uint8_t key = (*gvars)[i]->key;

Constant *init = gvar->getInitializer();
ConstantDataSequential *cdata = dyn_cast<ConstantDataSequential>(init);

unsigned len = cdata->getNumElements()*cdata->getElementByteSize();
--len;

BasicBlock *preHeaderBB=builder.GetInsertBlock();
BasicBlock* for_body = BasicBlock::Create(mod->getContext(), "for-body", fdecode);
BasicBlock* for_end = BasicBlock::Create(mod->getContext(), "for-end", fdecode);
builder.CreateBr(for_body);
builder.SetInsertPoint(for_body);
PHINode *variable = builder.CreatePHI(Type::getInt32Ty(mod->getContext()), 2, "i");
Value *startValue = builder.getInt32(0);
Value *endValue = builder.getInt32(len);
variable->addIncoming(startValue, preHeaderBB);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//LoadInst *Load=builder.CreateLoad(gvar);
//errs()<<"Load: "<<*(Load->getPointerOperand())<<"\n";
Value* indexList[2] = {ConstantInt::get(variable->getType(), 0), variable};
Value *const_key=builder.getInt8(key);
Value *GEP=builder.CreateGEP(gvar,ArrayRef<Value*>(indexList, 2),"arrayIdx");
LoadInst *loadElement=builder.CreateLoad(GEP,false);
loadElement->setAlignment(1);
//errs()<<"Type: "<<*loadElement<<"\n";
//CastInst* extended = new ZExtInst(const_key, loadElement->getType(), "extended", for_body);
//Value* extended = builder.CreateZExtOrBitCast(const_key, loadElement->getType(),"extended");
Value *Xor = builder.CreateXor(loadElement,const_key,"xor");
StoreInst *Store = builder.CreateStore(Xor, GEP,false);
Store->setAlignment(1);

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Value *stepValue = builder.getInt32(1);
Value *nextValue = builder.CreateAdd(variable, stepValue, "next-value");
Value *endCondition = builder.CreateICmpULT(variable, endValue, "end-condition");
endCondition = builder.CreateICmpNE(endCondition, builder.getInt1(0), "loop-condition");
BasicBlock *loopEndBB = builder.GetInsertBlock();
builder.CreateCondBr(endCondition, loopEndBB, for_end);
builder.SetInsertPoint(for_end);
variable->addIncoming(nextValue, loopEndBB);

}
builder.CreateRetVoid();
appendToGlobalCtors(*mod,fdecode,0);

// Add per-GV local decode code:
// for len(globVar): globVar[i] = globVar[i]^key

ConstantInt* const_len = ConstantInt::get(mod->getContext(), APInt(32, len));
BasicBlock* label_for_body = BasicBlock::Create(mod->getContext(), "for.body", fdecode, 0);
BasicBlock* label_for_end = BasicBlock::Create(mod->getContext(), "for.end", fdecode, 0);

ICmpInst* cmp = new ICmpInst(*label_entry, ICmpInst::ICMP_EQ, const_len, const_0, "cmp");
BranchInst::Create(label_for_end, label_for_body, cmp, label_entry);

// Block for.body (label_for_body)
Argument* fwdref_18 = new Argument(IntegerType::get(mod->getContext(), 32));
PHINode* int32_i = PHINode::Create(IntegerType::get(mod->getContext(), 32), 2, "i.09", label_for_body);
int32_i->addIncoming(fwdref_18, label_for_body);
int32_i->addIncoming(const_0, label_entry);

CastInst* int64_idxprom = new ZExtInst(int32_i, IntegerType::get(mod->getContext(), 64), "idxprom", label_for_body);
LoadInst* ptr_19 = new LoadInst(gvar, "", false, label_for_body);
ptr_19->setAlignment(8);
// Array/ptr load (GetElementPtr can be a bitch about this!)
std::vector<Value*> ptr_32_indices;
ptr_32_indices.push_back(const_0);
ptr_32_indices.push_back(int64_idxprom);
ArrayRef<Value*> ref_ptr_32_indices = ArrayRef<Value*>(ptr_32_indices);
Instruction* ptr_arrayidx = GetElementPtrInst::Create(NULL, gvar, ref_ptr_32_indices, "arrayidx", label_for_body);
// Load
LoadInst* int8_20 = new LoadInst(ptr_arrayidx, "", false, label_for_body);
int8_20->setAlignment(1);
// Decode
ConstantInt* const_key = ConstantInt::get(mod->getContext(), APInt(8, key));
//BinaryOperator* int8_dec = BinaryOperator::Create(Instruction::Add, int8_20, const_key, "sub", label_for_body);
BinaryOperator* int8_dec = BinaryOperator::Create(Instruction::Xor, int8_20, const_key, "xor", label_for_body);
// Store
StoreInst* void_21 = new StoreInst(int8_dec, ptr_arrayidx, false, label_for_body);
void_21->setAlignment(1);

// Adjust loop counter
BinaryOperator* int32_inc = BinaryOperator::Create(Instruction::Add, int32_i, const_1, "inc", label_for_body);

ICmpInst* int1_cmp = new ICmpInst(*label_for_body, ICmpInst::ICMP_EQ, int32_inc, const_len, "cmp");
BranchInst::Create(label_for_end, label_for_body, int1_cmp, label_for_body);

// Resolve Forward References
fwdref_18->replaceAllUsesWith(int32_inc); delete fwdref_18;

// adjust for next iteration
label_entry = label_for_end;
}

// Block for.end (label_for_end)
ReturnInst::Create(mod->getContext(), label_entry);


// Lets add our function to the constructors
std::vector<Type*>StructTy_4_fields;
StructTy_4_fields.push_back(IntegerType::get(mod->getContext(), 32));
std::vector<Type*>FuncTy_6_args;
FunctionType* FuncTy_6 = FunctionType::get(
/*Result=*/Type::getVoidTy(mod->getContext()),
/*Params=*/FuncTy_6_args,
/*isVarArg=*/false);

PointerType* PointerTy_5 = PointerType::get(FuncTy_6, 0);
StructTy_4_fields.push_back(PointerTy_5);
StructType *StructTy_4 = StructType::get(mod->getContext(), StructTy_4_fields, /*isPacked=*/false);
ArrayType* ArrayTy_3 = ArrayType::get(StructTy_4, 1);

GlobalVariable* gvar_array_llvm_global_ctors = NULL;
for (Module::global_iterator gi = mod->global_begin(); gi != mod->global_end(); ++gi)
{
if(gi->getName() == "llvm.global_ctors")
gvar_array_llvm_global_ctors = &*gi;
}

std::vector<Constant*> const_array_10_elems;
std::vector<Constant*> const_struct_11_fields;
ConstantInt* const_int32_16max = ConstantInt::get(mod->getContext(), APInt(32, StringRef("65535"), 10));
const_struct_11_fields.push_back(const_int32_16max);
const_struct_11_fields.push_back(fdecode);
Constant* const_struct_11 = ConstantStruct::get(StructTy_4, const_struct_11_fields);
const_array_10_elems.push_back(const_struct_11);
Constant* const_array_10 = ConstantArray::get(ArrayTy_3, const_array_10_elems);
// Global Variable Definitions
if(!gvar_array_llvm_global_ctors)
{
gvar_array_llvm_global_ctors = new GlobalVariable(/*Module=*/*mod,
/*Type=*/ArrayTy_3,
/*isConstant=*/false,
/*Linkage=*/GlobalValue::AppendingLinkage,
/*Initializer=*/0, // has initializer, specified below
/*Name=*/"llvm.global_ctors");
gvar_array_llvm_global_ctors->setInitializer(const_array_10);
}
else
{
ConstantArray* initer = dyn_cast<ConstantArray>(gvar_array_llvm_global_ctors->getInitializer());
for (Use &f : initer->operands())
const_array_10_elems.push_back(dyn_cast<Constant>(&*f));
const_array_10 = ConstantArray::get(ArrayTy_3, const_array_10_elems);
gvar_array_llvm_global_ctors->setInitializer(const_array_10);
}
}

};
Expand Down

0 comments on commit 7507d66

Please sign in to comment.