From facfd66caaa5ba7aafe4f261ebe8eb5774c6bbbe Mon Sep 17 00:00:00 2001 From: superp00t Date: Wed, 1 Apr 2026 17:39:27 -0400 Subject: [PATCH] chore(build): add new ghidra scripts --- .gitattributes | 1 + ghidra/MSVCExportSymbolsScript.py | 90 ++++++++++++++++++++++++++++ ghidra/SuperExportSymbolsScript.py | 87 +++++++++++++++++++++++++++ ghidra/YankCurrentFunctionSymbol.py | 75 +++++++++++++++++++++++ ghidra/logo.png | Bin 0 -> 1913 bytes 5 files changed, 253 insertions(+) create mode 100644 ghidra/MSVCExportSymbolsScript.py create mode 100644 ghidra/SuperExportSymbolsScript.py create mode 100644 ghidra/YankCurrentFunctionSymbol.py create mode 100755 ghidra/logo.png diff --git a/.gitattributes b/.gitattributes index 6b704f6..4aad274 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,5 @@ * text eol=lf +*.png binary *.dd32 binary *.parquet filter=lfs diff=lfs merge=lfs -text profile/*/x64dbg/game.* -diff diff --git a/ghidra/MSVCExportSymbolsScript.py b/ghidra/MSVCExportSymbolsScript.py new file mode 100644 index 0000000..c425442 --- /dev/null +++ b/ghidra/MSVCExportSymbolsScript.py @@ -0,0 +1,90 @@ +#Export all autoanalysis MSVC functions to a Binana symbol file +# @runtime Jython +# @category Binana +# @author Thunderbrew +# @menupath +# @toolbar logo.png + +from ghidra.program.model.symbol import SymbolType +from java.awt import Toolkit +from java.awt.datatransfer import StringSelection +from ghidra.app.decompiler import DecompInterface +from ghidra.util.task import ConsoleTaskMonitor +from ghidra.program.model.symbol.SourceType import * +from ghidra.program.model.symbol import SourceType + +functionManager = currentProgram.getFunctionManager() + +file_location = askFile("Choose a file to save your Binana symbols to", "Go") + +listing = currentProgram.getListing() + +decomp_interface = DecompInterface() +decomp_interface.openProgram(currentProgram) + +def get_function_type(func): + """Uses the Decompiler to get the refined signature.""" + if func is None: + return "" + + results = decomp_interface.decompileFunction(func, 30, ConsoleTaskMonitor()) + high_func = results.getHighFunction() + + if high_func is None: + return "" + + ret_type = high_func.getFunctionPrototype().getReturnType().getName().replace(" *", "*") + + call_conv = high_func.getFunctionPrototype().getModelName() + + params = [] + num_params = high_func.getFunctionPrototype().getNumParams() + for i in range(num_params): + p = high_func.getFunctionPrototype().getParam(i) + params.append("{} {}".format(p.getDataType().getName().replace(" *", "*"), p.getName())) + + param_str = "(" + (", ".join(params)) + ")" + return ret_type + " " + call_conv + " func" + param_str + +def get_symbol_entry_for_function(func): + name = func.getName() + + entry_addr = func.getEntryPoint().toString().upper()[-8:] + body = func.getBody() + end_addr = (body.getMaxAddress().add(1)).toString().upper()[-8:] + + func_type = get_function_type(func) + # func_type = "" + + if func_type == "": + output = "{} {} f end={} auto".format(name, entry_addr, end_addr) + else: + output = "{} {} f end={} type=\"{}\" auto".format( + name, + entry_addr, + end_addr, + func_type + ) + return output + +def export_function_symbols(file): + monitor.setMessage("Exporting MSVC autoanalysis function symbols...") + + for f in functionManager.getFunctionsNoStubs(1): + monitor.checkCanceled() # throws exception if canceled + + if f.isExternal() or f.isThunk(): + continue + + symbol = f.getSymbol() + if symbol.getSource() == SourceType.ANALYSIS: + func_line = get_symbol_entry_for_function(f) + monitor.setMessage(func_line) + + file.write(func_line + "\n") + + return + +with open(file_location.absolutePath, "w") as file: + export_function_symbols(file) + file.close() diff --git a/ghidra/SuperExportSymbolsScript.py b/ghidra/SuperExportSymbolsScript.py new file mode 100644 index 0000000..4033340 --- /dev/null +++ b/ghidra/SuperExportSymbolsScript.py @@ -0,0 +1,87 @@ +#Export all functions in the database to a Binana symbol file +# @runtime Jython +# @category Binana +# @author Thunderbrew +# @keybinding Shift-E +# @menupath +# @toolbar logo.png + +from ghidra.program.model.symbol import SymbolType +from java.awt import Toolkit +from java.awt.datatransfer import StringSelection +from ghidra.app.decompiler import DecompInterface +from ghidra.util.task import ConsoleTaskMonitor +from ghidra.program.model.symbol.SourceType import * + +functionManager = currentProgram.getFunctionManager() + +file_location = askFile("Choose a file to save your Binana symbols ot", "Go") + +listing = currentProgram.getListing() + +decomp_interface = DecompInterface() +decomp_interface.openProgram(currentProgram) + +def get_function_type(func): + """Uses the Decompiler to get the refined signature.""" + if func is None: + return "" + + results = decomp_interface.decompileFunction(func, 30, ConsoleTaskMonitor()) + high_func = results.getHighFunction() + + if high_func is None: + return "" + + ret_type = high_func.getFunctionPrototype().getReturnType().getName().replace(" *", "*") + + call_conv = high_func.getFunctionPrototype().getModelName() + + params = [] + num_params = high_func.getFunctionPrototype().getNumParams() + for i in range(num_params): + p = high_func.getFunctionPrototype().getParam(i) + params.append("{} {}".format(p.getDataType().getName().replace(" *", "*"), p.getName())) + + param_str = "(" + (", ".join(params)) + ")" + return ret_type + " " + call_conv + " func" + param_str + +def get_symbol_entry_for_function(func): + name = func.getName() + + entry_addr = func.getEntryPoint().toString().upper()[-8:] + body = func.getBody() + end_addr = (body.getMaxAddress().add(1)).toString().upper()[-8:] + + func_type = get_function_type(func) + + if func_type == "": + output = "{} {} f end={}".format(name, entry_addr, end_addr) + else: + output = "{} {} f end={} type=\"{}\"".format( + name, + entry_addr, + end_addr, + func_type + ) + return output + +def export_function_symbols(file): + monitor.setMessage("Exporting function symbols...") + + for f in functionManager.getFunctionsNoStubs(1): + monitor.checkCanceled() # throws exception if canceled + + if f.isExternal() or f.isThunk(): + continue + + func_line = get_symbol_entry_for_function(f) + monitor.setMessage(func_line) + + file.write(func_line + "\n") + + return + +with open(file_location.absolutePath, "w") as file: + export_function_symbols(file) + file.close() diff --git a/ghidra/YankCurrentFunctionSymbol.py b/ghidra/YankCurrentFunctionSymbol.py new file mode 100644 index 0000000..d3aa8b2 --- /dev/null +++ b/ghidra/YankCurrentFunctionSymbol.py @@ -0,0 +1,75 @@ +#Copy the current function as a Binana symbol entry to your clipboard +# @runtime Jython +# @category Binana +# @author Thunderbrew +# @keybinding Shift-F +# @menupath +# @toolbar logo.png + +from ghidra.program.model.symbol import SymbolType +from java.awt import Toolkit +from java.awt.datatransfer import StringSelection +from ghidra.app.decompiler import DecompInterface +from ghidra.util.task import ConsoleTaskMonitor + +def yank_to_clipboard(text): + selection = StringSelection(text) + clipboard = Toolkit.getDefaultToolkit().getSystemClipboard() + clipboard.setContents(selection, None) + +def get_high_function_signature(func): + """Uses the Decompiler to get the refined signature.""" + if func is None: + return "" + + iface = DecompInterface() + iface.openProgram(currentProgram) + + results = iface.decompileFunction(func, 30, ConsoleTaskMonitor()) + high_func = results.getHighFunction() + + if high_func is None: + return + + ret_type = high_func.getFunctionPrototype().getReturnType().getName().replace(" *", "*") + + call_conv = high_func.getFunctionPrototype().getModelName() + + params = [] + num_params = high_func.getFunctionPrototype().getNumParams() + for i in range(num_params): + p = high_func.getFunctionPrototype().getParam(i) + params.append("{} {}".format(p.getDataType().getName().replace(" *", "*"), p.getName())) + + param_str = "(" + (", ".join(params)) + ")" + return ret_type + " " + call_conv + " func" + param_str + +def get_symbol_entry_for_function(func): + name = func.getName() + + entry_addr = func.getEntryPoint().toString().upper()[-8:] + body = func.getBody() + end_addr = (body.getMaxAddress().add(1)).toString().upper()[-8:] + + full_signature = get_high_function_signature(func) + + output = "{} {} f end={} type=\"{}\"".format( + name, + entry_addr, + end_addr, + full_signature + ) + return output + +def yank_current_function_symbol(): + listing = currentProgram.getListing() + func = listing.getFunctionContaining(currentAddress) + + if func is None: + print("No function found at the current cursor position.") + return + output = get_symbol_entry_for_function(func) + yank_to_clipboard(output) + print("Copied to clipboard: {}".format(output)) + +yank_current_function_symbol() diff --git a/ghidra/logo.png b/ghidra/logo.png new file mode 100755 index 0000000000000000000000000000000000000000..5959088c4ef118ca7d72c8c5515031365c9ca6d6 GIT binary patch literal 1913 zcmV-<2Zs2GP)EX>4Tx04R}tkv&MmP!xqvQ?;TM2Rn#3WT-CMMMWG-6^me@v=v%)FnQ@8G-*gu zTpR`0f`dPcRR9%C|}6B ztZ?4qtX68QbxwZ6U|w5EbDh>G;#figNr;e9Lm3rVh|pgn#YBqsV;=qy$DbsZOs+B* zITlcb3d!+nuX~pHz^ncx?gPjV+;uF0?oQ@e;?a+^91le16NwxUu^($pQP8@ zTKEVU+y*YL+nT%wT_CX>@2HM@dakSAh-}000G0NklNdO9wTzp`z%6 zlA6W_TagMyEcQVx1T9D&TBM~FYb&}Wx%F%<5ug=e}j9xoA4C9p_rllvZ)^k6W{|dnJp#yiJ`H{kzw-o)lw!QiQ zshQKfG^?X$W!nKX#m_pRBx8+W$^ugrH;~#VSU*v2D}d^+gq&wxP7otB4QK{y5o10_ zT-&Fw{7AMh184t)#+9!uwH6E7j0T7F(=!p>x5yAu_1V|Ch8P)s|&M$2W;Qk|k zwogvUrW7IC4xnwJ4Il=L1z|5mxjg`jzdgD`b4F7nM~jW&B7`yE6ve$?LUUyRqr;yu zZajSh!XUNHU#mNRum~_(UEf=JAxB8oVq!$vw(A2CR24<~te=_DUw`>p>T+H_{P?Sv zH4F0Gy&o4V-@`DgITMY7|uq=j~-CKim7UxTB zQ9xBfQKCgb>h-bX7KxKYO93)iAaje{^ytZd3!sM|_$XEmBU*#f0VF~b2yI}zx{Sor z?6~HGi1pwsI00+H3K;3MWdKc}4x|D+s0S$*P`O3+fA!=)$xwfG-!81oA=Lk9y^5-m zV@quQLJVhFyKrK1Qa~-J={5$K9LoeMYj+I>RCghA^j|k&?G|bCQ;P0X?et9UN}#bF zjD{~A5Z~a85XSS2hJEUp>n}bWb4gNl0+fN~45>VVWV&rmZ~22n*N({2FCN`38_Q2y z@{P`bH(jVShI(cn#niQ6-NiCk0n#LR2EvPS(|7k=mJD?`C(FmaGre&1{=1DdkCoF* z*~tw~1Pdgmv}ccFiz)127L4mmNISPgQa2^Za#=nw{=-+?iC;eSu(jdAvIskBuasUf zA{bR{1`Uum8brpdFaL(YyKcw$ogi+~S-C5XB*fF6 z+uV&Rl7<0o5>iJL5xiN zU=x6ycKu=5P(u`m1`)y34(S<8&msPGeP6O{=dhA_#i)GRePZd@8|QZTyLokZ9d7Dl zi0Gz0;7A8;lV4!y&)a$m*PF)H1B|N>F`c$m-{^V(Rbn$@d?TdRYIJ0gGU4m&!Idfdrm+9rvDp;pM2=8gw-#J z=pEwY`zRAqr!&;)k79XVaZj6li}U<{y$S2@(0_swBpO{100000NkvXXu0mjf?^brs literal 0 HcmV?d00001