mirror of
https://github.com/ARMSX2/ARMSX3.git
synced 2026-08-24 16:58:52 -07:00
unself: add some OOB checks
This commit is contained in:
+70
-55
@@ -90,7 +90,7 @@ inline void Write64(const fs::file& f, const be_t<u64> data)
|
||||
f.write(&data, sizeof(data));
|
||||
}
|
||||
|
||||
void WriteEhdr(const fs::file& f, Elf64_Ehdr& ehdr)
|
||||
void WriteEhdr(const fs::file& f, const Elf64_Ehdr& ehdr)
|
||||
{
|
||||
Write32(f, ehdr.e_magic);
|
||||
Write8(f, ehdr.e_class);
|
||||
@@ -113,7 +113,7 @@ void WriteEhdr(const fs::file& f, Elf64_Ehdr& ehdr)
|
||||
Write16(f, ehdr.e_shstrndx);
|
||||
}
|
||||
|
||||
void WritePhdr(const fs::file& f, Elf64_Phdr& phdr)
|
||||
void WritePhdr(const fs::file& f, const Elf64_Phdr& phdr)
|
||||
{
|
||||
Write32(f, phdr.p_type);
|
||||
Write32(f, phdr.p_flags);
|
||||
@@ -125,7 +125,7 @@ void WritePhdr(const fs::file& f, Elf64_Phdr& phdr)
|
||||
Write64(f, phdr.p_align);
|
||||
}
|
||||
|
||||
void WriteShdr(const fs::file& f, Elf64_Shdr& shdr)
|
||||
void WriteShdr(const fs::file& f, const Elf64_Shdr& shdr)
|
||||
{
|
||||
Write32(f, shdr.sh_name);
|
||||
Write32(f, shdr.sh_type);
|
||||
@@ -139,7 +139,7 @@ void WriteShdr(const fs::file& f, Elf64_Shdr& shdr)
|
||||
Write64(f, shdr.sh_entsize);
|
||||
}
|
||||
|
||||
void WriteEhdr(const fs::file& f, Elf32_Ehdr& ehdr)
|
||||
void WriteEhdr(const fs::file& f, const Elf32_Ehdr& ehdr)
|
||||
{
|
||||
Write32(f, ehdr.e_magic);
|
||||
Write8(f, ehdr.e_class);
|
||||
@@ -162,7 +162,7 @@ void WriteEhdr(const fs::file& f, Elf32_Ehdr& ehdr)
|
||||
Write16(f, ehdr.e_shstrndx);
|
||||
}
|
||||
|
||||
void WritePhdr(const fs::file& f, Elf32_Phdr& phdr)
|
||||
void WritePhdr(const fs::file& f, const Elf32_Phdr& phdr)
|
||||
{
|
||||
Write32(f, phdr.p_type);
|
||||
Write32(f, phdr.p_offset);
|
||||
@@ -174,7 +174,7 @@ void WritePhdr(const fs::file& f, Elf32_Phdr& phdr)
|
||||
Write32(f, phdr.p_align);
|
||||
}
|
||||
|
||||
void WriteShdr(const fs::file& f, Elf32_Shdr& shdr)
|
||||
void WriteShdr(const fs::file& f, const Elf32_Shdr& shdr)
|
||||
{
|
||||
Write32(f, shdr.sh_name);
|
||||
Write32(f, shdr.sh_type);
|
||||
@@ -674,7 +674,7 @@ bool SCEDecrypter::LoadMetadata(const u8 erk[32], const u8 riv[16])
|
||||
|
||||
// Load the metadata section headers.
|
||||
meta_shdr.clear();
|
||||
for (unsigned int i = 0; i < meta_hdr.section_count; i++)
|
||||
for (u32 i = 0; i < meta_hdr.section_count; i++)
|
||||
{
|
||||
const usz shdr_offset = sizeof(meta_hdr) + sizeof(MetadataSectionHeader) * i;
|
||||
ensure(metadata_headers.size() > shdr_offset);
|
||||
@@ -699,9 +699,9 @@ bool SCEDecrypter::DecryptData()
|
||||
usz data_buf_length = 0;
|
||||
|
||||
// Calculate the total data size.
|
||||
for (unsigned int i = 0; i < meta_hdr.section_count; i++)
|
||||
for (const MetadataSectionHeader& hdr : meta_shdr)
|
||||
{
|
||||
data_buf_length += ::narrow<u32>(meta_shdr[i].data_size);
|
||||
data_buf_length += ::narrow<u32>(hdr.data_size);
|
||||
}
|
||||
|
||||
// Allocate a buffer to store decrypted data.
|
||||
@@ -711,7 +711,7 @@ bool SCEDecrypter::DecryptData()
|
||||
u32 data_buf_offset = 0;
|
||||
|
||||
// Parse the metadata section headers to find the offsets of encrypted data.
|
||||
for (unsigned int i = 0; i < meta_hdr.section_count; i++)
|
||||
for (const MetadataSectionHeader& hdr : meta_shdr)
|
||||
{
|
||||
usz ctr_nc_off = 0;
|
||||
u8 ctr_stream_block[0x10];
|
||||
@@ -719,43 +719,43 @@ bool SCEDecrypter::DecryptData()
|
||||
u8 data_iv[0x10];
|
||||
|
||||
// Check if this is an encrypted section.
|
||||
if (meta_shdr[i].encrypted == 3)
|
||||
if (hdr.encrypted == 3)
|
||||
{
|
||||
// Make sure the key and iv are not out of boundaries.
|
||||
if ((meta_shdr[i].key_idx <= meta_hdr.key_count - 1) && (meta_shdr[i].iv_idx <= meta_hdr.key_count))
|
||||
if ((hdr.key_idx <= meta_hdr.key_count - 1) && (hdr.iv_idx <= meta_hdr.key_count))
|
||||
{
|
||||
// Get the key and iv from the previously stored key buffer.
|
||||
std::memcpy(data_key, data_keys.data() + meta_shdr[i].key_idx * 0x10, 0x10);
|
||||
std::memcpy(data_iv, data_keys.data() + meta_shdr[i].iv_idx * 0x10, 0x10);
|
||||
std::memcpy(data_key, data_keys.data() + hdr.key_idx * 0x10, 0x10);
|
||||
std::memcpy(data_iv, data_keys.data() + hdr.iv_idx * 0x10, 0x10);
|
||||
|
||||
// Allocate a buffer to hold the data.
|
||||
auto buf = std::make_unique<u8[]>(meta_shdr[i].data_size);
|
||||
auto buf = std::make_unique<u8[]>(hdr.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);
|
||||
sce_f.seek(hdr.data_offset);
|
||||
sce_f.read(buf.get(), hdr.data_size);
|
||||
|
||||
// Zero out our ctr nonce.
|
||||
std::memset(ctr_stream_block, 0, sizeof(ctr_stream_block));
|
||||
|
||||
// Perform AES-CTR encryption on the data blocks.
|
||||
aes_setkey_enc(&aes, data_key, 128);
|
||||
aes_crypt_ctr(&aes, meta_shdr[i].data_size, &ctr_nc_off, data_iv, ctr_stream_block, buf.get(), buf.get());
|
||||
aes_crypt_ctr(&aes, hdr.data_size, &ctr_nc_off, data_iv, ctr_stream_block, buf.get(), buf.get());
|
||||
|
||||
// Copy the decrypted data.
|
||||
std::memcpy(data_buf.data() + data_buf_offset, buf.get(), meta_shdr[i].data_size);
|
||||
std::memcpy(data_buf.data() + data_buf_offset, buf.get(), hdr.data_size);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto buf = std::make_unique<u8[]>(meta_shdr[i].data_size);
|
||||
sce_f.seek(meta_shdr[i].data_offset);
|
||||
sce_f.read(buf.get(), meta_shdr[i].data_size);
|
||||
std::memcpy(data_buf.data() + data_buf_offset, buf.get(), meta_shdr[i].data_size);
|
||||
auto buf = std::make_unique<u8[]>(hdr.data_size);
|
||||
sce_f.seek(hdr.data_offset);
|
||||
sce_f.read(buf.get(), hdr.data_size);
|
||||
std::memcpy(data_buf.data() + data_buf_offset, buf.get(), hdr.data_size);
|
||||
}
|
||||
|
||||
// Advance the buffer's offset.
|
||||
data_buf_offset += ::narrow<u32>(meta_shdr[i].data_size);
|
||||
data_buf_offset += ::narrow<u32>(hdr.data_size);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -770,9 +770,8 @@ std::vector<fs::file> SCEDecrypter::MakeFile()
|
||||
u32 data_buf_offset = 0;
|
||||
|
||||
// Write data.
|
||||
for (u32 i = 0; i < meta_hdr.section_count; i++)
|
||||
for (const MetadataSectionHeader& hdr : meta_shdr)
|
||||
{
|
||||
const MetadataSectionHeader& hdr = meta_shdr[i];
|
||||
const u8* src = data_buf.data() + data_buf_offset;
|
||||
fs::file out_f = fs::make_stream<std::vector<u8>>();
|
||||
|
||||
@@ -851,13 +850,13 @@ bool SELFDecrypter::LoadHeaders(bool isElf32, SelfAdditionalInfo* out_info)
|
||||
if (isElf32)
|
||||
{
|
||||
phdr32_arr.clear();
|
||||
if(elf32_hdr.e_phoff == 0 && elf32_hdr.e_phnum)
|
||||
if (elf32_hdr.e_phoff == 0 && elf32_hdr.e_phnum)
|
||||
{
|
||||
self_log.error("ELF program header offset is null!");
|
||||
return false;
|
||||
}
|
||||
self_f.seek(m_ext_hdr.phdr_offset);
|
||||
for(u32 i = 0; i < elf32_hdr.e_phnum; ++i)
|
||||
for (u32 i = 0; i < elf32_hdr.e_phnum; ++i)
|
||||
{
|
||||
phdr32_arr.emplace_back();
|
||||
phdr32_arr.back().Load(self_f);
|
||||
@@ -886,7 +885,7 @@ bool SELFDecrypter::LoadHeaders(bool isElf32, SelfAdditionalInfo* out_info)
|
||||
m_seg_ext_hdr.clear();
|
||||
self_f.seek(m_ext_hdr.segment_ext_hdr_offset);
|
||||
|
||||
for(u32 i = 0; i < (isElf32 ? elf32_hdr.e_phnum : elf64_hdr.e_phnum); ++i)
|
||||
for (u32 i = 0; i < (isElf32 ? elf32_hdr.e_phnum : elf64_hdr.e_phnum); ++i)
|
||||
{
|
||||
if (self_f.pos() >= self_size)
|
||||
{
|
||||
@@ -952,7 +951,7 @@ bool SELFDecrypter::LoadHeaders(bool isElf32, SelfAdditionalInfo* out_info)
|
||||
|
||||
self_f.seek(m_ext_hdr.shdr_offset);
|
||||
|
||||
for(u32 i = 0; i < elf32_hdr.e_shnum; ++i)
|
||||
for (u32 i = 0; i < elf32_hdr.e_shnum; ++i)
|
||||
{
|
||||
shdr32_arr.emplace_back();
|
||||
shdr32_arr.back().Load(self_f);
|
||||
@@ -969,7 +968,7 @@ bool SELFDecrypter::LoadHeaders(bool isElf32, SelfAdditionalInfo* out_info)
|
||||
|
||||
self_f.seek(m_ext_hdr.shdr_offset);
|
||||
|
||||
for(u32 i = 0; i < elf64_hdr.e_shnum; ++i)
|
||||
for (u32 i = 0; i < elf64_hdr.e_shnum; ++i)
|
||||
{
|
||||
shdr64_arr.emplace_back();
|
||||
shdr64_arr.back().Load(self_f);
|
||||
@@ -1004,13 +1003,21 @@ void SELFDecrypter::ShowHeaders(bool isElf32)
|
||||
self_log.notice("----------------------------------------------------");
|
||||
self_log.notice("ELF program headers");
|
||||
self_log.notice("----------------------------------------------------");
|
||||
for(unsigned int i = 0; i < ((isElf32) ? phdr32_arr.size() : phdr64_arr.size()); i++)
|
||||
isElf32 ? phdr32_arr[i].Show() : phdr64_arr[i].Show();
|
||||
if (isElf32)
|
||||
{
|
||||
for (const Elf32_Phdr& hdr : phdr32_arr)
|
||||
hdr.Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const Elf64_Phdr& hdr : phdr64_arr)
|
||||
hdr.Show();
|
||||
}
|
||||
self_log.notice("----------------------------------------------------");
|
||||
self_log.notice("Section info");
|
||||
self_log.notice("----------------------------------------------------");
|
||||
for(unsigned int i = 0; i < m_seg_ext_hdr.size(); i++)
|
||||
m_seg_ext_hdr[i].Show();
|
||||
for (const segment_ext_header& hdr : m_seg_ext_hdr)
|
||||
hdr.Show();
|
||||
self_log.notice("----------------------------------------------------");
|
||||
self_log.notice("SCE version info");
|
||||
self_log.notice("----------------------------------------------------");
|
||||
@@ -1018,13 +1025,21 @@ void SELFDecrypter::ShowHeaders(bool isElf32)
|
||||
self_log.notice("----------------------------------------------------");
|
||||
self_log.notice("Control info");
|
||||
self_log.notice("----------------------------------------------------");
|
||||
for(unsigned int i = 0; i < m_supplemental_hdr_arr.size(); i++)
|
||||
m_supplemental_hdr_arr[i].Show();
|
||||
for (const supplemental_header& hdr : m_supplemental_hdr_arr)
|
||||
hdr.Show();
|
||||
self_log.notice("----------------------------------------------------");
|
||||
self_log.notice("ELF section headers");
|
||||
self_log.notice("----------------------------------------------------");
|
||||
for(unsigned int i = 0; i < ((isElf32) ? shdr32_arr.size() : shdr64_arr.size()); i++)
|
||||
isElf32 ? shdr32_arr[i].Show() : shdr64_arr[i].Show();
|
||||
if (isElf32)
|
||||
{
|
||||
for (const Elf32_Shdr& hdr : shdr32_arr)
|
||||
hdr.Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const Elf64_Shdr& hdr : shdr64_arr)
|
||||
hdr.Show();
|
||||
}
|
||||
self_log.notice("----------------------------------------------------");
|
||||
}
|
||||
|
||||
@@ -1162,7 +1177,7 @@ bool SELFDecrypter::LoadMetadata(const u8* klic_key)
|
||||
|
||||
// Load the metadata section headers.
|
||||
meta_shdr.clear();
|
||||
for (unsigned int i = 0; i < meta_hdr.section_count; i++)
|
||||
for (u32 i = 0; i < meta_hdr.section_count; i++)
|
||||
{
|
||||
const usz shdr_offset = sizeof(meta_hdr) + sizeof(MetadataSectionHeader) * i;
|
||||
ensure(metadata_headers.size() > shdr_offset);
|
||||
@@ -1187,12 +1202,12 @@ bool SELFDecrypter::DecryptData()
|
||||
usz data_buf_length = 0;
|
||||
|
||||
// Calculate the total data size.
|
||||
for (unsigned int i = 0; i < meta_hdr.section_count; i++)
|
||||
for (const MetadataSectionHeader& hdr : meta_shdr)
|
||||
{
|
||||
if (meta_shdr[i].encrypted == 3)
|
||||
if (hdr.encrypted == 3)
|
||||
{
|
||||
if ((meta_shdr[i].key_idx <= meta_hdr.key_count - 1) && (meta_shdr[i].iv_idx <= meta_hdr.key_count))
|
||||
data_buf_length += ::narrow<u32>(meta_shdr[i].data_size);
|
||||
if ((hdr.key_idx <= meta_hdr.key_count - 1) && (hdr.iv_idx <= meta_hdr.key_count))
|
||||
data_buf_length += ::narrow<u32>(hdr.data_size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1203,7 +1218,7 @@ bool SELFDecrypter::DecryptData()
|
||||
u32 data_buf_offset = 0;
|
||||
|
||||
// Parse the metadata section headers to find the offsets of encrypted data.
|
||||
for (unsigned int i = 0; i < meta_hdr.section_count; i++)
|
||||
for (const MetadataSectionHeader& hdr : meta_shdr)
|
||||
{
|
||||
usz ctr_nc_off = 0;
|
||||
u8 ctr_stream_block[0x10];
|
||||
@@ -1211,34 +1226,34 @@ bool SELFDecrypter::DecryptData()
|
||||
u8 data_iv[0x10];
|
||||
|
||||
// Check if this is an encrypted section.
|
||||
if (meta_shdr[i].encrypted == 3)
|
||||
if (hdr.encrypted == 3)
|
||||
{
|
||||
// Make sure the key and iv are not out of boundaries.
|
||||
if((meta_shdr[i].key_idx <= meta_hdr.key_count - 1) && (meta_shdr[i].iv_idx <= meta_hdr.key_count))
|
||||
if ((hdr.key_idx <= meta_hdr.key_count - 1) && (hdr.iv_idx <= meta_hdr.key_count))
|
||||
{
|
||||
// Get the key and iv from the previously stored key buffer.
|
||||
std::memcpy(data_key, data_keys.data() + meta_shdr[i].key_idx * 0x10, 0x10);
|
||||
std::memcpy(data_iv, data_keys.data() + meta_shdr[i].iv_idx * 0x10, 0x10);
|
||||
std::memcpy(data_key, data_keys.data() + hdr.key_idx * 0x10, 0x10);
|
||||
std::memcpy(data_iv, data_keys.data() + hdr.iv_idx * 0x10, 0x10);
|
||||
|
||||
// Allocate a buffer to hold the data.
|
||||
auto buf = std::make_unique<u8[]>(meta_shdr[i].data_size);
|
||||
auto buf = std::make_unique<u8[]>(hdr.data_size);
|
||||
|
||||
// Seek to the section data offset and read the encrypted data.
|
||||
self_f.seek(meta_shdr[i].data_offset);
|
||||
self_f.read(buf.get(), meta_shdr[i].data_size);
|
||||
self_f.seek(hdr.data_offset);
|
||||
self_f.read(buf.get(), hdr.data_size);
|
||||
|
||||
// Zero out our ctr nonce.
|
||||
std::memset(ctr_stream_block, 0, sizeof(ctr_stream_block));
|
||||
|
||||
// Perform AES-CTR encryption on the data blocks.
|
||||
aes_setkey_enc(&aes, data_key, 128);
|
||||
aes_crypt_ctr(&aes, meta_shdr[i].data_size, &ctr_nc_off, data_iv, ctr_stream_block, buf.get(), buf.get());
|
||||
aes_crypt_ctr(&aes, hdr.data_size, &ctr_nc_off, data_iv, ctr_stream_block, buf.get(), buf.get());
|
||||
|
||||
// Copy the decrypted data.
|
||||
std::memcpy(data_buf.data() + data_buf_offset, buf.get(), meta_shdr[i].data_size);
|
||||
std::memcpy(data_buf.data() + data_buf_offset, buf.get(), hdr.data_size);
|
||||
|
||||
// Advance the buffer's offset.
|
||||
data_buf_offset += ::narrow<u32>(meta_shdr[i].data_size);
|
||||
data_buf_offset += ::narrow<u32>(hdr.data_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-13
@@ -482,7 +482,7 @@ public:
|
||||
|
||||
private:
|
||||
template<typename EHdr, typename SHdr, typename PHdr>
|
||||
void WriteElf(fs::file& e, EHdr ehdr, SHdr shdr, PHdr phdr)
|
||||
void WriteElf(fs::file& e, EHdr ehdr, const std::vector<SHdr>& shdrs, const std::vector<PHdr>& phdrs)
|
||||
{
|
||||
// Set initial offset.
|
||||
u32 data_buf_offset = 0;
|
||||
@@ -491,20 +491,22 @@ private:
|
||||
WriteEhdr(e, ehdr);
|
||||
|
||||
// Write program headers.
|
||||
for (u32 i = 0; i < ehdr.e_phnum; ++i)
|
||||
for (const PHdr& phdr : phdrs)
|
||||
{
|
||||
WritePhdr(e, phdr[i]);
|
||||
WritePhdr(e, phdr);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < meta_hdr.section_count; i++)
|
||||
for (const MetadataSectionHeader& hdr : meta_shdr)
|
||||
{
|
||||
// PHDR type.
|
||||
if (meta_shdr[i].type == 2)
|
||||
if (hdr.type == 2)
|
||||
{
|
||||
const PHdr& phdr = ::at32(phdrs, hdr.program_idx);
|
||||
|
||||
// Decompress if necessary.
|
||||
if (meta_shdr[i].compressed == 2)
|
||||
if (hdr.compressed == 2)
|
||||
{
|
||||
const auto filesz = phdr[meta_shdr[i].program_idx].p_filesz;
|
||||
const auto filesz = phdr.p_filesz;
|
||||
|
||||
// Create a pointer to a buffer for decompression.
|
||||
std::unique_ptr<u8[]> decomp_buf(new u8[filesz]);
|
||||
@@ -528,18 +530,18 @@ private:
|
||||
}
|
||||
|
||||
// Seek to the program header data offset and write the data.
|
||||
e.seek(phdr[meta_shdr[i].program_idx].p_offset);
|
||||
e.seek(phdr.p_offset);
|
||||
e.write(decomp_buf.get(), filesz);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Seek to the program header data offset and write the data.
|
||||
e.seek(phdr[meta_shdr[i].program_idx].p_offset);
|
||||
e.write(data_buf.data() + data_buf_offset, meta_shdr[i].data_size);
|
||||
e.seek(phdr.p_offset);
|
||||
e.write(data_buf.data() + data_buf_offset, hdr.data_size);
|
||||
}
|
||||
|
||||
// Advance the data buffer offset by data size.
|
||||
data_buf_offset += ::narrow<u32>(meta_shdr[i].data_size);
|
||||
data_buf_offset += ::narrow<u32>(hdr.data_size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -548,9 +550,9 @@ private:
|
||||
{
|
||||
e.seek(ehdr.e_shoff);
|
||||
|
||||
for (u32 i = 0; i < ehdr.e_shnum; ++i)
|
||||
for (const SHdr& shdr : shdrs)
|
||||
{
|
||||
WriteShdr(e, shdr[i]);
|
||||
WriteShdr(e, shdr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user