├── README.md └── MakeSig.java /README.md: -------------------------------------------------------------------------------- 1 | # MakeSig 2 | Ghidra script to find unique function signature 3 | -------------------------------------------------------------------------------- /MakeSig.java: -------------------------------------------------------------------------------- 1 | // Finds unique signature for a function (Based of Asher Bakers makesig.idc for IDA pro) 2 | 3 | 4 | //@author Rachnus 5 | //@keybinding ctrl insert 6 | 7 | import ghidra.app.script.GhidraScript; 8 | import ghidra.program.model.listing.*; 9 | import ghidra.program.model.lang.*; 10 | import ghidra.program.model.address.*; 11 | 12 | import ghidra.util.HashUtilities; 13 | 14 | public class MakeSig extends GhidraScript 15 | { 16 | public void run() throws Exception 17 | { 18 | Function func = getCursorFunction(); 19 | if(func == null) 20 | { 21 | println("Error: Select a function first."); 22 | return; 23 | } 24 | 25 | Address startAddr = getFunctionStartAddr(func); 26 | Address endAddr = getFunctionEndAddr(func); 27 | 28 | printf("Finding unique sig for function: %s (%s)", func.getName(), func.getSignature().getPrototypeString()); 29 | boolean found = false; 30 | String sig = ""; 31 | 32 | // Add .next to endAddr to include return statement 33 | for(Address currentAddr = startAddr; !currentAddr.equals(endAddr.next()) && !monitor.isCancelled(); currentAddr = currentAddr.next()) 34 | { 35 | // Get instruction at current address 36 | Instruction ins = getInstructionAt(currentAddr); 37 | 38 | ///println("CURRENT ADDR: " + currentAddr + " - " + ins); 39 | if(ins != null) 40 | { 41 | // Opcodes for this instruction 42 | byte[] bytes = ins.getBytes(); 43 | 44 | for(int i = 0; i < bytes.length; i++) 45 | { 46 | ///printf("OP TYPE: %d (0x%X)\n", ins.getOperandType(i), bytes[i]); 47 | 48 | int opType = ins.getOperandType(i); 49 | if((opType & OperandType.DYNAMIC) == OperandType.DYNAMIC) 50 | { 51 | // Wildcard dynamic operands 52 | sig += "."; 53 | } 54 | else 55 | { 56 | // Else append the byte code 57 | sig += String.format("\\x%02X", bytes[i]); 58 | } 59 | 60 | if(isSigUnique(sig)) 61 | { 62 | found = true; 63 | break; 64 | } 65 | } 66 | 67 | if(found) 68 | break; 69 | } 70 | } 71 | 72 | if(!found) 73 | { 74 | printf("Could not find unique signature."); 75 | return; 76 | } 77 | 78 | // Do not print of we cancelled script 79 | if(monitor.isCancelled()) 80 | return; 81 | 82 | printf("--- %s SIGS ---\n", func.getName()); 83 | printf("GHIDRA: %s\n", sig); 84 | printf("IDA: %s\n", ghidraSigToIDASig(sig)); 85 | printf("SM: %s\n", ghidraSigToSourceModSig(sig)); 86 | } 87 | 88 | /** 89 | * Gets the start address of a function 90 | * 91 | * @param Function function object 92 | * @return Address function start address 93 | */ 94 | public Address getFunctionStartAddr(Function func) 95 | { 96 | AddressSetView setView = func.getBody(); 97 | return setView.getMinAddress(); 98 | } 99 | 100 | /** 101 | * Gets the end address of a function 102 | * 103 | * @param Function function object 104 | * @return Address function end address 105 | */ 106 | public Address getFunctionEndAddr(Function func) 107 | { 108 | AddressSetView setView = func.getBody(); 109 | return setView.getMaxAddress(); 110 | } 111 | 112 | /** 113 | * Returns array of addresses found by signature 114 | * 115 | * @param sig signature string 116 | * @return Address[] array of addresses 117 | */ 118 | public Address[] findSigAddr(String sig, int count) 119 | { 120 | return findBytes(null, sig, count); 121 | } 122 | 123 | /** 124 | * Checks if signature is unique 125 | * 126 | * Dot (.) is used as wildcard 127 | * Example sig string using wildcards: \x55\x8B.\x55.... 128 | * is equivalent to 129 | * 55 8B ? 55 ? ? ? ? // IDA 130 | * \x55\x8B\x2A\x55\x2A\x2A\x2A\x2A // SOURCEMOD 131 | * 132 | * @param sig signature string 133 | * @return bool true if unique 134 | */ 135 | public boolean isSigUnique(String sig) 136 | { 137 | // If it finds more than 1 sig, its not unique 138 | return findSigAddr(sig, 2).length == 1; 139 | } 140 | 141 | /** 142 | * Converts ghidra sig to SourceMod sig 143 | * 144 | * @param sig ghidra sig 145 | * @return String SM sig 146 | */ 147 | public String ghidraSigToSourceModSig(String sig) 148 | { 149 | return sig.replaceAll("\\.", "\\\\x2A"); 150 | } 151 | 152 | /** 153 | * Converts ghidra sig to IDA sig 154 | * 155 | * @param sig ghidra sig 156 | * @return String IDA sig 157 | */ 158 | public String ghidraSigToIDASig(String sig) 159 | { 160 | StringBuilder sb = new StringBuilder(sig); 161 | for(int i = 0; i < sb.length(); i++) 162 | { 163 | if(sb.charAt(i) == '\\') 164 | sb.deleteCharAt(i); 165 | } 166 | 167 | return sb.toString().replaceAll("\\.", " ? ").replaceAll("x", " "); 168 | } 169 | 170 | /** 171 | * Gets selected function 172 | * 173 | * @return void 174 | */ 175 | public Function getCursorFunction() 176 | { 177 | AddressSetView scope = currentSelection; 178 | if (scope == null) 179 | return getFunctionContaining(currentAddress); 180 | 181 | return null; 182 | } 183 | } 184 | --------------------------------------------------------------------------------