You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
apphost-extract/src/apphost-extract/apphost-extract-v2/Analyzer.cs

101 lines
3.6 KiB

using apphost_extract_v2.General;
using apphost_extract_v2.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection.PortableExecutable;
using System.Text;
namespace apphost_extract_v2
{
public class Analyzer
{
private FileStream File;
public PEHeaders PEHeader;
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)
{
File = 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)
{
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();
}
}
}