from__future__importannotationsimportloggingfromenumimportEnum,autofromtypingimportTYPE_CHECKINGfromdataclassesimportdataclassfromangr.analysesimportAnalysis,AnalysesHubifTYPE_CHECKING:fromangr.knowledge_pluginsimportFunctionlog=logging.getLogger(__name__)classCodeCaveClassification(Enum):""" Type of code caves. """ALIGNMENT=auto()UNREACHABLE=auto()@dataclassclassCodeCave:""" Describes a code cave in a binary. """func:Function|Noneaddr:intsize:intclassification:CodeCaveClassification
[文档]classCodeCaveAnalysis(Analysis):""" Best-effort static location of potential vacant code caves for possible code injection: - Padding functions - Unreachable code """codecaves:list[CodeCave]
[文档]def__init__(self):self.codecaves=[]iflen(self.project.kb.functions)==0andself.project.kb.cfgs.get_most_accurate()isNone:log.warning("Please run CFGFast analysis first, to identify functions")return# Alignment functionsforfuncinself.project.kb.functions.values():iffunc.is_alignment:forblockinfunc.blocks:self.codecaves.append(CodeCave(func,block.addr,block.size,CodeCaveClassification.ALIGNMENT))# Unreachable codeforfuncinself.project.kb.functions.values():iffunc.is_alignmentorfunc.is_pltorfunc.is_simprocedureorfunc.addrinself.project.kb.labels:continuein_degree=self.project.kb.callgraph.in_degree(func.addr)ifin_degree==0or(in_degree==1andself.project.kb.functions[next(self.project.kb.callgraph.predecessors(func.addr))].is_alignment):forblockinfunc.blocks:self.codecaves.append(CodeCave(func,block.addr,block.size,CodeCaveClassification.UNREACHABLE))
# FIXME: find dead blocks with argument propagation# FIXME: find dead blocks with external coverage infoAnalysesHub.register_default("CodeCaves",CodeCaveAnalysis)