diff --git a/BinaryObjectScanner/Packer/EmbeddedArchive.cs b/BinaryObjectScanner/Packer/EmbeddedArchive.cs
index 877ed5b0..63635e9c 100644
--- a/BinaryObjectScanner/Packer/EmbeddedArchive.cs
+++ b/BinaryObjectScanner/Packer/EmbeddedArchive.cs
@@ -1,6 +1,5 @@
using System;
using System.IO;
-using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Serialization.Wrappers;
@@ -22,11 +21,24 @@ namespace BinaryObjectScanner.Packer
return null;
// Get the resources that have a PKZIP signature
- if (pex.ResourceData != null
- && pex.ResourceData.Values.Any(v => v is byte[] ba
- && ba.StartsWith(SabreTools.Models.PKZIP.Constants.LocalFileHeaderSignatureBytes)))
+ if (pex.ResourceData != null)
{
- return "Embedded Archive";
+ foreach (var value in pex.ResourceData.Values)
+ {
+ if (value == null || value is not byte[] ba)
+ continue;
+ if (!ba.StartsWith(SabreTools.Models.PKZIP.Constants.LocalFileHeaderSignatureBytes))
+ continue;
+
+ return "Embedded Archive";
+ }
+ }
+
+ // Check the overlay, if it exists
+ if (pex.OverlayData != null && pex.OverlayData.Length > 0)
+ {
+ if (pex.OverlayData.StartsWith(SabreTools.Models.PKZIP.Constants.LocalFileHeaderSignatureBytes))
+ return "Embedded Archive";
}
return null;
@@ -34,6 +46,52 @@ namespace BinaryObjectScanner.Packer
///
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
+ {
+ bool overlay = ExtractFromOverlay(pex, outDir, includeDebug);
+ bool resources = ExtractFromResources(pex, outDir, includeDebug);
+ return overlay || resources;
+ }
+
+ ///
+ /// Extract archive data from the overlay
+ ///
+ private static bool ExtractFromOverlay(PortableExecutable pex, string outDir, bool includeDebug)
+ {
+ try
+ {
+ // Get the overlay data for easier reading
+ var overlayData = pex.OverlayData;
+ if (overlayData == null)
+ return false;
+
+ // Only process the overlay if it has an archive signature
+ if (!overlayData.StartsWith(SabreTools.Models.PKZIP.Constants.LocalFileHeaderSignatureBytes))
+ return false;
+
+ // Create the temp filename
+ string tempFile = $"embedded_overlay.zip";
+ tempFile = Path.Combine(outDir, tempFile);
+ var directoryName = Path.GetDirectoryName(tempFile);
+ if (directoryName != null && !Directory.Exists(directoryName))
+ Directory.CreateDirectory(directoryName);
+
+ // Write the resource data to a temp file
+ using var tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
+ tempStream?.Write(overlayData, 0, overlayData.Length);
+
+ return true;
+ }
+ catch (Exception ex)
+ {
+ if (includeDebug) Console.WriteLine(ex);
+ return false;
+ }
+ }
+
+ ///
+ /// Extract archive data from the resources
+ ///
+ private static bool ExtractFromResources(PortableExecutable pex, string outDir, bool includeDebug)
{
try
{
@@ -41,24 +99,19 @@ namespace BinaryObjectScanner.Packer
if (pex.ResourceData == null)
return false;
- // Get the resources that have a PKZIP signature
- var resources = pex.ResourceData.Values
- .Where(v => v != null && v is byte[])
- .Select(v => v as byte[])
- .Where(b => b != null && b.StartsWith(SabreTools.Models.PKZIP.Constants.LocalFileHeaderSignatureBytes))
- .ToList();
-
- for (int i = 0; i < resources.Count; i++)
+ // Get the resources that have an archive signature
+ int i = 0;
+ foreach (var value in pex.ResourceData.Values)
{
+ if (value == null || value is not byte[] ba)
+ continue;
+ if (!ba.StartsWith(SabreTools.Models.PKZIP.Constants.LocalFileHeaderSignatureBytes))
+ continue;
+
try
{
- // Get the resource data
- var data = resources[i];
- if (data == null)
- continue;
-
// Create the temp filename
- string tempFile = $"embedded_resource_{i}.zip";
+ string tempFile = $"embedded_resource_{i++}.zip";
tempFile = Path.Combine(outDir, tempFile);
var directoryName = Path.GetDirectoryName(tempFile);
if (directoryName != null && !Directory.Exists(directoryName))
@@ -66,7 +119,7 @@ namespace BinaryObjectScanner.Packer
// Write the resource data to a temp file
using var tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
- tempStream?.Write(data, 0, data.Length);
+ tempStream?.Write(ba, 0, ba.Length);
}
catch (Exception ex)
{
diff --git a/BinaryObjectScanner/Packer/EmbeddedExecutable.cs b/BinaryObjectScanner/Packer/EmbeddedExecutable.cs
index 11dd568e..33309448 100644
--- a/BinaryObjectScanner/Packer/EmbeddedExecutable.cs
+++ b/BinaryObjectScanner/Packer/EmbeddedExecutable.cs
@@ -1,6 +1,5 @@
using System;
using System.IO;
-using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Serialization.Wrappers;
@@ -22,11 +21,24 @@ namespace BinaryObjectScanner.Packer
return null;
// Get the resources that have an executable signature
- if (pex.ResourceData != null
- && pex.ResourceData.Values.Any(v => v is byte[] ba
- && ba.StartsWith(SabreTools.Models.MSDOS.Constants.SignatureBytes)))
+ if (pex.ResourceData != null)
{
- return "Embedded Executable";
+ foreach (var value in pex.ResourceData.Values)
+ {
+ if (value == null || value is not byte[] ba)
+ continue;
+ if (!ba.StartsWith(SabreTools.Models.MSDOS.Constants.SignatureBytes))
+ continue;
+
+ return "Embedded Executable";
+ }
+ }
+
+ // Check the overlay, if it exists
+ if (pex.OverlayData != null && pex.OverlayData.Length > 0)
+ {
+ if (pex.OverlayData.StartsWith(SabreTools.Models.MSDOS.Constants.SignatureBytes))
+ return "Embedded Executable";
}
return null;
@@ -34,6 +46,52 @@ namespace BinaryObjectScanner.Packer
///
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
+ {
+ bool overlay = ExtractFromOverlay(pex, outDir, includeDebug);
+ bool resources = ExtractFromResources(pex, outDir, includeDebug);
+ return overlay || resources;
+ }
+
+ ///
+ /// Extract executable data from the overlay
+ ///
+ private static bool ExtractFromOverlay(PortableExecutable pex, string outDir, bool includeDebug)
+ {
+ try
+ {
+ // Get the overlay data for easier reading
+ var overlayData = pex.OverlayData;
+ if (overlayData == null)
+ return false;
+
+ // Only process the overlay if it has an executable signature
+ if (!overlayData.StartsWith(SabreTools.Models.MSDOS.Constants.SignatureBytes))
+ return false;
+
+ // Create the temp filename
+ string tempFile = $"embedded_overlay.bin"; // exe/dll
+ tempFile = Path.Combine(outDir, tempFile);
+ var directoryName = Path.GetDirectoryName(tempFile);
+ if (directoryName != null && !Directory.Exists(directoryName))
+ Directory.CreateDirectory(directoryName);
+
+ // Write the resource data to a temp file
+ using var tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
+ tempStream?.Write(overlayData, 0, overlayData.Length);
+
+ return true;
+ }
+ catch (Exception ex)
+ {
+ if (includeDebug) Console.WriteLine(ex);
+ return false;
+ }
+ }
+
+ ///
+ /// Extract executable data from the resources
+ ///
+ private static bool ExtractFromResources(PortableExecutable pex, string outDir, bool includeDebug)
{
try
{
@@ -42,23 +100,18 @@ namespace BinaryObjectScanner.Packer
return false;
// Get the resources that have an executable signature
- var resources = pex.ResourceData.Values
- .Where(v => v != null && v is byte[])
- .Select(v => v as byte[])
- .Where(b => b != null && b.StartsWith(SabreTools.Models.MSDOS.Constants.SignatureBytes))
- .ToList();
-
- for (int i = 0; i < resources.Count; i++)
+ int i = 0;
+ foreach (var value in pex.ResourceData.Values)
{
+ if (value == null || value is not byte[] ba)
+ continue;
+ if (!ba.StartsWith(SabreTools.Models.MSDOS.Constants.SignatureBytes))
+ continue;
+
try
{
- // Get the resource data
- var data = resources[i];
- if (data == null)
- continue;
-
// Create the temp filename
- string tempFile = $"embedded_resource_{i}.bin";
+ string tempFile = $"embedded_resource_{i++}.bin"; // exe/dll
tempFile = Path.Combine(outDir, tempFile);
var directoryName = Path.GetDirectoryName(tempFile);
if (directoryName != null && !Directory.Exists(directoryName))
@@ -66,7 +119,7 @@ namespace BinaryObjectScanner.Packer
// Write the resource data to a temp file
using var tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
- tempStream?.Write(data, 0, data.Length);
+ tempStream?.Write(ba, 0, ba.Length);
}
catch (Exception ex)
{