|
|
|
@ -7,6 +7,7 @@ using System.IO;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Reflection.PortableExecutable;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using static apphost_extract_v2.Util;
|
|
|
|
|
|
|
|
|
|
namespace apphost_extract_v2
|
|
|
|
|
{
|
|
|
|
@ -18,31 +19,35 @@ namespace apphost_extract_v2
|
|
|
|
|
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 = "xxx???xxxx???xxxx???x";
|
|
|
|
|
|
|
|
|
|
public Analyzer(FileStream fs)
|
|
|
|
|
public Analyzer(FileInfo fi)
|
|
|
|
|
{
|
|
|
|
|
File = fs;
|
|
|
|
|
PEHeader = new PEHeaders(fs);
|
|
|
|
|
File = new FileStream(fi.FullName, FileMode.Open, FileAccess.Read);
|
|
|
|
|
PEHeader = new PEHeaders(File);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public IApphostFile Open()
|
|
|
|
|
{
|
|
|
|
|
var textSegment = GetSegment(".text");
|
|
|
|
|
var textSegment = PEHeader.GetSegment(".text");
|
|
|
|
|
|
|
|
|
|
var sw = Stopwatch.StartNew();
|
|
|
|
|
var sigscanResults = Util.PatternScan(File,
|
|
|
|
|
Log.Info("Scanning for version string pointer...");
|
|
|
|
|
|
|
|
|
|
var sigscanResults = 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 versionStringPtr = PEHeader.AddVirtualOffset(sigscanResults[0] + 7, versionOffset);
|
|
|
|
|
var versionString = Encoding.Unicode.GetString(
|
|
|
|
|
File.ReadBuffer(
|
|
|
|
|
versionStringPtr, 6));
|
|
|
|
|
|
|
|
|
|
Log.Info($"Translated virtual offset -> {versionStringPtr:X8}: {versionString}");
|
|
|
|
|
Log.Info($"Found version string at 0x{versionStringPtr:X8} in {sw.ElapsedMilliseconds}ms -> {versionString}");
|
|
|
|
|
Console.WriteLine();
|
|
|
|
|
|
|
|
|
|
switch (versionString)
|
|
|
|
|
{
|
|
|
|
@ -58,43 +63,5 @@ namespace apphost_extract_v2
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
var section = PEHeader.SectionHeaders.Where(x => x.Name == name).FirstOrDefault();
|
|
|
|
|
return section;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|