diff --git a/src/apphost-extract/apphost-extract-v2/Analyzer.cs b/src/apphost-extract/apphost-extract-v2/Analyzer.cs index 9a893d8..8ca8153 100644 --- a/src/apphost-extract/apphost-extract-v2/Analyzer.cs +++ b/src/apphost-extract/apphost-extract-v2/Analyzer.cs @@ -27,27 +27,28 @@ namespace apphost_extract_v2 public IApphostFile Open() { - var textSegment = PEHeader.GetSegment(".text"); + var textSegment = PEHeader.GetSegment(".text"); - var sw = Stopwatch.StartNew(); - Log.Info("Scanning for version string pointer..."); + var sw = Stopwatch.StartNew(); + Log.Info("Scanning for version string pointer..."); - var sigscanResults = PatternScan(File, - textSegment.PointerToRawData, textSegment.SizeOfRawData, - VERSION_SIGNATURE, VERSION_SIGNATURE_MASK); - sw.Stop(); + var sigscanResults = PatternScan(File, + textSegment.PointerToRawData, textSegment.SizeOfRawData, + VERSION_SIGNATURE, VERSION_SIGNATURE_MASK); + sw.Stop(); - if (sigscanResults.Length == 0) - return null; - - var versionOffset = (int)BitConverter.ToUInt32(File.ReadBuffer(sigscanResults[0] + 3, 4)); - var versionStringPtr = PEHeader.AddVirtualOffset(sigscanResults[0] + 7, versionOffset); - var versionString = Encoding.Unicode.GetString( - File.ReadBuffer( - versionStringPtr, 6)); + if (sigscanResults.Length == 0) + return null; + + var versionOffset = (int)BitConverter.ToUInt32(File.ReadBuffer(sigscanResults[0] + 3, 4)); + var versionStringPtr = PEHeader.AddVirtualOffset(sigscanResults[0] + 7, versionOffset); + var versionString = Encoding.Unicode.GetString( + File.ReadBuffer( + versionStringPtr, 6)); + + Log.Info($"Found version string at 0x{versionStringPtr:X8} in {sw.ElapsedMilliseconds}ms -> {versionString}"); + Console.WriteLine(); - Log.Info($"Found version string at 0x{versionStringPtr:X8} in {sw.ElapsedMilliseconds}ms -> {versionString}"); - Console.WriteLine(); switch (versionString) { @@ -63,5 +64,22 @@ namespace apphost_extract_v2 return null; } } + + public IApphostFile Open(string versionString, uint headerOffset) + { + switch (versionString) + { + case "3.0": + return new ApphostFile30(File, PEHeader, headerOffset); + + case "3.1": + return new ApphostFile31(File, PEHeader, headerOffset); + + case "5": + return new ApphostFile5(File, PEHeader, headerOffset); + default: + return null; + } + } } } diff --git a/src/apphost-extract/apphost-extract-v2/Models/ApphostFile30.cs b/src/apphost-extract/apphost-extract-v2/Models/ApphostFile30.cs index e92b8db..addcf5e 100644 --- a/src/apphost-extract/apphost-extract-v2/Models/ApphostFile30.cs +++ b/src/apphost-extract/apphost-extract-v2/Models/ApphostFile30.cs @@ -30,6 +30,23 @@ namespace apphost_extract_v2.Models Header.Manifest = ParseManifest(); } + public ApphostFile30(FileStream fs, PEHeaders peheader, uint headerOffset) : base(fs, peheader) + { + Header = new AppHostFileHeader(); + Log.Info($"Reading header at 0x{HEADER_OFFSET_PTR:X8}..."); + var headerAddress = headerOffset; + + if (headerAddress == 0) + Log.Fatal("The address of the Bundle header is 0 :/"); + + var headerBuffer = fs.ReadBuffer(headerAddress, HEADER_SIZE); + + Header.Raw = headerBuffer; + Header.Path = Encoding.UTF8.GetString(fs.ReadBuffer(headerAddress + HEADER_SIZE, 0xC)); + + Header.Manifest = ParseManifest(); + } + private AppHostManifest ParseManifest() { AppHostManifest manifest = new AppHostManifest(); diff --git a/src/apphost-extract/apphost-extract-v2/Models/ApphostFile31.cs b/src/apphost-extract/apphost-extract-v2/Models/ApphostFile31.cs index 506bd7d..1c7679b 100644 --- a/src/apphost-extract/apphost-extract-v2/Models/ApphostFile31.cs +++ b/src/apphost-extract/apphost-extract-v2/Models/ApphostFile31.cs @@ -29,6 +29,22 @@ namespace apphost_extract_v2.Models Header.Manifest = ParseManifest(); } + public ApphostFile31(FileStream fs, PEHeaders peheader, uint headerOffset) : base(fs, peheader) + { + Header = new AppHostFileHeader(); + var headerAddress = headerOffset; + + if (headerAddress == 0) + Log.Fatal("The address of the Bundle header is 0 :/"); + + var headerBuffer = fs.ReadBuffer(headerAddress, HEADER_SIZE); + Log.Info($"Reading header at 0x{HEADER_OFFSET_PTR:X8}..."); + Header.Raw = headerBuffer; + Header.Path = Encoding.UTF8.GetString(fs.ReadBuffer(headerAddress + HEADER_SIZE, 0xC)); + + Header.Manifest = ParseManifest(); + } + private AppHostManifest ParseManifest() { AppHostManifest manifest = new AppHostManifest(); diff --git a/src/apphost-extract/apphost-extract-v2/Models/ApphostFile5.cs b/src/apphost-extract/apphost-extract-v2/Models/ApphostFile5.cs index 75924df..b31f642 100644 --- a/src/apphost-extract/apphost-extract-v2/Models/ApphostFile5.cs +++ b/src/apphost-extract/apphost-extract-v2/Models/ApphostFile5.cs @@ -34,6 +34,24 @@ namespace apphost_extract_v2.Models } + public ApphostFile5(FileStream fs, PEHeaders peheader, uint headerOffset) : base(fs, peheader) + { + Header = new AppHostFileHeader(); + var headerAddress = headerOffset; + + if (headerAddress == 0) + Log.Fatal("Unable to located bundle header :/"); + + var headerBuffer = fs.ReadBuffer(headerAddress, HEADER_SIZE); + + Header.Raw = headerBuffer; + Header.Path = Encoding.UTF8.GetString( + fs.ReadBuffer(headerAddress + HEADER_SIZE, 0xC)); + + Header.Manifest = ParseManifest(); + + } + private uint FindHeaderOffset() { var textSegment = PEHeader.GetSegment(".text"); diff --git a/src/apphost-extract/apphost-extract-v2/Program.cs b/src/apphost-extract/apphost-extract-v2/Program.cs index c1b5549..7a7f3d5 100644 --- a/src/apphost-extract/apphost-extract-v2/Program.cs +++ b/src/apphost-extract/apphost-extract-v2/Program.cs @@ -18,9 +18,17 @@ namespace apphost_extract_v2 var apphostAnalyzer = new Analyzer(fileInfo); var apphost = apphostAnalyzer.Open(); - - if(apphost == null) - Log.Fatal("Unable to determine apphost version."); + + if (apphost == null) + { + Log.Error("Unable to determine apphost version automatically."); + var version = Log.QueryString("Please enter the apphost version, you can find it in the entry point of the app (3.0, 3.1, 5): "); + var headerOffset = uint.Parse(Log.QueryString("Please enter the Header offset \n(parse pdb, search for header_offset in names or\n use string reference 'Bundle Header Offset: [%lx]', find the .data ptr and enter its value): ").Replace("0x", ""), System.Globalization.NumberStyles.HexNumber); + + apphostAnalyzer = new Analyzer(fileInfo); + apphost = apphostAnalyzer.Open(version, headerOffset); + } + Log.Info("File parsed successfully, extracting contents..."); Console.WriteLine(); diff --git a/src/apphost-extract/apphost-extract-v2/Properties/launchSettings.json b/src/apphost-extract/apphost-extract-v2/Properties/launchSettings.json new file mode 100644 index 0000000..bd0253e --- /dev/null +++ b/src/apphost-extract/apphost-extract-v2/Properties/launchSettings.json @@ -0,0 +1,7 @@ +{ + "profiles": { + "apphost-extract-v2": { + "commandName": "Project" + } + } +} \ No newline at end of file