static Uint32 locate_in_zip(el_zip_file_t* zip, const el_zip_file_entry_t* key) { el_zip_file_entry_t* file; if ((zip == 0) || (key == 0)) { LOG_ERROR("Invalid key or zip"); return 0; } if (zip->count == 0) { return 0; } file = (el_zip_file_entry_t*) bsearch(key, zip->files, zip->count, sizeof(el_zip_file_entry_t), compare_el_zip_file_entry); if (file != 0) { unzGoToFilePos64(zip->file, &file->position); return 1; } else { return 0; } }
int archiveFileOpen(const char *file, int flags, SceMode mode) { int res; if (!uf) return -1; const char *archive_path = file + archive_path_start; int name_length = strlen(archive_path); FileListEntry *archive_entry = archive_list.head; int i; for (i = 0; i < archive_list.length; i++) { if (archive_entry->name_length == name_length && strcasecmp(archive_entry->name, archive_path) == 0) { // Set pos unzGoToFilePos64(uf, (unz64_file_pos *)&archive_entry->reserved); // Open res = unzOpenCurrentFile(uf); if (res < 0) return res; return ARCHIVE_FD; } // Next archive_entry = archive_entry->next; } return -1; }
CZipStream::CZipStream(std::shared_ptr<CIOApi> api, const boost::filesystem::path & archive, unz64_file_pos filepos) { zlib_filefunc64_def zlibApi; zlibApi = api->getApiStructure(); file = unzOpen2_64(archive.c_str(), &zlibApi); unzGoToFilePos64(file, &filepos); unzOpenCurrentFile(file); }
char *ZipFile::GetFileDataByIdx(size_t fileindex, size_t *len) { if (!uf) return NULL; if (fileindex >= filenames.Count()) return NULL; int err = -1; if (filepos.At(fileindex).num_of_file != INVALID_ZIP_FILE_POS) err = unzGoToFilePos64(uf, &filepos.At(fileindex)); if (err != UNZ_OK) { char fileNameA[MAX_PATH]; UINT cp = (fileinfo.At(fileindex).flag & (1 << 11)) ? CP_UTF8 : CP_ZIP; str::conv::ToCodePageBuf(fileNameA, dimof(fileNameA), filenames.At(fileindex), cp); err = unzLocateFile(uf, fileNameA, 0); } if (err != UNZ_OK) return NULL; err = unzOpenCurrentFilePassword(uf, NULL); if (err != UNZ_OK) return NULL; unsigned int len2 = (unsigned int)fileinfo.At(fileindex).uncompressed_size; // overflow check if (len2 != fileinfo.At(fileindex).uncompressed_size || len2 + sizeof(WCHAR) < sizeof(WCHAR) || len2 / 1024 > fileinfo.At(fileindex).compressed_size) { unzCloseCurrentFile(uf); return NULL; } char *result = (char *)Allocator::Alloc(allocator, len2 + sizeof(WCHAR)); if (result) { unsigned int readBytes = unzReadCurrentFile(uf, result, len2); // zero-terminate for convenience result[len2] = result[len2 + 1] = '\0'; if (readBytes != len2) { Allocator::Free(allocator, result); result = NULL; } else if (len) { *len = len2; } } err = unzCloseCurrentFile(uf); if (err != UNZ_OK) { // CRC mismatch, file content is likely damaged Allocator::Free(allocator, result); result = NULL; } return result; }
HRESULT WINAPI CZipFs::Close(void) { HRESULT hr = S_OK; if (m_handle != INVALID_HANDLE_VALUE && m_handle != NULL) { hr = (unzCloseCurrentFile((void*)m_handle) == UNZ_OK) ? S_OK : E_FAIL; if (SUCCEEDED(hr)) { if (UNZ_OK != unzGoToFilePos64((void*)m_handle, &m_currentFilePos)) hr = E_UNEXPECTED; } } m_handle = INVALID_HANDLE_VALUE; m_stream->SetFileHandle(m_handle); return hr; }
int archiveCheckFilesForUnsafeFself() { if (!uf) return -1; FileListEntry *archive_entry = archive_list.head; int i; for (i = 0; i < archive_list.length; i++) { // Set pos unzGoToFilePos64(uf, (unz64_file_pos *)&archive_entry->reserved); // Open if (unzOpenCurrentFile(uf) >= 0) { uint32_t magic = 0; archiveFileRead(ARCHIVE_FD, &magic, sizeof(uint32_t)); // SCE magic if (magic == 0x00454353) { char sce_header[0x84]; archiveFileRead(ARCHIVE_FD, sce_header, sizeof(sce_header)); uint64_t elf1_offset = *(uint64_t *)(sce_header + 0x3C); uint64_t phdr_offset = *(uint64_t *)(sce_header + 0x44); uint64_t section_info_offset = *(uint64_t *)(sce_header + 0x54); int i; // jump to elf1 // Until here we have read 0x88 bytes for (i = 0; i < elf1_offset - 0x88; i += sizeof(uint32_t)) { uint32_t dummy = 0; archiveFileRead(ARCHIVE_FD, &dummy, sizeof(uint32_t)); } // Check imports char *buffer = malloc(archive_entry->size); if (buffer) { int size = archiveFileRead(ARCHIVE_FD, buffer, archive_entry->size); Elf32_Ehdr *elf1 = (Elf32_Ehdr*)buffer; Elf32_Phdr *phdr = (Elf32_Phdr*)(buffer + phdr_offset - elf1_offset); segment_info *info = (segment_info*)(buffer + section_info_offset - elf1_offset); // segment is elf2 section char *segment = buffer + info->offset - elf1_offset; // zlib compress magic char *uncompressed_buffer = NULL; if (segment[0] == 0x78) { // uncompressedBuffer will return elf2 section uncompressed_buffer = uncompressBuffer(elf1, phdr, info, segment); if (uncompressed_buffer) { segment = uncompressed_buffer; } } int unsafe = checkForUnsafeImports(segment); if (uncompressed_buffer) { free(uncompressed_buffer); } free(buffer); if (unsafe) { archiveFileClose(ARCHIVE_FD); return unsafe; } } // Check authid flag uint64_t authid = *(uint64_t *)(sce_header + 0x7C); if (authid != 0x2F00000000000002) { archiveFileClose(ARCHIVE_FD); return 1; // Unsafe } } archiveFileClose(ARCHIVE_FD); } // Next archive_entry = archive_entry->next; } return 0; // Safe }