From 095d02e41bc67efc65b0565074f5e927205bdd18 Mon Sep 17 00:00:00 2001 From: Jake Date: Wed, 20 Jun 2018 20:50:57 -0500 Subject: [PATCH] elf: handle decompress flag for 32 bit elfs --- rpcs3/Crypto/unself.cpp | 106 +--------------------------------------- rpcs3/Crypto/unself.h | 77 +++++++++++++++++++++++++++++ rpcs3/rpcs3.vcxproj | 8 +-- 3 files changed, 83 insertions(+), 108 deletions(-) diff --git a/rpcs3/Crypto/unself.cpp b/rpcs3/Crypto/unself.cpp index 452030629f..7f670136cf 100644 --- a/rpcs3/Crypto/unself.cpp +++ b/rpcs3/Crypto/unself.cpp @@ -1274,115 +1274,13 @@ fs::file SELFDecrypter::MakeElf(bool isElf32) // Create a new ELF file. fs::file e = fs::make_stream>(); - // Set initial offset. - u32 data_buf_offset = 0; - if (isElf32) { - // Write ELF header. - WriteEhdr(e, elf32_hdr); - - // Write program headers. - for (u32 i = 0; i < elf32_hdr.e_phnum; ++i) - { - WritePhdr(e, phdr32_arr[i]); - } - - for (unsigned int i = 0; i < meta_hdr.section_count; i++) - { - // PHDR type. - if (meta_shdr[i].type == 2) - { - // Seek to the program header data offset and write the data. - e.seek(phdr32_arr[meta_shdr[i].program_idx].p_offset); - e.write(data_buf.get() + data_buf_offset, meta_shdr[i].data_size); - - // Advance the data buffer offset by data size. - data_buf_offset += meta_shdr[i].data_size; - } - } - - // Write section headers. - if (self_hdr.se_shdroff != 0) - { - e.seek(elf32_hdr.e_shoff); - - for (u32 i = 0; i < elf32_hdr.e_shnum; ++i) - { - WriteShdr(e, shdr32_arr[i]); - } - } + WriteElf(e, elf32_hdr, shdr32_arr, phdr32_arr); } else { - // Write ELF header. - WriteEhdr(e, elf64_hdr); - - // Write program headers. - for (u32 i = 0; i < elf64_hdr.e_phnum; ++i) - { - WritePhdr(e, phdr64_arr[i]); - } - - // Write data. - for (unsigned int i = 0; i < meta_hdr.section_count; i++) - { - // PHDR type. - if (meta_shdr[i].type == 2) - { - // Decompress if necessary. - if (meta_shdr[i].compressed == 2) - { - // Store the length in writeable memory space. - std::unique_ptr decomp_buf_length(new uLongf); - memcpy(decomp_buf_length.get(), &phdr64_arr[meta_shdr[i].program_idx].p_filesz, sizeof(uLongf)); - - /// Create a pointer to a buffer for decompression. - std::unique_ptr decomp_buf(new u8[phdr64_arr[meta_shdr[i].program_idx].p_filesz]); - - // Create a buffer separate from data_buf to uncompress. - std::unique_ptr zlib_buf(new u8[data_buf_length]); - memcpy(zlib_buf.get(), data_buf.get(), data_buf_length); - - // Use zlib uncompress on the new buffer. - // decomp_buf_length changes inside the call to uncompress, so it must be a pointer to correct type (in writeable mem space). - int rv = uncompress(decomp_buf.get(), decomp_buf_length.get(), zlib_buf.get() + data_buf_offset, data_buf_length); - - // Check for errors (TODO: Probably safe to remove this once these changes have passed testing.) - switch (rv) - { - case Z_MEM_ERROR: LOG_ERROR(LOADER, "MakeELF encountered a Z_MEM_ERROR!"); break; - case Z_BUF_ERROR: LOG_ERROR(LOADER, "MakeELF encountered a Z_BUF_ERROR!"); break; - case Z_DATA_ERROR: LOG_ERROR(LOADER, "MakeELF encountered a Z_DATA_ERROR!"); break; - default: break; - } - - // Seek to the program header data offset and write the data. - e.seek(phdr64_arr[meta_shdr[i].program_idx].p_offset); - e.write(decomp_buf.get(), phdr64_arr[meta_shdr[i].program_idx].p_filesz); - } - else - { - // Seek to the program header data offset and write the data. - e.seek(phdr64_arr[meta_shdr[i].program_idx].p_offset); - e.write(data_buf.get() + data_buf_offset, meta_shdr[i].data_size); - } - - // Advance the data buffer offset by data size. - data_buf_offset += meta_shdr[i].data_size; - } - } - - // Write section headers. - if (self_hdr.se_shdroff != 0) - { - e.seek(elf64_hdr.e_shoff); - - for (u32 i = 0; i < elf64_hdr.e_shnum; ++i) - { - WriteShdr(e, shdr64_arr[i]); - } - } + WriteElf(e, elf64_hdr, shdr64_arr, phdr64_arr); } return e; diff --git a/rpcs3/Crypto/unself.h b/rpcs3/Crypto/unself.h index 257a21dbef..24f8a4dc03 100644 --- a/rpcs3/Crypto/unself.h +++ b/rpcs3/Crypto/unself.h @@ -1,6 +1,7 @@ #pragma once #include "key_vault.h" +#include "zlib.h" struct AppInfo { @@ -414,6 +415,82 @@ public: bool DecryptData(); bool DecryptNPDRM(u8 *metadata, u32 metadata_size); bool GetKeyFromRap(u8 *content_id, u8 *npdrm_key); + +private: + template + void WriteElf(fs::file& e, EHdr ehdr, SHdr shdr, PHdr phdr) + { + // Set initial offset. + u32 data_buf_offset = 0; + + // Write ELF header. + WriteEhdr(e, ehdr); + + // Write program headers. + for (u32 i = 0; i < ehdr.e_phnum; ++i) + { + WritePhdr(e, phdr[i]); + } + + for (unsigned int i = 0; i < meta_hdr.section_count; i++) + { + // PHDR type. + if (meta_shdr[i].type == 2) + { + // Decompress if necessary. + if (meta_shdr[i].compressed == 2) + { + const auto filesz = phdr[meta_shdr[i].program_idx].p_filesz; + + // Create a pointer to a buffer for decompression. + std::unique_ptr decomp_buf(new u8[filesz]); + + // Create a buffer separate from data_buf to uncompress. + std::unique_ptr zlib_buf(new u8[data_buf_length]); + memcpy(zlib_buf.get(), data_buf.get(), data_buf_length); + + uLongf decomp_buf_length = ::narrow(filesz); + + // Use zlib uncompress on the new buffer. + // decomp_buf_length changes inside the call to uncompress + int rv = uncompress(decomp_buf.get(), &decomp_buf_length, zlib_buf.get() + data_buf_offset, data_buf_length); + + // Check for errors (TODO: Probably safe to remove this once these changes have passed testing.) + switch (rv) + { + case Z_MEM_ERROR: LOG_ERROR(LOADER, "MakeELF encountered a Z_MEM_ERROR!"); break; + case Z_BUF_ERROR: LOG_ERROR(LOADER, "MakeELF encountered a Z_BUF_ERROR!"); break; + case Z_DATA_ERROR: LOG_ERROR(LOADER, "MakeELF encountered a Z_DATA_ERROR!"); break; + default: break; + } + + // Seek to the program header data offset and write the data. + e.seek(phdr[meta_shdr[i].program_idx].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.get() + data_buf_offset, meta_shdr[i].data_size); + } + + // Advance the data buffer offset by data size. + data_buf_offset += meta_shdr[i].data_size; + } + } + + // Write section headers. + if (self_hdr.se_shdroff != 0) + { + e.seek(ehdr.e_shoff); + + for (u32 i = 0; i < ehdr.e_shnum; ++i) + { + WriteShdr(e, shdr[i]); + } + } + } }; extern fs::file decrypt_self(fs::file elf_or_self, u8* klic_key = nullptr); diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index 01a4d1f1dd..756df6006c 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -107,20 +107,20 @@ true - ..\3rdparty\hidapi\hidapi;.\;..\;..\asmjit\src;..\3rdparty\yaml-cpp\include;..\3rdparty\ffmpeg\WindowsInclude;..\3rdparty\cereal\include;..\3rdparty\ffmpeg\Windows\x86_64\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(UniversalCRT_IncludePath);..\3rdparty\minidx12\Include;..\3rdparty\GSL\include;..\3rdparty\libpng;..\3rdparty\GL;..\3rdparty\stblib;..\3rdparty\OpenAL\include;..\3rdparty\pugixml\src;..\3rdparty\Optional;..\3rdparty\discord-rpc\include + ..\3rdparty\hidapi\hidapi;.\;..\;..\asmjit\src;..\3rdparty\yaml-cpp\include;..\3rdparty\ffmpeg\WindowsInclude;..\3rdparty\cereal\include;..\3rdparty\ffmpeg\Windows\x86_64\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(UniversalCRT_IncludePath);..\3rdparty\minidx12\Include;..\3rdparty\GSL\include;..\3rdparty\libpng;..\3rdparty\GL;..\3rdparty\stblib;..\3rdparty\OpenAL\include;..\3rdparty\pugixml\src;..\3rdparty\Optional;..\3rdparty\discord-rpc\include;..\3rdparty\zlib $(SolutionDir)lib\$(Configuration)-$(Platform)\;$(UniversalCRT_LibraryPath_x64);$(LibraryPath) - ..\3rdparty\hidapi\hidapi;.\;..\;..\asmjit\src;..\3rdparty\yaml-cpp\include;..\3rdparty\ffmpeg\WindowsInclude;..\3rdparty\cereal\include;..\3rdparty\ffmpeg\Windows\x86_64\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(UniversalCRT_IncludePath);..\3rdparty\minidx12\Include;..\3rdparty\GSL\include;..\3rdparty\libpng;..\3rdparty\GL;..\3rdparty\stblib;..\3rdparty\OpenAL\include;..\3rdparty\pugixml\src;..\3rdparty\Optional;..\3rdparty\discord-rpc\include + ..\3rdparty\hidapi\hidapi;.\;..\;..\asmjit\src;..\3rdparty\yaml-cpp\include;..\3rdparty\ffmpeg\WindowsInclude;..\3rdparty\cereal\include;..\3rdparty\ffmpeg\Windows\x86_64\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(UniversalCRT_IncludePath);..\3rdparty\minidx12\Include;..\3rdparty\GSL\include;..\3rdparty\libpng;..\3rdparty\GL;..\3rdparty\stblib;..\3rdparty\OpenAL\include;..\3rdparty\pugixml\src;..\3rdparty\Optional;..\3rdparty\discord-rpc\include;..\3rdparty\zlib $(SolutionDir)lib\Debug-x64;$(SolutionDir)lib\$(Configuration)-$(Platform)\;$(UniversalCRT_LibraryPath_x64);$(LibraryPath) $(SolutionDir)lib\$(Configuration)-$(Platform)\;$(UniversalCRT_LibraryPath_x64);$(LibraryPath) - ..\3rdparty\hidapi\hidapi;.\;..\;..\asmjit\src;..\3rdparty\yaml-cpp\include;..\3rdparty\ffmpeg\WindowsInclude;..\3rdparty\cereal\include;..\3rdparty\ffmpeg\Windows\x86_64\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(UniversalCRT_IncludePath);..\3rdparty\minidx12\Include;..\3rdparty\GSL\include;..\3rdparty\libpng;..\3rdparty\GL;..\3rdparty\stblib;..\3rdparty\OpenAL\include;..\3rdparty\pugixml\src;..\3rdparty\Optional;..\3rdparty\discord-rpc\include + ..\3rdparty\hidapi\hidapi;.\;..\;..\asmjit\src;..\3rdparty\yaml-cpp\include;..\3rdparty\ffmpeg\WindowsInclude;..\3rdparty\cereal\include;..\3rdparty\ffmpeg\Windows\x86_64\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(UniversalCRT_IncludePath);..\3rdparty\minidx12\Include;..\3rdparty\GSL\include;..\3rdparty\libpng;..\3rdparty\GL;..\3rdparty\stblib;..\3rdparty\OpenAL\include;..\3rdparty\pugixml\src;..\3rdparty\Optional;..\3rdparty\discord-rpc\include;..\3rdparty\zlib $(SolutionDir)lib\Release-x64;$(SolutionDir)lib\$(Configuration)-$(Platform)\;$(UniversalCRT_LibraryPath_x64);$(LibraryPath) - ..\3rdparty\hidapi\hidapi;.\;..\;..\asmjit\src;..\3rdparty\yaml-cpp\include;..\3rdparty\ffmpeg\WindowsInclude;..\3rdparty\cereal\include;..\3rdparty\ffmpeg\Windows\x86_64\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(UniversalCRT_IncludePath);..\3rdparty\minidx12\Include;..\3rdparty\GSL\include;..\3rdparty\libpng;..\3rdparty\GL;..\3rdparty\stblib;..\3rdparty\OpenAL\include;..\3rdparty\pugixml\src;..\3rdparty\Optional;..\3rdparty\discord-rpc\include + ..\3rdparty\hidapi\hidapi;.\;..\;..\asmjit\src;..\3rdparty\yaml-cpp\include;..\3rdparty\ffmpeg\WindowsInclude;..\3rdparty\cereal\include;..\3rdparty\ffmpeg\Windows\x86_64\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(UniversalCRT_IncludePath);..\3rdparty\minidx12\Include;..\3rdparty\GSL\include;..\3rdparty\libpng;..\3rdparty\GL;..\3rdparty\stblib;..\3rdparty\OpenAL\include;..\3rdparty\pugixml\src;..\3rdparty\Optional;..\3rdparty\discord-rpc\include;..\3rdparty\zlib