/// <summary> /// Jump to the .data section of an executable stream /// </summary> private void JumpToTheData() { currentFormat = new FormatProperty(); currentFormat.ExecutableType = ExecutableType.Unknown; dataBase = 0; currentFormat.CodeSectionLength = 0; currentFormat.ExecutableOffset = 0; // dataStart bool searchAgainAtEnd = true; do { searchAgainAtEnd = false; dataBase += currentFormat.ExecutableOffset; currentFormat.ExecutableOffset = 0; currentFormat.ExecutableType = ExecutableType.Unknown; inputFile.Seek(dataBase + currentFormat.ExecutableOffset); IMAGE_DOS_HEADER exeHdr = IMAGE_DOS_HEADER.Deserialize(inputFile); if ((exeHdr.Magic == Constants.IMAGE_NT_SIGNATURE || exeHdr.Magic == Constants.IMAGE_DOS_SIGNATURE) && exeHdr.HeaderParagraphSize >= 4 && exeHdr.NewExeHeaderAddr >= 0x40) { currentFormat.ExecutableOffset = exeHdr.NewExeHeaderAddr; inputFile.Seek(dataBase + currentFormat.ExecutableOffset); exeHdr = IMAGE_DOS_HEADER.Deserialize(inputFile); } switch (exeHdr.Magic) { case Constants.IMAGE_OS2_SIGNATURE: currentFormat.ExecutableType = ProcessNe(); break; case Constants.IMAGE_OS2_SIGNATURE_LE: case (ushort)Constants.IMAGE_NT_SIGNATURE: currentFormat.ExecutableType = ProcessPe(ref searchAgainAtEnd); break; default: break; } }while (searchAgainAtEnd); }
/// <summary> /// Attempt to extract a Wise installer /// </summary> /// <param name="file">Possible Wise installer</param> /// <param name="outputPath">Output directory for extracted files</param> public bool ExtractTo(string file, string outputPath) { file = Path.GetFullPath(file); outputPath = Path.GetFullPath(outputPath); Directory.CreateDirectory(outputPath); if (!Open(file)) { return(false); } // Move to data and determine if this is a known format JumpToTheData(); inputFile.Seek(dataBase + currentFormat.ExecutableOffset); for (int i = 0; i < knownFormats.Length; i++) { if (currentFormat.Equals(knownFormats[i])) { currentFormat = knownFormats[i]; break; } } // Fall back on heuristics if we couldn't match if (currentFormat.ArchiveEnd == 0) { inputFile.Seek(0); Approximate(); if (!pkzip) { if (FindReal(outputPath)) { ExtractFiles(outputPath); RenameFiles(outputPath); Close(); return(true); } } else { offsetReal = offsetApproximate; ExtractFiles(outputPath); RenameFiles(outputPath); Close(); return(true); } Close(); return(false); } // Skip over the addditional DLL name, if we expect it long dataStart = currentFormat.ExecutableOffset; if (currentFormat.Dll) { byte[] dll = new byte[256]; inputFile.Read(dll, 0, 1); dataStart++; if (dll[0] != 0x00) { inputFile.Read(dll, 1, dll[0]); dataStart += dll[0]; int dllLength = inputFile.ReadInt32(); dataStart += 4; } } // Check if flags are consistent if (!currentFormat.NoCrc) { int flags = inputFile.ReadInt32(); if ((flags & 0x0100) != 0) { return(false); } } if (currentFormat.ArchiveEnd > 0) { inputFile.Seek(dataBase + dataStart + currentFormat.ArchiveEnd); int archiveEndLoaded = inputFile.ReadInt32(); if (archiveEndLoaded != 0) { currentFormat.ArchiveEnd = archiveEndLoaded + dataBase; } } inputFile.Seek(dataBase + dataStart + currentFormat.ArchiveStart); // Skip over the initialization text, if we expect it if (currentFormat.InitText) { byte[] waitingBytes = new byte[256]; inputFile.Read(waitingBytes, 0, 1); inputFile.Read(waitingBytes, 1, waitingBytes[0]); } offsetReal = inputFile.Position; ExtractFiles(outputPath); RenameFiles(outputPath); Close(); return(true); }