This commit is contained in:
Nekotekina 2017-02-16 16:56:51 +03:00
parent 0c8bda4f41
commit 3ecba8e57f
2 changed files with 137 additions and 40 deletions

View file

@ -867,7 +867,7 @@ std::vector<fs::file> SCEDecrypter::MakeFile()
// Advance the data buffer offset by data size.
data_buf_offset += meta_shdr[i].data_size;
if (out_f.pos() != out_f.size())
fmt::throw_exception("MakeELF written bytes (%llu) does not equal buffer size (%llu).", out_f.pos(), out_f.size());
@ -877,24 +877,40 @@ std::vector<fs::file> SCEDecrypter::MakeFile()
return vec;
}
bool SELFDecrypter::LoadHeaders()
SELFDecrypter::SELFDecrypter(const fs::file& s)
: self_f(s)
, key_v()
, data_buf_length(0)
{
if(!SCEDecrypter::LoadHeaders()) return false;
}
bool SELFDecrypter::LoadHeaders(bool isElf32)
{
// Read SCE header.
self_f.seek(0);
sce_hdr.Load(self_f);
// Check SCE magic.
if (!sce_hdr.CheckMagic())
{
LOG_ERROR(LOADER, "SELF: Not a SELF file!");
return false;
}
// Read SELF header.
self_hdr.Load(sce_f);
self_hdr.Load(self_f);
// Read the APP INFO.
sce_f.seek(self_hdr.se_appinfooff);
app_info.Load(sce_f);
self_f.seek(self_hdr.se_appinfooff);
app_info.Load(self_f);
// Read ELF header.
sce_f.seek(self_hdr.se_elfoff);
self_f.seek(self_hdr.se_elfoff);
if (isElf32)
elf32_hdr.Load(sce_f);
elf32_hdr.Load(self_f);
else
elf64_hdr.Load(sce_f);
elf64_hdr.Load(self_f);
// Read ELF program headers.
if (isElf32)
@ -905,11 +921,11 @@ bool SELFDecrypter::LoadHeaders()
LOG_ERROR(LOADER, "SELF: ELF program header offset is null!");
return false;
}
sce_f.seek(self_hdr.se_phdroff);
self_f.seek(self_hdr.se_phdroff);
for(u32 i = 0; i < elf32_hdr.e_phnum; ++i)
{
phdr32_arr.emplace_back();
phdr32_arr.back().Load(sce_f);
phdr32_arr.back().Load(self_f);
}
}
else
@ -922,40 +938,40 @@ bool SELFDecrypter::LoadHeaders()
return false;
}
sce_f.seek(self_hdr.se_phdroff);
self_f.seek(self_hdr.se_phdroff);
for (u32 i = 0; i < elf64_hdr.e_phnum; ++i)
{
phdr64_arr.emplace_back();
phdr64_arr.back().Load(sce_f);
phdr64_arr.back().Load(self_f);
}
}
// Read section info.
secinfo_arr.clear();
sce_f.seek(self_hdr.se_secinfoff);
self_f.seek(self_hdr.se_secinfoff);
for(u32 i = 0; i < ((isElf32) ? elf32_hdr.e_phnum : elf64_hdr.e_phnum); ++i)
{
secinfo_arr.emplace_back();
secinfo_arr.back().Load(sce_f);
secinfo_arr.back().Load(self_f);
}
// Read SCE version info.
sce_f.seek(self_hdr.se_sceveroff);
scev_info.Load(sce_f);
self_f.seek(self_hdr.se_sceveroff);
scev_info.Load(self_f);
// Read control info.
ctrlinfo_arr.clear();
sce_f.seek(self_hdr.se_controloff);
self_f.seek(self_hdr.se_controloff);
u32 i = 0;
while(i < self_hdr.se_controlsize)
{
ctrlinfo_arr.emplace_back();
ControlInfo &cinfo = ctrlinfo_arr.back();
cinfo.Load(sce_f);
cinfo.Load(self_f);
i += cinfo.size;
}
@ -970,12 +986,12 @@ bool SELFDecrypter::LoadHeaders()
return true;
}
sce_f.seek(self_hdr.se_shdroff);
self_f.seek(self_hdr.se_shdroff);
for(u32 i = 0; i < elf32_hdr.e_shnum; ++i)
{
shdr32_arr.emplace_back();
shdr32_arr.back().Load(sce_f);
shdr32_arr.back().Load(self_f);
}
}
else
@ -987,19 +1003,19 @@ bool SELFDecrypter::LoadHeaders()
return true;
}
sce_f.seek(self_hdr.se_shdroff);
self_f.seek(self_hdr.se_shdroff);
for(u32 i = 0; i < elf64_hdr.e_shnum; ++i)
{
shdr64_arr.emplace_back();
shdr64_arr.back().Load(sce_f);
shdr64_arr.back().Load(self_f);
}
}
return true;
}
void SELFDecrypter::ShowHeaders()
void SELFDecrypter::ShowHeaders(bool isElf32)
{
LOG_NOTICE(LOADER, "SCE header");
LOG_NOTICE(LOADER, "----------------------------------------------------");
@ -1116,8 +1132,76 @@ bool SELFDecrypter::DecryptNPDRM(u8 *metadata, u32 metadata_size)
bool SELFDecrypter::LoadMetadata()
{
aes_context aes;
u32 metadata_info_size = SIZE_32(meta_info);
auto metadata_info = std::make_unique<u8[]>(metadata_info_size);
u32 metadata_headers_size = sce_hdr.se_hsize - (SIZE_32(sce_hdr) + sce_hdr.se_meta + SIZE_32(meta_info));
auto metadata_headers = std::make_unique<u8[]>(metadata_headers_size);
// Locate and read the encrypted metadata info.
self_f.seek(sce_hdr.se_meta + sizeof(sce_hdr));
self_f.read(metadata_info.get(), metadata_info_size);
// Locate and read the encrypted metadata header and section header.
self_f.seek(sce_hdr.se_meta + sizeof(sce_hdr) + metadata_info_size);
self_f.read(metadata_headers.get(), metadata_headers_size);
// Find the right keyset from the key vault.
SELF_KEY keyset = key_v.FindSelfKey(app_info.self_type, sce_hdr.se_flags, app_info.version);
return SCEDecrypter::LoadMetadata(keyset.erk,keyset.riv);
// Copy the necessary parameters.
u8 metadata_key[0x20];
u8 metadata_iv[0x10];
memcpy(metadata_key, keyset.erk, 0x20);
memcpy(metadata_iv, keyset.riv, 0x10);
// Check DEBUG flag.
if ((sce_hdr.se_flags & 0x8000) != 0x8000)
{
// Decrypt the NPDRM layer.
if (!DecryptNPDRM(metadata_info.get(), metadata_info_size))
return false;
// Decrypt the metadata info.
aes_setkey_dec(&aes, metadata_key, 256); // AES-256
aes_crypt_cbc(&aes, AES_DECRYPT, metadata_info_size, metadata_iv, metadata_info.get(), metadata_info.get());
}
// Load the metadata info.
meta_info.Load(metadata_info.get());
// If the padding is not NULL for the key or iv fields, the metadata info
// is not properly decrypted.
if ((meta_info.key_pad[0] != 0x00) ||
(meta_info.iv_pad[0] != 0x00))
{
LOG_ERROR(LOADER, "SELF: Failed to decrypt metadata info!");
return false;
}
// Perform AES-CTR encryption on the metadata headers.
size_t ctr_nc_off = 0;
u8 ctr_stream_block[0x10];
aes_setkey_enc(&aes, meta_info.key, 128);
aes_crypt_ctr(&aes, metadata_headers_size, &ctr_nc_off, meta_info.iv, ctr_stream_block, metadata_headers.get(), metadata_headers.get());
// Load the metadata header.
meta_hdr.Load(metadata_headers.get());
// Load the metadata section headers.
meta_shdr.clear();
for (unsigned int i = 0; i < meta_hdr.section_count; i++)
{
meta_shdr.emplace_back();
meta_shdr.back().Load(metadata_headers.get() + sizeof(meta_hdr) + sizeof(MetadataSectionHeader) * i);
}
// Copy the decrypted data keys.
data_keys_length = meta_hdr.key_count * 0x10;
data_keys = std::make_unique<u8[]>(data_keys_length);
memcpy(data_keys.get(), metadata_headers.get() + sizeof(meta_hdr) + meta_hdr.section_count * sizeof(MetadataSectionHeader), data_keys_length);
return true;
}
bool SELFDecrypter::DecryptData()
@ -1162,8 +1246,8 @@ bool SELFDecrypter::DecryptData()
auto buf = std::make_unique<u8[]>(meta_shdr[i].data_size);
// Seek to the section data offset and read the encrypted data.
sce_f.seek(meta_shdr[i].data_offset);
sce_f.read(buf.get(), meta_shdr[i].data_size);
self_f.seek(meta_shdr[i].data_offset);
self_f.read(buf.get(), meta_shdr[i].data_size);
// Zero out our ctr nonce.
memset(ctr_stream_block, 0, sizeof(ctr_stream_block));
@ -1184,7 +1268,7 @@ bool SELFDecrypter::DecryptData()
return true;
}
fs::file SELFDecrypter::MakeFile()
fs::file SELFDecrypter::MakeElf(bool isElf32)
{
// Create a new ELF file.
fs::file e = fs::make_stream<std::vector<u8>>();
@ -1419,10 +1503,10 @@ extern fs::file decrypt_self(fs::file elf_or_self)
bool isElf32 = IsSelfElf32(elf_or_self);
// Start the decrypter on this SELF file.
SELFDecrypter self_dec(elf_or_self, isElf32);
SELFDecrypter self_dec(elf_or_self);
// Load the SELF file headers.
if (!self_dec.LoadHeaders())
if (!self_dec.LoadHeaders(isElf32))
{
LOG_ERROR(LOADER, "SELF: Failed to load SELF file headers!");
return fs::file{};
@ -1443,7 +1527,7 @@ extern fs::file decrypt_self(fs::file elf_or_self)
}
// Make a new ELF file from this SELF.
return self_dec.MakeFile();
return self_dec.MakeElf(isElf32);
}
return elf_or_self;

