Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}