SPU Isolated Modules Reverse Engineering: Difference between revisions
No edit summary |
m (→Usage) |
||
(25 intermediate revisions by 9 users not shown) | |||
Line 1: | Line 1: | ||
== anergistic == | == anergistic == | ||
Line 7: | Line 6: | ||
*https://github.com/kraiskil/anergistic.git | *https://github.com/kraiskil/anergistic.git | ||
*http://foxbrew.org/git/anergistic.git/ | *http://git.gitbrew.org/ps3/anergistic.git/ | ||
*https://github.com/psfree/anergistic | |||
*<span style="text-decoration: line-through;">http://foxbrew.org/git/anergistic.git/</span> | |||
*<span style="text-decoration: line-through;">http://git.fail0verflow.com/?p=anergistic.git</span> | |||
=== | === Usage === | ||
anergistic can be launched in two different modes, one that '''only emulates''' (runs) the program through the SPU and the the other that lets you '''debug''' the process through gdb | anergistic can be launched in two different modes, one that '''only emulates''' (runs) the program through the SPU and the the other that lets you '''debug''' the process through gdb | ||
Line 15: | Line 17: | ||
==== only emulate ==== | ==== only emulate ==== | ||
< | {{keyboard|content=<syntaxhighlight lang="bash">./anergistic spu_elf_name.elf</syntaxhighlight>}} | ||
./anergistic spu_elf_name.elf | |||
</ | |||
this mode runs an elf with all the parameters and actions defined on main.c, channel.c a | this mode runs an elf with all the parameters and actions defined on main.c, channel.c a | ||
==== debug ==== | ==== debug ==== | ||
terminal 1 | terminal 1 | ||
< | {{keyboard|content=<syntaxhighlight lang="bash">./anergistic -g1234 spu_elf_name.elf</syntaxhighlight>}} | ||
./anergistic - | |||
</ | simulate debug server in the local host on port 1234 | ||
terminal 2 | terminal 2 | ||
< | {{keyboard|content=<syntaxhighlight lang="bash"> | ||
gdb | spu-gdb spu_elf_name.elf | ||
(gdb)target remote :1234 | (gdb)target remote :1234 | ||
</ | </syntaxhighlight>}} | ||
connect to the local host on port 1234 | |||
(gdb)help will give you information of the command available | |||
==== Documentation ==== | |||
*http://publib.boulder.ibm.com/infocenter/ieduasst/stgv1r0/topic/com.ibm.iea.cbe/cbe/1.0/LinuxOnCell/L2T1H1_31_LinuxonCellToolchainGDB.pdf | |||
*SPU specific commands | |||
**http://sourceware.org/gdb/onlinedocs/gdb/SPU.html | |||
this mode performs the same as above but lets you debug the process through gdb | this mode performs the same as above but lets you debug the process through gdb | ||
Line 37: | Line 48: | ||
=== Customizations === | === Customizations === | ||
See example below. | |||
'''Running in aim_spu_module anergistic''' | '''Running in aim_spu_module anergistic''' | ||
Line 43: | Line 54: | ||
=== Problems === | === Problems === | ||
====Connection | ==== Connection problem ==== | ||
when in debugger mode | when in debugger mode | ||
<pre> | <pre> | ||
Line 50: | Line 62: | ||
recv failed: Success | recv failed: Success | ||
</pre> | </pre> | ||
==== Solution ==== | |||
Use spu-gdb. | |||
=== Tools === | |||
[http://pastie.org/2810870 gnuify_ida.pl][http://paste.ubuntu.com/25615421/ mirror] | |||
Use this to convert IDA disassembly into a format suitable for GNU AS. Literals in IDA are unsigned while AS expects signed literals. Conversion of literals is a work in progress. | |||
== Loading Isolated Modules in GameOS == | |||
This code kinda represents how GameOS applications load and execute isolated SPU SELFs. For example: psp emulator. | |||
<source lang="C"> | |||
sys_spu_initialize(1,1); | |||
syscall(230, sys_spu_t *id,img &iso_spuSCEself,void *arg,0,0,0); //sys_isolated_spu_create | |||
sys_ppu_thread_create(sys_ppu_thread_t *thread_id,void* iso_spu_handler,sys_spu_t *id, 0x64, 0x1000, 2,"iso_spu_handler"); | |||
syscall(233, sys_spu_t *id,2,0,sys_interrupt_tag_t intrtag); //sys_iso_spu_create_interrupt_tag | |||
sys_interrupt_thread_establish(sys_interrupt_thread_handle_t *ih,sys_interrupt_tag_t intrtag,sys_ppu_thread_t t_id, | |||
sys_spu_t id,0); | |||
syscall(234, sys_spu_t *id,2,7); //sys_iso_spu_set_int_mask | |||
syscall(232, sys_spu_t *id); //sys_iso_spu_start | |||
... | |||
iso_spu_handler(...) { | |||
syscall(237, sys_spu_t id,2,void *out1); // sys_iso_spu_get_int_stat | |||
syscall(240, void *out2, out1); // sys_iso_spu_mmio_read / sys_isolated_spu_read_puint_mb ? | |||
syscall(236, sys_spu_t id,2, out1) // sys_iso_spu_set_int_stat | |||
sys_interrupt_thread_eoi() | |||
} | |||
</source> | |||
== aim_spu_module == | == aim_spu_module == | ||
It is used to retrieve the device type, Device Id, OpenPSID and the PsCode from the EID0 data that is passed in. | |||
=== Debug messages === | === Debug messages === | ||
{| class="wikitable" | {| class="wikitable" | ||
! colspan="2" | Address !! rowspan="2" | Message | ! colspan="2" | Address !! rowspan="2" | Message | ||
Line 72: | Line 115: | ||
| 0x3790 || 0x3610 || "(spu) PU DMA area size is not equall to AIM_DMA_SIZE\n" | | 0x3790 || 0x3610 || "(spu) PU DMA area size is not equall to AIM_DMA_SIZE\n" | ||
|} | |} | ||
These messages are sent via DMA to the PPU if a debug output address is specified. | |||
=== Data === | === Data === | ||
{| class="wikitable" | {| class="wikitable" | ||
! colspan="2" | Address !! rowspan="2" | Message | ! colspan="2" | Address !! rowspan="2" | Message | ||
Line 81: | Line 125: | ||
! ? 3.41 ? !! 355 CEX | ! ? 3.41 ? !! 355 CEX | ||
|- | |- | ||
| 0x37e0 || - || Reference | | 0x37e0 || - || Reference Tool fallback IDPS | ||
|- | |- | ||
| 0x37f0 - ... || 0x3650 - ... || Start of | | 0x37f0 - ... || 0x3650 - ... || Start of [[Keys#aim_spu_module_Keys|aim_spu_module keys]] | ||
|- | |- | ||
| 0x3ac0 || 0x3870 || AES sbox (16*16 bytes) | | 0x3ac0 || 0x3870 || AES sbox (16*16 bytes) | ||
Line 90: | Line 134: | ||
|} | |} | ||
=== Functions === | |||
{| class="wikitable" | {| class="wikitable" | ||
! colspan="2" | Address !! rowspan="2" | Name !! rowspan="2" | Parameters !! rowspan="2" | Info | ! colspan="2" | Address !! rowspan="2" | Name !! rowspan="2" | Parameters !! rowspan="2" | Info | ||
Line 111: | Line 155: | ||
| 0x17f0 || || - || - || AES 1 Part of aes implementation. | | 0x17f0 || || - || - || AES 1 Part of aes implementation. | ||
|- | |- | ||
| 0x1c48 || || | | 0x1c48 || || aes_encrypt_ecb || - || AES 2 Part of aes implementation. | ||
|- | |- | ||
| 0x1df0 || || | | 0x1df0 || || cellCryptoSpuAesCbcCfb128Decrypt || - || AES 3 Probably part of aes implementation. | ||
|- | |- | ||
| 0x20f0 || || | | 0x20f0 || || aes_omac1 || - || AES 4 Probably part of aes implementation. | ||
|- | |- | ||
| 0x2300 || || | | 0x2300 || || aes_set_key_dec || - || AES 5 Probably part of aes implementation. | ||
|- | |- | ||
| 0x2418 || || | | 0x2418 || || aes_decrypt_ecb || - || AES 6 Part of aes implementation. | ||
|- | |- | ||
| 0x2608 || || | | 0x2608 || || aes_decrypt_ecb_aligned || - || AES 7 Part of aes implementation. | ||
|- | |- | ||
| 0x30c0 || || do_dma || ls_addr:$4, dma_effective_addr:$5, size:$6, tag_id:$7, unk0:$8, unk1:$9 || Used to dma data in and out of the isolated module's LS. | | 0x30c0 || || do_dma || ls_addr:$4, dma_effective_addr:$5, size:$6, tag_id:$7, unk0:$8, unk1:$9 || Used to dma data in and out of the isolated module's LS. | ||
Line 128: | Line 172: | ||
|} | |} | ||
==== Disasm ==== | |||
The complete disassembly is available at [http://pastebin.com/7vArGweJ]. | The complete disassembly is available at [http://pastebin.com/7vArGweJ]. | ||
== Decrypting EID == | |||
== | === Dumper iso.self === | ||
Is there one ? | |||
=== Dumper Payload === | === Dumper Payload === | ||
=== Running in | * [https://web.archive.org/web/20150912102728/http://pastie.org/pastes/2101977 Dumper payload code] | ||
//Partial code modified to run aim_spu_module | * [http://paste.ubuntu.com/25615310/ mirror] | ||
* http:// | |||
=== Running aim_spu_module in anergistic === | |||
* [https://web.archive.org/web/20150912053633/http://pastie.org/2000330 Partial code modified to run aim_spu_module] | |||
* [http://paste.ubuntu.com/25615344/ mirror] | |||
== isoldr == | == isoldr == | ||
Loads, decrypts, runs isolated modules, and creates through AES the required key in LS 0x0. | |||
=== Debug messages === | === Debug messages === | ||
This module | |||
This module doesn't contain debug messages. | |||
=== Data === | === Data === | ||
{| class="wikitable" | {| class="wikitable" | ||
! colspan="2" | Address !! rowspan="2" | Message | ! colspan="2" | Address !! rowspan="2" | Message | ||
Line 158: | Line 208: | ||
|- | |- | ||
|- | |- | ||
| 0x34C40 - ... || | | 0x34C40 - ... || 0x34d10 || Start of isoldr keys [[Keys#Modules]] | ||
|- | |- | ||
| 0x35130 || | | 0x35130 || 0x35050 || AES sbox (16*16 bytes) | ||
|- | |- | ||
| 0x35300 || | | 0x35300 || 0x35220 || AES inverse sbox (16*16 bytes) | ||
|} | |} | ||
=== Functions === | |||
{| class="wikitable" | {| class="wikitable" | ||
! colspan="2" | Address !! rowspan="2" | Name !! rowspan="2" | Parameters !! rowspan="2" | Info | ! colspan="2" | Address !! rowspan="2" | Name !! rowspan="2" | Parameters !! rowspan="2" | Info | ||
Line 172: | Line 222: | ||
! ? 3.41 ? !! 355 CEX | ! ? 3.41 ? !! 355 CEX | ||
|- | |- | ||
| | | 0x259E0 || || cleanup_jump_code || unknown || cleans all the registers and jump to the loader | ||
|- | |||
| 0x259E0 || || main_func || unknown || Main routine. | |||
|- | |||
| 0x346B0 || || write_tag_mask_bit || mask_bit:$4 || Used to set a specific bit in MFC_WrTagMask. | |||
|- | |||
| 0x27438 || || aes128_cbc_decrypt || || | |||
|- | |||
| 0x27508 || || aes128_cbc_encrypt || || | |||
|- | |||
| 0x29DC0 || || aes_ctr || || | |||
|- | |||
| 0x2BB28 || || aes_set_key_enc || || | |||
|- | |||
| 0x2C0D0 || || cellCryptoSpuAesCbcCfb128Encrypt || || | |||
|- | |||
| 0x2C240 || || cellCryptoSpuAesCbcCfb128Decrypt || || | |||
|- | |||
| 0x2C540 || || cellCryptoSpuAesCtr || || | |||
|- | |||
| 0x2C8D0 || || aes_omac1 || || | |||
|- | |||
| 0x2CAE0 || || sha1_buffer || || | |||
|- | |||
| 0x2CB70 || || sha1_hmac_init || || | |||
|- | |||
| 0x2CC70 || || sha1_hmac_update || || | |||
|- | |||
| 0x2CC90 || || sha1_hmac_final || || | |||
|- | |||
| 0x2CD28 || || sha1_hmac_buffer || || | |||
|- | |||
| 0x2CDC8 || || aes_set_key_dec || || | |||
|- | |- | ||
| | | 0x2CEE0 || || aes_encrypt_ecb_aligned || || | ||
|- | |- | ||
| | | 0x2D7C0 || || aes_decrypt_ecb || || | ||
|- | |- | ||
| | | 0x2D9B0 || || aes_decrypt_ecb_aligned || || | ||
|- | |- | ||
| | | 0x2E450 || || sha1_init || || | ||
|- | |- | ||
| | | 0x2E4C8 || || sha1_update || || | ||
|- | |- | ||
| | | 0x2E700 || || sha1_final || || | ||
|- | |- | ||
| | | 0x2EA88 || || sha1_process || || | ||
|} | |} | ||
* [https://web.archive.org/web/20141118195818/http://pastie.org/2774207 REed functions names from FW 3.41 isoldr] (offsets relative to segment start). | |||
* [http://paste.ubuntu.com/25615363/ mirror] | |||
{{Reverse engineering}}<noinclude>[[Category:Main]]</noinclude> |
Latest revision as of 17:47, 15 September 2021
anergistic[edit | edit source]
Using a static analysis (IDA) could give you a good view of what the program does, but sometimes you want to know what a program does in real time and how it reacts to different parameters, this is where anergistics becomes a powerful tool. It simulates the SPU including its communication, and storage.
Current repos[edit | edit source]
- https://github.com/kraiskil/anergistic.git
- http://git.gitbrew.org/ps3/anergistic.git/
- https://github.com/psfree/anergistic
- http://foxbrew.org/git/anergistic.git/
- http://git.fail0verflow.com/?p=anergistic.git
Usage[edit | edit source]
anergistic can be launched in two different modes, one that only emulates (runs) the program through the SPU and the the other that lets you debug the process through gdb
only emulate[edit | edit source]
./anergistic spu_elf_name.elf
this mode runs an elf with all the parameters and actions defined on main.c, channel.c a
debug[edit | edit source]
terminal 1
./anergistic -g1234 spu_elf_name.elf
simulate debug server in the local host on port 1234
terminal 2
spu-gdb spu_elf_name.elf (gdb)target remote :1234
connect to the local host on port 1234
(gdb)help will give you information of the command available
Documentation[edit | edit source]
- http://publib.boulder.ibm.com/infocenter/ieduasst/stgv1r0/topic/com.ibm.iea.cbe/cbe/1.0/LinuxOnCell/L2T1H1_31_LinuxonCellToolchainGDB.pdf
- SPU specific commands
this mode performs the same as above but lets you debug the process through gdb
Customizations[edit | edit source]
See example below.
Running in aim_spu_module anergistic
Problems[edit | edit source]
Connection problem[edit | edit source]
when in debugger mode
Waiting for gdb to connect... Client connected. recv failed: Success
Solution[edit | edit source]
Use spu-gdb.
Tools[edit | edit source]
Use this to convert IDA disassembly into a format suitable for GNU AS. Literals in IDA are unsigned while AS expects signed literals. Conversion of literals is a work in progress.
Loading Isolated Modules in GameOS[edit | edit source]
This code kinda represents how GameOS applications load and execute isolated SPU SELFs. For example: psp emulator.
sys_spu_initialize(1,1);
syscall(230, sys_spu_t *id,img &iso_spuSCEself,void *arg,0,0,0); //sys_isolated_spu_create
sys_ppu_thread_create(sys_ppu_thread_t *thread_id,void* iso_spu_handler,sys_spu_t *id, 0x64, 0x1000, 2,"iso_spu_handler");
syscall(233, sys_spu_t *id,2,0,sys_interrupt_tag_t intrtag); //sys_iso_spu_create_interrupt_tag
sys_interrupt_thread_establish(sys_interrupt_thread_handle_t *ih,sys_interrupt_tag_t intrtag,sys_ppu_thread_t t_id,
sys_spu_t id,0);
syscall(234, sys_spu_t *id,2,7); //sys_iso_spu_set_int_mask
syscall(232, sys_spu_t *id); //sys_iso_spu_start
...
iso_spu_handler(...) {
syscall(237, sys_spu_t id,2,void *out1); // sys_iso_spu_get_int_stat
syscall(240, void *out2, out1); // sys_iso_spu_mmio_read / sys_isolated_spu_read_puint_mb ?
syscall(236, sys_spu_t id,2, out1) // sys_iso_spu_set_int_stat
sys_interrupt_thread_eoi()
}
aim_spu_module[edit | edit source]
It is used to retrieve the device type, Device Id, OpenPSID and the PsCode from the EID0 data that is passed in.
Debug messages[edit | edit source]
Address | Message | |
---|---|---|
? 3.41 ? | 355 CEX | |
0x36f0 | 0x3570 | "(spu)start aim spu module!\n" |
0x3710 | 0x3590 | "(spu) PU DMA area start address is not align 16byte\n" |
0x3750 | 0x35d0 | "(spu) PU EID area start address is not align 16byte\n" |
0x3790 | 0x3610 | "(spu) PU DMA area size is not equall to AIM_DMA_SIZE\n" |
These messages are sent via DMA to the PPU if a debug output address is specified.
Data[edit | edit source]
Address | Message | |
---|---|---|
? 3.41 ? | 355 CEX | |
0x37e0 | - | Reference Tool fallback IDPS |
0x37f0 - ... | 0x3650 - ... | Start of aim_spu_module keys |
0x3ac0 | 0x3870 | AES sbox (16*16 bytes) |
0x3c70 | 0x3a20 | AES inverse sbox (16*16 bytes) |
Functions[edit | edit source]
Address | Name | Parameters | Info | |
---|---|---|---|---|
3.41 CEX/DEX | 355 CEX | |||
0x9e0 | stop_func | unknown | Stops the module execution with various stop codes. | |
0xa18 | main_func | unknown | Main routine. | |
0xf18 | response | unknown | Sends response to ppu over DMA. | |
0x1158 | process_eid | unknown | Decrypts EID0. | |
0x1438 | prepare_print | unknown | Prepares debug output. | |
0x1440 | debug_print | unknown | As the name already states... (this outputs over DMA) | |
0x17f0 | - | - | AES 1 Part of aes implementation. | |
0x1c48 | aes_encrypt_ecb | - | AES 2 Part of aes implementation. | |
0x1df0 | cellCryptoSpuAesCbcCfb128Decrypt | - | AES 3 Probably part of aes implementation. | |
0x20f0 | aes_omac1 | - | AES 4 Probably part of aes implementation. | |
0x2300 | aes_set_key_dec | - | AES 5 Probably part of aes implementation. | |
0x2418 | aes_decrypt_ecb | - | AES 6 Part of aes implementation. | |
0x2608 | aes_decrypt_ecb_aligned | - | AES 7 Part of aes implementation. | |
0x30c0 | do_dma | ls_addr:$4, dma_effective_addr:$5, size:$6, tag_id:$7, unk0:$8, unk1:$9 | Used to dma data in and out of the isolated module's LS. | |
0x3168 | write_tag_mask_bit | mask_bit:$4 | Used to set a specific bit in MFC_WrTagMask. |
Disasm[edit | edit source]
The complete disassembly is available at [1].
Decrypting EID[edit | edit source]
Dumper iso.self[edit | edit source]
Is there one ?
Dumper Payload[edit | edit source]
Running aim_spu_module in anergistic[edit | edit source]
isoldr[edit | edit source]
Loads, decrypts, runs isolated modules, and creates through AES the required key in LS 0x0.
Debug messages[edit | edit source]
This module doesn't contain debug messages.
Data[edit | edit source]
Address | Message | |
---|---|---|
? 3.41 ? | 355 CEX | |
0x34C40 - ... | 0x34d10 | Start of isoldr keys Keys#Modules |
0x35130 | 0x35050 | AES sbox (16*16 bytes) |
0x35300 | 0x35220 | AES inverse sbox (16*16 bytes) |
Functions[edit | edit source]
Address | Name | Parameters | Info | |
---|---|---|---|---|
? 3.41 ? | 355 CEX | |||
0x259E0 | cleanup_jump_code | unknown | cleans all the registers and jump to the loader | |
0x259E0 | main_func | unknown | Main routine. | |
0x346B0 | write_tag_mask_bit | mask_bit:$4 | Used to set a specific bit in MFC_WrTagMask. | |
0x27438 | aes128_cbc_decrypt | |||
0x27508 | aes128_cbc_encrypt | |||
0x29DC0 | aes_ctr | |||
0x2BB28 | aes_set_key_enc | |||
0x2C0D0 | cellCryptoSpuAesCbcCfb128Encrypt | |||
0x2C240 | cellCryptoSpuAesCbcCfb128Decrypt | |||
0x2C540 | cellCryptoSpuAesCtr | |||
0x2C8D0 | aes_omac1 | |||
0x2CAE0 | sha1_buffer | |||
0x2CB70 | sha1_hmac_init | |||
0x2CC70 | sha1_hmac_update | |||
0x2CC90 | sha1_hmac_final | |||
0x2CD28 | sha1_hmac_buffer | |||
0x2CDC8 | aes_set_key_dec | |||
0x2CEE0 | aes_encrypt_ecb_aligned | |||
0x2D7C0 | aes_decrypt_ecb | |||
0x2D9B0 | aes_decrypt_ecb_aligned | |||
0x2E450 | sha1_init | |||
0x2E4C8 | sha1_update | |||
0x2E700 | sha1_final | |||
0x2EA88 | sha1_process |
- REed functions names from FW 3.41 isoldr (offsets relative to segment start).
- mirror