for (int i = 0; i < function_string.size(); i++) { // i64 index Value *Index = ConstantInt::get(Type::getInt64Ty(F.getContext()), i); // i8 char Value *CDATA = ConstantInt::get(Type::getInt8Ty(F.getContext()), function_string[i]); // get ptr bufferr[i] Value *GEP = IRB.CreateGEP(alloc, {Zero, Index}); // store data IRB.CreateStore(CDATA, GEP); }
代码里的注释已经很详细了。
5、好,准备完毕,寻找并调用printf
1 2
Function *func_printf = F.getParent()->getFunction("printf"); IRB.CreateCall(func_printf, {str});
voiddeclarePrintf(Function &F){ Function *func_printf = F.getParent()->getFunction("printf"); if (!func_printf) { FunctionType *FT = FunctionType::get(Type::getInt8PtrTy(F.getContext()), true); Function::Create(FT, Function::ExternalLinkage, "printf", F.getParent()); } }
voidinsertRodata(Function &F){ // get entry block BasicBlock *entryBlock = &F.getEntryBlock(); // insert printfBlock before entry block BasicBlock *printfBlock = BasicBlock::Create(F.getContext(), "printfRodataBlock", &F, entryBlock); // create function_string std::string function_string = "Function "; function_string += F.getName(); function_string += " is invoked! @rodatan"; // insert at end of printfBlock IRBuilder<> IRB(printfBlock); // find printf Function *func_printf = F.getParent()->getFunction("printf"); if (!func_printf) assert(false && "printf not found"); // create string ptr Value *str = IRB.CreateGlobalStringPtr(function_string); // create printf(funcName) IRB.CreateCall(func_printf, {str}); // create branch to entryBlock IRB.CreateBr(entryBlock); }
voidinsertData(Function &F){ // get entry block BasicBlock *entryBlock = &F.getEntryBlock(); // insert printfBlock before entry block BasicBlock *printfBlock = BasicBlock::Create(F.getContext(), "printfDataBlock", &F, entryBlock); // create function_string std::string function_string = "Function "; function_string += F.getName(); function_string += " is invoked! @datan"; // insert at end of printfBlock IRBuilder<> IRB(printfBlock); // find printf Function *func_printf = F.getParent()->getFunction("printf"); if (!func_printf) assert(false && "printf not found"); // create string ptr GlobalVariable *GV = IRB.CreateGlobalString(function_string); // set writable GV->setConstant(false); // i32 0 Constant *Zero = ConstantInt::get(Type::getInt32Ty(F.getContext()), 0); // for index Constant *Indices[] = {Zero, Zero}; // get ptr buffer[0] Value *str = ConstantExpr::getInBoundsGetElementPtr(GV->getValueType(), GV, Indices); // create printf(funcName) IRB.CreateCall(func_printf, {str}); // create branch to entryBlock IRB.CreateBr(entryBlock); }
voidinsertStack(Function &F){ // get entry block BasicBlock *entryBlock = &F.getEntryBlock(); // insert printfBlock before entry block BasicBlock *printfBlock = BasicBlock::Create(F.getContext(), "printfStackBlock", &F, entryBlock); // create function_string std::string function_string = "Function "; function_string += F.getName(); function_string += " is invoked! @stackn"; // insert at end of printfBlock IRBuilder<> IRB(printfBlock); // find printf Function *func_printf = F.getParent()->getFunction("printf"); if (!func_printf) assert(false && "printf not found"); // i8 0 Value *Zero = ConstantInt::get(Type::getInt8Ty(F.getContext()), 0); // i64 size Value *Size = ConstantInt::get(Type::getInt64Ty(F.getContext()), function_string.size() + 1); // i1 bool Value *Bool = ConstantInt::get(Type::getInt1Ty(F.getContext()), 0); // type: i8[size] ArrayType *arrayType = ArrayType::get(IntegerType::getInt8Ty(F.getContext()), function_string.size() + 1); // find llvm.memset.p0i8.i64 Function *func_memset = Intrinsic::getDeclaration(F.getParent(), Intrinsic::memset, {IntegerType::getInt8PtrTy(F.getContext()), IntegerType::getInt64Ty(F.getContext())}); // new i8[size] AllocaInst *alloc = IRB.CreateAlloca(arrayType); // align 16 alloc->setAlignment(16); // get ptr buffer[0] Value *str = IRB.CreateGEP(alloc, {Zero, Zero}); IRB.CreateCall(func_memset, {str, Zero, Size, Bool});
for (int i = 0; i < function_string.size(); i++) { // i64 index Value *Index = ConstantInt::get(Type::getInt64Ty(F.getContext()), i); // i8 char Value *CDATA = ConstantInt::get(Type::getInt8Ty(F.getContext()), function_string[i]); // get ptr bufferr[i] Value *GEP = IRB.CreateGEP(alloc, {Zero, Index}); // store data IRB.CreateStore(CDATA, GEP); } // create printf(funcName) IRB.CreateCall(func_printf, {str}); // create branch to entryBlock IRB.CreateBr(entryBlock); }
➜ /tmp clang -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include -Xclang -load -Xclang libmypass.so -w test.c -o test.bin Main Function Not Found! So create.
➜ /tmp ./test.bin f1 f2
六、总结
最开始写起来挺难受的,后面就觉得不难了,难点在于对 API 的不熟悉、对常见的 IR 约定不熟悉,本文讲的是最最最基础的一些操作,真正写混淆器时,遇到的困难比这个多多了,将来会分析前辈们的项目,讲讲实现方式。有机会的话,也会把一些不敏感的Pass 讲一下,但可能性不大。