View file

@ -366,14 +366,16 @@ public:
bool DecryptData();
};
class SELFDecrypter : private SCEDecrypter
class SELFDecrypter
{
// SELF, APP headers.
// Main SELF file stream.
const fs::file& self_f;
// SCE, SELF and APP headers.
SceHeader sce_hdr;
SelfHeader self_hdr;
AppInfo app_info;
bool isElf32;
// ELF64 header and program header/section header arrays.
Elf64_Ehdr elf64_hdr;
std::vector<Elf64_Shdr> shdr64_arr;
@ -389,14 +391,25 @@ class SELFDecrypter : private SCEDecrypter
SCEVersionInfo scev_info;
std::vector<ControlInfo> ctrlinfo_arr;
// Metadata structs.
MetadataInfo meta_info;
MetadataHeader meta_hdr;
std::vector<MetadataSectionHeader> meta_shdr;
// Internal data buffers.
std::unique_ptr<u8[]> data_keys;
u32 data_keys_length;
std::unique_ptr<u8[]> data_buf;
u32 data_buf_length;
// Main key vault instance.
KeyVault key_v;
public:
SELFDecrypter(const fs::file& s, bool isElf32) : SCEDecrypter(s), key_v(), isElf32(isElf32) {};
fs::file MakeFile();
bool LoadHeaders();
void ShowHeaders();
SELFDecrypter(const fs::file& s);
fs::file MakeElf(bool isElf32);
bool LoadHeaders(bool isElf32);
void ShowHeaders(bool isElf32);
bool LoadMetadata();
bool DecryptData();
bool DecryptNPDRM(u8 *metadata, u32 metadata_size);