Making Isolated SPU Modules and Loaders
Jump to navigation
Jump to search
Introduction
- E.g. to dump your ATA, ENCDEC or EID2 keys you have to make signed isolated SPU modules or loaders.
- This is a tutorial how to do it on Linux (it doesn't matter on PC or PS3).
Tools
- My Debian LiveCD has all tools you will need.
- See http://www.ps3devwiki.com/wiki/Debian_LiveCD
SPU GCC Compiler
- You need SPU GCC compiler to compile your code and create binary version of it.
- On PS3 Debian, just install spu toolchain with aptitude.
- You can also cross-compile SPU GCC toolchain for your Linux PC.
- See http://gitorious.ps3dev.net/ps3linux/powerpc64-cross-compiler if you want to build SPU GCC cross-compiler. Just change in HOWTO target option from powerpc64-linux to spu-elf.
ps3tools
- You need these tools to decrypt PS3 isolated SPU modules and loaders.
- You also need it to sign and encrypt your own SPU modules and loaders.
- self_rebuilder doesn't work properly with isolated SPU modules or loaders. Therefore, i made a new tool which works with isolated SPU modules and loaders. It's called iso_rebuilder and is a modified version of self_rebuilder.
- See my GIT repop: http://gitorious.ps3dev.net/ps3otheros/ps3tools
How To Test Isolated SPU Modules and Loaders
- I test my isolated SPU modules and loaders with PS3 Linux and spuisofs/spuldrfs Virtual File Systems.
spuisofs
- You can test with spuisofs isolated SPU modules which are decrypted by isoldr.
- You cannot test loaders with spuisofs.
- But spuisofs has the advantage that it's alot easier to execute isolated SPUs with it than with spuldrfs.
See http://www.ps3devwiki.com/wiki/Spuisofs
spuldrfs
- You can test with spuldrfs isolated SPU modules which are decrypted by isoldr and loaders which are decrypted by metldr.
- Use spuisofs if you want to execute isoldr SPUs, it's easier to do than with spuldrfs.
See http://www.ps3devwiki.com/wiki/Spuldrfs
Example: Making dump_ata_keys.self
- First you need sb_iso_spu_module.self from your NOR/NAND flash or from PS3 update file.
# compile your SPU code spu-elf-gcc -c dump_ata_keys.S ls -l dump_ata_keys.o # convert your code to binary spu-elf-objcopy -O binary dump_ata_keys.o dump_ata_keys.bin ls -l dump_ata_keys.bin # decrypt sb_iso_spu_module.self unself sb_iso_spu_module.self sb_iso_spu_module.elf ls -l sb_iso_spu_module.elf mv sb_iso_spu_module.elf dump_ata_keys.elf # print program header of decrypted SPU module readelf -l dump_ata_keys.elf Elf file type is EXEC (Executable file) Entry point 0x880 There are 3 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x000100 0x00000880 0x00000880 0x05040 0x05040 R E 0x80 LOAD 0x005180 0x00005900 0x00005900 0x00030 0x001c0 RW 0x80 NOTE 0x0051b0 0x00000000 0x00000000 0x00034 0x00000 R 0x10 Section to Segment mapping: Segment Sections... 00 .unknown .unknown 01 .unknown .unknown .unknown .unknown 02 .unknown # entry point is 0x880 which is in first program segment at file offset 0x100 # now we kill all old code and data with 0s before we put our code there. # seek parameter is the offset of the first program segment. # count parameter is the sum of the offset of the last program segment plus its size and # minus the offset of the first program segmnet. # killing old code and data with 0s is a good idea because 0x00000000 means stop opcode. dd if=/dev/zero of=dump_ata_keys.elf bs=1 seek=$((0x100)) count=$((0x51b0 + 0x34 - 0x100)) conv=notrunc # after you filled out the SPU module with 0s, check it with spu-objdump spu-elf-objdump -d dump_ata_keys.elf dump_ata_keys.elf: file format elf32-spu Disassembly of section : 00000880 <>: ... # now we copy our code to SPU module # seek parameter is the entry point offset in file dd if=dump_ata_keys.bin of=dump_ata_keys.elf bs=1 seek=$((0x100)) conv=notrunc # now build isolated SPU module iso_rebuilder dump_ata_keys.elf dump_ata_keys.self sb_iso_spu_module.self # we are done :) # time to test it with spuisofs !!! # mount spuisofs (we do it of course on PS3 Linux and not on PC) # you could use my Debian LiveCD e.g. which has all tools you need sudo mount -t spuisofs none /mnt ls -l /mnt total 0 -rw-rw-rw- 1 root root 1048576 Sep 7 12:12 app -rw-rw-rw- 1 root root 1048576 Sep 7 12:12 arg1 -rw-rw-rw- 1 root root 1048576 Sep 7 12:12 arg2 --w--w--w- 1 root root 0 Sep 7 12:12 cont -r--r--r-- 1 root root 0 Sep 7 12:12 info -rw-rw-rw- 1 root root 262144 Sep 7 12:12 ls -rw-rw-rw- 1 root root 131072 Sep 7 12:12 priv2 -rw-rw-rw- 1 root root 131072 Sep 7 12:12 problem --w--w--w- 1 root root 24 Sep 7 12:12 run -r--r--r-- 1 root root 4096 Sep 7 12:12 shadow # compile dump_ata_keys application tar xvzf dump_ata_keys.tar.gz cd dump_ata_keys make ls -l dump_ata_keys ./dump_ata_keys usage: ./dump_ata_keys <self path> <eid4 path> # NOTE: you don't really need eid4 to run the application or to dump your ATA keys ./dump_ata_keys ./dump_ata_keys.self ./eid4 spuisofs found at /mnt arg1 kernel virtual address d000000003375000 shadow: spe_execution_status 7 priv2: puint_mb_R 2 shadow: spe_execution_status b problem: spu_status_R 6660082 # here is important to check the stop code which is 0x666 :) # my dump_ata_keys.S code stops with stop code 0x666 when it's done # this way you can be really sure that your dump_ata_keys.self was correctly signed, # encrypted and accepted by isoldr # dump your ATA keys hexdump -C /mnt/arg1
Example: Making dump_encdec_keys.self
- First you need lv1ldr from your NOR/NAND flash or from PS3 update file.
# compile your SPU code spu-elf-gcc -c dump_encdec_keys.S ls -l dump_encdec_keys.o # convert your code to binary spu-elf-objcopy -O binary dump_encdec_keys.o dump_encdec_keys.bin ls -l dump_encdec_keys.bin # decrypt lv1ldr unself lv1ldr lv1ldr.elf ls -l lv1ldr.elf mv lv1ldr.elf dump_encdec_keys.elf # print program header of decrypted SPU module readelf -l dump_encdec_keys.elf Elf file type is EXEC (Executable file) Entry point 0x12c00 There are 3 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x000080 0x00000800 0x00000800 0x00000 0x0cd20 RW 0x80 LOAD 0x000100 0x00012c00 0x00012c00 0x1ca00 0x1ca00 R E 0x80 LOAD 0x01cb00 0x0002f600 0x0002f600 0x004f0 0x004f0 RW 0x80 Section to Segment mapping: Segment Sections... 00 .unknown 01 .unknown .unknown 02 .unknown .unknown .unknown # entry point is 0x12c00 which is in first program segment at file offset 0x100 # now we kill all old code and data with 0s before we put our code there. # seek parameter is the offset of the first program segment. # count parameter is the sum of the offset of the last program segment plus its size and # minus the offset of the first program segmnet. # killing old code and data with 0s is a good idea because 0x00000000 means stop opcode. dd if=/dev/zero of=dump_encdec_keys.elf bs=1 seek=$((0x100)) count=$((0x1cb00 + 0x4f0 - 0x100)) conv=notrunc # after you filled out the SPU module with 0s, check it with spu-objdump spu-elf-objdump -d dump_encdec_keys.elf dump_encdec_keys.elf: file format elf32-spu Disassembly of section : 00012c00 <>: ... # now we copy our code to SPU module # seek parameter is the entry point offset in file dd if=dump_encdec_keys.bin of=dump_encdec_keys.elf bs=1 seek=$((0x100)) conv=notrunc # now build loader iso_rebuilder dump_encdec_keys.elf dump_encdec_keys.self lv1ldr # we are done :) # time to test it with spuldrfs !!! # mount spuldrfs (we do it of course on PS3 Linux and not on PC) # you could use my Debian LiveCD e.g. which has all tools you need sudo mount -t spuldrfs none /mnt ls -l /mnt total 0 -rw-rw-rw- 1 root root 1048576 Sep 7 13:20 buf1 -rw-rw-rw- 1 root root 1048576 Sep 7 13:20 buf2 -rw-rw-rw- 1 root root 1048576 Sep 7 13:20 buf3 -r--r--r-- 1 root root 0 Sep 7 13:20 info -rw-rw-rw- 1 root root 1048576 Sep 7 13:20 ldr -rw-rw-rw- 1 root root 262144 Sep 7 13:20 ls -rw-rw-rw- 1 root root 1048576 Sep 7 13:20 metldr -rw-rw-rw- 1 root root 131072 Sep 7 13:20 priv2 -rw-rw-rw- 1 root root 131072 Sep 7 13:20 problem --w--w--w- 1 root root 0 Sep 7 13:20 run -r--r--r-- 1 root root 4096 Sep 7 13:20 shadow # compile dump_encdec_keys application tar xvzf dump_encdec_keys.tar.gz cd dump_encdec_keys make ls -l dump_encdec_keys ./dump_encdec_keys usage: ./dump_encdec_keys <metldr path> <ldr path> # NOTE: you will need your metldr ./dump_encdec_keys ./metldr ./dump_encdec_keys.self spuldrfs found at /mnt buf1 kernel virtual address d000000003c48000 buf2 kernel virtual address d000000003d49000 priv2: puint_mb_R 1 problem: pu_mb_R 1 priv2: puint_mb_R 666 problem: spu_status_R 6660082 # here is important to check the stop code which is 0x666 :) # my dump_encdec_keys.S code stops with stop code 0x666 when it's done # this way you can be really sure that your dump_encdec_keys.self was correctly signed, # encrypted and accepted by metldr # dump your ENCDEC keys (not really, you have to calculate your ENCDEC keys) hexdump -C /mnt/buf2