Add Relocation section skeleton

This commit is contained in:
Matt Nadareski
2022-03-15 10:15:05 -07:00
parent ca4d08567d
commit ba4c56997a
4 changed files with 130 additions and 10 deletions

View File

@@ -0,0 +1,48 @@
using System.IO;
using BurnOutSharp.Tools;
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Entries
{
/// <summary>
/// The base relocation table is divided into blocks.
/// Each block represents the base relocations for a 4K page.
/// Each block must start on a 32-bit boundary.
/// </summary>
/// <remarks>https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#base-relocation-block</remarks>
public class BaseRelocationBlock
{
/// <summary>
/// The image base plus the page RVA is added to each offset to create the VA where the base relocation must be applied.
/// </summary>
public uint PageRVA;
/// <summary>
/// The total number of bytes in the base relocation block, including the Page RVA and Block Size fields and the Type/Offset fields that follow.
/// </summary>
public uint BlockSize;
public static BaseRelocationBlock Deserialize(Stream stream)
{
var brb = new BaseRelocationBlock();
brb.PageRVA = stream.ReadUInt32();
brb.BlockSize = stream.ReadUInt32();
// TODO: Read in the type/offset field entries
return brb;
}
public static BaseRelocationBlock Deserialize(byte[] content, ref int offset)
{
var brb = new BaseRelocationBlock();
brb.PageRVA = content.ReadUInt32(ref offset);
brb.BlockSize = content.ReadUInt32(ref offset);
// TODO: Read in the type/offset field entries
return brb;
}
}
}

View File

@@ -89,6 +89,12 @@ namespace BurnOutSharp.ExecutableType.Microsoft.PE
/// </summary>
public ImportDataSection ImportTable;
/// <summary>
/// The base relocation table contains entries for all base relocations in the image.
/// The Base Relocation Table field in the optional header data directories gives the number of bytes in the base relocation table.
/// </summary>
public RelocationSection RelocationTable;
/// <summary>
/// Resources are indexed by a multiple-level binary-sorted tree structure.
/// The general design can incorporate 2**31 levels.
@@ -110,7 +116,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.PE
// X - .edata *1 protection Export tables
// X - .idata *1 protection Import tables
// X - .rdata 11 protections Read-only initialized data
// - .rsrc *1 protection Resource directory [Mostly taken care of, last protection needs research]
// - .rsrc *1 protection Resource directory [TODO: Mostly taken care of, last protection needs research]
// X - .text 6 protections Executable code (free format)
// Y - .tls *1 protection Thread-local storage (object only)
//
@@ -120,7 +126,11 @@ namespace BurnOutSharp.ExecutableType.Microsoft.PE
// X - .grand *1 protection CD-Cops / DVD-Cops
// X - .init *1 protection SolidShield
// - .pec2 *1 protection PE Compact [Unconfirmed]
// - .NOS0 *1 protection UPX (NOS Variant)
// - .NOS1 *1 protection UPX (NOS Variant)
// X - .txt2 *1 protection SafeDisc
// - .UPX0 *1 protection UPX
// - .UPX1 *1 protection UPX
//
// Here is a list of non-standard sections whose data is not read by various protections:
// - .brick 1 protection StarForce
@@ -131,15 +141,11 @@ namespace BurnOutSharp.ExecutableType.Microsoft.PE
// - .ldr 1 protection 3PLock
// - .ldt 1 protection 3PLock
// - .nicode 1 protection Armadillo
// - .NOS0 1 protection UPX (NOS Variant) [Used as endpoint]
// - .NOS1 1 protection UPX (NOS Variant) [Used as endpoint]
// - .pec1 1 protection PE Compact
// - .securom 1 protection SecuROM
// - .sforce 1 protection StarForce
// - stxt371 1 protection SafeDisc
// - stxt774 1 protection SafeDisc
// - .UPX0 1 protection UPX [Used as endpoint]
// - .UPX1 1 protection UPX [Used as endpoint]
// - .vob.pcd 1 protection VOB ProtectCD
// - _winzip_ 1 protection WinZip SFX
// - XPROT 1 protection JoWood
@@ -266,6 +272,14 @@ namespace BurnOutSharp.ExecutableType.Microsoft.PE
// this.ImportTable = ImportDataSection.Deserialize(stream, this.OptionalHeader.Magic == OptionalHeaderType.PE32Plus, hintCount: 0);
// }
// // Relocation Section
// var table = this.GetLastSection(".reloc", true);
// if (table != null && table.VirtualSize > 0)
// {
// stream.Seek((int)table.PointerToRawData, SeekOrigin.Begin);
// this.RelocationTable = RelocationSection.Deserialize(stream);
// }
// Resource Table
var table = this.GetLastSection(".rsrc", true);
if (table != null && table.VirtualSize > 0)
@@ -362,7 +376,15 @@ namespace BurnOutSharp.ExecutableType.Microsoft.PE
// if (table != null && table.VirtualSize > 0)
// {
// int tableAddress = (int)table.PointerToRawData;
// this.ImportTable = ImportDataSection.Deserialize(content, tableAddress, this.OptionalHeader.Magic == OptionalHeaderType.PE32Plus, hintCount: 0);
// this.ImportTable = ImportDataSection.Deserialize(content, ref tableAddress, this.OptionalHeader.Magic == OptionalHeaderType.PE32Plus, hintCount: 0);
// }
// // Relocation Section
// var table = this.GetLastSection(".reloc", true);
// if (table != null && table.VirtualSize > 0)
// {
// int tableAddress = (int)table.PointerToRawData;
// this.RelocationTable = RelocationSection.Deserialize(content, ref tableAddress);
// }
// Resource Table
@@ -420,13 +442,13 @@ namespace BurnOutSharp.ExecutableType.Microsoft.PE
if (sectionNames == null)
return false;
// If we're checking exactly, return only exact matches (with nulls trimmed)
// If we're checking exactly, return only exact matches
if (exact)
return sectionNames.Any(n => n.Trim('\0').Equals(sectionName));
return sectionNames.Any(n => n.Equals(sectionName));
// Otherwise, check if section name starts with the value
else
return sectionNames.Any(n => n.Trim('\0').StartsWith(sectionName));
return sectionNames.Any(n => n.StartsWith(sectionName));
}
/// <summary>

