Advertisement
xerpi

VitaLoader Ghidra not finished

Mar 10th, 2019
312
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 11.71 KB | None | 0 0
  1. //@author Sergi Granell
  2. //@category _NEW_
  3. //@keybinding
  4. //@menupath
  5. //@toolbar
  6.  
  7. import java.io.File;
  8. import java.io.FileInputStream;
  9. import java.io.IOException;
  10. import java.io.InputStream;
  11. import java.nio.ByteBuffer;
  12. import java.nio.ByteOrder;
  13. import java.nio.IntBuffer;
  14. import java.util.HashMap;
  15.  
  16. import generic.continues.RethrowContinuesFactory;
  17. import ghidra.app.script.GhidraScript;
  18. import ghidra.app.util.bin.BinaryReader;
  19. import ghidra.app.util.bin.ByteArrayProvider;
  20. import ghidra.app.util.bin.ByteProvider;
  21. import ghidra.app.util.bin.StructConverter;
  22. import ghidra.app.util.bin.StructConverterUtil;
  23. import ghidra.app.util.bin.format.elf.ElfException;
  24. import ghidra.app.util.bin.format.elf.ElfHeader;
  25. import ghidra.app.util.opinion.ElfLoader;
  26. import ghidra.program.model.address.Address;
  27. import ghidra.program.model.data.DataType;
  28. import ghidra.program.model.listing.Program;
  29. import ghidra.program.model.mem.MemoryAccessException;
  30. import ghidra.program.model.mem.MemoryBlock;
  31. import ghidra.util.Msg;
  32. import ghidra.util.exception.DuplicateNameException;
  33. import org.yaml.snakeyaml.Yaml;
  34.  
  35. public class VitaLoader extends GhidraScript {
  36.     private final short ET_SCE_RELEXEC = (short)0xFE04;
  37.    
  38.         /*sce_module_info_t = new StructureDataType(new CategoryPath("/Vita"), "sce_module_info_t", 0);
  39.         sce_module_info_t.add(StructConverter.WORD, "attributes", null);
  40.         sce_module_info_t.add(StructConverter.WORD, "version", null);
  41.         sce_module_info_t.add(StructConverter.STRING, 27, "name", null);
  42.         sce_module_info_t.add(StructConverter.BYTE, "type", null);
  43.         sce_module_info_t.add(Pointer32DataType.dataType, "gp_value", null);
  44.         sce_module_info_t.add(StructConverter.DWORD, "export_top", null);
  45.         sce_module_info_t.add(StructConverter.DWORD, "export_end", null);
  46.         sce_module_info_t.add(StructConverter.DWORD, "import_top", null);
  47.         sce_module_info_t.add(StructConverter.DWORD, "import_end", null);
  48.         sce_module_info_t.add(StructConverter.DWORD, "module_nid", null);
  49.         sce_module_info_t.add(StructConverter.DWORD, "field_38", null);
  50.         sce_module_info_t.add(StructConverter.DWORD, "field_3C", null);
  51.         sce_module_info_t.add(StructConverter.DWORD, "field_40", null);
  52.         sce_module_info_t.add(StructConverter.DWORD, "module_start", null);
  53.         sce_module_info_t.add(StructConverter.DWORD, "module_stop", null);
  54.         sce_module_info_t.add(StructConverter.DWORD, "exidx_top", null);
  55.         sce_module_info_t.add(StructConverter.DWORD, "exidx_end", null);
  56.         sce_module_info_t.add(StructConverter.DWORD, "extab_top", null);
  57.         sce_module_info_t.add(StructConverter.DWORD, "extab_end", null);*/
  58.    
  59.     public class SceModuleInfo implements StructConverter {
  60.         public short attributes;
  61.         public short version;
  62.         public String name;
  63.         public byte type;
  64.         public int gp_value;
  65.         public int export_top;
  66.         public int export_end;
  67.         public int import_top;
  68.         public int import_end;
  69.         public int module_nid;
  70.         public int field_38;
  71.         public int field_3C;
  72.         public int field_40;
  73.         public int module_start;
  74.         public int module_stop;
  75.         public int exidx_top;
  76.         public int exidx_end;
  77.         public int extab_top;
  78.         public int extab_end;
  79.         public static final int SIZE = 0x5c;
  80.        
  81.         SceModuleInfo(BinaryReader reader) throws IOException {
  82.             attributes = reader.readNextShort();
  83.             version = reader.readNextShort();
  84.             name = reader.readNextAsciiString(27);
  85.             type = reader.readNextByte();
  86.             gp_value = reader.readNextInt();
  87.             export_top = reader.readNextInt();
  88.             export_end = reader.readNextInt();
  89.             import_top = reader.readNextInt();
  90.             import_end = reader.readNextInt();
  91.             module_nid = reader.readNextInt();
  92.             field_38 = reader.readNextInt();
  93.             field_3C = reader.readNextInt();
  94.             field_40 = reader.readNextInt();
  95.             module_start = reader.readNextInt();
  96.             module_stop = reader.readNextInt();
  97.             exidx_top = reader.readNextInt();
  98.             exidx_end = reader.readNextInt();
  99.             extab_top = reader.readNextInt();
  100.             extab_end = reader.readNextInt();
  101.         }
  102.  
  103.         public DataType toDataType() throws DuplicateNameException, IOException {
  104.             return StructConverterUtil.toDataType(this);
  105.         }
  106.     }
  107.    
  108.     public class SceModuleImports implements StructConverter {
  109.         public short size;
  110.         public short version;
  111.         public short flags;
  112.         public short num_syms_funcs;
  113.         public short num_syms_vars;
  114.         public short num_syms_unk;
  115.         public int reserved1;
  116.         public int library_nid;
  117.         public int library_name;
  118.         public int reserved2;
  119.         public int func_nid_table;
  120.         public int func_entry_table;
  121.         public int var_nid_table;
  122.         public int var_entry_table;
  123.         public int unk_nid_table;
  124.         public int unk_entry_table;
  125.         public static final int SIZE = 0x34;
  126.        
  127.         SceModuleImports(BinaryReader reader) throws IOException {
  128.             size = reader.readNextShort();
  129.             version = reader.readNextShort();
  130.             flags = reader.readNextShort();
  131.             num_syms_funcs = reader.readNextShort();
  132.             num_syms_vars = reader.readNextShort();
  133.             num_syms_unk = reader.readNextShort();
  134.             reserved1 = reader.readNextInt();
  135.             library_nid = reader.readNextInt();
  136.             library_name = reader.readNextInt();
  137.             reserved2 = reader.readNextInt();
  138.             func_nid_table = reader.readNextInt();
  139.             func_entry_table = reader.readNextInt();
  140.             var_nid_table = reader.readNextInt();
  141.             var_entry_table = reader.readNextInt();
  142.             unk_nid_table = reader.readNextInt();
  143.             unk_entry_table = reader.readNextInt();
  144.         }
  145.  
  146.         public DataType toDataType() throws DuplicateNameException, IOException {
  147.             return StructConverterUtil.toDataType(this);
  148.         }
  149.     }
  150.    
  151.     public class NidDb {
  152.         public class NidDbLibrary {
  153.             public int nid;
  154.             public HashMap<Integer, String> functions;
  155.    
  156.             public NidDbLibrary(int nid) {
  157.                 this.nid = nid;
  158.                 functions = new HashMap<Integer, String>();
  159.             }
  160.            
  161.             public boolean functionExists(int nid) {
  162.                 return functions.containsKey(nid);
  163.             }
  164.            
  165.             public void insertFunction(int nid, String name) {
  166.                 functions.put(nid, name);
  167.             }
  168.            
  169.             public String getFunctionName(int nid) {
  170.                 return functions.get(nid);
  171.             }
  172.         }
  173.        
  174.         public class NidDbModule {
  175.             private int nid;
  176.             private HashMap<Integer, NidDbLibrary> libraries;
  177.            
  178.             public NidDbModule(int nid) {
  179.                 this.nid = nid;
  180.                 libraries = new HashMap<Integer, NidDbLibrary>();
  181.             }
  182.            
  183.             public boolean libraryExists(int nid) {
  184.                 return libraries.containsKey(nid);
  185.             }
  186.            
  187.             public void insertLibrary(int nid, NidDbLibrary library) {
  188.                 libraries.put(nid, library);
  189.             }
  190.            
  191.             public NidDbLibrary getLibrary(int nid) {
  192.                 return libraries.get(nid);
  193.             }
  194.            
  195.             public String getFunctionName(int libraryNid, int functionNid) {
  196.                 return getLibrary(libraryNid).getFunctionName(functionNid);
  197.             }
  198.         }
  199.        
  200.         private HashMap<Integer, NidDbModule> modules;
  201.        
  202.         public NidDb() {
  203.             modules = new HashMap<Integer, NidDbModule>();
  204.         }
  205.        
  206.         public boolean moduleExists(int nid) {
  207.             return modules.containsKey(nid);
  208.         }
  209.        
  210.         public void insertModule(int nid, NidDbModule module) {
  211.             modules.put(nid, module);
  212.         }
  213.        
  214.         public NidDbModule getModule(int nid) {
  215.             return modules.get(nid);
  216.         }
  217.        
  218.         public String getModuleLibraryFunctionName(int moduleNid, int libraryNid, int functionNid) {
  219.             return getModule(moduleNid).getFunctionName(libraryNid, functionNid);
  220.         }
  221.        
  222.     }
  223.    
  224.    
  225.     private ElfHeader getElfHeader(Program program) throws MemoryAccessException, ElfException {
  226.         MemoryBlock elfHeaderMemoryBlock = currentProgram.getMemory().getBlock("_elfHeader");
  227.        
  228.         int elfHeaderSize = (int)elfHeaderMemoryBlock.getSize();
  229.         Address elfHeaderStart = elfHeaderMemoryBlock.getStart();
  230.         byte[] elfHeaderBytes = new byte[elfHeaderSize];
  231.        
  232.         elfHeaderMemoryBlock.getBytes(elfHeaderStart, elfHeaderBytes);
  233.        
  234.         ByteArrayProvider elfHeaderProvider = new ByteArrayProvider(elfHeaderBytes);
  235.         return ElfHeader.createElfHeader(RethrowContinuesFactory.INSTANCE, elfHeaderProvider);
  236.     }
  237.  
  238.     private MemoryBlock getExecutableMemoryBlock(Program program) {
  239.         for (MemoryBlock block : program.getMemory().getBlocks()) {
  240.             if ((block.getPermissions() & MemoryBlock.EXECUTE) != 0)
  241.                 return block;
  242.         }
  243.         return null;
  244.     }
  245.    
  246.     private void processImports(MemoryBlock block, SceModuleImports imports) throws MemoryAccessException {
  247.         println("Imports NID: " + String.format("0x%08X", imports.library_nid));
  248.         println("Imports num funcs: " + String.format("0x%08X", imports.num_syms_funcs));
  249.         println("Imports nid table: " + String.format("0x%08X", imports.func_nid_table));
  250.         println("Imports size: " + String.format("0x%08X", imports.size));
  251.        
  252.         Address funcNidTableAddress = block.getStart().getNewAddress(imports.func_nid_table);
  253.         Address funcEntryTableAddress = block.getStart().getNewAddress(imports.func_entry_table);
  254.        
  255.         byte[] funcNidTableBytes = new byte[4 * imports.num_syms_funcs];
  256.         byte[] funcEntryTableBytes = new byte[4 * imports.num_syms_funcs];
  257.        
  258.         block.getBytes(funcNidTableAddress, funcNidTableBytes, 0, funcNidTableBytes.length);
  259.         block.getBytes(funcEntryTableAddress, funcEntryTableBytes, 0, funcEntryTableBytes.length);
  260.         IntBuffer funcNidTableIntBuffer = ByteBuffer.wrap(funcNidTableBytes).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer();
  261.         IntBuffer funcEntryTableIntBuffer = ByteBuffer.wrap(funcEntryTableBytes).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer();
  262.        
  263.         for (int i = 0; i < imports.num_syms_funcs; i++) {
  264.             println(" NID[" + i + "]: " + String.format("0x%08X", funcNidTableIntBuffer.get(i)));
  265.         }
  266.     }
  267.    
  268.     private void processModuleInfo(MemoryBlock block, SceModuleInfo moduleInfo) throws MemoryAccessException, IOException {
  269.         println("Module name: " + moduleInfo.name);
  270.        
  271.         Address importsTop = block.getStart().add(moduleInfo.import_top);
  272.         Address importsEnd = block.getStart().add(moduleInfo.import_end);
  273.         while (!importsTop.equals(importsEnd)) {
  274.             byte[] importsBytes = new byte[SceModuleImports.SIZE];
  275.             block.getBytes(importsTop, importsBytes, 0, importsBytes.length);
  276.            
  277.             ByteProvider importsByteProvider = new ByteArrayProvider(importsBytes);
  278.             BinaryReader importsBinaryReader = new BinaryReader(importsByteProvider, true);
  279.             SceModuleImports moduleImports = new SceModuleImports(importsBinaryReader);
  280.             if (moduleImports.size != SceModuleImports.SIZE) {
  281.                 println("Imports size mismatch");
  282.                 break;
  283.             }
  284.            
  285.             processImports(block, moduleImports);
  286.            
  287.             importsTop = importsTop.add(moduleImports.size);
  288.         }  
  289.     }
  290.    
  291.     @Override
  292.     public void run() throws Exception {
  293.         println("VitaLoader by xerpi");
  294.        
  295.         if (!ElfLoader.ELF_NAME.equals(currentProgram.getExecutableFormat())) {
  296.             Msg.showError(this, null, "VitaLoader",
  297.                     "Current program is not an ELF program!  (" + currentProgram.getExecutableFormat() + ")");
  298.             return;
  299.         }
  300.        
  301.         ElfHeader elfHeader = getElfHeader(currentProgram);
  302.         if (elfHeader.e_type() != ET_SCE_RELEXEC) {
  303.             Msg.showError(this, null, "VitaLoader",
  304.                     "Current program is not an PSVita ELF program!  (" + String.format("0x%04X", elfHeader.e_type()) + ")");
  305.             return;
  306.         }
  307.        
  308.        
  309.         InputStream input = new FileInputStream(new File("/home/xerpi/Desktop/Vita/vita-headers/db.yml"));
  310.         Yaml yaml = new Yaml();
  311.         Object data = yaml.load(input);
  312.  
  313.        
  314.         MemoryBlock textMemoryBlock = getExecutableMemoryBlock(currentProgram);
  315.  
  316.         println("ELF entry:" + String.format("0x%08X", elfHeader.e_entry()));
  317.         println(".text size: " + String.format("0x%08X", textMemoryBlock.getSize()));
  318.        
  319.         Address moduleInfoAddress = textMemoryBlock.getStart().add(elfHeader.e_entry());
  320.         byte[] moduleInfoBytes = new byte[SceModuleInfo.SIZE];
  321.         textMemoryBlock.getBytes(moduleInfoAddress, moduleInfoBytes, 0, moduleInfoBytes.length);
  322.        
  323.         ByteProvider provider = new ByteArrayProvider(moduleInfoBytes);
  324.         BinaryReader reader = new BinaryReader(provider, true);
  325.         SceModuleInfo moduleInfo = new SceModuleInfo(reader);
  326.        
  327.         processModuleInfo(textMemoryBlock, moduleInfo);
  328.     }
  329. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement