本文为看雪论坛精华文章
看雪论坛作者ID:王cb
这篇文章旨在介绍一款对基于LLVM的retdec开源反编译器工具进行二次开发的IDA自动结构体识别插件实现原理分析。
一
源码分析
typedef struct TypeDescriptor
{
void * pVFTable; // Field overloaded by RTTI
void * spare; // reserved, possible for RTTI
char name[]; // The decorated name of the type; 0 terminated.类名称
} TypeDescriptor;
struct PMD
{
ptrdiff_t mdisp; //member displacement vftable offset
ptrdiff_t pdisp; //vftable displacement vftable offset
ptrdiff_t vdisp; //displacement within vftable offset(for virtual base class)
};
typedef const struct _s_RTTIBaseClassDescriptor
{
TypeDescriptor *pTypeDescriptor;
DWORD numContainedBases;
PMD where;
DWORD attributes;
} _RTTIBaseClassDescriptor;
typedef const struct _s_RTTIBaseClassArray
{
_RTTIBaseClassDescriptor* arrayOfBaseClassDescriptors[3];
}_RTTIBaseClassArray;
typedef const struct _s_RTTIClassHierarchyDescriptor
{
DWORD signature;
DWORD attributes;
DWORD numBaseClasses;
_RTTIBaseClassArray *pBaseClassArray;
}_RTTIClassHierarchyDescriptor;
typedef const struct _s_RTTICompleteObjectLocator
{
DWORD signature;
DWORD offset; //vftbl相对this的偏移
DWORD cdOffset; //constructor displacement
TypeDescriptor *pTypeDescriptor;
_RTTIClassHierarchyDescriptor *pClassDescriptor;
}_RTTICompleteObjectLocator;
typedef struct TypeDescriptor
{
#if defined(_WIN64) || defined(_RTTI) || defined(BUILDING_C1XX_FORCEINCLUDE)
const void * pVFTable; // Field overloaded by RTTI
#else
unsigned long hash; // Hash value computed from type's decorated name
#endif
void * spare; // reserved, possible for RTTI
char name[]; // The decorated name of the type; 0 terminated.
} TypeDescriptor;
//获取静态已知的跳转目标JumpTargets
void Decoder::initJumpTargets()
{
initJumpTargetsConfig();
initStaticCode();
initJumpTargetsEntryPoint();
initJumpTargetsExterns();
initJumpTargetsImports();
initJumpTargetsDebug();
initJumpTargetsSymbols();
initJumpTargetsExports();
initVtables();
}
//递归解析每个跳转目标JumpTarget直到没有跳转目标
void Decoder::decode()
{
JumpTarget jt;
while (getJumpTarget(jt))
{
decodeJumpTarget(jt);
}
}
//递归解析每个跳转目标JumpTarget
void Decoder::decodeJumpTarget(const JumpTarget& jt)
{
//使用反编译引擎capstone2llvmir转换ASM指令
auto res = translate(bytes, addr, irb);
llvm::CallInst*& pCall = res.branchCall;
//处理所有call类型及其条件call类型
if (_c2l->isCallFunctionCall(pCall)||_c2l->isBranchFunctionCall(pCall)||_c2l->isCondBranchFunctionCall(pCall))
{
auto t = getJumpTarget(addr, pCall, pCall->getArgOperand(0)){
//生成SymbolicTree
auto st = SymbolicTree::OnDemandRda(val, 20);
//获取跳转目标JumpTarget的常量值
llvm::ConstantInt* ci = nullptr;
if (match(st, m_ConstantInt(ci)))
{
return ci->getZExtValue();
}
}
//处理分支跳转条件表addrTblCi和索引计算获取所有跳转cases加入JumpTarget
getJumpTargetSwitch(addr, branchCall, val, st){
if(match(st, m_Load(
m_c_Add(
m_CombineOr(
m_c_Mul(m_Value(), m_ConstantInt(mulShlCi), &mulOp),
m_Shl(m_Value(), m_ConstantInt(mulShlCi), &shlOp)),
m_ConstantInt(addrTblCi))))){
llvm::Value* idx = mulOp ? mulOp->getOperand(0) : shlOp->getOperand(0);
std::vector<Address> cases;
while (true)
{
Address item = addrTblCi->getZExtValue();
addrTblCi += pointersize;
cases.push_back(item);
}
for (auto c : cases)
{
_jumpTargets.push(
c,
JumpTarget::eType::CONTROL_FLOW_SWITCH_CASE,
_c2l->getBasicMode(), // mode should not change here
addr);
}
}
};
_jumpTargets.push(t,JumpTarget::eType::CONTROL_FLOW_CALL_TARGET,determineMode(tr.capstoneInsn, t),addr);
}else if (_c2l->isReturnFunctionCall(pCall))
{
//如果是返回指令类型直接创建ReturnInst
transformToReturn(pCall);
}
}
capstone2llvmir::Capstone2LlvmIrTranslator::TranslationResultOne
Decoder::translate(ByteData& bytes, common::Address& addr, llvm::IRBuilder<>& irb)
{
cs_insn* insn = cs_malloc(_handle);
//调用capstone将二进制代码数据转换为cs_insn
bool disasmRes = cs_disasm_iter(_handle, &bytes, &size, &address, insn);
translateInstruction(insn, irb);
}
void Capstone2LlvmIrTranslatorX86_impl::translateInstruction(
cs_insn* i,
llvm::IRBuilder<>& irb)
{
//函数入口地址pc保存在"asm_program_counter"这个全局变量中
retdec::common::Address a = i->address;
auto* s = irb.CreateStore(llvm::ConstantInt::get(gv->getValueType(), a, false), asm_program_counter, true);
//这个表维护了所有可以转化的X86汇编指令
Capstone2LlvmIrTranslatorX86_impl::_i2fm =
{
...
{X86_INS_ADD, &Capstone2LlvmIrTranslatorX86_impl::translateAdd},
{X86_INS_MOV, &Capstone2LlvmIrTranslatorX86_impl::translateMov},
...
}
auto fIt = _i2fm.find(i->id);
if (fIt != _i2fm.end() && fIt->second != nullptr)
{
auto f = fIt->second;
//就是调用Capstone2LlvmIrTranslatorX86_impl::translateXXX
(this->*f)(i, xi, irb);
}else{
//转换函数调用
void Capstone2LlvmIrTranslator_impl<CInsn, CInsnOp>::translatePseudoAsmGeneric(
cs_insn* i,
CInsn* ci,
llvm::IRBuilder<>& irb)
{
llvm::Function* fnc = getPseudoAsmFunction(
i,
retType,
types);
auto* c = irb.CreateCall(fnc, vals);
//根据OperandAccess获取Call的返回值类型
llvm::Value* val = retType->isVoidTy()
? llvm::cast<llvm::Value>(
llvm::UndefValue::get(getRegisterType(r)))
: llvm::cast<llvm::Value>(c);
storeRegister(r, val, irb);
}
}
}
//对应转换函数
void Capstone2LlvmIrTranslatorX86_impl::translateXXX(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb)
{
//创建汇编代码的对应指令
std::tie(op0, op1) = loadOpXXX(xi, irb, eOpConv::SEXT_TRUNC_OR_BITCAST);
auto* add = irb.CreateXXX(op0, op1);
//生成指令操作
op1 = loadOp(xi->operands[1], irb);
storeOp(xi->operands[0], add, irb);
if (i->id == X86_INS_XADD)
{
storeOp(xi->operands[1], op0, irb);
}
}
int main(int argc, char *argv[])
{
std::vector<uint8_t> CODE = retdec::utils::hexStringToBytes("80 05 78 56 34 12 11 00");
ProgramOptions po(argc, argv);
llvm::LLVMContext ctx;
llvm::Module module("test", ctx);
auto* f = llvm::Function::Create(
llvm::FunctionType::get(llvm::Type::getVoidTy(ctx), false),
llvm::GlobalValue::ExternalLinkage,
"root",
&module);
llvm::BasicBlock::Create(module.getContext(), "entry", f);
llvm::IRBuilder<> irb(&f->front());
auto* ret = irb.CreateRetVoid();
irb.SetInsertPoint(ret);
auto c2l = Capstone2LlvmIrTranslator::createArch(
po.arch,
&module,
po.basicMode,
po.extraMode);
//调用capstone转换函数
auto res=c2l->translate(po.code.data(), po.code.size(), po.base, irb);
return EXIT_SUCCESS;
}
bool HLLWriter::emitTargetCode(ShPtr<Module> module) {
...
//输出模块静态引用相关信息
if (emitXXXHeader()) {}
....
emitFunctions();
...
}
//输出函数主体
bool HLLWriter::emitFunctions() {
FuncVector funcs(module->func_definition_begin(), module->func_definition_end());
sortFuncsForEmission(funcs);
bool somethingEmitted = false;
for (const auto &func : funcs) {
if (somethingEmitted) {
// To produce an empty line between functions.
out->newLine();
}
somethingEmitted |= emitFunction(func);
}
return somethingEmitted;
}
void CHLLWriter::visit(ShPtr<Function> func) {
if (func->isDeclaration()) {
emitFunctionPrototype(func);
}
else {
emitFunctionDefinition(func);
}
}
void CHLLWriter::emitFunctionDefinition(ShPtr<Function> func) {
PRECONDITION(func->isDefinition(), "it has to be a definition");
out->addressPush(func->getStartAddress());
emitFunctionHeader(func);
out->space();
emitBlock(func->getBody());
out->addressPop();
out->newLine();
}
//输出块主体
void CHLLWriter::emitBlock(ShPtr<Statement> stmt) {
out->punctuation('{');
out->newLine();
increaseIndentLevel();
// Emit the block, statement by statement.
do {
out->addressPush(stmt->getAddress());
emitGotoLabelIfNeeded(stmt);
// Are there any metadata?
std::string metadata = stmt->getMetadata();
if (!metadata.empty()) {
emitDebugComment(metadata);
}
stmt->accept(this);
out->addressPop();
//递归后继直到没有后继
stmt = stmt->getSuccessor();
} while (stmt);
decreaseIndentLevel();
out->space(getCurrentIndent());
out->punctuation('}');
}
bool SymbolicTypeReconstructor::runOnModule(llvm::Module& m)
{
for (auto addr : image->getRtti().getVtablesMsvc())
{
const Interpreter::InterpreterOptions opt;
RetdecInterpreterHandler interpreterHandlerPtr = new RetdecInterpreterHandler(M);
interpreter = Interpreter::create(ctx, opt, interpreterHandlerPtr);
_config = ConfigProvider::getConfig(M);
_module = _config->_module;
interpreter->initSingleModule(M);
DataLayout TD = _module->getDataLayout();
Context::initialize(TD.isLittleEndian(),
static_cast<Expr::Width>(TD.getPointerSizeInBits()));
llvm::Function* func = _config->getLlvmFunction(addr);
char * argv = nullptr;
char * env = nullptr;
//构建runFunctionAsMain执行每个要分析的函数
interpreter->runFunctionAsMain(func, 0, &argv, &env);
}
}
//重构函数入口处执行
void Executor::runFunctionAsMain(Function *f,
int argc,
char **argv,
char **envp) {
std::vector<ref<Expr> > arguments;{
ExecutionState *state = new ExecutionState(kmodule->functionMap[f]);
MemoryManager* memory = new MemoryManager(NULL);
//构建参数内存对象
MemoryObject* argvMO =
memory->allocate((argc + 1 + envc + 1 + 1) * NumPtrBytes,
/*isLocal=*/false, /*isGlobal=*/true,
/*allocSite=*/first, /*alignment=*/8);
//初始化全局变量:
initializeGlobals(*state);
void Executor::run(ExecutionState &state){
searcher = constructUserSearcher(*this);
std::vector<ExecutionState *> newStates(states.begin(), states.end());
searcher->update(0, newStates, std::vector<ExecutionState *>());
while (!states.empty() && !haltExecution) {
ExecutionState &state = searcher->selectState();
KInstruction *ki = state.pc;
stepInstruction(state);
executeInstruction(state, ki);
updateStates(&state);
}
//造一个伪造的预先分配rcx结构体和rsp栈结构体处理Function的参数
void Executor::initializeGlobalObjects(ExecutionState &state) {
...
if (isStackPointer(&v))
{
initializePreAllocedGlobalObjects(state, &op, v, true);
}
if (isThisPointer(&v))
{
MemoryObject *that=initializePreAllocedGlobalObjects(state, &op, v, false);
interpreterHandler->setThisPointerMemoryObject(that);
}
...
}
MemoryObject * Executor::initializePreAllocedGlobalObjects(ExecutionState &state, ObjectPair *op, const GlobalVariable &v, bool negative)
{
const MemoryObject *mo = op->first;
ObjectState *os = const_cast<ObjectState *>(op->second);
std::size_t allocationAlignment = getAllocationAlignment(&v);
MemoryObject *mo1 = memory->allocate(fixedStackSize, /*isLocal=*/false, /*isGlobal=*/true, /*allocSite=*/&v,/*alignment=*/allocationAlignment);
ObjectState *os1 = bindObjectInState(state, mo1, false);
uint64_t stackptr = negative ? mo1->address + (mo1->size / 2) - mo->size : mo1->address;
ref<ConstantExpr> stackexp = ConstantExpr::create(stackptr, Context::get().getPointerWidth());
os->write(0, stackexp);
return mo1;
}
void Executor::transferToBasicBlock(BasicBlock *dst, BasicBlock *src,
KFunction *kf = state.stack.back().kf;
unsigned entry = kf->basicBlockEntry[dst];
state.pc = &kf->instructions[entry];
if (state.pc->inst->getOpcode() == Instruction::PHI) {
PHINode *first = static_cast<PHINode*>(state.pc->inst);
state.incomingBBIndex = first->getBasicBlockIndex(src);
}
}
void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) {
Instruction *i = ki->inst;
switch (i->getOpcode()) {
...
case Instruction::Br: {
case Instruction::IndirectBr: {
transferToBasicBlock(bi->getSuccessor(0), bi->getParent(), state);
}
//读操作
case Instruction::Load: {
ref<Expr> base = eval(ki, 0, state).value;
executeMemoryOperation(state, false, base, 0, ki);
break;
}
//写操作
case Instruction::Store: {
ref<Expr> base = eval(ki, 1, state).value;
ref<Expr> value = eval(ki, 0, state).value;
executeMemoryOperation(state, true, base, value, 0);
break;
}
void Executor::executeMemoryOperation(ExecutionState &state,
bool isWrite,
ref<Expr> address,
ref<Expr> value /* undef if read */,
KInstruction *target /* undef if write */) {
ObjectPair op;//MemoryObject* mo 和ObjectState* os
//调用符号执行解释器(solver)采用符号化的方式求出需要操作ObjectPair
bool success=state.addressSpace.resolveOne(state, solver, address, op, success)) ;
ref<Expr> offset = mo->getOffsetExpr(address);
if (isWrite) {
ObjectState *wos = state.addressSpace.getWriteable(mo, os);
wos->write(offset, value);
}
else {
ref<Expr> result = os->read(offset, type);
}
ref<ConstantExpr> resultoffset;
bool successoffset = solver->getValue(state.constraints, offset, resultoffset,state.queryMetaData);
uint64_t offsetInBits = resultoffset->getZExtValue() * 8;
//笔者的内存插桩操作,判断mo是不是rcx的MemoryObject
interpreterHandler->instrumentMemoryOperation(isWrite, mo, offsetInBits, type);
}
Function
└── ExecutionState
└── AddressSpace
├── ObjectState
│ ├── Size
│ ├── ConcreteStore
│ └──UpdateList
│ ├── Index
│ └── Value
MemoryManager-> └── MemoryObject
├── Address
└── Size
class UpdateNode {
const ref<UpdateNode> next;
ref<Expr> index, value;
UpdateNode::UpdateNode(const ref<UpdateNode> &_next, const ref<Expr> &_index,
const ref<Expr> &_value)
: next(_next), index(_index), value(_value) {
size = next ? next->size + 1 : 1;
}}
class UpdateList {
const Array *root;
ref<UpdateNode> head;
UpdateList::UpdateList(const Array *_root, const ref<UpdateNode> &_head)
: root(_root), head(_head) {}
void UpdateList::extend(const ref<Expr> &index, const ref<Expr> &vlue) {
head = new UpdateNode(head, index, value);
}}
const UpdateList &ObjectState::getUpdates() const {
if (!updates.root) {
unsigned NumWrites = updates.head ? updates.head->getSize() : 0;
std::vector< std::pair< ref<Expr>, ref<Expr> > > Writes(NumWrites);
const auto *un = updates.head.get();
//从后至前反过来调用构造链表
for (unsigned i = NumWrites; i != 0; un = un->next.get()) {
--i;
Writes[i] = std::make_pair(un->index, un->value);
}
std::vector< ref<ConstantExpr> > Contents(size);
for (unsigned i = 0, e = size; i != e; ++i)
Contents[i] = ConstantExpr::create(0, Expr::Int8);
unsigned Begin = 0, End = Writes.size();
//从前至后构造执行链表操作
for (; Begin != End; ++Begin) {
ConstantExpr *Index = dyn_cast<ConstantExpr>(Writes[Begin].first);
if (!Index)
break;
ConstantExpr *Value = dyn_cast<ConstantExpr>(Writes[Begin].second);
if (!Value)
break;
Contents[Index->getZExtValue()] = Value;
}
static unsigned id = 0;
const Array *array = getArrayCache()->CreateArray(
"const_arr" + llvm::utostr(++id), size, &Contents[0],
&Contents[0] + Contents.size());
//链表重构一遍
updates = UpdateList(array, 0);
for (; Begin != End; ++Begin)
updates.extend(Writes[Begin].first, Writes[Begin].second);
}
return updates;
}
//解释器(solver)实现,解析表达式
bool Z3SolverImpl::internalRunSolver(
const Query &query, const std::vector<const Array *> *objects,
std::vector<std::vector<unsigned char> > *values, bool &hasSolution) {
Z3_solver theSolver = Z3_mk_solver(builder->ctx);
//当前ExecutionState的ConstraintManage表达式空间容器
ConstantArrayFinder constant_arrays_in_query;
for (auto const &constraint : query.constraints) {
Z3_solver_assert(builder->ctx, theSolver, builder->construct(constraint));
constant_arrays_in_query.visit(constraint);
Z3ASTHandle z3QueryExpr =
Z3ASTHandle(builder->construct(query.expr), builder->ctx);
//被描述成Kquery语法格式
constant_arrays_in_query.visit(query.expr);
SolverRunStatus runStatusCode = handleSolverResponse(theSolver, satisfiable, objects, values,
hasSolution);
return true;
}
笔者使用的替代方案是,当结构体体头部存在空隙时,,生成当前指针大小的int类型数组填充空隙,直到空隙小于指针大小,并用这个大小生成对应的int字段填充剩余空隙,对于结构体中间存在的空隙,也是采用同样的方法扩展空隙前的一个字段为数组类型直到到空隙小于字段大小,,同样用这个剩余大小生成对应的int字段填充剩余空隙,具体实现见笔者工程源码(https://gitee.com/cbwang505/llvmanalyzer/blob/master/retdec-master-build/LLVMSymbolicExecution/lib/Support/RetdecInterpreterHandler.cpp)。
//插桩操作
void RetdecInterpreterHandler::instrumentMemoryOperation(bool isWrite, const MemoryObject *mo, uint64_t offset, uint64_t width)
{
if (mo->address == thisptr->address)
{
if (isWrite)
{
klee_message("This point struct [operation:=>store] offset :=> %d , length :=> %d", offset, width);
}
else
{
klee_message("This point struct [operation:=>load ] offset :=> %d , length :=> %d", offset, width);
}
//模拟的结构体类型
llvm::Type* tp = llvm::Type::getIntNTy(_module->getContext(), width);
POverlappedEmulatedType typeEmu = new OverlappedEmulatedType{
offset,width,tp
};
classtp->typesct->emplace_back(typeEmu);
}
};
//模拟执行call指令
void Executor::callExternalFunction(ExecutionState &state,
KInstruction *target,
Function *function,
std::vector< ref<Expr> > &arguments) {
//调用内置调用函数接口(SpecialFunctionHandler)
if (specialFunctionHandler->handle(state, function, target, arguments))
return;
bool success = externalDispatcher->executeCall(function, target->inst, args);
if (!success) {
klee_warning("failed external call: %s ,try to skip" , function->getName().str().c_str());
//当前函数返回值的虚拟寄存器赋
Type *resultType = target->inst->getType();
if (resultType != Type::getVoidTy(function->getContext())) {
//构造默认的0返回值
ref<Expr> e = ConstantExpr::create(0,
getWidthForLLVMType(resultType));
bindLocal(target, state, e);
}
}
}
bool IDAStructWriter::emitTargetCode(ShPtr<Module> module)
{
ShPtr<UsedTypes> usedTypes(UsedTypesVisitor::getUsedTypes(module));
for (const auto &structType : usedStructTypes)
{
emitStructIDA(structType){
tid_t strucval = 0;
//通过名称匹配
std::regex vtblreg("Class_vtable_(.+)_type");
auto i = structNames.find(structType);
if (i != structNames.end()) {
std::string rawname = i->second;
uint64_t vtbladdr = 0;
std::cmatch results;
std::regex express(vtblreg);
if (std::regex_search(rawname.c_str(), results, express))
{
if (results.size() == 2)
{
std::string vtbstr = results[1];
vtbladdr = strtoull(vtbstr.c_str(), 0, 16);
}
}
strucval = get_struc_id(rawname.c_str());
if (strucval != BADADDR)
{
struc_t* sptr = get_struc(strucval);
del_struc(sptr);
}
//生成结构体
strucval = add_struc(BADADDR, rawname.c_str());
Address field_offset = 0;
const StructType::ElementTypes& elements = structType->getElementTypes();
for (StructType::ElementTypes::size_type i = 0; i < elements.size(); ++i) {
ShPtr<Type> elemType(elements.at(i));
uint64_t elelen = emitVarWithType(Variable::create("field_" + field_offset.toHexString(), elemType), strucval, field_offset.getValue());
field_offset += elelen;
}
INFO_MSG("Create Vtable Struct : " << rawname << " ,Size :"<< field_offset << std::endl);
}
}
}
uint64_t IDAStructWriter::emitVarWithType(ShPtr<Variable> var, tid_t strucval, Address field_offset)
{
struc_t* sptr = get_struc(strucval);
ShPtr<Type> varType(var->getType());
uint64_t elelen = DetermineTypeSize(varType);
var->accept(this);
flags_t flag = byte_flag();
flags_t flag2 = byte_flag();
std::string filename = var->getName();
if (isa<ArrayType>(varType))
{
...
}
else {
if (elelen == 1)
{
flag = byte_flag();
}
else if (elelen == 2)
{
flag = word_flag();
}
else if (elelen == 4)
{
flag = dword_flag();
}
else if (elelen == 6)
{
flag = word_flag();
flag2 = word_flag();
}
else if (elelen == 8)
{
flag = qword_flag();
}
if (elelen == 6)
{
//添加结构体成员
std::string filename2 = filename+"_";
add_struc_member(sptr, filename.c_str(), BADADDR, flag, nullptr, elelen-2);
add_struc_member(sptr, filename2.c_str(), BADADDR, flag2, nullptr, elelen-4);
}
else {
add_struc_member(sptr, filename.c_str(), BADADDR, flag, nullptr, elelen);
}
}
return elelen;
}
//注册ida的F5按键hexrays回调
install_hexrays_callback(my_hexrays_cb_t, nullptr);
ida_dll_data int idaapi my_hexrays_cb_t(void *ud, hexrays_event_t event, va_list va)
{
switch (event)
{
case hxe_open_pseudocode:
{
vdui_t* vu = va_arg(va, vdui_t *);
cfuncptr_t cfunc = vu.cfunc;
ea_t vtaddrreal=vtbl2fns.find(cfunc->entry_ea).first;
rawname.sprnt("Class_vtable_%x_type", vtaddrreal);
tid_t strucval = get_struc_id(rawname.c_str());
if (strucval)
{
tinfo_t new_type = create_typedef(rawname.c_str());
tinfo_t new_type_ptr = make_pointer(new_type);
for (lvar_t& vr : *cfunc->get_lvars())
{
qstring nm = vr.name;
//设置为分析出来的结构体引用
vr.set_lvar_type(new_type_ptr);
vu.refresh_view(false);
return;
}
}
//生成x86架构的Coff文件格式的功能的pass
bool BinWriter::runOnModule(llvm::Module& m)
{
SMDiagnostic Err;
_config = ConfigProvider::getConfig(_module);
std::string TheTriple = _module->getTargetTriple();
Triple ModuleTriple(TheTriple);
_module->setTargetTriple(TheTriple);
char *ErrorMsg = 0;
std::string Error;
const Target *TheTarget = TargetRegistry::lookupTarget(TheTriple,
Error);
TargetOptions opt;
std::unique_ptr<TargetMachine> Target_Machine(TheTarget->createTargetMachine(
TheTriple, "", "", opt, None, None, CodeGenOpt::None));
llvm::legacy::PassManager pm;
TargetLibraryInfoImpl TLII(ModuleTriple);
TLII.disableAllFunctions();
pm.add(new TargetLibraryInfoWrapperPass(TLII)); \
std::error_code EC;
_module->setDataLayout(Target_Machine->createDataLayout());
bool usefile = false;
bool ret = false;
std::string binOut = _config->getConfig().parameters.getOutputBinFile();
usefile = false;
SmallVector<char, 0> Buffer;
raw_svector_ostream OS(Buffer);
MCContext *Ctx;
cantFail(_module->materializeAll());
//编译代码到输出流
ret = Target_Machine->addPassesToEmitMC(pm, Ctx, OS);
pm.run(*_module);
size_t len = Buffer.size();
std::unique_ptr<MemoryBuffer> CompiledObjBuffer(
new SmallVectorMemoryBuffer(std::move(Buffer)));
Expected<std::unique_ptr<object::ObjectFile>> LoadedObject =
object::ObjectFile::createObjectFile(CompiledObjBuffer->getMemBufferRef());
RTDyldMM = new SectionMemoryManager();
//生成coff结构
Dyld = new RuntimeDyld(*static_cast<RuntimeDyld::MemoryManager*>(this), *static_cast<JITSymbolResolver*>(this));
LoadedObjectPtr = LoadedObject->get();
std::unique_ptr<RuntimeDyld::LoadedObjectInfo> L =
Dyld->loadObject(*LoadedObjectPtr);
this->remapSecLoadAddress();
Dyld->resolveRelocations();
this->remapGlobalSymbolTable(Dyld->getSymbolTable());
Dyld->registerEHFrames();
this->finalizeMemory();
size_t len_org = CompiledObjBuffer->getBufferSize();
for (auto sec : LoadedObjectPtr->sections())
{
if (sec.isText() && !sec.isData())
{
auto pair = realSecBuf.find(sec.getIndex());
if (pair != realSecBuf.end())
{
std::uint8_t* buffer_start = reinterpret_cast<std::uint8_t*>(pair->second);
size_t len = sec.getSize();
outbuf->reserve(len);
outbuf->clear();
for (int i = 0; i < len; i++)
{
outbuf->emplace_back(static_cast<unsigned char>(*(buffer_start + i)));
}
break;
}
}
}
size_t rawlen = outbuf->size();
std::ostringstream logstr;
logstr << "target compiler generate function binary buff :=> total size ";
logstr << std::hex << len_org;
logstr <<" bytes , raw size ";
logstr << std::hex << rawlen;
logstr << " bytes";
io::Log::phase(logstr.str(), io::Log::SubPhase);
return !ret;
}
//复制到ida新建的Segment
static bool idaapi moveBufferToSegment(LLVMFunctionTable* tbl, std::vector<std::uint8_t>& outBuff, int i)
{
put_bytes(tbl->raw_fuc[tbl->num_func].start_fun, outBuff.data(), len);
}
二
将笔者插件编译后Release文件解压至ida安装目录"C:\Program Files\IDA 7.0\plugins"
在plugins目录下plugins.cfg文件中添加以下两行:
在点击ida菜单中"Edit->Plugins->LLVMAnalyzer"启动插件
三
工具使用介绍
四
工作支持环境
Ida Pro 7.0
只支持Windows操作系统,X86架构输入文件
编译环境 Visual Studio 2017
QT环境版本5.6.0及vs插件
五
源代码编译方法
六
工具使用效果
可点击『阅读原文』查看
看雪ID:王cb
https://bbs.pediy.com/user-home-609565.htm
# 往期推荐
2.Go解析
球分享
球点赞
球在看
点击“阅读原文”,了解更多!