ConfuserEx/Confuser.Core/NativeEraser.cs

102 строки
3.0 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using dnlib.DotNet;
using dnlib.DotNet.Writer;
using dnlib.IO;
using dnlib.PE;
using SR = System.Reflection;
namespace Confuser.Core {
internal class NativeEraser {
static void Erase(Tuple<uint, uint, byte[]> section, uint offset, uint len) {
Array.Clear(section.Item3, (int)(offset - section.Item1), (int)len);
}
static void Erase(List<Tuple<uint, uint, byte[]>> sections, uint beginOffset, uint size) {
foreach (var sect in sections)
if (beginOffset >= sect.Item1 && beginOffset + size < sect.Item2) {
Erase(sect, beginOffset, size);
break;
}
}
static void Erase(List<Tuple<uint, uint, byte[]>> sections, IFileSection s) {
foreach (var sect in sections)
if ((uint)s.StartOffset >= sect.Item1 && (uint)s.EndOffset < sect.Item2) {
Erase(sect, (uint)s.StartOffset, (uint)(s.EndOffset - s.StartOffset));
break;
}
}
static void Erase(List<Tuple<uint, uint, byte[]>> sections, uint methodOffset) {
foreach (var sect in sections)
if (methodOffset >= sect.Item1 && methodOffset - sect.Item1 < sect.Item3.Length) {
uint f = sect.Item3[methodOffset - sect.Item1];
uint size;
switch ((f & 7)) {
case 2:
case 6:
size = (f >> 2) + 1;
break;
case 3:
f |= (uint)((sect.Item3[methodOffset - sect.Item1 + 1]) << 8);
size = (f >> 12) * 4;
uint codeSize = BitConverter.ToUInt32(sect.Item3, (int)(methodOffset - sect.Item1 + 4));
size += codeSize;
break;
default:
return;
}
Erase(sect, methodOffset, size);
}
}
public static void Erase(NativeModuleWriter writer, ModuleDefMD module) {
if (writer == null || module == null)
return;
var sections = new List<Tuple<uint, uint, byte[]>>();
var s = new MemoryStream();
foreach (var origSect in writer.OrigSections) {
var oldChunk = origSect.Chunk;
var sectHdr = origSect.PESection;
s.SetLength(0);
oldChunk.WriteTo(new DataWriter(s));
var buf = s.ToArray();
var newChunk = new DataReaderChunk(oldChunk.CreateReader());
newChunk.SetOffset(oldChunk.FileOffset, oldChunk.RVA);
origSect.Chunk = newChunk;
sections.Add(Tuple.Create(
sectHdr.PointerToRawData,
sectHdr.PointerToRawData + sectHdr.SizeOfRawData,
buf));
}
var md = module.Metadata;
var row = md.TablesStream.MethodTable.Rows;
for (uint i = 1; i <= row; i++) {
if (md.TablesStream.TryReadMethodRow(i, out var method)) {
var codeType = ((MethodImplAttributes)method.ImplFlags & MethodImplAttributes.CodeTypeMask);
if (codeType == MethodImplAttributes.IL)
Erase(sections, (uint)md.PEImage.ToFileOffset((RVA)method.RVA));
}
}
var res = md.ImageCor20Header.Resources;
if (res.Size > 0)
Erase(sections, (uint)res.StartOffset, res.Size);
Erase(sections, md.ImageCor20Header);
Erase(sections, md.MetadataHeader);
foreach (var stream in md.AllStreams)
Erase(sections, stream);
}
}
}