Making Isolated SPU Modules and Loaders: Difference between revisions

From PS3 Developer wiki
Jump to navigation Jump to search
mNo edit summary
 
(29 intermediate revisions by 3 users not shown)
Line 1: Line 1:
[[Category:OtherOS]]
=Introduction=
=Introduction=


Line 5: Line 6:


=Tools=
=Tools=
* My Debian LiveCD has all tools you will need.
* See http://www.ps3devwiki.com/wiki/Debian_LiveCD


==SPU GCC Compiler==
==SPU GCC Compiler==


* You need SPU GCC compiler to compile your code and create binary version of it.
* You need SPU GCC compiler to compile your code and create binary version of it.
* On PS3 Debian, just install spu toolchain.
* On PS3 Debian, just install spu toolchain with aptitude.
* You can also cross-compile SPU GCC toolchain for your Linux PC.
* 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==
==ps3tools==
Line 42: Line 47:
* First you need '''sb_iso_spu_module.self''' from your NOR/NAND flash or from PS3 update file.
* First you need '''sb_iso_spu_module.self''' from your NOR/NAND flash or from PS3 update file.


<pre>
{{Keyboard|content=<syntaxhighlight lang="bash">
# compile your SPU code
# compile your SPU code


Line 84: Line 89:
# entry point is 0x880 which is in first program segment at file offset 0x100
# entry point is 0x880 which is in first program segment at file offset 0x100


# now we kill all old code with 0s before we put our code there.
# 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.
# 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
# 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.
# 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
dd if=/dev/zero of=dump_ata_keys.elf bs=1 seek=$((0x100)) count=$((0x51b0 + 0x34 - 0x100)) conv=notrunc
Line 114: Line 121:
# we are done :)
# we are done :)
# time to test it with spuisofs !!!
# time to test it with spuisofs !!!
</pre>
 
# 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
</syntaxhighlight>}}


=Example: Making dump_encdec_keys.self=
=Example: Making dump_encdec_keys.self=


* First you need '''lv1ldr''' from your NOR/NAND flash or from PS3 update file.
* First you need '''lv1ldr''' from your NOR/NAND flash or from PS3 update file.
{{Keyboard|content=<syntaxhighlight lang="bash">
# 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 loader
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 second 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 second program segment.
# count parameter is the sum of the offset of the last program segment plus its size and
# minus the offset of the second program segment.
# 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 loader
# 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
</syntaxhighlight>}}
{{Linux}}<noinclude>[[Category:Main]]</noinclude>

Latest revision as of 03:03, 3 February 2014

Introduction[edit | edit source]

  • 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[edit | edit source]

SPU GCC Compiler[edit | edit source]

  • 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[edit | edit source]

  • 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[edit | edit source]

  • I test my isolated SPU modules and loaders with PS3 Linux and spuisofs/spuldrfs Virtual File Systems.

spuisofs[edit | edit source]

  • 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[edit | edit source]

  • 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[edit | edit source]

  • First you need sb_iso_spu_module.self from your NOR/NAND flash or from PS3 update file.
Type This
# 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[edit | edit source]

  • First you need lv1ldr from your NOR/NAND flash or from PS3 update file.
Type This
# 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 loader

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 second 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 second program segment.
# count parameter is the sum of the offset of the last program segment plus its size and
# minus the offset of the second program segment.

# 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 loader
# 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