Advertisement
Guest User

spu program dumper.py

a guest
Mar 7th, 2022
44
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. from idaapi import *
  2. from idc import *
  3. import idaapi as ida
  4. import idc
  5.  
  6. def dump_image(start_ptr, end_ptr, name):
  7.  
  8.         h = "7F 45 4C 46 01 02 01 00 00 00 00 00 00 00 00 00 00 02 00 17 00 00 00 01 00 00 00 00 00 00 00 34 00 00 00 00 00 00 00 00 00 34 00 20 00 01 00 00 00 00 00 00 00 00 00 01 00 00 00 54 00 00 00 00 00 00 00 00 00 04 00 00 00 04 00 00 00 00 00 07 00 00 00 00"
  9.         size = end_ptr - start_ptr
  10.         filename = ask_file(1, name + ".elf", "Output file name")
  11.         with open(filename, "wb") as out:
  12.             # Images are raw, so lets add elf header for easier loading,
  13.             # and to mitigate ida 7.3+ bug to set SPU to LE if raw image is loaded.
  14.             header = bytearray.fromhex(h)
  15.             data = get_bytes(start_ptr, size, False)
  16.             out.write(header)
  17.             out.seek(0x54, 0)
  18.             out.write(data)
  19.  
  20. def find_addresses(pattern, name):
  21.  
  22.     address = 0
  23.     address = idaapi.find_binary(address, ida_idaapi.BADADDR, pattern, 0x10, SEARCH_DOWN)
  24.     if address == BADADDR:
  25.         print("Pattern " + name + " not found!")
  26.         return 1
  27.     print("Found " + name + " pattern at: " + hex(address))
  28.     ptr = idaapi.find_binary(0, ida_idaapi.BADADDR, hex(address), 0x10, SEARCH_DOWN)
  29.     if ptr == BADADDR:
  30.         print("False positive, skipping...")
  31.         return 1
  32.     ptr -= 1
  33.     print("Program name pointer at: " + hex(ptr))
  34.     start_ptr = get_wide_dword(ptr + 8)
  35.     end_ptr = get_wide_dword(ptr + 16)
  36.     if start_ptr > end_ptr:
  37.         print("Error: dump start addr > dump end addr")
  38.         return 1
  39.     print(name + " start offset: " + hex(start_ptr))
  40.     print(name + " end offset: " + hex(end_ptr))
  41.     if pattern == "66 65 00 00":
  42.         # Try to dump "be" which seems to be always after fe.
  43.         # "be" pattern is tricky because multi xrefs.
  44.         be_start_ptr = get_wide_dword(ptr + 32)
  45.         be_end_ptr   = get_wide_dword(ptr + 40)
  46.         print("Dumping spu_be")
  47.         print("Start offset" + be_start_ptr)
  48.         print("End offset" + be_end_ptr)
  49.         dump_image(be_start_ptr, be_end_ptr, "spu_be")
  50.    
  51.     dump_image(start_ptr, end_ptr, name)
  52.  
  53. def start():
  54.  
  55.     spu_eedma_pattern = "73 70 75 5F 65 65 64 6D 61 00"
  56.     spu_iop_pattern = "73 70 75 5F 69 6F 70 00"
  57.     spu_ipu_pattern = "73 70 75 5F 69 70 75 00"
  58.     spu_spu2_pattern = "73 70 75 5F 73 70 75 32 00"
  59.     spu_vu1_pattern = "73 70 75 5F 76 75 31 00"
  60.     spu_gse_pattern = "73 70 75 5F 67 73 65 00"
  61.     spu_gsegif_pattern = "73 70 75 5F 67 73 65 67 69 66 00"
  62.     spu_gsgif_pattern = "73 70 75 5F 67 73 67 69 66 00"
  63.     spu_fe_pattern = "66 65 00 00" # Tricky, can give false possitives
  64.     #spu_be_pattern = "62 65 00 00" # Of course...
  65.    
  66.     find_addresses(spu_eedma_pattern, "spu_eedma")
  67.     find_addresses(spu_iop_pattern, "spu_iop")
  68.     find_addresses(spu_ipu_pattern, "spu_ipu")
  69.     find_addresses(spu_spu2_pattern, "spu_spu2")
  70.     find_addresses(spu_vu1_pattern, "spu_vu1")
  71.     find_addresses(spu_gse_pattern, "spu_gse")
  72.     find_addresses(spu_gsegif_pattern, "spu_gsegif")
  73.     find_addresses(spu_gsgif_pattern, "spu_gsgif")
  74.     find_addresses(spu_fe_pattern, "spu_fe")
  75.  
  76.     address = 0
  77.     # Search for function responsible for starting SPE cores.
  78.     # Function take (LS base, start_addr) as arguments.
  79.     # LS base is 40000000 for SPE0, 40080000 for SPE1, 40100000 for SPE2,
  80.     # 40180000 for SPE3, 40200000 for SPE4, 40280000 for SPE5, and 40300000 for SPE6.
  81.     # Todo: Make this automatic, grab function vars, and add start address to elf header, and resolve 40xx0000 xref.
  82.     start_spe_pattern = "3D 43 00 04 7C 08 02 A6 F8 21 FF 91 F8 01 00 80 80 0A 40 24 54 00 07 FE 2F 80 00 00"
  83.     address = idaapi.find_binary(address, ida_idaapi.BADADDR, start_spe_pattern, 0x10, SEARCH_DOWN)
  84.     if address == BADADDR:
  85.         print("BADADDR in find_start")
  86.         return 1
  87.     set_name(address, "start_spe", 0)
  88.     print("Found start_spe function at: " + hex(address))
  89.     print("Second arg (r4) to that function is entry point in matching elf.")
  90.    
  91. start()
Advertisement
RAW Paste Data Copied
Advertisement