Skip to content

Instantly share code, notes, and snippets.

@Sup3rc4l1fr4g1l1571c3xp14l1d0c10u5
Last active June 13, 2016 09:20
Show Gist options
  • Save Sup3rc4l1fr4g1l1571c3xp14l1d0c10u5/45d28052890ef2580f29eebb3c9f0ae6 to your computer and use it in GitHub Desktop.
Save Sup3rc4l1fr4g1l1571c3xp14l1d0c10u5/45d28052890ef2580f29eebb3c9f0ae6 to your computer and use it in GitHub Desktop.
Example of Self-extracting archive for .NET 3.5 Client Profile
/**
*
* 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