-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
465 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
using Workshell.PE.Annotations; | ||
using Workshell.PE.Native; | ||
|
||
namespace Workshell.PE | ||
{ | ||
|
||
public enum RelocationType : byte | ||
{ | ||
[EnumAnnotationAttribute("IMAGE_REL_BASED_ABSOLUTE")] | ||
Absolute = 0, | ||
[EnumAnnotationAttribute("IMAGE_REL_BASED_HIGH")] | ||
High = 1, | ||
[EnumAnnotationAttribute("IMAGE_REL_BASED_LOW")] | ||
Low = 2, | ||
[EnumAnnotationAttribute("IMAGE_REL_BASED_HIGHLOW")] | ||
HighLow = 3, | ||
[EnumAnnotationAttribute("IMAGE_REL_BASED_HIGHADJ")] | ||
HighAdj = 4, | ||
[EnumAnnotationAttribute("IMAGE_REL_BASED_MIPS_JMPADDR")] | ||
MIPSJmpAddr = 5, | ||
[EnumAnnotationAttribute("IMAGE_REL_BASED_ARM_MOV32A")] | ||
ARMMov32a = 6, | ||
[EnumAnnotationAttribute("IMAGE_REL_BASED_ARM_MOV32T")] | ||
ARMMov32t = 7, | ||
[EnumAnnotationAttribute("IMAGE_REL_BASED_MIPS_JMPADDR16")] | ||
MIPSJmpAddr16 = 9, | ||
[EnumAnnotationAttribute("IMAGE_REL_BASED_DIR64")] | ||
Dir64 = 10 | ||
} | ||
|
||
public sealed class Relocation | ||
{ | ||
|
||
private RelocationBlock block; | ||
private RelocationType type; | ||
private ushort offset; | ||
private ushort value; | ||
private uint computed_rva; | ||
|
||
internal Relocation(RelocationBlock relocBlock, ushort relocValue) | ||
{ | ||
block = relocBlock; | ||
|
||
int reloc_type = relocValue >> 12; | ||
int reloc_offset = relocValue & 0xFFF; | ||
|
||
type = (RelocationType)reloc_type; | ||
offset = Convert.ToUInt16(reloc_offset); | ||
value = relocValue; | ||
computed_rva = block.PageRVA; | ||
|
||
switch (type) | ||
{ | ||
case RelocationType.Absolute: | ||
break; | ||
case RelocationType.HighLow: | ||
computed_rva += offset; | ||
break; | ||
case RelocationType.Dir64: | ||
computed_rva += offset; | ||
break; | ||
case RelocationType.High: | ||
case RelocationType.Low: | ||
default: | ||
computed_rva = 0; | ||
break; | ||
} | ||
} | ||
|
||
#region Methods | ||
|
||
public override string ToString() | ||
{ | ||
return String.Format("Type: {0}, Computed RVA: 0x{1:X8}",type,computed_rva); | ||
} | ||
|
||
#endregion | ||
|
||
#region Properties | ||
|
||
public RelocationBlock Block | ||
{ | ||
get | ||
{ | ||
return block; | ||
} | ||
} | ||
|
||
public RelocationType Type | ||
{ | ||
get | ||
{ | ||
return type; | ||
} | ||
} | ||
|
||
public ushort Offset | ||
{ | ||
get | ||
{ | ||
return offset; | ||
} | ||
} | ||
|
||
public ushort Value | ||
{ | ||
get | ||
{ | ||
return value; | ||
} | ||
} | ||
|
||
public uint ComputedRVA | ||
{ | ||
get | ||
{ | ||
return computed_rva; | ||
} | ||
} | ||
|
||
#endregion | ||
|
||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace Workshell.PE | ||
{ | ||
|
||
public sealed class RelocationBlock : IEnumerable<Relocation>, IReadOnlyCollection<Relocation>, ISupportsLocation, ISupportsBytes | ||
{ | ||
|
||
private RelocationBlocks blocks; | ||
private Location location; | ||
private uint page_rva; | ||
private uint block_size; | ||
private Section reloc_section; | ||
private List<Relocation> relocations; | ||
|
||
internal RelocationBlock(RelocationBlocks relocBlocks, Location blockLocation, uint pageRVA, uint blockSize, IEnumerable<ushort> relocs) | ||
{ | ||
LocationCalculator calc = relocBlocks.Content.DataDirectory.Directories.Reader.GetCalculator(); | ||
|
||
blocks = relocBlocks; | ||
location = blockLocation; | ||
page_rva = pageRVA; | ||
block_size = blockSize; | ||
reloc_section = calc.RVAToSection(pageRVA); | ||
relocations = new List<Relocation>(); | ||
|
||
foreach(ushort reloc_offset in relocs) | ||
{ | ||
Relocation reloc = new Relocation(this,reloc_offset); | ||
|
||
relocations.Add(reloc); | ||
} | ||
} | ||
|
||
#region Methods | ||
|
||
public IEnumerator<Relocation> GetEnumerator() | ||
{ | ||
return relocations.GetEnumerator(); | ||
} | ||
|
||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() | ||
{ | ||
return GetEnumerator(); | ||
} | ||
|
||
public override string ToString() | ||
{ | ||
return String.Format("Page RVA: 0x{0:X8}, Block Size: {1}, Relocations: {2}",page_rva,block_size,relocations.Count); | ||
} | ||
|
||
public byte[] GetBytes() | ||
{ | ||
Stream stream = blocks.Content.DataDirectory.Directories.Reader.GetStream(); | ||
byte[] buffer = Utils.ReadBytes(stream,location); | ||
|
||
return buffer; | ||
} | ||
|
||
#endregion | ||
|
||
#region Properties | ||
|
||
public RelocationBlocks Blocks | ||
{ | ||
get | ||
{ | ||
return blocks; | ||
} | ||
} | ||
|
||
public Location Location | ||
{ | ||
get | ||
{ | ||
return location; | ||
} | ||
} | ||
|
||
public uint PageRVA | ||
{ | ||
get | ||
{ | ||
return page_rva; | ||
} | ||
} | ||
|
||
public uint BlockSize | ||
{ | ||
get | ||
{ | ||
return block_size; | ||
} | ||
} | ||
|
||
public Section RelocationSection | ||
{ | ||
get | ||
{ | ||
return reloc_section; | ||
} | ||
} | ||
|
||
public int Count | ||
{ | ||
get | ||
{ | ||
return relocations.Count; | ||
} | ||
} | ||
|
||
public Relocation this[int index] | ||
{ | ||
get | ||
{ | ||
return relocations[index]; | ||
} | ||
} | ||
|
||
#endregion | ||
|
||
} | ||
|
||
} |
107 changes: 107 additions & 0 deletions
107
Src/Workshell.PE/Content/Relocation/RelocationBlocks.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace Workshell.PE | ||
{ | ||
|
||
public sealed class RelocationBlocks : IEnumerable<RelocationBlock>, IReadOnlyCollection<RelocationBlock> | ||
{ | ||
|
||
private RelocationTableContent content; | ||
private Location location; | ||
private Section section; | ||
private List<RelocationBlock> blocks; | ||
|
||
internal RelocationBlocks(RelocationTableContent relocContent, Location relocLocation, Section relocSection, List<Tuple<ulong,uint,uint,ushort[]>> relocBlocks, ulong imageBase) | ||
{ | ||
content = relocContent; | ||
location = relocLocation; | ||
section = relocSection; | ||
blocks = new List<RelocationBlock>(); | ||
|
||
Load(relocBlocks,imageBase); | ||
} | ||
|
||
#region Methods | ||
|
||
public IEnumerator<RelocationBlock> GetEnumerator() | ||
{ | ||
return blocks.GetEnumerator(); | ||
} | ||
|
||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() | ||
{ | ||
return GetEnumerator(); | ||
} | ||
|
||
private void Load(List<Tuple<ulong,uint,uint,ushort[]>> relocBlocks, ulong imageBase) | ||
{ | ||
LocationCalculator calc = content.DataDirectory.Directories.Reader.GetCalculator(); | ||
|
||
foreach(Tuple<ulong,uint,uint,ushort[]> tuple in relocBlocks) | ||
{ | ||
ulong offset = tuple.Item1; | ||
uint rva = calc.OffsetToRVA(section,offset); | ||
ulong va = imageBase + rva; | ||
uint size = tuple.Item2; | ||
uint page_rva = tuple.Item3; | ||
ushort[] relocs = tuple.Item4; | ||
Location block_location = new Location(offset,rva,va,size,size); | ||
RelocationBlock block = new RelocationBlock(this,block_location,page_rva,size,relocs); | ||
|
||
blocks.Add(block); | ||
} | ||
} | ||
|
||
#endregion | ||
|
||
#region Properties | ||
|
||
public RelocationTableContent Content | ||
{ | ||
get | ||
{ | ||
return content; | ||
} | ||
} | ||
|
||
public Location Location | ||
{ | ||
get | ||
{ | ||
return location; | ||
} | ||
} | ||
|
||
public Section Section | ||
{ | ||
get | ||
{ | ||
return section; | ||
} | ||
} | ||
|
||
public int Count | ||
{ | ||
get | ||
{ | ||
return blocks.Count; | ||
} | ||
} | ||
|
||
public RelocationBlock this[int index] | ||
{ | ||
get | ||
{ | ||
return blocks[index]; | ||
} | ||
} | ||
|
||
#endregion | ||
|
||
} | ||
|
||
} |
Oops, something went wrong.