Fixed two bugs in the Golang function recovery script

-Removal of spaces from function names now replaces all spaces, instead of only the first one
-Function creation now no longer faults when a part of the function name was already defined data within Ghidra's listing, as it could not create the complete function name string in Ghidra. It now clears all bytes of types, and then creates the ASCII string. This improvement works for all supported Golang versions on all supported operating systems and respective architectures
This commit is contained in:
ThisIsLibra
2024-09-19 11:11:57 +02:00
committed by GitHub
parent 6dd382b6e2
commit f8eea138d7
+67 -9
View File
@@ -5,6 +5,7 @@
//@menupath
//@toolbar
import ghidra.app.script.GhidraScript;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressOutOfBoundsException;
@@ -242,6 +243,7 @@ public class GolangFunctionRecovery extends GhidraScript {
// Iterate over all results
for (Address pclntab : pclntabs) {
log("Potential pclntab found at : " + Long.toHexString(pclntab.getOffset()));
/*
* Bytes have been found based on the given magic value
*/
@@ -284,6 +286,44 @@ public class GolangFunctionRecovery extends GhidraScript {
return null;
}
/**
* Gets the length of the ascii string, from the given address until the first
* null byte (0x00).
*
* @param start the address to start looking for the null byte (0x00)
* @return the number of characters, excluding the null byte (0x00)
* @throws MemoryAccessException
*/
private int getAsciiStringLength(Address start) throws MemoryAccessException {
/*
* Declare and initialise the length variable, which is to be returned from this
* function
*/
int length = 0;
/*
* Iterate until no address is available anymore, or until the while-loop is
* broken
*/
while (start != null) {
// Get the byte at the given address
byte b = getByte(start);
// Check if the byte's value is null
if (b == 0) {
// Break the loop if it is
break;
}
// If the byte isn't null, increment the length
length++;
// Additionally, increment the address by fetching the next
start = start.add(1);
// Jump to the top of the while-loop
}
// Return the length of the string, once the while-loop is broken
return length;
}
/**
* Creates a new function, or renames the function if it already exists, based
* on the newly found name, which is obtained via the name address variable
@@ -306,8 +346,10 @@ public class GolangFunctionRecovery extends GhidraScript {
// If no data resides at this address
if (functionNameData == null) {
try {
int length = getAsciiStringLength(nameAddress);
clearListing(nameAddress, nameAddress.add(length));
// Create an ASCII string within Ghidra
functionNameData = createAsciiString(nameAddress);
functionNameData = createAsciiString(nameAddress, length);
} catch (Exception e) {
// Print an error if the ASCII string creation fails
printerr(String.format("Unable to create an ASCII string at 0x%x!", nameAddress.getOffset()));
@@ -337,20 +379,36 @@ public class GolangFunctionRecovery extends GhidraScript {
if (func != null) {
// Get the old name
String functionNameOld = func.getName();
// Rename the function with the new name, without spaces
func.setName(functionName.replace(" ", ""), SourceType.USER_DEFINED);
// Optionally print the function name change, along with the location
log("Function renamed from \"" + functionNameOld + "\" to \"" + functionName + "\", located at 0x"
+ Long.toHexString(functionAddress.getOffset()));
// Get the new name, removing spaces
String functionNameNew = functionName.replaceAll(" ", "").replaceAll("Â", "").replaceAll("·", "");
/*
* Replacing the function with a name which already exists, throws a
* ghidra.util.exception.DuplicateNameException. This check avoids this
* exception by only replacing a function name if the old and new name are not
* the same.
*/
if (functionNameOld.equalsIgnoreCase(functionNameNew) == false) {
// Change the function name
try {
func.setName(functionNameNew, SourceType.USER_DEFINED);
} catch (DuplicateNameException ex) {
func.setName(functionNameNew + "_", SourceType.USER_DEFINED);
}
// Optionally print the renamed function
log("Function renamed from \"" + functionNameOld + "\" to \"" + functionNameNew + "\", located at 0x"
+ Long.toHexString(functionAddress.getOffset()));
// Increment the function count
functionCount++;
}
} else {
// If no function exists at the given address, create one
func = createFunction(functionAddress, functionName);
// Optionally print the function name and address
log("Function \"" + functionName + "\" created at 0x" + Long.toHexString(functionAddress.getOffset()));
// Increment the function count
functionCount++;
}
// Increment the function count
functionCount++;
}
/**