|
|
#11 | |
|
Member
![]() Join Date: Dec 2008
Posts: 30
Likes: 0
Liked 8 Times in 6 Posts
Mentioned: 3 Post(s)
Tagged: 0 Thread(s)
|
So maybe your work isn't incomplete. And also, if syscall471 is used to verify act.dat, what's the purpose to call that also for free content? |
|
|
|
|
|
Likes: (1) |
|
|
#12 |
|
Senior Member
![]() Join Date: Aug 2011
Posts: 1,268
Likes: 178
Liked 838 Times in 391 Posts
Mentioned: 59 Post(s)
Tagged: 0 Thread(s)
|
this is a really interesting read. thanks for sharing.
|
|
|
|
|
|
#13 |
|
Homebrew Developer
Join Date: Oct 2011
Posts: 9
Likes: 0
Liked 33 Times in 6 Posts
Mentioned: 6 Post(s)
Tagged: 0 Thread(s)
|
Don't doubt yourself, JuanNadie! The algorithm you posted is correct. It is indeed the plain IDPS. Using your posted algorithm I was able to completely remove the NPDRM layer on an encrypted, paid SELF to get the decrypted metadata keys. I suspect the game sharing people download games while logged in to a friend's PS3. When they download the game to their friend's PS3, the NPDRM layer is added using their friend's IDPS.
|
|
|
|
|
Likes: (1) |
|
|
#14 |
|
Member
![]() Join Date: Sep 2011
Location: York,PA USA
Posts: 509
Likes: 11
Liked 92 Times in 60 Posts
Mentioned: 32 Post(s)
Tagged: 0 Thread(s)
|
This is good news for me. I lost all of my content with that dumb QA setting. Yes I tried it before I should have and yes it is my fault,But it will still be nice to get my stuff back.
|
|
|
|
|
|
#16 |
![]() ![]() Join Date: Jul 2011
Posts: 79
Likes: 94
Liked 81 Times in 35 Posts
Mentioned: 7 Post(s)
Tagged: 0 Thread(s)
|
Great work JuanNadie !!
Thanks for sharing ... |
|
|
|
|
|
#17 |
|
Apprentice
![]() Join Date: Sep 2011
Posts: 13
Likes: 0
Liked 5 Times in 2 Posts
Mentioned: 0 Post(s)
Tagged: 0 Thread(s)
|
so how long untill someone codes a app to use this huh
|
|
|
|
|
|
#18 |
|
Member
![]() Join Date: Sep 2010
Posts: 49
Likes: 1
Liked 36 Times in 15 Posts
Mentioned: 10 Post(s)
Tagged: 0 Thread(s)
|
Here's sources of unself_gnpdrm (tool for decrypting NPDRM'ed SELFs generated with Geohot's make_self_npdrm static key):
Code:
// Copyright 2010 Sven Peter <svenpeter@gmail.com>
// Licensed under the terms of the GNU GPL, version 2
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
#include "tools.h"
#include "types.h"
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#define MAX_SECTIONS 255
static u8 *self = NULL;
static u8 *elf = NULL;
static FILE *out = NULL;
static u64 info_offset;
static u32 key_ver;
static u64 phdr_offset;
static u64 shdr_offset;
static u64 sec_offset;
static u64 ver_offset;
static u64 version;
static u64 elf_offset;
static u64 meta_offset;
static u64 header_len;
static u64 filesize;
static u32 arch64;
static u32 n_sections;
static u64 ctrl_offset;
static u64 ctrl_size;
static u64 unknown2;
static u64 authid;
static u32 vendorid;
static u32 app_type;
static u64 unknown3;
static u64 elf_ident;
static u64 elf_ident2;
static struct elf_hdr ehdr;
static struct {
u32 offset;
u32 size;
u32 compressed;
u32 size_uncompressed;
u32 elf_offset;
} self_sections[MAX_SECTIONS];
static void read_header(void)
{
key_ver = be16(self + 0x08);
meta_offset = be32(self + 0x0c);
header_len = be64(self + 0x10);
filesize = be64(self + 0x18);
info_offset = be64(self + 0x28);
elf_offset = be64(self + 0x30);
phdr_offset = be64(self + 0x38) - elf_offset;
shdr_offset = be64(self + 0x40) - elf_offset;
sec_offset = be64(self + 0x48);
ver_offset = be64(self + 0x50);
ctrl_offset = be64(self + 0x58);
ctrl_size = be64(self + 0x60);
unknown2 = be64(self + 0x68);
authid = be64(self + info_offset + 0x00);
vendorid = be32(self + info_offset + 0x08);
app_type = be32(self + info_offset + 0x0c);
version = be64(self + info_offset + 0x10);
unknown3 = be64(self + info_offset + 0x18);
elf_ident = be64(self + elf_offset + 0x00);
elf_ident2 = be64(self + elf_offset + 0x08);
elf = self + elf_offset;
arch64 = elf_read_hdr(elf, &ehdr);
}
struct self_sec {
u32 idx;
u64 offset;
u64 size;
u32 compressed;
u32 encrypted;
u64 next;
};
static void read_section(u32 i, struct self_sec *sec)
{
u8 *ptr;
ptr = self + sec_offset + i*0x20;
sec->idx = i;
sec->offset = be64(ptr + 0x00);
sec->size = be64(ptr + 0x08);
sec->compressed = be32(ptr + 0x10) == 2 ? 1 : 0;
sec->encrypted = be32(ptr + 0x1c);
sec->next = be64(ptr + 0x20);
}
static int qsort_compare(const void *a, const void *b)
{
const struct self_sec *sa, *sb;
sa = a;
sb = b;
if (sa->offset > sb->offset)
return 1;
else if(sa->offset < sb->offset)
return -1;
else
return 0;
}
static void read_sections(void)
{
struct self_sec s[MAX_SECTIONS];
struct elf_phdr p;
u32 i;
u32 j;
u32 n_secs;
u32 self_offset, elf_offset;
memset(s, 0, sizeof s);
for (i = 0, j = 0; i < ehdr.e_phnum; i++) {
read_section(i, &s[j]);
if (s[j].compressed)
j++;
}
n_secs = j;
qsort(s, n_secs, sizeof(*s), qsort_compare);
elf_offset = 0;
self_offset = header_len;
j = 0;
i = 0;
while (elf_offset < filesize) {
if (i == n_secs) {
self_sections[j].offset = self_offset;
self_sections[j].size = filesize - elf_offset;
self_sections[j].compressed = 0;
self_sections[j].size_uncompressed = filesize - elf_offset;
self_sections[j].elf_offset = elf_offset;
elf_offset = filesize;
} else if (self_offset == s[i].offset) {
self_sections[j].offset = self_offset;
self_sections[j].size = s[i].size;
self_sections[j].compressed = 1;
elf_read_phdr(arch64, elf + phdr_offset +
(ehdr.e_phentsize * s[i].idx), &p);
self_sections[j].size_uncompressed = p.p_filesz;
self_sections[j].elf_offset = p.p_off;
elf_offset = p.p_off + p.p_filesz;
self_offset = s[i].next;
i++;
} else {
elf_read_phdr(arch64, elf + phdr_offset +
(ehdr.e_phentsize * s[i].idx), &p);
self_sections[j].offset = self_offset;
self_sections[j].size = p.p_off - elf_offset;
self_sections[j].compressed = 0;
self_sections[j].size_uncompressed = self_sections[j].size;
self_sections[j].elf_offset = elf_offset;
elf_offset += self_sections[j].size;
self_offset += s[i].offset - self_offset;
}
j++;
}
n_sections = j;
}
static void write_elf(void)
{
u32 i;
u8 *bfr;
u32 size;
u32 offset = 0;
for (i = 0; i < n_sections; i++) {
fseek(out, self_sections[i].elf_offset, SEEK_SET);
offset = self_sections[i].elf_offset;
if (self_sections[i].compressed) {
size = self_sections[i].size_uncompressed;
bfr = malloc(size);
if (bfr == NULL)
fail("failed to allocate %d bytes", size);
offset += size;
printf("compressed self_sections[i].offset 0x%x self_sections[i].size 0x%x\n",
self_sections[i].offset,self_sections[i].size);
decompress(self + self_sections[i].offset,
self_sections[i].size,
bfr, size);
fwrite(bfr, size, 1, out);
free(bfr);
} else {
bfr = self + self_sections[i].offset;
size = self_sections[i].size;
offset += size;
fwrite(bfr, size, 1, out);
}
}
}
static void remove_shnames(u64 shdr_offset, u16 n_shdr, u64 shstrtab_offset, u32 strtab_size)
{
u16 i;
u32 size;
struct elf_shdr s;
if (arch64)
size = 0x40;
else
size = 0x28;
for (i = 0; i < n_shdr; i++) {
elf_read_shdr(arch64, elf + shdr_offset + i * size, &s);
s.sh_name = 0;
if (s.sh_type == 3) {
s.sh_offset = shstrtab_offset;
s.sh_size = strtab_size;
}
elf_write_shdr(arch64, elf + shdr_offset + i * size, &s);
}
}
static void check_elf(void)
{
u8 bfr[0x48];
u64 elf_offset;
u64 phdr_offset;
u64 shdr_offset;
u64 phdr_offset_new;
u64 shdr_offset_new;
u64 shstrtab_offset;
u16 n_phdr;
u16 n_shdr;
const char shstrtab[] = ".unknown\0\0";
const char elf_magic[4] = {0x7f, 'E', 'L', 'F'};
fseek(out, 0, SEEK_SET);
fread(bfr, 4, 1, out);
if (memcmp(bfr, elf_magic, sizeof elf_magic) == 0)
return;
elf_offset = be64(self + 0x30);
phdr_offset = be64(self + 0x38) - elf_offset;
shdr_offset = be64(self + 0x40) - elf_offset;
if (arch64) {
fseek(out, 0x48, SEEK_SET);
phdr_offset_new = 0x48;
fseek(out, 0, SEEK_END);
shdr_offset_new = ftell(out);
n_phdr = be16(elf + 0x38);
n_shdr = be16(elf + 0x3c);
shstrtab_offset = shdr_offset_new + n_shdr * 0x40;
remove_shnames(shdr_offset, n_shdr, shstrtab_offset, sizeof shstrtab);
fseek(out, phdr_offset_new, SEEK_SET);
fwrite(elf + phdr_offset, 0x38, n_phdr, out);
fseek(out, shdr_offset_new, SEEK_SET);
fwrite(elf + shdr_offset, 0x40, n_shdr, out);
wbe64(elf + 0x20, phdr_offset_new);
wbe64(elf + 0x28, shdr_offset_new);
fseek(out, SEEK_SET, 0);
fwrite(elf, 0x48, 1, out);
fseek(out, shstrtab_offset, SEEK_SET);
fwrite(shstrtab, sizeof shstrtab, 1, out);
} else {
fseek(out, 0x34, SEEK_SET);
phdr_offset_new = 0x34;
fseek(out, 0, SEEK_END);
shdr_offset_new = ftell(out);
n_phdr = be16(elf + 0x2c);
n_shdr = be16(elf + 0x30);
shstrtab_offset = shdr_offset_new + n_shdr * 0x40;
remove_shnames(shdr_offset, n_shdr, shstrtab_offset, sizeof shstrtab);
fseek(out, phdr_offset_new, SEEK_SET);
fwrite(elf + phdr_offset, 0x20, n_phdr, out);
fseek(out, shdr_offset_new, SEEK_SET);
fwrite(elf + shdr_offset, 0x28, n_shdr, out);
wbe32(elf + 0x1c, phdr_offset_new);
wbe32(elf + 0x20, shdr_offset_new);
fseek(out, SEEK_SET, 0);
fwrite(elf, 0x34, 1, out);
fseek(out, shstrtab_offset, SEEK_SET);
fwrite(shstrtab, sizeof shstrtab, 1, out);
}
}
static void sce_decrypt_header_gnpdrm(u8 *ptr)
{
u32 meta_offset;
u32 meta_len;
u64 header_len;
meta_offset = be32(ptr + 0x0c);
header_len = be64(ptr + 0x10);
u8 npdrm_key[] = {
0x87,0xC7,0x4F,0xFE,0x66,0x93,0x0B,0xAA,0xA1,0x6F,0x86,0x40,0x91,0xC5,0x66,0xFB};
u8 npdrm_iv[] = {
0x08,0x28,0xB5,0x8F,0xAC,0xF9,0xDE,0xC8,0xD7,0x0D,0xFE,0xF0,0xF3,0x76,0x63,0xAE};
aes128ctr(npdrm_key, npdrm_iv, ptr + meta_offset + 0x60, 0x20, ptr + meta_offset + 0x60);
meta_len = header_len - meta_offset;
aes128ctr(npdrm_key, npdrm_iv, ptr + meta_offset + 0x80, meta_len - 0x80, ptr + meta_offset + 0x80);
}
static void self_decrypt(void)
{
if (sce_decrypt_data(self) < 0)
fail("self_decrypt_data failed");
}
int main(int argc, char *argv[])
{
if (argc != 3)
fail("usage: unself in.self out.elf");
self = mmap_file(argv[1]);
if (be32(self) != 0x53434500)
fail("not a SELF");
read_header();
read_sections();
sce_decrypt_header_gnpdrm(self);
self_decrypt();
out = fopen(argv[2], "wb+");
write_elf();
check_elf();
fclose(out);
return 0;
}
|
|
|
|
|
|
#19 |
![]() ![]() Join Date: Feb 2007
Posts: 6,930
Likes: 370
Liked 7,987 Times in 1,233 Posts
Mentioned: 568 Post(s)
Tagged: 0 Thread(s)
|
Moved to PS3 | Technical Development and Coding Area
|
|
|
|
|
|
#20 |
|
Member
![]() Join Date: Dec 2010
Posts: 333
Likes: 6
Liked 44 Times in 24 Posts
Mentioned: 11 Post(s)
Tagged: 0 Thread(s)
|
as long as it takes, mate : )
|
|
|
|
![]() |
| Bookmarks |
| Thread Tools | |
|
|