mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-07-08 18:06:34 +00:00
Ceeate wrapper base class, PE raw reads
This commit is contained in:
@@ -3,7 +3,7 @@ namespace BurnOutSharp.Wrappers
|
||||
/// <summary>
|
||||
/// Location that the data originated from
|
||||
/// </summary>
|
||||
internal enum DataSource
|
||||
public enum DataSource
|
||||
{
|
||||
/// <summary>
|
||||
/// Unknown origin / testing
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
using System.IO;
|
||||
|
||||
// TODO: Create base class for all wrappers
|
||||
namespace BurnOutSharp.Wrappers
|
||||
{
|
||||
public class LinearExecutable
|
||||
public class LinearExecutable : WrapperBase
|
||||
{
|
||||
#region Pass-Through Properties
|
||||
|
||||
@@ -285,29 +284,6 @@ namespace BurnOutSharp.Wrappers
|
||||
/// </summary>
|
||||
private Models.LinearExecutable.Executable _executable;
|
||||
|
||||
/// <summary>
|
||||
/// Source of the original data
|
||||
/// </summary>
|
||||
private DataSource _dataSource = DataSource.UNKNOWN;
|
||||
|
||||
/// <summary>
|
||||
/// Source byte array data
|
||||
/// </summary>
|
||||
/// <remarks>This is only populated if <see cref="_dataSource"/> is <see cref="DataSource.ByteArray"/></remarks>
|
||||
private byte[] _byteArrayData = null;
|
||||
|
||||
/// <summary>
|
||||
/// Source byte array data offset
|
||||
/// </summary>
|
||||
/// <remarks>This is only populated if <see cref="_dataSource"/> is <see cref="DataSource.ByteArray"/></remarks>
|
||||
private int _byteArrayOffset = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Source Stream data
|
||||
/// </summary>
|
||||
/// <remarks>This is only populated if <see cref="_dataSource"/> is <see cref="DataSource.Stream"/></remarks>
|
||||
private Stream _streamData = null;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
@@ -360,7 +336,7 @@ namespace BurnOutSharp.Wrappers
|
||||
/// <summary>
|
||||
/// Pretty print the Linear Executable information
|
||||
/// </summary>
|
||||
public void Print()
|
||||
public override void Print()
|
||||
{
|
||||
// TODO: Implement printing
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
// TODO: Create base class for all wrappers
|
||||
namespace BurnOutSharp.Wrappers
|
||||
{
|
||||
public class MSDOS
|
||||
public class MSDOS : WrapperBase
|
||||
{
|
||||
#region Pass-Through Properties
|
||||
|
||||
@@ -89,29 +88,6 @@ namespace BurnOutSharp.Wrappers
|
||||
/// </summary>
|
||||
private Models.MSDOS.Executable _executable;
|
||||
|
||||
/// <summary>
|
||||
/// Source of the original data
|
||||
/// </summary>
|
||||
private DataSource _dataSource = DataSource.UNKNOWN;
|
||||
|
||||
/// <summary>
|
||||
/// Source byte array data
|
||||
/// </summary>
|
||||
/// <remarks>This is only populated if <see cref="_dataSource"/> is <see cref="DataSource.ByteArray"/></remarks>
|
||||
private byte[] _byteArrayData = null;
|
||||
|
||||
/// <summary>
|
||||
/// Source byte array data offset
|
||||
/// </summary>
|
||||
/// <remarks>This is only populated if <see cref="_dataSource"/> is <see cref="DataSource.ByteArray"/></remarks>
|
||||
private int _byteArrayOffset = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Source Stream data
|
||||
/// </summary>
|
||||
/// <remarks>This is only populated if <see cref="_dataSource"/> is <see cref="DataSource.Stream"/></remarks>
|
||||
private Stream _streamData = null;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
@@ -164,7 +140,7 @@ namespace BurnOutSharp.Wrappers
|
||||
/// <summary>
|
||||
/// Pretty print the MS-DOS executable information
|
||||
/// </summary>
|
||||
public void Print()
|
||||
public override void Print()
|
||||
{
|
||||
Console.WriteLine("MS-DOS Executable Information:");
|
||||
Console.WriteLine("-------------------------");
|
||||
|
||||
@@ -4,10 +4,9 @@ using System.IO;
|
||||
using System.Text;
|
||||
using static BurnOutSharp.Builder.Extensions;
|
||||
|
||||
// TODO: Create base class for all wrappers
|
||||
namespace BurnOutSharp.Wrappers
|
||||
{
|
||||
public class NewExecutable
|
||||
public class NewExecutable : WrapperBase
|
||||
{
|
||||
#region Pass-Through Properties
|
||||
|
||||
@@ -217,29 +216,6 @@ namespace BurnOutSharp.Wrappers
|
||||
/// </summary>
|
||||
private Models.NewExecutable.Executable _executable;
|
||||
|
||||
/// <summary>
|
||||
/// Source of the original data
|
||||
/// </summary>
|
||||
private DataSource _dataSource = DataSource.UNKNOWN;
|
||||
|
||||
/// <summary>
|
||||
/// Source byte array data
|
||||
/// </summary>
|
||||
/// <remarks>This is only populated if <see cref="_dataSource"/> is <see cref="DataSource.ByteArray"/></remarks>
|
||||
private byte[] _byteArrayData = null;
|
||||
|
||||
/// <summary>
|
||||
/// Source byte array data offset
|
||||
/// </summary>
|
||||
/// <remarks>This is only populated if <see cref="_dataSource"/> is <see cref="DataSource.ByteArray"/></remarks>
|
||||
private int _byteArrayOffset = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Source Stream data
|
||||
/// </summary>
|
||||
/// <remarks>This is only populated if <see cref="_dataSource"/> is <see cref="DataSource.Stream"/></remarks>
|
||||
private Stream _streamData = null;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
@@ -292,7 +268,7 @@ namespace BurnOutSharp.Wrappers
|
||||
/// <summary>
|
||||
/// Pretty print the New Executable information
|
||||
/// </summary>
|
||||
public void Print()
|
||||
public override void Print()
|
||||
{
|
||||
Console.WriteLine("New Executable Information:");
|
||||
Console.WriteLine("-------------------------");
|
||||
|
||||
@@ -5,10 +5,9 @@ using System.Text;
|
||||
using System.Xml;
|
||||
using static BurnOutSharp.Builder.Extensions;
|
||||
|
||||
// TODO: Create base class for all wrappers
|
||||
namespace BurnOutSharp.Wrappers
|
||||
{
|
||||
public class PortableExecutable
|
||||
public class PortableExecutable : WrapperBase
|
||||
{
|
||||
#region Pass-Through Properties
|
||||
|
||||
@@ -316,6 +315,33 @@ namespace BurnOutSharp.Wrappers
|
||||
|
||||
#region Extension Properties
|
||||
|
||||
/// <summary>
|
||||
/// Array of sanitized section names
|
||||
/// </summary>
|
||||
public string[] SectionNames
|
||||
{
|
||||
get
|
||||
{
|
||||
// Use the cached data if possible
|
||||
if (_sectionNames != null)
|
||||
return _sectionNames;
|
||||
|
||||
// Otherwise, build and return the cached array
|
||||
_sectionNames = new string[_executable.SectionTable.Length];
|
||||
for (int i = 0; i < _sectionNames.Length; i++)
|
||||
{
|
||||
var section = _executable.SectionTable[i];
|
||||
|
||||
// TODO: Handle long section names with leading `/`
|
||||
byte[] sectionNameBytes = section.Name;
|
||||
string sectionNameString = Encoding.UTF8.GetString(sectionNameBytes).TrimEnd('\0');
|
||||
_sectionNames[i] = sectionNameString;
|
||||
}
|
||||
|
||||
return _sectionNames;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Determine what extension properties are needed
|
||||
|
||||
#endregion
|
||||
@@ -328,30 +354,7 @@ namespace BurnOutSharp.Wrappers
|
||||
private Models.PortableExecutable.Executable _executable;
|
||||
|
||||
/// <summary>
|
||||
/// Source of the original data
|
||||
/// </summary>
|
||||
private DataSource _dataSource = DataSource.UNKNOWN;
|
||||
|
||||
/// <summary>
|
||||
/// Source byte array data
|
||||
/// </summary>
|
||||
/// <remarks>This is only populated if <see cref="_dataSource"/> is <see cref="DataSource.ByteArray"/></remarks>
|
||||
private byte[] _byteArrayData = null;
|
||||
|
||||
/// <summary>
|
||||
/// Source byte array data offset
|
||||
/// </summary>
|
||||
/// <remarks>This is only populated if <see cref="_dataSource"/> is <see cref="DataSource.ByteArray"/></remarks>
|
||||
private int _byteArrayOffset = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Source Stream data
|
||||
/// </summary>
|
||||
/// <remarks>This is only populated if <see cref="_dataSource"/> is <see cref="DataSource.Stream"/></remarks>
|
||||
private Stream _streamData = null;
|
||||
|
||||
/// <summary>
|
||||
/// Array of santiized section names
|
||||
/// Array of sanitized section names
|
||||
/// </summary>
|
||||
private string[] _sectionNames = null;
|
||||
|
||||
@@ -363,7 +366,7 @@ namespace BurnOutSharp.Wrappers
|
||||
/// <summary>
|
||||
/// Cached raw section data
|
||||
/// </summary>
|
||||
private Dictionary<string, byte[]> _rawSectionData = null;
|
||||
private readonly Dictionary<string, byte[]> _rawSectionData = new Dictionary<string, byte[]>();
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -414,31 +417,6 @@ namespace BurnOutSharp.Wrappers
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get all section names from the executable
|
||||
/// </summary>
|
||||
/// <returns>A PE executable wrapper on success, null on failure</returns>
|
||||
public string[] GetSectionNames()
|
||||
{
|
||||
// Use the cached data if possible
|
||||
if (_sectionNames != null)
|
||||
return _sectionNames;
|
||||
|
||||
// Otherwise, build and return the cached array
|
||||
_sectionNames = new string[_executable.SectionTable.Length];
|
||||
for (int i = 0; i < _sectionNames.Length; i++)
|
||||
{
|
||||
var section = _executable.SectionTable[i];
|
||||
|
||||
// TODO: Handle long section names with leading `/`
|
||||
byte[] sectionNameBytes = section.Name;
|
||||
string sectionNameString = Encoding.UTF8.GetString(sectionNameBytes).TrimEnd('\0');
|
||||
_sectionNames[i] = sectionNameString;
|
||||
}
|
||||
|
||||
return _sectionNames;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get raw section data from the source file
|
||||
/// </summary>
|
||||
@@ -451,32 +429,15 @@ namespace BurnOutSharp.Wrappers
|
||||
return null;
|
||||
|
||||
// Validate the data source
|
||||
switch (_dataSource)
|
||||
{
|
||||
// If we don't have a valid data source, we can't read the section data
|
||||
case DataSource.UNKNOWN:
|
||||
return null;
|
||||
|
||||
// Byte array data requires both a valid array and offset
|
||||
case DataSource.ByteArray:
|
||||
if (_byteArrayData == null || _byteArrayOffset < 0)
|
||||
return null;
|
||||
break;
|
||||
|
||||
// Stream data requires both a valid stream
|
||||
case DataSource.Stream:
|
||||
if (_streamData == null)
|
||||
return null;
|
||||
break;
|
||||
}
|
||||
if (!DataSourceIsValid())
|
||||
return null;
|
||||
|
||||
// Make sure the section exists
|
||||
string[] sectionNames = GetSectionNames();
|
||||
if (sectionNames == null)
|
||||
if (SectionNames == null)
|
||||
return null;
|
||||
|
||||
// Get the section index from the array
|
||||
int sectionIndex = Array.IndexOf(sectionNames, sectionName);
|
||||
int sectionIndex = Array.IndexOf(SectionNames, sectionName);
|
||||
if (sectionIndex < 0)
|
||||
return null;
|
||||
|
||||
@@ -490,33 +451,11 @@ namespace BurnOutSharp.Wrappers
|
||||
lock (_rawSectionsLock)
|
||||
{
|
||||
// If we already have cached data, just use that immediately
|
||||
if (_rawSectionData != null && _rawSectionData.ContainsKey(sectionName))
|
||||
if (_rawSectionData.ContainsKey(sectionName))
|
||||
return _rawSectionData[sectionName];
|
||||
|
||||
// If the section dictionary doesn't exist, create it
|
||||
if (_rawSectionData == null)
|
||||
_rawSectionData = new Dictionary<string, byte[]>();
|
||||
|
||||
// Populate the raw section data based on the source
|
||||
byte[] sectionData = null;
|
||||
switch (_dataSource)
|
||||
{
|
||||
case DataSource.ByteArray:
|
||||
if (_byteArrayOffset + sectionAddress + sectionSize >= _byteArrayData.Length)
|
||||
return null;
|
||||
sectionData = new byte[sectionSize];
|
||||
Array.Copy(_byteArrayData, _byteArrayOffset + sectionAddress, sectionData, 0, sectionSize);
|
||||
break;
|
||||
|
||||
case DataSource.Stream:
|
||||
if (sectionAddress + sectionSize >= _streamData.Length)
|
||||
return null;
|
||||
long currentLocation = _streamData.Position;
|
||||
_streamData.Seek(sectionAddress, SeekOrigin.Begin);
|
||||
sectionData = _streamData.ReadBytes((int)sectionSize);
|
||||
_streamData.Seek(currentLocation, SeekOrigin.Begin);
|
||||
break;
|
||||
}
|
||||
byte[] sectionData = ReadFromDataSource((int)sectionAddress, (int)sectionSize);
|
||||
|
||||
// Cache and return the section data, even if null
|
||||
_rawSectionData[sectionName] = sectionData;
|
||||
@@ -527,7 +466,7 @@ namespace BurnOutSharp.Wrappers
|
||||
/// <summary>
|
||||
/// Pretty print the New Executable information
|
||||
/// </summary>
|
||||
public void Print()
|
||||
public override void Print()
|
||||
{
|
||||
Console.WriteLine("Portable Executable Information:");
|
||||
Console.WriteLine("-------------------------");
|
||||
|
||||
135
BurnOutSharp.Wrappers/WrapperBase.cs
Normal file
135
BurnOutSharp.Wrappers/WrapperBase.cs
Normal file
@@ -0,0 +1,135 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using static BurnOutSharp.Builder.Extensions;
|
||||
|
||||
namespace BurnOutSharp.Wrappers
|
||||
{
|
||||
public abstract class WrapperBase
|
||||
{
|
||||
#region Instance Variabled
|
||||
|
||||
/// <summary>
|
||||
/// Source of the original data
|
||||
/// </summary>
|
||||
protected DataSource _dataSource = DataSource.UNKNOWN;
|
||||
|
||||
/// <summary>
|
||||
/// Source byte array data
|
||||
/// </summary>
|
||||
/// <remarks>This is only populated if <see cref="_dataSource"/> is <see cref="DataSource.ByteArray"/></remarks>
|
||||
protected byte[] _byteArrayData = null;
|
||||
|
||||
/// <summary>
|
||||
/// Source byte array data offset
|
||||
/// </summary>
|
||||
/// <remarks>This is only populated if <see cref="_dataSource"/> is <see cref="DataSource.ByteArray"/></remarks>
|
||||
protected int _byteArrayOffset = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Source Stream data
|
||||
/// </summary>
|
||||
/// <remarks>This is only populated if <see cref="_dataSource"/> is <see cref="DataSource.Stream"/></remarks>
|
||||
protected Stream _streamData = null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Data
|
||||
|
||||
/// <summary>
|
||||
/// Validate the backing data source
|
||||
/// </summary>
|
||||
/// <returns>True if the data source is valid, false otherwise</returns>
|
||||
protected bool DataSourceIsValid()
|
||||
{
|
||||
switch (_dataSource)
|
||||
{
|
||||
// Byte array data requires both a valid array and offset
|
||||
case DataSource.ByteArray:
|
||||
return _byteArrayData != null && _byteArrayOffset >= 0;
|
||||
|
||||
// Stream data requires both a valid stream
|
||||
case DataSource.Stream:
|
||||
return _streamData != null && _streamData.CanRead && _streamData.CanSeek;
|
||||
|
||||
// Everything else is invalid
|
||||
case DataSource.UNKNOWN:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if a data segment is valid in the data source
|
||||
/// </summary>
|
||||
/// <param name="position">Position in the source</param>
|
||||
/// <param name="length">Length of the data to check</param>
|
||||
/// <returns>True if the positional data is valid, false otherwise</returns>
|
||||
protected bool SegmentValid(int position, int length)
|
||||
{
|
||||
// Validate the data souece
|
||||
if (!DataSourceIsValid())
|
||||
return false;
|
||||
|
||||
switch (_dataSource)
|
||||
{
|
||||
case DataSource.ByteArray:
|
||||
return _byteArrayOffset + position + length < _byteArrayData.Length;
|
||||
|
||||
case DataSource.Stream:
|
||||
return position + length < _streamData.Length;
|
||||
|
||||
// Everything else is invalid
|
||||
case DataSource.UNKNOWN:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read data from the source
|
||||
/// </summary>
|
||||
/// <param name="position">Position in the source to read from</param>
|
||||
/// <param name="length">Length of the requested data</param>
|
||||
/// <returns>Byte array containing the requested data, null on error</returns>
|
||||
protected byte[] ReadFromDataSource(int position, int length)
|
||||
{
|
||||
// Validate the data souece
|
||||
if (!DataSourceIsValid())
|
||||
return null;
|
||||
|
||||
// Validate the requested segment
|
||||
if (!SegmentValid(position, length))
|
||||
return null;
|
||||
|
||||
// Read and retuen the data
|
||||
byte[] sectionData = null;
|
||||
switch (_dataSource)
|
||||
{
|
||||
case DataSource.ByteArray:
|
||||
sectionData = new byte[length];
|
||||
Array.Copy(_byteArrayData, _byteArrayOffset + position, sectionData, 0, length);
|
||||
break;
|
||||
|
||||
case DataSource.Stream:
|
||||
long currentLocation = _streamData.Position;
|
||||
_streamData.Seek(position, SeekOrigin.Begin);
|
||||
sectionData = _streamData.ReadBytes(length);
|
||||
_streamData.Seek(currentLocation, SeekOrigin.Begin);
|
||||
break;
|
||||
}
|
||||
|
||||
return sectionData;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Printing
|
||||
|
||||
/// <summary>
|
||||
/// Pretty print the Executable information
|
||||
/// </summary>
|
||||
public abstract void Print();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user