ghidra/Ghidra/Features/Base/ghidra_scripts/MarkupWallaceSrcScript.java

163 lines
8.2 KiB
Java

/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//This script applies labels and comments to the WallaceSrc.exe program for use with GhidraClass exercises
//@category Training.GhidraClass
import ghidra.app.script.GhidraScript;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.ArrayDataType;
import ghidra.program.model.data.BooleanDataType;
import ghidra.program.model.data.CharDataType;
import ghidra.program.model.data.IntegerDataType;
import ghidra.program.model.data.PointerDataType;
import ghidra.program.model.data.Structure;
import ghidra.program.model.data.StructureDataType;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.Function.FunctionUpdateType;
import ghidra.program.model.listing.Parameter;
import ghidra.program.model.listing.ParameterImpl;
import ghidra.program.model.symbol.Namespace;
import ghidra.program.model.symbol.SourceType;
import ghidra.program.model.symbol.SymbolTable;
import ghidra.util.exception.InvalidInputException;
public class MarkupWallaceSrcScript extends GhidraScript {
@Override
public void run() throws Exception {
if(!currentProgram.getName().contains("WallaceSrc") || (!currentProgram.getExecutableMD5().equals("2527c463a079c81af7b3bc1d26bd3b5d"))) {
println("This script is only meant to work on the WallaceSrc executable with md5 hash 2527c463a079c81af7b3bc1d26bd3b5d.");
return;
}
//Create Person structure
Structure personStruct = new StructureDataType("Person", 0);
personStruct.add(new IntegerDataType(), "id", "");
ArrayDataType adt = new ArrayDataType(new CharDataType(), 32, 1);
personStruct.add(adt, "name", "");
personStruct.add(new BooleanDataType(), "likesCheese", "");
PointerDataType ptrPersonStruct = new PointerDataType(personStruct);
personStruct.add(ptrPersonStruct, "next", "");
//Create Gadget structure
Structure gadgetStruct = new StructureDataType("Gadget", 0);
PointerDataType charPtr = new PointerDataType(new CharDataType());
gadgetStruct.add(charPtr,"name","");
gadgetStruct.add(new IntegerDataType(),"type", "");
gadgetStruct.add(new BooleanDataType(), "deployed","");
gadgetStruct.add(ptrPersonStruct, "workingOn","");
//apply data types to function parameters, locals, and returns
//Gadget::Gadget(Gadget * this, undefined4 param_1)
Function gadgetFunction = getFunctionAt(toAddr(0x00411440));
Parameter[] parameters = gadgetFunction.getParameters();
parameters[0] = new ParameterImpl("this", new PointerDataType(gadgetStruct), currentProgram);
gadgetFunction.replaceParameters(FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS,true, SourceType.USER_DEFINED, parameters);
//deployGadget - return type = Gadget *
Function deployGadgetFunction = getFunctionAt(toAddr(0x004118f0));
deployGadgetFunction.setReturnType(new PointerDataType(gadgetStruct), SourceType.USER_DEFINED);
//initializePeople(Person *)
Function initPeopleFunction = getFunctionAt(toAddr(0x004117c0));
parameters = initPeopleFunction.getParameters();
parameters[0] = new ParameterImpl("people", new PointerDataType(personStruct), currentProgram);
initPeopleFunction.replaceParameters(FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS,true, SourceType.USER_DEFINED, parameters);
//use(Gadget *this, Person *person)
Function useFunction = getFunctionAt(toAddr(0x00411570));
parameters = useFunction.getParameters();
parameters[0] = new ParameterImpl("this", new PointerDataType(gadgetStruct), currentProgram);
parameters[1] = new ParameterImpl("person", new PointerDataType(personStruct), currentProgram);
useFunction.replaceParameters(FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS,true, SourceType.USER_DEFINED, parameters);
//addPerson(Person ** list, char * name)
Function addPersonFunction = getFunctionAt(toAddr(0x00411860));
parameters = addPersonFunction.getParameters();
parameters[0] = new ParameterImpl("list", new PointerDataType(new PointerDataType(personStruct)), currentProgram);
parameters[1] = new ParameterImpl("name", new PointerDataType(new CharDataType()), currentProgram);
addPersonFunction.replaceParameters(FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS,true, SourceType.USER_DEFINED, parameters);
//addPeople(Person ** list)
Function addPeopleFunction = getFunctionAt(toAddr(0x00411700));
parameters = addPeopleFunction.getParameters();
parameters[0] = new ParameterImpl("list", new PointerDataType(new PointerDataType(personStruct)), currentProgram);
addPeopleFunction.replaceParameters(FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS,true, SourceType.USER_DEFINED, parameters);
//print(Gadget * pGadget)
Function printFunction = getFunctionAt(toAddr(0x004115d0));
parameters = printFunction.getParameters();
parameters[0] = new ParameterImpl("this", new PointerDataType(gadgetStruct), currentProgram);
printFunction.replaceParameters(FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS,true, SourceType.USER_DEFINED, parameters);
// Create labels for some of the functions
SymbolTable symbolTable = currentProgram.getSymbolTable();
//create the Class "Gadget" to put most function symbols in
Namespace namespace = null;
namespace = symbolTable.getNamespace("Gadget", null);
if(namespace == null) {
namespace = symbolTable.createClass(null, "Gadget", SourceType.USER_DEFINED);
}
//Functions in Gadget class
createNewLabel(toAddr(0x00411440), "Gadget", namespace, SourceType.USER_DEFINED);
createNewLabel(toAddr(0x004115d0), "print", namespace, SourceType.USER_DEFINED);
createNewLabel(toAddr(0x00411570), "use", namespace, SourceType.USER_DEFINED);
//Functions not in class
createNewLabel(toAddr(0x004117c0), "initializePeople", namespace, SourceType.USER_DEFINED);
createNewLabel(toAddr(0x004118f0), "deployGadget", namespace, SourceType.USER_DEFINED);
createNewLabel(toAddr(0x00411700), "addPeople", namespace, SourceType.USER_DEFINED);
createNewLabel(toAddr(0x00411860), "addPerson", namespace, SourceType.USER_DEFINED);
createNewLabel(toAddr(0x00418138), "personList", namespace, SourceType.USER_DEFINED);
createNewLabel(toAddr(0x00411a30), "main", null, SourceType.USER_DEFINED);
// Add other labels
Function function = currentProgram.getFunctionManager().getFunctionAt(toAddr(0x004117c0));
createNewLabel(toAddr(0x004117e5), "LoopOverPeople", function, SourceType.USER_DEFINED);
if(getSymbolAt(toAddr(0x00418138)).getSource().equals(SourceType.DEFAULT)){
createLabel(toAddr(0x00418138),"personList", true);
}
// Add comments
setPlateComment(toAddr(0x00411440), "This is the init method for the Gadget class");
setPlateComment(toAddr(0x004115d0), "This method prints the status of a Person -- whether they are deployed or not and who they are deployed on. ");
setPlateComment(toAddr(0x00411700), "This function adds all the people to the Person list.");
setPlateComment(toAddr(0x004117c0), "This function initializes each person's record with whether or not they like cheese, their id, and a pointer to the next person.");
setPlateComment(toAddr(0x00411860), "This function adds a person to the Person list.");
setPlateComment(toAddr(0x004118f0), "This function checks to see if the person on the list is Wallace and if so, it deploys the Infrared Garden Gnome.");
setEOLComment(toAddr(0x004117e7), "Randomly assign whether each person likes cheese or not.");
}
void createNewLabel(Address address, String name, Namespace namespace, SourceType sourceType) {
SymbolTable symbolTable = currentProgram.getSymbolTable();
if(getSymbolAt(address).getSource().equals(SourceType.DEFAULT)){
try {
symbolTable.createLabel(address, name, namespace, sourceType);
} catch (InvalidInputException e) {
println("Invalid input to create label.");
}
}
}
}