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