basic cmplog std::string support

This commit is contained in:
van Hauser 2021-01-22 15:58:12 +01:00
parent 46010a8704
commit baf1ac2e69
3 changed files with 208 additions and 10 deletions

View File

@ -32,6 +32,8 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
- fixed endless loop for allow/blocklist lines starting with a
comment (thanks to Zherya for reporting)
- cmplog/redqueen now also tracks floating point, _ExtInt() + 128bit
- cmplog/redqueen can now process basic libc++ and libstdc++
std::string comparisons (though no position or length type variants)
- added AFL_LLVM_INSTRUMENT option NATIVE for native clang pc-guard
support (less performant than our own), GCC for old afl-gcc and
CLANG for old afl-clang

View File

@ -1549,10 +1549,10 @@ void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) {
u32 i;
if (!area_is_mapped(ptr1, 32) || !area_is_mapped(ptr2, 32)) return;
fprintf(stderr, "rtn arg0=");
for (i = 0; i < 8; i++)
for (i = 0; i < 24; i++)
fprintf(stderr, "%02x", ptr1[i]);
fprintf(stderr, " arg1=");
for (i = 0; i < 8; i++)
for (i = 0; i < 24; i++)
fprintf(stderr, "%02x", ptr2[i]);
fprintf(stderr, "\n");
*/

View File

@ -87,7 +87,7 @@ char CmpLogRoutines::ID = 0;
bool CmpLogRoutines::hookRtns(Module &M) {
std::vector<CallInst *> calls;
std::vector<CallInst *> calls, llvmStdStd, llvmStdC, gccStdStd, gccStdC;
LLVMContext & C = M.getContext();
Type *VoidTy = Type::getVoidTy(C);
@ -112,6 +112,78 @@ bool CmpLogRoutines::hookRtns(Module &M) {
FunctionCallee cmplogHookFn = c;
#endif
#if LLVM_VERSION_MAJOR < 9
Constant *
#else
FunctionCallee
#endif
c1 = M.getOrInsertFunction("__cmplog_rtn_llvm_stdstring_stdstring",
VoidTy, i8PtrTy, i8PtrTy
#if LLVM_VERSION_MAJOR < 5
,
NULL
#endif
);
#if LLVM_VERSION_MAJOR < 9
Function *cmplogLlvmStdStd = cast<Function>(c1);
#else
FunctionCallee cmplogLlvmStdStd = c1;
#endif
#if LLVM_VERSION_MAJOR < 9
Constant *
#else
FunctionCallee
#endif
c2 = M.getOrInsertFunction("__cmplog_rtn_llvm_stdstring_cstring", VoidTy,
i8PtrTy, i8PtrTy
#if LLVM_VERSION_MAJOR < 5
,
NULL
#endif
);
#if LLVM_VERSION_MAJOR < 9
Function *cmplogLlvmStdC = cast<Function>(c2);
#else
FunctionCallee cmplogLlvmStdC = c2;
#endif
#if LLVM_VERSION_MAJOR < 9
Constant *
#else
FunctionCallee
#endif
c3 = M.getOrInsertFunction("__cmplog_rtn_gcc_stdstring_stdstring", VoidTy,
i8PtrTy, i8PtrTy
#if LLVM_VERSION_MAJOR < 5
,
NULL
#endif
);
#if LLVM_VERSION_MAJOR < 9
Function *cmplogGccStdStd = cast<Function>(c3);
#else
FunctionCallee cmplogGccStdStd = c3;
#endif
#if LLVM_VERSION_MAJOR < 9
Constant *
#else
FunctionCallee
#endif
c4 = M.getOrInsertFunction("__cmplog_rtn_gcc_stdstring_cstring", VoidTy,
i8PtrTy, i8PtrTy
#if LLVM_VERSION_MAJOR < 5
,
NULL
#endif
);
#if LLVM_VERSION_MAJOR < 9
Function *cmplogGccStdC = cast<Function>(c4);
#else
FunctionCallee cmplogGccStdC = c4;
#endif
/* iterate over all functions, bbs and instruction and add suitable calls */
for (auto &F : M) {
@ -131,19 +203,67 @@ bool CmpLogRoutines::hookRtns(Module &M) {
FunctionType *FT = Callee->getFunctionType();
// _ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7compareEmmPKcm
// => libc++ => llvm => __cmplog_rtn_llvm_stdstring_cstring(u8 *stdstring1, u8 *stdstring2)
// _ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE7compareEPKc
// => libstdc++ => gcc => __cmplog_rtn_gcc_stdstring_cstring
bool isPtrRtn = FT->getNumParams() >= 2 &&
!FT->getReturnType()->isVoidTy() &&
FT->getParamType(0) == FT->getParamType(1) &&
FT->getParamType(0)->isPointerTy();
if (!isPtrRtn) continue;
bool isGccStdStringStdString =
Callee->getName().find("__is_charIT_EE7__value") !=
std::string::npos &&
Callee->getName().find(
"St7__cxx1112basic_stringIS2_St11char_traits") !=
std::string::npos &&
FT->getNumParams() >= 2 &&
FT->getParamType(0) == FT->getParamType(1) &&
FT->getParamType(0)->isPointerTy();
calls.push_back(callInst);
bool isGccStdStringCString =
Callee->getName().find(
"St7__cxx1112basic_stringIcSt11char_"
"traitsIcESaIcEE7compareEPK") != std::string::npos &&
FT->getNumParams() >= 2 && FT->getParamType(0)->isPointerTy() &&
FT->getParamType(1)->isPointerTy();
bool isLlvmStdStringStdString =
Callee->getName().find("_ZNSt3__1eqINS") != std::string::npos &&
Callee->getName().find("_12basic_stringIcNS_11char_traits") !=
std::string::npos &&
FT->getNumParams() >= 2 && FT->getParamType(0)->isPointerTy() &&
FT->getParamType(1)->isPointerTy();
bool isLlvmStdStringCString =
Callee->getName().find("ZNSt3__1eqIcNS") != std::string::npos &&
Callee->getName().find("_12basic_stringI") != std::string::npos &&
FT->getNumParams() >= 2 && FT->getParamType(0)->isPointerTy() &&
FT->getParamType(1)->isPointerTy();
/*
fprintf(stderr, "F:%s C:%s argc:%u\n",
F.getName().str().c_str(), Callee->getName().str().c_str(),
FT->getNumParams()); fprintf(stderr, "ptr0:%u ptr1:%u ptr2:%u\n",
FT->getParamType(0)->isPointerTy(),
FT->getParamType(1)->isPointerTy(),
FT->getNumParams() > 2 ? FT->getParamType(2)->isPointerTy()
: 22 );
*/
if (isGccStdStringCString || isGccStdStringStdString ||
isLlvmStdStringStdString || isLlvmStdStringCString) {
isPtrRtn = false;
fprintf(stderr, "%u %u %u %u\n", isGccStdStringCString,
isGccStdStringStdString, isLlvmStdStringStdString,
isLlvmStdStringCString);
}
if (isPtrRtn) { calls.push_back(callInst); }
if (isGccStdStringStdString) { gccStdStd.push_back(callInst); }
if (isGccStdStringCString) { gccStdC.push_back(callInst); }
if (isLlvmStdStringStdString) { llvmStdStd.push_back(callInst); }
if (isLlvmStdStringCString) { llvmStdC.push_back(callInst); }
}
@ -179,6 +299,82 @@ bool CmpLogRoutines::hookRtns(Module &M) {
}
for (auto &callInst : gccStdStd) {
Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);
IRBuilder<> IRB(callInst->getParent());
IRB.SetInsertPoint(callInst);
std::vector<Value *> args;
Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
args.push_back(v1Pcasted);
args.push_back(v2Pcasted);
IRB.CreateCall(cmplogGccStdStd, args);
// errs() << callInst->getCalledFunction()->getName() << "\n";
}
for (auto &callInst : gccStdC) {
Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);
IRBuilder<> IRB(callInst->getParent());
IRB.SetInsertPoint(callInst);
std::vector<Value *> args;
Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
args.push_back(v1Pcasted);
args.push_back(v2Pcasted);
IRB.CreateCall(cmplogGccStdC, args);
// errs() << callInst->getCalledFunction()->getName() << "\n";
}
for (auto &callInst : llvmStdStd) {
Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);
IRBuilder<> IRB(callInst->getParent());
IRB.SetInsertPoint(callInst);
std::vector<Value *> args;
Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
args.push_back(v1Pcasted);
args.push_back(v2Pcasted);
IRB.CreateCall(cmplogLlvmStdStd, args);
// errs() << callInst->getCalledFunction()->getName() << "\n";
}
for (auto &callInst : llvmStdC) {
Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);
IRBuilder<> IRB(callInst->getParent());
IRB.SetInsertPoint(callInst);
std::vector<Value *> args;
Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
args.push_back(v1Pcasted);
args.push_back(v2Pcasted);
IRB.CreateCall(cmplogLlvmStdC, args);
// errs() << callInst->getCalledFunction()->getName() << "\n";
}
return true;
}