1 // Copyright 2010 Sven Peter <svenpeter@gmail.com>
2 // Licensed under the terms of the GNU GPL, version 2
3 // http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
6 // Thanks to xorloser for his selftool!
19 static struct elf_hdr ehdr
;
22 static u32 meta_offset
;
23 static u64 elf_offset
;
24 static u64 header_len
;
25 static u64 phdr_offset
;
26 static u64 shdr_offset
;
30 static u64 app_version
;
33 static u64 info_offset
;
34 static u64 sec_offset
;
36 static u64 ctrl_offset
;
39 static int decrypted
= -1;
41 struct id2name_tbl t_sdk_type
[] = {
42 {0, "Retail (Type 0)"},
44 {2, "Retail (Type 1)"},
49 struct id2name_tbl t_app_type
[] = {
54 {5, "isolated SPU module"},
56 {8, "NP-DRM application"},
60 static struct id2name_tbl t_shdr_type
[] = {
76 static struct id2name_tbl t_elf_type
[] = {
78 {ET_REL
, "Relocatable file"},
79 {ET_EXEC
, "Executable file"},
80 {ET_DYN
, "Shared object file"},
81 {ET_CORE
, "Core file"},
85 static struct id2name_tbl t_elf_machine
[] = {
93 static struct id2name_tbl t_phdr_type
[] = {
104 static struct id2name_tbl t_compressed
[] = {
110 static struct id2name_tbl t_encrypted
[] = {
117 static void parse_self(void)
119 sdk_type
= be16(self
+ 0x08);
120 meta_offset
= be32(self
+ 0x0c);
121 header_len
= be64(self
+ 0x10);
122 filesize
= be64(self
+ 0x18);
123 info_offset
= be64(self
+ 0x28);
124 elf_offset
= be64(self
+ 0x30);
125 phdr_offset
= be64(self
+ 0x38) - elf_offset
;
126 shdr_offset
= be64(self
+ 0x40) - elf_offset
;
127 sec_offset
= be64(self
+ 0x48);
128 ver_info
= be64(self
+ 0x50);
129 ctrl_offset
= be64(self
+ 0x58);
130 ctrl_size
= be64(self
+ 0x60);
132 vendorid
= be32(self
+ info_offset
+ 0x08);
133 authid
= be64(self
+ info_offset
+ 0x00);
134 app_type
= be32(self
+ info_offset
+ 0x0c);
135 app_version
= be64(self
+ info_offset
+ 0x10);
137 elf
= self
+ elf_offset
;
138 arch64
= elf_read_hdr(elf
, &ehdr
);
142 static struct keylist
*self_load_keys(void)
169 fail("invalid type: %08x", app_type
);
175 static void decrypt_header(void)
177 struct keylist
*klist
;
179 klist
= self_load_keys();
183 decrypted
= sce_decrypt_header(self
, klist
);
189 static const char *get_auth_type(void)
194 static void show_self_header(void)
196 printf("SELF header\n");
197 printf(" elf #1 offset: %08x_%08x\n", (u32
)(elf_offset
>>32), (u32
)elf_offset
);
198 printf(" header len: %08x_%08x\n", (u32
)(header_len
>>32), (u32
)header_len
);
199 printf(" meta offset: %08x_%08x\n", 0, meta_offset
);
200 printf(" phdr offset: %08x_%08x\n", (u32
)(phdr_offset
>>32), (u32
)phdr_offset
);
201 printf(" shdr offset: %08x_%08x\n", (u32
)(shdr_offset
>>32), (u32
)shdr_offset
);
202 printf(" file size: %08x_%08x\n", (u32
)(filesize
>>32), (u32
)filesize
);
203 printf(" auth id: %08x_%08x (%s)\n", (u32
)(authid
>>32), (u32
)authid
, get_auth_type());
204 printf(" vendor id: %08x\n", vendorid
);
205 printf(" info offset: %08x_%08x\n", (u32
)(info_offset
>> 32), (u32
)info_offset
);
206 printf(" sinfo offset: %08x_%08x\n", (u32
)(sec_offset
>> 32), (u32
)sec_offset
);
207 printf(" version offset: %08x_%08x\n", (u32
)(ver_info
>> 32), (u32
)ver_info
);
208 printf(" control info: %08x_%08x (%08x_%08x bytes)\n",
209 (u32
)(ctrl_offset
>> 32), (u32
)ctrl_offset
,
210 (u32
)(ctrl_size
>> 32), (u32
)ctrl_size
);
212 printf(" app version: %x.%x.%x\n", (u16
)(app_version
>> 48), (u16
)(app_version
>> 32), (u32
)app_version
);
213 printf(" SDK type: %s\n", id2name(sdk_type
, t_sdk_type
, "unknown"));
214 printf(" app type: %s\n", id2name(app_type
, t_app_type
, "unknown"));
220 static void print_hash(u8
*ptr
, u32 len
)
223 printf(" %02x", *ptr
++);
227 static void show_ctrl(void)
232 printf("Control info\n");
234 for (i
= 0; i
< ctrl_size
; ) {
235 type
= be32(self
+ ctrl_offset
+ i
);
236 length
= be32(self
+ ctrl_offset
+ i
+ 0x04);
239 if (length
== 0x30) {
240 printf(" control flags:\n ");
241 print_hash(self
+ ctrl_offset
+ i
+ 0x10, 0x10);
246 if (length
== 0x40) {
247 printf(" file digest:\n ");
248 print_hash(self
+ ctrl_offset
+ i
+ 0x10, 0x14);
250 print_hash(self
+ ctrl_offset
+ i
+ 0x24, 0x14);
254 if (length
== 0x30) {
255 printf(" file digest:\n ");
256 print_hash(self
+ ctrl_offset
+ i
+ 0x10, 0x14);
261 if (length
== 0x90) {
265 memcpy(id
, self
+ ctrl_offset
+ i
+ 0x20, 0x30);
267 printf(" NPDRM info:\n");
268 printf(" magic: %08x\n", be32(self
+ ctrl_offset
+ i
+ 0x10));
269 printf(" unk0 : %08x\n", be32(self
+ ctrl_offset
+ i
+ 0x14));
270 printf(" unk1 : %08x\n", be32(self
+ ctrl_offset
+ i
+ 0x18));
271 printf(" unk2 : %08x\n", be32(self
+ ctrl_offset
+ i
+ 0x1c));
272 printf(" content_id: %s\n", id
);
274 print_hash(self
+ ctrl_offset
+ i
+ 0x50, 0x10);
275 printf("\n invdigest: ");
276 print_hash(self
+ ctrl_offset
+ i
+ 0x60, 0x10);
277 printf("\n xordigest: ");
278 print_hash(self
+ ctrl_offset
+ i
+ 0x70, 0x10);
283 printf(" unknown:\n");
284 for(j
= 0; j
< length
; j
++) {
287 printf(" %02x", be8(self
+ ctrl_offset
+ i
+ j
));
288 if ((j
% 16) == 15 || (j
== length
- 1))
298 static void show_sinfo(void)
302 u32 compressed
, encrypted
;
305 printf("Section header\n");
307 printf(" offset size compressed unk1"
308 " unk2 encrypted\n");
310 for (i
= 0; i
< ehdr
.e_phnum
; i
++) {
311 offset
= be64(self
+ sec_offset
+ i
*0x20 + 0x00);
312 size
= be64(self
+ sec_offset
+ i
*0x20 + 0x08);
313 compressed
= be32(self
+ sec_offset
+ i
*0x20 + 0x10);
314 unk1
= be32(self
+ sec_offset
+ i
*0x20 + 0x14);
315 unk2
= be32(self
+ sec_offset
+ i
*0x20 + 0x18);
316 encrypted
= be32(self
+ sec_offset
+ i
*0x20 + 0x1c);
317 printf(" %08x_%08x %08x_%08x %s %08x %08x %s\n",
318 (u32
)(offset
>> 32), (u32
)offset
,
319 (u32
)(size
>> 32), (u32
)size
,
320 id2name(compressed
, t_compressed
, "[???]"),
322 id2name(encrypted
, t_encrypted
, "[???]")
329 static void show_meta(void)
338 printf("Encrypted Metadata\n");
340 if (sdk_type
== 0x8000) {
341 printf(" no encrypted metadata in fselfs.\n\n");
346 printf(" unable to decrypt metadata\n\n");
350 meta_len
= be32(self
+ meta_offset
+ 0x60 + 0x4);
351 meta_n_hdr
= be32(self
+ meta_offset
+ 0x60 + 0xc);
352 meta_n_keys
= be32(self
+ meta_offset
+ 0x60 + 0x10);
355 print_hash(self
+ meta_offset
+ 0x20, 0x10);
359 print_hash(self
+ meta_offset
+ 0x40, 0x10);
362 printf(" Signature end %08x\n", meta_len
);
363 printf(" Sections %d\n", meta_n_hdr
);
364 printf(" Keys %d\n", meta_n_keys
);
367 printf(" Sections\n");
368 printf(" Offset Length Key IV SHA1\n");
369 for (i
= 0; i
< meta_n_hdr
; i
++) {
370 tmp
= self
+ meta_offset
+ 0x80 + 0x30*i
;
372 size
= be64(tmp
+ 8);
373 printf(" %08x_%08x %08x_%08x %03d %03d %03d\n",
374 (u32
)(offset
>> 32), (u32
)offset
, (u32
)(size
>> 32), (u32
)size
,
375 be32(tmp
+ 0x24), be32(tmp
+ 0x28), be32(tmp
+ 0x1c));
380 printf(" Idx Data\n");
381 tmp
= self
+ meta_offset
+ 0x80 + 0x30*meta_n_hdr
;
382 for (i
= 0; i
< meta_n_keys
; i
++) {
384 print_hash(tmp
+ i
*0x10, 0x10);
393 static void show_elf_header(void)
395 printf("ELF header\n");
397 printf(" type: %s\n", id2name(ehdr
.e_type
, t_elf_type
, "unknown"));
398 printf(" machine: %s\n", id2name(ehdr
.e_machine
, t_elf_machine
, "unknown"));
399 printf(" version: %d\n", ehdr
.e_version
);
402 printf(" phdr offset: %08x_%08x\n",
403 (u32
)(ehdr
.e_phoff
>>32), (u32
)ehdr
.e_phoff
);
404 printf(" shdr offset: %08x_%08x\n",
405 (u32
)(ehdr
.e_phoff
>>32), (u32
)ehdr
.e_shoff
);
406 printf(" entry: %08x_%08x\n",
407 (u32
)(ehdr
.e_entry
>>32), (u32
)ehdr
.e_entry
);
409 printf(" phdr offset: %08x\n",
411 printf(" shdr offset: %08x\n",
413 printf(" entry: %08x\n",
417 printf(" flags: %08x\n", ehdr
.e_flags
);
418 printf(" header size: %08x\n", ehdr
.e_ehsize
);
419 printf(" program header size: %08x\n",
421 printf(" program headers: %d\n", ehdr
.e_phnum
);
422 printf(" section header size: %08x\n",
424 printf(" section headers: %d\n", ehdr
.e_shnum
);
425 printf(" section header string table index: %d\n", ehdr
.e_shtrndx
);
430 static void get_flags(u32 flags
, char *ptr
)
443 static void show_phdr(unsigned int idx
)
446 char ppc
[4], spe
[4], rsx
[4];
448 elf_read_phdr(arch64
, elf
+ phdr_offset
+ (ehdr
.e_phentsize
* idx
), &p
);
450 get_flags(p
.p_flags
, ppc
);
451 get_flags(p
.p_flags
>> 20, spe
);
452 get_flags(p
.p_flags
>> 24, rsx
);
455 printf(" %5s %08x_%08x %08x_%08x %08x_%08x\n"
456 " %08x_%08x %08x_%08x"
457 " %s %s %s %08x_%08x\n",
458 id2name(p
.p_type
, t_phdr_type
, "?????"),
459 (u32
)(p
.p_off
>> 32) , (u32
)p
.p_off
,
460 (u32
)(p
.p_vaddr
>> 32) , (u32
)p
.p_vaddr
,
461 (u32
)(p
.p_paddr
>> 32) , (u32
)p
.p_paddr
,
462 (u32
)(p
.p_memsz
>> 32) , (u32
)p
.p_memsz
,
463 (u32
)(p
.p_filesz
>> 32) , (u32
)p
.p_filesz
,
465 (u32
)(p
.p_align
>> 32) , (u32
)p
.p_align
468 printf(" %5s %08x %08x %08x "
469 "%08x %08x %s %s %s %08x\n",
470 id2name(p
.p_type
, t_phdr_type
, "?????"),
471 (u32
)p
.p_off
, (u32
)p
.p_vaddr
,
472 (u32
)p
.p_paddr
, (u32
)p
.p_memsz
, (u32
)p
.p_filesz
,
473 ppc
, spe
, rsx
, (u32
)p
.p_align
);
477 static void get_shdr_flags(u32 flags
, char *ptr
)
490 static void show_shdr(unsigned int idx
)
495 elf_read_shdr(arch64
, elf
+ shdr_offset
+ (ehdr
.e_shentsize
* idx
), &s
);
496 get_shdr_flags(s
.sh_flags
, flags
);
499 printf(" [%02d] %-15s %-9s %08x_%08x"
500 " %02d %-3s %02d %03d %02d\n"
501 " %08x_%08x %08x_%08x\n",
503 id2name(s
.sh_type
, t_shdr_type
, "????"),
504 (u32
)(s
.sh_addr
>> 32), (u32
)s
.sh_addr
,
505 s
.sh_entsize
, flags
, s
.sh_link
, s
.sh_info
,
507 (u32
)(s
.sh_offset
>> 32), (u32
)s
.sh_offset
,
511 printf(" [%02d] %-15s %-9s %08x"
512 " %08x %08x %02d %-3s %02d %02d %02d\n",
514 id2name(s
.sh_type
, t_shdr_type
, "????"),
515 (u32
)s
.sh_addr
, (u32
)s
.sh_offset
,
516 s
.sh_size
, s
.sh_entsize
,
517 flags
, s
.sh_link
, s
.sh_info
, s
.sh_addralign
);
522 static void show_phdrs(void)
526 printf("Program headers\n");
528 if (ehdr
.e_phnum
== 0) {
529 printf("No program headers in this file.\n");
532 printf(" type offset vaddr "
533 "paddr\n memsize filesize"
534 " PPU SPE RSX align\n");
536 printf(" type offset vaddr paddr "
537 "memsize filesize PPU SPE RSX align\n");
538 for (i
= 0; i
< ehdr
.e_phnum
; i
++)
545 static void show_shdrs(void)
549 printf("Section headers\n");
551 if (ehdr
.e_shnum
== 0) {
552 printf("No section headers in this file.\n");
555 printf(" [Nr] Name Type Addr"
556 " ES Flg Lk Inf Al\n"
559 printf(" [Nr] Name Type Addr"
560 " Off Size ES Flg Lk Inf Al\n");
561 for (i
= 0; i
< ehdr
.e_shnum
; i
++)
568 int main(int argc
, char *argv
[])
571 fail("usage: readself file.self");
573 self
= mmap_file(argv
[1]);