|
|
@ -1,5 +1,8 @@
|
|
|
|
using System;
|
|
|
|
using apphost_extract_v2.General;
|
|
|
|
|
|
|
|
using apphost_extract_v2.Models;
|
|
|
|
|
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
using System.IO;
|
|
|
|
using System.IO;
|
|
|
|
using System.Linq;
|
|
|
|
using System.Linq;
|
|
|
|
using System.Reflection.PortableExecutable;
|
|
|
|
using System.Reflection.PortableExecutable;
|
|
|
@ -12,8 +15,8 @@ namespace apphost_extract_v2
|
|
|
|
private FileStream File;
|
|
|
|
private FileStream File;
|
|
|
|
public PEHeaders PEHeader;
|
|
|
|
public PEHeaders PEHeader;
|
|
|
|
|
|
|
|
|
|
|
|
private readonly byte[] VERSION_SIGNATURE = new byte[] { };
|
|
|
|
private readonly byte[] VERSION_SIGNATURE = new byte[] { 0x4C, 0x8D, 0x05, 0x0, 0x0, 0x0, 0x0, 0x48, 0x8D, 0x15, 0x0, 0x0, 0x0, 0x0, 0x48, 0x8D, 0x0D, 0x0, 0x0, 0x0, 0x0 };
|
|
|
|
private const string VERSION_SIGNATURE_MASK = "";
|
|
|
|
private const string VERSION_SIGNATURE_MASK = "xxx???xxxx???xxxx???x";
|
|
|
|
|
|
|
|
|
|
|
|
public Analyzer(FileStream fs)
|
|
|
|
public Analyzer(FileStream fs)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -21,23 +24,77 @@ namespace apphost_extract_v2
|
|
|
|
PEHeader = new PEHeaders(fs);
|
|
|
|
PEHeader = new PEHeaders(fs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public IApphostFile Open()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var textSegment = GetSegment(".text");
|
|
|
|
|
|
|
|
var sw = Stopwatch.StartNew();
|
|
|
|
|
|
|
|
var sigscanResults = Util.PatternScan(File,
|
|
|
|
|
|
|
|
textSegment.PointerToRawData, textSegment.SizeOfRawData,
|
|
|
|
|
|
|
|
VERSION_SIGNATURE, VERSION_SIGNATURE_MASK);
|
|
|
|
|
|
|
|
sw.Stop();
|
|
|
|
|
|
|
|
Log.Info($"Scan took {sw.ElapsedMilliseconds}ms | Version String Instructions -> {sigscanResults[0]:X8}");
|
|
|
|
|
|
|
|
if (sigscanResults.Length == 0)
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var versionOffset = (int)BitConverter.ToUInt32(File.ReadBuffer(sigscanResults[0] + 3, 4));
|
|
|
|
|
|
|
|
var versionStringPtr = AddVirtualOffset(sigscanResults[0] + 7, versionOffset);
|
|
|
|
|
|
|
|
var versionString = Encoding.Unicode.GetString(
|
|
|
|
|
|
|
|
File.ReadBuffer(
|
|
|
|
|
|
|
|
versionStringPtr, 6));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Log.Info($"Translated virtual offset -> {versionStringPtr:X8}: {versionString}");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (versionString)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
case "3.0":
|
|
|
|
|
|
|
|
return new ApphostFile30(File, PEHeader);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case "3.1":
|
|
|
|
|
|
|
|
return new ApphostFile31(File, PEHeader);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case "5.0":
|
|
|
|
|
|
|
|
return new ApphostFile5(File, PEHeader);
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private int AddVirtualOffset(int fileAddress, int offset)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return VirtualAddressToFileOffset(FileOffsetToVirtualAddress(fileAddress) + offset);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private int FileOffsetToVirtualAddress(int offset)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var section = FindSection(offset, true);
|
|
|
|
|
|
|
|
return offset + (section.VirtualAddress - section.PointerToRawData);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private int VirtualAddressToFileOffset(int address)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var section = FindSection(address, false);
|
|
|
|
|
|
|
|
return address - (section.VirtualAddress - section.PointerToRawData);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public SectionHeader GetSegment(string name)
|
|
|
|
public SectionHeader GetSegment(string name)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var section = PEHeader.SectionHeaders.Where(x => x.Name == name).FirstOrDefault();
|
|
|
|
var section = PEHeader.SectionHeaders.Where(x => x.Name == name).FirstOrDefault();
|
|
|
|
return section;
|
|
|
|
return section;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public ApphostVersion GetVersion()
|
|
|
|
public SectionHeader FindSection(int address, bool fileOffset)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
foreach (var section in PEHeader.SectionHeaders)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (fileOffset)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (section.PointerToRawData < address && section.PointerToRawData + section.SizeOfRawData > address) return section;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
if (section.VirtualAddress < address && section.VirtualAddress + section.VirtualSize > address) return section;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return new SectionHeader();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public enum ApphostVersion
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
NET30,
|
|
|
|
|
|
|
|
NET31,
|
|
|
|
|
|
|
|
NET5
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|