Last active
June 13, 2016 09:20
-
-
Save Sup3rc4l1fr4g1l1571c3xp14l1d0c10u5/45d28052890ef2580f29eebb3c9f0ae6 to your computer and use it in GitHub Desktop.
Example of Self-extracting archive for .NET 3.5 Client Profile
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* | |
* Example of Self-extracting archive for .NET 3.5 Client Profile | |
* | |
* Dependency: | |
* https://github.com/yallie/unzip/blob/master/Unzip.cs | |
* | |
* Build: | |
* 1. Perform either | |
* A) Open the "Command Prompt" from the Start menu . | |
* B) Press the Windows key + R key , and enter 'cmd.exe' to shown dialog box. | |
* 2. Download https://github.com/yallie/unzip/blob/master/Unzip.cs and put that in the same directory as nwget.cs. | |
* 3. enter %windir%\Microsoft.NET\Framework\v3.5\csc.exe nwget.cs Unzip.cs | |
* | |
* Create SFX: | |
* 1. Open command prompt | |
* 2. copy /B SelfExtractZip.exe + {ZipArchiveFile} sfx.exe | |
* | |
* License: | |
* NYSL http://www.kmonos.net/nysl/index.en.html | |
* Japanese original text: http://www.kmonos.net/nysl/ | |
* | |
*/ | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Runtime.InteropServices; | |
using System.ComponentModel; | |
using System.IO; | |
using System.Reflection; | |
using System.IO.Compression; | |
namespace SelfExtractZip | |
{ | |
class SelfExtractZip | |
{ | |
static void Main(string[] args) | |
{ | |
var selfAssembly = Assembly.GetEntryAssembly(); | |
var selfPath = selfAssembly.Location; | |
var outputDirectory = Path.GetDirectoryName(selfPath); | |
if (outputDirectory == null) | |
{ | |
return; | |
} | |
using (var selfStream = new FileStream(selfPath, FileMode.Open, FileAccess.Read, FileShare.Read)) | |
{ | |
var sizeOfSelf = selfStream.Length; | |
NativeMethods.IMAGE_DOS_HEADER imageDosHeader; | |
if ((selfStream.ReadStructure(out imageDosHeader) == false) || | |
(imageDosHeader.e_magic[0] != 'M' || imageDosHeader.e_magic[1] != 'Z')) | |
{ | |
// Invalid dos header | |
return; | |
} | |
// read IMAGE_NT_HEADERS32 | |
selfStream.Seek(imageDosHeader.e_lfanew, SeekOrigin.Begin); | |
NativeMethods.IMAGE_NT_HEADERS32 imageNtHeaders32; | |
if ((selfStream.ReadStructure(out imageNtHeaders32) == false) || | |
(imageNtHeaders32.Signature[0] != 'P') || | |
(imageNtHeaders32.Signature[1] != 'E') || | |
(imageNtHeaders32.Signature[2] != '\0') || | |
(imageNtHeaders32.Signature[3] != '\0')) | |
{ | |
// Invalid nt header | |
return; | |
} | |
// Skip ImageOptionalHeader32 | |
selfStream.Seek(imageNtHeaders32.FileHeader.SizeOfOptionalHeader, SeekOrigin.Current); | |
// Scan each IMAGE_SECTION_HEADER | |
var offsetOfLastSection = 0U; | |
var sizeoOfLastSection = 0U; | |
for (var i = 0; i < imageNtHeaders32.FileHeader.NumberOfSections; i++) | |
{ | |
NativeMethods.IMAGE_SECTION_HEADER imageSectionHeader; | |
if (selfStream.ReadStructure(out imageSectionHeader) == false) | |
{ | |
// Invalid nt header | |
return; | |
} | |
if (offsetOfLastSection < imageSectionHeader.PointerToRawData) | |
{ | |
offsetOfLastSection = imageSectionHeader.PointerToRawData; | |
sizeoOfLastSection = imageSectionHeader.SizeOfRawData; | |
} | |
} | |
var startOfArchive = offsetOfLastSection + sizeoOfLastSection; | |
var sizeOfArchive = sizeOfSelf - startOfArchive; | |
if (sizeOfArchive <= 0) | |
{ | |
return; | |
} | |
var ps = new PartialStream(selfStream, startOfArchive, sizeOfArchive); | |
using (var unzip = new Internals.Unzip(ps)) | |
{ | |
Console.WriteLine("Extracting files from the archive:"); | |
unzip.ExtractProgress += | |
(s, e) => | |
Console.WriteLine("{0} of {1}: {2}", e.CurrentFile, e.TotalFiles, e.FileName); | |
unzip.ExtractToDirectory(outputDirectory); | |
Console.WriteLine("Extract finish."); | |
Console.ReadKey(true); | |
} | |
} | |
} | |
} | |
internal class PartialStream : Stream | |
{ | |
private Stream _stream; | |
private Stream Stream | |
{ | |
get | |
{ | |
if (_stream == null) | |
{ | |
throw new IOException("Partial stream is closed."); | |
} | |
return _stream; | |
} | |
} | |
private readonly long _start; | |
private readonly long _size; | |
private long _current; | |
public PartialStream(Stream stream, long start, long size) | |
{ | |
_stream = stream; | |
_start = start; | |
_size = size; | |
_current = 0; | |
} | |
public override void Close() | |
{ | |
_stream = null; | |
} | |
public override void Flush() | |
{ | |
throw new NotSupportedException(); | |
} | |
public override long Seek(long offset, SeekOrigin origin) | |
{ | |
switch (origin) | |
{ | |
case SeekOrigin.Begin: | |
_current = Math.Min(Math.Max(0, offset), _size); | |
break; | |
case SeekOrigin.Current: | |
_current = Math.Min(Math.Max(0, _current + offset), _size); | |
break; | |
case SeekOrigin.End: | |
_current = Math.Min(Math.Max(0, _size + offset), _size); | |
break; | |
default: | |
throw new ArgumentOutOfRangeException("origin", origin, null); | |
} | |
return _current; | |
} | |
public override void SetLength(long value) | |
{ | |
throw new NotSupportedException(); | |
} | |
public override int Read(byte[] buffer, int offset, int count) | |
{ | |
var copysize = Math.Min((int)(_size - _current), count); | |
Stream.Seek(_current + _start, SeekOrigin.Begin); | |
var readedsize = Stream.Read(buffer, offset, copysize); | |
_current += readedsize; | |
return readedsize; | |
} | |
public override void Write(byte[] buffer, int offset, int count) | |
{ | |
throw new NotSupportedException(); | |
} | |
public override bool CanRead { get { return true; } } | |
public override bool CanSeek { get { return true; } } | |
public override bool CanWrite { get { return false; } } | |
public override long Length { get { return _size; } } | |
public override long Position | |
{ | |
get { return _current; } | |
set { _current = Math.Min(Math.Max(0, value), _size); } | |
} | |
} | |
internal static class FileStreamExt | |
{ | |
public static bool ReadStructure<T>(this FileStream self, out T structure) where T : struct | |
{ | |
var size = Marshal.SizeOf(typeof(T)); | |
var buffer = new byte[size]; | |
var pos = self.Position; | |
if (self.Read(buffer, 0, size) != size) | |
{ | |
self.Seek(pos, SeekOrigin.Begin); | |
structure = default(T); | |
return false; | |
} | |
GCHandle gch = GCHandle.Alloc(buffer, GCHandleType.Pinned); | |
try | |
{ | |
structure = (T)Marshal.PtrToStructure(gch.AddrOfPinnedObject(), typeof(T)); | |
return true; | |
} | |
finally | |
{ | |
gch.Free(); | |
} | |
} | |
} | |
internal static class NativeMethods | |
{ | |
[StructLayout(LayoutKind.Sequential, Pack = 1)] | |
public struct IMAGE_DOS_HEADER | |
{ | |
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] | |
public char[] e_magic; // Magic number | |
public UInt16 e_cblp; // Bytes on last page of file | |
public UInt16 e_cp; // Pages in file | |
public UInt16 e_crlc; // Relocations | |
public UInt16 e_cparhdr; // Size of header in paragraphs | |
public UInt16 e_minalloc; // Minimum extra paragraphs needed | |
public UInt16 e_maxalloc; // Maximum extra paragraphs needed | |
public UInt16 e_ss; // Initial (relative) SS value | |
public UInt16 e_sp; // Initial SP value | |
public UInt16 e_csum; // Checksum | |
public UInt16 e_ip; // Initial IP value | |
public UInt16 e_cs; // Initial (relative) CS value | |
public UInt16 e_lfarlc; // File address of relocation table | |
public UInt16 e_ovno; // Overlay number | |
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] | |
public UInt16[] e_res1; // Reserved words | |
public UInt16 e_oemid; // OEM identifier (for e_oeminfo) | |
public UInt16 e_oeminfo; // OEM information; e_oemid specific | |
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] | |
public UInt16[] e_res2; // Reserved words | |
public Int32 e_lfanew; // File address of new exe header | |
} | |
[StructLayout(LayoutKind.Sequential, Pack = 1)] | |
internal struct IMAGE_NT_HEADERS32 | |
{ | |
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] | |
public char[] Signature; | |
public IMAGE_FILE_HEADER FileHeader; | |
} | |
[StructLayout(LayoutKind.Sequential, Pack = 1)] | |
internal struct IMAGE_FILE_HEADER | |
{ | |
public UInt16 Machine; | |
public UInt16 NumberOfSections; | |
public UInt32 TimeDateStamp; | |
public UInt32 PointerToSymbolTable; | |
public UInt32 NumberOfSymbols; | |
public UInt16 SizeOfOptionalHeader; | |
public UInt16 Characteristics; | |
} | |
[StructLayout(LayoutKind.Sequential, Pack = 1)] | |
internal struct IMAGE_OPTIONAL_HEADER32 | |
{ | |
public enum MagicType : ushort | |
{ | |
IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b, | |
IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b | |
} | |
public enum SubSystemType : ushort | |
{ | |
IMAGE_SUBSYSTEM_UNKNOWN = 0, | |
IMAGE_SUBSYSTEM_NATIVE = 1, | |
IMAGE_SUBSYSTEM_WINDOWS_GUI = 2, | |
IMAGE_SUBSYSTEM_WINDOWS_CUI = 3, | |
IMAGE_SUBSYSTEM_POSIX_CUI = 7, | |
IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9, | |
IMAGE_SUBSYSTEM_EFI_APPLICATION = 10, | |
IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11, | |
IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12, | |
IMAGE_SUBSYSTEM_EFI_ROM = 13, | |
IMAGE_SUBSYSTEM_XBOX = 14 | |
} | |
public enum DllCharacteristicsType : ushort | |
{ | |
RES_0 = 0x0001, | |
RES_1 = 0x0002, | |
RES_2 = 0x0004, | |
RES_3 = 0x0008, | |
IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE = 0x0040, | |
IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY = 0x0080, | |
IMAGE_DLL_CHARACTERISTICS_NX_COMPAT = 0x0100, | |
IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = 0x0200, | |
IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400, | |
IMAGE_DLLCHARACTERISTICS_NO_BIND = 0x0800, | |
RES_4 = 0x1000, | |
IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = 0x2000, | |
IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000 | |
} | |
// | |
// Standard fields. | |
// | |
public MagicType Magic; | |
public Byte MajorLinkerVersion; | |
public Byte MinorLinkerVersion; | |
public UInt32 SizeOfCode; | |
public UInt32 SizeOfInitializedData; | |
public UInt32 SizeOfUninitializedData; | |
public UInt32 AddressOfEntryPoint; | |
public UInt32 BaseOfCode; | |
public UInt32 BaseOfData; | |
// | |
// NT additional fields. | |
// | |
public UInt32 ImageBase; | |
public UInt32 SectionAlignment; | |
public UInt32 FileAlignment; | |
public UInt16 MajorOperatingSystemVersion; | |
public UInt16 MinorOperatingSystemVersion; | |
public UInt16 MajorImageVersion; | |
public UInt16 MinorImageVersion; | |
public UInt16 MajorSubsystemVersion; | |
public UInt16 MinorSubsystemVersion; | |
public UInt32 Win32VersionValue; | |
public UInt32 SizeOfImage; | |
public UInt32 SizeOfHeaders; | |
public UInt32 CheckSum; | |
public SubSystemType Subsystem; | |
public DllCharacteristicsType DllCharacteristics; | |
public UInt32 SizeOfStackReserve; | |
public UInt32 SizeOfStackCommit; | |
public UInt32 SizeOfHeapReserve; | |
public UInt32 SizeOfHeapCommit; | |
public UInt32 LoaderFlags; | |
public UInt32 NumberOfRvaAndSizes; | |
public IMAGE_DATA_DIRECTORY ExportTable; | |
public IMAGE_DATA_DIRECTORY ImportTable; | |
public IMAGE_DATA_DIRECTORY ResourceTable; | |
public IMAGE_DATA_DIRECTORY ExceptionTable; | |
public IMAGE_DATA_DIRECTORY CertificateTable; | |
public IMAGE_DATA_DIRECTORY BaseRelocationTable; | |
public IMAGE_DATA_DIRECTORY Debug; | |
public IMAGE_DATA_DIRECTORY Architecture; | |
public IMAGE_DATA_DIRECTORY GlobalPtr; | |
public IMAGE_DATA_DIRECTORY TLSTable; | |
public IMAGE_DATA_DIRECTORY LoadConfigTable; | |
public IMAGE_DATA_DIRECTORY BoundImport; | |
public IMAGE_DATA_DIRECTORY IAT; | |
public IMAGE_DATA_DIRECTORY DelayImportDescriptor; | |
public IMAGE_DATA_DIRECTORY CLRRuntimeHeader; | |
public IMAGE_DATA_DIRECTORY Reserved; | |
} | |
[StructLayout(LayoutKind.Sequential, Pack = 1)] | |
internal struct IMAGE_DATA_DIRECTORY | |
{ | |
public UInt32 VirtualAddress; | |
public UInt32 Size; | |
} | |
[StructLayout(LayoutKind.Sequential, Pack = 1)] | |
internal struct IMAGE_SECTION_HEADER | |
{ | |
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] | |
public Byte[] Name; | |
public UInt32 PhysicalAddress; | |
public UInt32 VirtualAddress; | |
public UInt32 SizeOfRawData; | |
public UInt32 PointerToRawData; | |
public UInt32 PointerToRelocations; | |
public UInt32 PointerToLinenumbers; | |
public UInt16 NumberOfRelocations; | |
public UInt16 NumberOfLinenumbers; | |
public UInt32 Characteristics; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment