#ifndef STARS_ida_Interface_h #define STARS_ida_Interface_h #include <cstdio> #include <memory> #include <map> #include <pro.h> #include <fpro.h> #include <lines.hpp> #include <segment.hpp> #include <funcs.hpp> #include "interfaces/abstract/STARSInterface.h" #include "interfaces/abstract/STARSInstructionID.h" #include "interfaces/idapro/STARSSegment.h" #include "interfaces/idapro/STARSFunction.h" #include "interfaces/idapro/STARSInstruction.h" class STARS_IDA_Interface_t : public STARS_Interface_t { public: // Constructors STARS_IDA_Interface_t() : CGCBinary(false) {}; // Destructor ~STARS_IDA_Interface_t() { this->funcmap.clear(); this->segmap.clear(); } // Segment accessors virtual STARS_Segment_t *getseg(const STARS_ea_t &addr) { segment_t* seg = ::getseg(addr); return seg2Seg(seg); } virtual STARS_Segment_t *getnseg(const int &index) { segment_t* seg = ::getnseg(index); return seg2Seg(seg); } virtual std::size_t get_segm_qty() { return ::get_segm_qty(); }; virtual STARS_Segment_t *get_next_seg(const STARS_ea_t &addr) { segment_t* seg = ::get_next_seg(addr); return seg2Seg(seg); } // Function accessors // find out how many functions there are virtual std::size_t get_func_qty() { return ::get_func_qty(); }; // get the index-th function virtual STARS_Function_t *getn_func(int index) { func_t* Func = ::getn_func(index); return func2Func(Func); } // get the function at the given address virtual STARS_Function_t *get_func(const STARS_ea_t ea) { func_t* f = ::get_func(ea); return func2Func(f); } virtual void get_func_name(const STARS_ea_t &ea, char* name, const std::size_t &len) { func_t* f = ::get_func(ea); if (f) { func2Func(f)->GetFunctionName(name, len); return; } /* empty name */ name[0] = '\0'; return; } // Instruction creation. virtual std::unique_ptr<STARS_Instruction_t> CreateInst(STARS_InstructionID_t InstID) { return std::unique_ptr<STARS_Instruction_t>{(STARS_Instruction_t *) new STARS_IDA_Instruction_t(InstID)}; } // File methods. virtual FILE *STARS_fopen(const char *file, const char *mode) { return qfopen(file, mode); }; virtual int STARS_fclose(FILE *fp) { return qfclose(fp); }; virtual int STARS_msg(const char *format, ...); virtual int STARS_fprintf(FILE *fp, const char *format, ...); virtual int STARS_fscanf(FILE *fp, const char *format, ...); virtual long STARS_ftell(FILE *fp); virtual char *STARS_fgets(char *buffer, int buflen, FILE *fp); virtual int STARS_fseek(FILE *fp, long offset, int whence); virtual int STARS_fgetc(FILE *fp) { return qfgetc(fp); }; // String methods virtual char *STARS_strncat(char *dst, const char *src, std::size_t dstsize) { return qstrncat(dst, src, dstsize); }; virtual char *STARS_strncpy(char *dst, const char *src, std::size_t dstsize) { return qstrncpy(dst, src, dstsize); }; virtual int STARS_snprintf(char *buffer, std::size_t n, const char *format, ...); // Disasm methods. #if (IDA_SDK_VERSION < 700) virtual STARS_ssize_t STARS_tag_remove(char *instr, char *buf, std::size_t bufsize) { return tag_remove(instr, buf, bufsize); }; #else virtual STARS_ssize_t STARS_tag_remove(char *instr, char *buf, std::size_t bufsize) { qstring *temp = new qstring(); temp->resize(bufsize); STARS_ssize_t ReturnLen = tag_remove(temp, buf); if (0 <= ReturnLen) { qstrncpy(instr, temp->c_str(), bufsize); } delete temp; return ReturnLen; }; #endif #if (IDA_SDK_VERSION < 700) virtual bool STARS_generate_disasm_line(STARS_ea_t addr, char *buf, std::size_t bufsize, int flags = 0) { return ::generate_disasm_line(addr, buf, bufsize, flags); } #else virtual bool STARS_generate_disasm_line(STARS_ea_t addr, char *buf, std::size_t bufsize, int flags = 0) { qstring *temp = new qstring(); temp->resize(bufsize); bool success = ::generate_disasm_line(temp, addr, flags); if (success) { qstrncpy(buf, temp->c_str(), bufsize); } delete temp; return success; } #endif // Miscellaneous methods. virtual bool STARS_getenv(const char *varname, char varvalue[STARS_MAXSTR]) const; virtual void SetCGCBinary(void) { CGCBinary = true; }; virtual bool IsCGCBinary(void) const { return CGCBinary; }; virtual bool InstHasNoCodeXrefs(STARS_InstructionID_t InstID) const; virtual bool IsInstJumpTarget(STARS_InstructionID_t InstID); virtual STARS_InstructionID_t FindFirstCallTarget(STARS_InstructionID_t CallInstID); // Find call target; first one, if any, for indirect call // Miscellaneous IDA-only methods. virtual void AuditTailChunkOwnership(void); virtual void AuditCodeTargets(void); // Detect IDA Pro func boundary problems, if code segment range; true if problems found virtual bool AuditFunctionBoundaries(const STARS_ea_t startEA, const STARS_ea_t endEA) const; // Detect IDA Pro func boundary problems using EH_FRAME FDE info; true if problems found virtual bool AuditEHFunctionBoundaries(void); virtual bool STARS_patch_byte(STARS_ea_t InstAddr, uint32_t ByteValue); // Patch IDA Pro database. private: bool CGCBinary; STARS_Segment_t* seg2Seg(segment_t* seg) { if (!seg) return NULL; if (segmap[seg] == NULL) segmap[seg] = new STARS_IDA_Segment_t(seg); return segmap[seg]; } std::map<segment_t*, STARS_Segment_t*> segmap; STARS_Function_t* func2Func(func_t* f) { if (!f) return NULL; if (funcmap[f] == NULL) funcmap[f] = new STARS_IDA_Function_t(f); return funcmap[f]; } std::map<func_t*, STARS_Function_t*> funcmap; // From StartAddr to LimitAddr - 1, make IDA Pro re-analyze so that one function contains all addrs. // StartFunc is current IDA Pro func for StartAddr, EndFunc is current IDA Pro func for LimitAddr - 1. // A nullptr value for either one indicates orphaned code, outside of any function. bool RedefineIDAFuncBounds(func_t *StartFunc, func_t *EndFunc, const STARS_ea_t StartAddr, const STARS_ea_t LimitAddr); // From StartAddr to LimitAddr - 1, do we have nothing but no-op instructions? bool IsNopInstSequence(const STARS_ea_t StartAddr, const STARS_ea_t LimitAddr); }; #endif