Check overlay for embedded data as well

This commit is contained in:
Matt Nadareski
2024-11-20 21:33:56 -05:00
parent 558e23a9cd
commit cebbe6a1e8
2 changed files with 145 additions and 39 deletions

View File

@@ -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
/// <inheritdoc/>
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;
}
/// <summary>
/// Extract archive data from the overlay
/// </summary>
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;
}
}
/// <summary>
/// Extract archive data from the resources
/// </summary>
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)
{

View File

@@ -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
/// <inheritdoc/>
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;
}
/// <summary>
/// Extract executable data from the overlay
/// </summary>
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;
}
}
/// <summary>
/// Extract executable data from the resources
/// </summary>
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)
{