bool SELFDecrypter::MakeElf(const std::string& elf, bool isElf32) { // Create a new ELF file. fs::file e(elf, o_write | o_create | o_trunc); if(!e) { LOG_ERROR(LOADER, "Could not create ELF file! (%s)", elf.c_str()); return false; } // 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 + 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]); } } 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) { // Allocate a buffer for decompression. u8 *decomp_buf = (u8 *)malloc(phdr64_arr[meta_shdr[i].program_idx].p_filesz); // Set up memory streams for input/output. wxMemoryInputStream decomp_stream_in(data_buf + data_buf_offset, meta_shdr[i].data_size); wxMemoryOutputStream decomp_stream_out; // Create a Zlib stream, read the data and flush the stream. wxZlibInputStream* z_stream = new wxZlibInputStream(decomp_stream_in); z_stream->Read(decomp_stream_out); delete z_stream; // Copy the decompressed result from the stream. decomp_stream_out.CopyTo(decomp_buf, phdr64_arr[meta_shdr[i].program_idx].p_filesz); // 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, phdr64_arr[meta_shdr[i].program_idx].p_filesz); // Release the decompression buffer. free(decomp_buf); } 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 + 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]); } } return true; }
bool SELFDecrypter::MakeElf(const std::string& elf, bool isElf32) { // Create a new ELF file. fs::file e(elf, fs::rewrite); if(!e) { LOG_ERROR(LOADER, "Could not create ELF file! (%s)", elf.c_str()); return false; } // 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 + 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]); } } } 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) { /// Removed all wxWidget dependent code. Replaced with zlib functions. /// Also changed local mallocs to unique_ptrs. // Store the length in writeable memory space. std::unique_ptr<uLongf> 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<u8[]> 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<u8[]> zlib_buf(new u8[data_buf_length]); memcpy(zlib_buf.get(), data_buf, 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 + 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]); } } } return true; }