View File

@@ -1,5 +1,4 @@
using System.IO;
using BurnOutSharp.ExecutableType.Microsoft.PE.Headers;
using BurnOutSharp.ExecutableType.Microsoft.PE.Tables;
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Sections

View File

@@ -0,0 +1,51 @@
using System.IO;
using BurnOutSharp.ExecutableType.Microsoft.PE.Entries;
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Sections
{
/// <summary>
/// The base relocation table contains entries for all base relocations in the image.
/// The Base Relocation Table field in the optional header data directories gives the number of bytes in the base relocation table.
/// The base relocation table is divided into blocks.
/// Each block represents the base relocations for a 4K page.
/// Each block must start on a 32-bit boundary.
/// </summary>
/// <remarks>https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-reloc-section-image-only</remarks>
public class RelocationSection
{
/// <summary>
/// The base relocation table is divided into blocks.
/// </summary>
public BaseRelocationBlock[] BaseRelocationTable;
public static RelocationSection Deserialize(Stream stream, int blockCount)
{
long originalPosition = stream.Position;
var rs = new RelocationSection();
rs.BaseRelocationTable = new BaseRelocationBlock[blockCount];
for (int i = 0; i < blockCount; i++)
{
rs.BaseRelocationTable[i] = BaseRelocationBlock.Deserialize(stream);
}
stream.Seek(originalPosition, SeekOrigin.Begin);
return rs;
}
public static RelocationSection Deserialize(byte[] content, ref int offset, int blockCount)
{
int originalPosition = offset;
var rs = new RelocationSection();
rs.BaseRelocationTable = new BaseRelocationBlock[blockCount];
for (int i = 0; i < blockCount; i++)
{
rs.BaseRelocationTable[i] = BaseRelocationBlock.Deserialize(content, ref offset);
}
offset = originalPosition;
return rs;
}
}
}