Add Scrap_analyze.py to locate and mark up engine vars and callbacks
This commit is contained in:
		
							parent
							
								
									b5afe0e2a5
								
							
						
					
					
						commit
						45f38885ec
					
				
					 1 changed files with 134 additions and 0 deletions
				
			
		
							
								
								
									
										134
									
								
								tools/ghidra_scripts/Scrap_analyze.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								tools/ghidra_scripts/Scrap_analyze.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,134 @@ | |||
| 
 | ||||
| try: | ||||
|     import ghidra_bridge | ||||
|     has_bridge=True | ||||
| except ImportError: | ||||
|     has_bridge=False | ||||
| 
 | ||||
| from contextlib import contextmanager | ||||
| 
 | ||||
| if has_bridge: | ||||
|     import ghidra_bridge | ||||
|     b = ghidra_bridge.GhidraBridge(namespace=globals(), hook_import=True) | ||||
|     @contextmanager | ||||
|     def transaction(): | ||||
|         start() | ||||
|         try: | ||||
|             yield | ||||
|         except Exception as e: | ||||
|             end(False) | ||||
|             raise e | ||||
|         end(True) | ||||
| else: | ||||
|     @contextmanager | ||||
|     def transaction(): | ||||
|         yield | ||||
| 
 | ||||
| import ghidra.program.model.symbol.SymbolType as SymbolType | ||||
| import ghidra.program.model.symbol.SourceType as SourceType | ||||
| from ghidra.app.cmd.label import CreateNamespacesCmd | ||||
| from ghidra.program.model.data.DataUtilities import createData | ||||
| from ghidra.program.model.data.DataUtilities import ClearDataMode | ||||
| from ghidra.program.model.listing.CodeUnit import PLATE_COMMENT | ||||
| def make_namespace(parts): | ||||
|     ns_cmd = CreateNamespacesCmd("::".join(parts), SourceType.USER_DEFINED) | ||||
|     ns_cmd.applyTo(currentProgram) | ||||
|     return ns_cmd.getNamespace() | ||||
| 
 | ||||
| 
 | ||||
| callback_refs = [ref.fromAddress for ref in getReferencesTo(toAddr(0x590C70)).tolist()] | ||||
| engine_var_refs = [ | ||||
|     ref.fromAddress for ref in getReferencesTo(toAddr(0x5319D0)).tolist() | ||||
| ] | ||||
| 
 | ||||
| dtm = currentProgram.getDataTypeManager() | ||||
| engine_var_dt = dtm.getDataType("/EngineVar") | ||||
| callback_dt = dtm.getDataType("/CCallback") | ||||
| 
 | ||||
| def create_data(addr,dtype): | ||||
|     return createData(currentProgram,addr,dtype,0,False,ClearDataMode.CLEAR_ALL_CONFLICT_DATA) | ||||
| 
 | ||||
| def create_str(addr): | ||||
|     str_len = (findBytes(addr, b"\0").offset - addr.offset) + 1 | ||||
|     clearListing(addr, addr.add(str_len)) | ||||
|     return createAsciiString(addr) | ||||
| 
 | ||||
| 
 | ||||
| def make_namespace(parts): | ||||
|     ns_cmd = CreateNamespacesCmd("::".join(parts), SourceType.USER_DEFINED) | ||||
|     ns_cmd.applyTo(currentProgram) | ||||
|     return ns_cmd.getNamespace() | ||||
| 
 | ||||
| 
 | ||||
| def get_call_obj(addr): | ||||
|     func = getFunctionContaining(addr) | ||||
|     if func is None: | ||||
|         disassemble(addr) | ||||
|         func = createFunction(addr,None) | ||||
|     call_obj = {"this": None, "stack": []} | ||||
|     for inst in currentProgram.listing.getInstructions(func.body, True): | ||||
|         affected_objs = [r.toString() for r in inst.resultObjects.tolist()] | ||||
|         inst_name = inst.getMnemonicString() | ||||
|         if inst_name == "PUSH": | ||||
|             val=inst.getScalar(0) | ||||
|             if val is not None: | ||||
|                 call_obj["stack"].insert(0, toAddr(val.getValue()).toString()) | ||||
|         elif inst_name == "MOV" and "ECX" in affected_objs: | ||||
|             this = inst.getScalar(1) | ||||
|             if this is not None: | ||||
|                 call_obj["this"] = toAddr(this.getValue()).toString() | ||||
|         elif inst_name == "CALL": | ||||
|             break | ||||
|     return func, call_obj | ||||
| 
 | ||||
| 
 | ||||
| with transaction(): | ||||
|     for ref in callback_refs: | ||||
|         register_callback, call_obj = get_call_obj(ref) | ||||
|         name, addr = call_obj["stack"] | ||||
|         this = toAddr(call_obj["this"]) | ||||
|         addr = toAddr(addr) | ||||
|         name = create_str(toAddr(name)).getValue() | ||||
|         callback_ns = make_namespace(["Callbacks"]) | ||||
|         ns = make_namespace(["Callbacks", name]) | ||||
|         clearListing(addr) | ||||
|         disassemble(addr) | ||||
|         func = createFunction(addr,None) | ||||
|         print(name,func) | ||||
|         createLabel(addr, name, callback_ns, True, SourceType.USER_DEFINED) | ||||
|         createLabel( | ||||
|             register_callback.getEntryPoint(), | ||||
|             "register", | ||||
|             ns, | ||||
|             True, | ||||
|             SourceType.USER_DEFINED, | ||||
|         ) | ||||
|         createLabel(this, name, None, True, SourceType.USER_DEFINED) | ||||
|         create_data(this,callback_dt) | ||||
| 
 | ||||
|     for ref in engine_var_refs: | ||||
|         register_engine_var, call_obj = get_call_obj(ref) | ||||
|         engine_var = call_obj['this'] | ||||
|         try: | ||||
|             name,flags,desc = call_obj['stack'][:3] | ||||
|         except ValueError: | ||||
|             continue | ||||
|         name=create_str(toAddr(name)).getValue() | ||||
|         desc=create_str(toAddr(desc)).getValue() | ||||
|         print(name,ref) | ||||
|         ev_ns = make_namespace(["EngineVars"]) | ||||
|         ns = make_namespace(["EngineVars", name]) | ||||
|         clearListing(toAddr(engine_var)) | ||||
|         create_data(toAddr(engine_var),engine_var_dt).setComment(PLATE_COMMENT,desc) | ||||
|         createLabel(toAddr(engine_var), name, ev_ns, True, SourceType.USER_DEFINED) | ||||
|         clearListing(register_engine_var.getEntryPoint()) | ||||
|         createLabel(register_engine_var.getEntryPoint(), "register", ns, True, SourceType.USER_DEFINED) | ||||
| 
 | ||||
| # listing = currentProgram.getListing() | ||||
| # codeUnit = listing.getCodeUnitAt(minAddress) | ||||
| # codeUnit.setComment(codeUnit.PLATE_COMMENT, "AddCommentToProgramScript - This is an added comment!") | ||||
| 
 | ||||
| 
 | ||||
| # dtm = currentProgram.getDataTypeManager() | ||||
| # dt_engine_var = dtm.getDataType("/EngineVar") | ||||
| # dt_engine_ptr = dtm.getPointer(dt_engine_var) | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue