mirror of
https://github.com/Perfare/Il2CppDumper.git
synced 2025-01-10 03:27:28 -03:00
添加数组类型读取
This commit is contained in:
parent
2c982f71f6
commit
79f60bd73a
10 changed files with 94 additions and 88 deletions
14
Il2CppDumper/Attributes/ArrayLengthAttribute.cs
Normal file
14
Il2CppDumper/Attributes/ArrayLengthAttribute.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Il2CppDumper
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Field)]
|
||||||
|
class ArrayLengthAttribute : Attribute
|
||||||
|
{
|
||||||
|
public int Length { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,29 +27,7 @@ namespace Il2CppDumper
|
||||||
public Elf(Stream stream, float version, long maxMetadataUsages) : base(stream, version, maxMetadataUsages)
|
public Elf(Stream stream, float version, long maxMetadataUsages) : base(stream, version, maxMetadataUsages)
|
||||||
{
|
{
|
||||||
is32Bit = true;
|
is32Bit = true;
|
||||||
elfHeader = new Elf32_Ehdr();
|
elfHeader = ReadClass<Elf32_Ehdr>();
|
||||||
elfHeader.ei_mag = ReadUInt32();
|
|
||||||
elfHeader.ei_class = ReadByte();
|
|
||||||
elfHeader.ei_data = ReadByte();
|
|
||||||
elfHeader.ei_version = ReadByte();
|
|
||||||
elfHeader.ei_osabi = ReadByte();
|
|
||||||
elfHeader.ei_abiversion = ReadByte();
|
|
||||||
elfHeader.ei_pad = ReadBytes(7);
|
|
||||||
elfHeader.e_type = ReadUInt16();
|
|
||||||
elfHeader.e_machine = ReadUInt16();
|
|
||||||
if (elfHeader.e_machine != EM_ARM && elfHeader.e_machine != EM_386)
|
|
||||||
throw new Exception("ERROR: Unsupported machines.");
|
|
||||||
elfHeader.e_version = ReadUInt32();
|
|
||||||
elfHeader.e_entry = ReadUInt32();
|
|
||||||
elfHeader.e_phoff = ReadUInt32();
|
|
||||||
elfHeader.e_shoff = ReadUInt32();
|
|
||||||
elfHeader.e_flags = ReadUInt32();
|
|
||||||
elfHeader.e_ehsize = ReadUInt16();
|
|
||||||
elfHeader.e_phentsize = ReadUInt16();
|
|
||||||
elfHeader.e_phnum = ReadUInt16();
|
|
||||||
elfHeader.e_shentsize = ReadUInt16();
|
|
||||||
elfHeader.e_shnum = ReadUInt16();
|
|
||||||
elfHeader.e_shtrndx = ReadUInt16();
|
|
||||||
programSegment = ReadClassArray<Elf32_Phdr>(elfHeader.e_phoff, elfHeader.e_phnum);
|
programSegment = ReadClassArray<Elf32_Phdr>(elfHeader.e_phoff, elfHeader.e_phnum);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,27 +18,7 @@ namespace Il2CppDumper
|
||||||
|
|
||||||
public Elf64(Stream stream, float version, long maxMetadataUsages) : base(stream, version, maxMetadataUsages)
|
public Elf64(Stream stream, float version, long maxMetadataUsages) : base(stream, version, maxMetadataUsages)
|
||||||
{
|
{
|
||||||
elfHeader = new Elf64_Ehdr();
|
elfHeader = ReadClass<Elf64_Ehdr>();
|
||||||
elfHeader.ei_mag = ReadUInt32();
|
|
||||||
elfHeader.ei_class = ReadByte();
|
|
||||||
elfHeader.ei_data = ReadByte();
|
|
||||||
elfHeader.ei_version = ReadByte();
|
|
||||||
elfHeader.ei_osabi = ReadByte();
|
|
||||||
elfHeader.ei_abiversion = ReadByte();
|
|
||||||
elfHeader.ei_pad = ReadBytes(7);
|
|
||||||
elfHeader.e_type = ReadUInt16();
|
|
||||||
elfHeader.e_machine = ReadUInt16();
|
|
||||||
elfHeader.e_version = ReadUInt32();
|
|
||||||
elfHeader.e_entry = ReadUInt64();
|
|
||||||
elfHeader.e_phoff = ReadUInt64();
|
|
||||||
elfHeader.e_shoff = ReadUInt64();
|
|
||||||
elfHeader.e_flags = ReadUInt32();
|
|
||||||
elfHeader.e_ehsize = ReadUInt16();
|
|
||||||
elfHeader.e_phentsize = ReadUInt16();
|
|
||||||
elfHeader.e_phnum = ReadUInt16();
|
|
||||||
elfHeader.e_shentsize = ReadUInt16();
|
|
||||||
elfHeader.e_shnum = ReadUInt16();
|
|
||||||
elfHeader.e_shtrndx = ReadUInt16();
|
|
||||||
programSegment = ReadClassArray<Elf64_Phdr>(elfHeader.e_phoff, elfHeader.e_phnum);
|
programSegment = ReadClassArray<Elf64_Phdr>(elfHeader.e_phoff, elfHeader.e_phnum);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace Il2CppDumper
|
||||||
public byte ei_version;
|
public byte ei_version;
|
||||||
public byte ei_osabi;
|
public byte ei_osabi;
|
||||||
public byte ei_abiversion;
|
public byte ei_abiversion;
|
||||||
|
[ArrayLength(Length = 7)]
|
||||||
public byte[] ei_pad;
|
public byte[] ei_pad;
|
||||||
public ushort e_type;
|
public ushort e_type;
|
||||||
public ushort e_machine;
|
public ushort e_machine;
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace Il2CppDumper
|
||||||
public byte ei_version;
|
public byte ei_version;
|
||||||
public byte ei_osabi;
|
public byte ei_osabi;
|
||||||
public byte ei_abiversion;
|
public byte ei_abiversion;
|
||||||
|
[ArrayLength(Length = 7)]
|
||||||
public byte[] ei_pad;
|
public byte[] ei_pad;
|
||||||
public ushort e_type;
|
public ushort e_type;
|
||||||
public ushort e_machine;
|
public ushort e_machine;
|
||||||
|
|
|
@ -13,52 +13,40 @@ namespace Il2CppDumper
|
||||||
|
|
||||||
public PE(Stream stream, float version, long maxMetadataUsages) : base(stream, version, maxMetadataUsages)
|
public PE(Stream stream, float version, long maxMetadataUsages) : base(stream, version, maxMetadataUsages)
|
||||||
{
|
{
|
||||||
if (ReadUInt16() != 0x5A4D)//e_magic
|
var dosHeader = ReadClass<DosHeader>();
|
||||||
throw new Exception("ERROR: Invalid PE file");
|
if (dosHeader.Magic != 0x5A4D)
|
||||||
Position = 0x3C;//e_lfanew
|
{
|
||||||
Position = ReadUInt32();
|
throw new InvalidDataException("ERROR: Invalid PE file");
|
||||||
if (ReadUInt32() != 0x00004550)//Signature
|
}
|
||||||
throw new Exception("ERROR: Invalid PE file");
|
Position = dosHeader.Lfanew;
|
||||||
|
if (ReadUInt32() != 0x4550u) //Signature
|
||||||
|
{
|
||||||
|
throw new InvalidDataException("ERROR: Invalid PE file");
|
||||||
|
}
|
||||||
var fileHeader = ReadClass<FileHeader>();
|
var fileHeader = ReadClass<FileHeader>();
|
||||||
if (fileHeader.Machine == 0x014c)//Intel 386
|
var pos = Position;
|
||||||
|
if (fileHeader.Machine == 0x14c) //Intel 386
|
||||||
{
|
{
|
||||||
is32Bit = true;
|
is32Bit = true;
|
||||||
var optionalHeader = ReadClass<OptionalHeader>();
|
var optionalHeader = ReadClass<OptionalHeader>();
|
||||||
optionalHeader.DataDirectory = ReadClassArray<DataDirectory>(optionalHeader.NumberOfRvaAndSizes);
|
|
||||||
imageBase = optionalHeader.ImageBase;
|
imageBase = optionalHeader.ImageBase;
|
||||||
}
|
}
|
||||||
else if (fileHeader.Machine == 0x8664) //AMD64
|
else if (fileHeader.Machine == 0x8664) //AMD64
|
||||||
{
|
{
|
||||||
var optionalHeader = ReadClass<OptionalHeader64>();
|
var optionalHeader = ReadClass<OptionalHeader64>();
|
||||||
optionalHeader.DataDirectory = ReadClassArray<DataDirectory>(optionalHeader.NumberOfRvaAndSizes);
|
|
||||||
imageBase = optionalHeader.ImageBase;
|
imageBase = optionalHeader.ImageBase;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new Exception("ERROR: Unsupported machine.");
|
throw new NotSupportedException("ERROR: Unsupported machine.");
|
||||||
}
|
|
||||||
sections = new SectionHeader[fileHeader.NumberOfSections];
|
|
||||||
for (int i = 0; i < fileHeader.NumberOfSections; i++)
|
|
||||||
{
|
|
||||||
sections[i] = new SectionHeader
|
|
||||||
{
|
|
||||||
Name = Encoding.UTF8.GetString(ReadBytes(8)).Trim('\0'),
|
|
||||||
VirtualSize = ReadUInt32(),
|
|
||||||
VirtualAddress = ReadUInt32(),
|
|
||||||
SizeOfRawData = ReadUInt32(),
|
|
||||||
PointerToRawData = ReadUInt32(),
|
|
||||||
PointerToRelocations = ReadUInt32(),
|
|
||||||
PointerToLinenumbers = ReadUInt32(),
|
|
||||||
NumberOfRelocations = ReadUInt16(),
|
|
||||||
NumberOfLinenumbers = ReadUInt16(),
|
|
||||||
Characteristics = ReadUInt32()
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
Position = pos + fileHeader.SizeOfOptionalHeader;
|
||||||
|
sections = ReadClassArray<SectionHeader>(fileHeader.NumberOfSections);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override ulong MapVATR(ulong uiAddr)
|
public override ulong MapVATR(ulong absAddr)
|
||||||
{
|
{
|
||||||
var addr = uiAddr - imageBase;
|
var addr = absAddr - imageBase;
|
||||||
var section = sections.First(x => addr >= x.VirtualAddress && addr <= x.VirtualAddress + x.VirtualSize);
|
var section = sections.First(x => addr >= x.VirtualAddress && addr <= x.VirtualAddress + x.VirtualSize);
|
||||||
return addr - (section.VirtualAddress - section.PointerToRawData);
|
return addr - (section.VirtualAddress - section.PointerToRawData);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,31 @@ using System.Text;
|
||||||
|
|
||||||
namespace Il2CppDumper
|
namespace Il2CppDumper
|
||||||
{
|
{
|
||||||
|
public class DosHeader
|
||||||
|
{
|
||||||
|
public ushort Magic;
|
||||||
|
public ushort Cblp;
|
||||||
|
public ushort Cp;
|
||||||
|
public ushort Crlc;
|
||||||
|
public ushort Cparhdr;
|
||||||
|
public ushort Minalloc;
|
||||||
|
public ushort Maxalloc;
|
||||||
|
public ushort Ss;
|
||||||
|
public ushort Sp;
|
||||||
|
public ushort Csum;
|
||||||
|
public ushort Ip;
|
||||||
|
public ushort Cs;
|
||||||
|
public ushort Lfarlc;
|
||||||
|
public ushort Ovno;
|
||||||
|
[ArrayLength(Length = 4)]
|
||||||
|
public ushort[] Res;
|
||||||
|
public ushort Oemid;
|
||||||
|
public ushort Oeminfo;
|
||||||
|
[ArrayLength(Length = 10)]
|
||||||
|
public ushort[] Res2;
|
||||||
|
public uint Lfanew;
|
||||||
|
}
|
||||||
|
|
||||||
public class FileHeader
|
public class FileHeader
|
||||||
{
|
{
|
||||||
public ushort Machine;
|
public ushort Machine;
|
||||||
|
@ -48,7 +73,7 @@ namespace Il2CppDumper
|
||||||
public uint SizeOfHeapCommit;
|
public uint SizeOfHeapCommit;
|
||||||
public uint LoaderFlags;
|
public uint LoaderFlags;
|
||||||
public uint NumberOfRvaAndSizes;
|
public uint NumberOfRvaAndSizes;
|
||||||
public DataDirectory[] DataDirectory { get; set; }
|
//public DataDirectory[] DataDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class OptionalHeader64
|
public class OptionalHeader64
|
||||||
|
@ -82,18 +107,19 @@ namespace Il2CppDumper
|
||||||
public ulong SizeOfHeapCommit;
|
public ulong SizeOfHeapCommit;
|
||||||
public uint LoaderFlags;
|
public uint LoaderFlags;
|
||||||
public uint NumberOfRvaAndSizes;
|
public uint NumberOfRvaAndSizes;
|
||||||
public DataDirectory[] DataDirectory { get; set; }
|
//public DataDirectory[] DataDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DataDirectory
|
/*public class DataDirectory
|
||||||
{
|
{
|
||||||
public uint VirtualAddress;
|
public uint VirtualAddress;
|
||||||
public uint Size;
|
public uint Size;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
public class SectionHeader
|
public class SectionHeader
|
||||||
{
|
{
|
||||||
public string Name;
|
[ArrayLength(Length = 8)]
|
||||||
|
public byte[] Name;
|
||||||
public uint VirtualSize;
|
public uint VirtualSize;
|
||||||
public uint VirtualAddress;
|
public uint VirtualAddress;
|
||||||
public uint SizeOfRawData;
|
public uint SizeOfRawData;
|
||||||
|
@ -104,4 +130,12 @@ namespace Il2CppDumper
|
||||||
public ushort NumberOfLinenumbers;
|
public ushort NumberOfLinenumbers;
|
||||||
public uint Characteristics;
|
public uint Characteristics;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum SectionCharacteristics : uint
|
||||||
|
{
|
||||||
|
IMAGE_SCN_MEM_EXECUTE = 0x20000000,
|
||||||
|
IMAGE_SCN_MEM_READ = 0x40000000,
|
||||||
|
IMAGE_SCN_MEM_WRITE = 0x80000000
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,8 @@ namespace Il2CppDumper
|
||||||
private BinaryReader reader;
|
private BinaryReader reader;
|
||||||
private BinaryWriter writer;
|
private BinaryWriter writer;
|
||||||
private MethodInfo readClass;
|
private MethodInfo readClass;
|
||||||
private Dictionary<Type, MethodInfo> readClassCache = new Dictionary<Type, MethodInfo>();
|
private MethodInfo readClassArray;
|
||||||
|
private Dictionary<Type, MethodInfo> genericMethodCache = new Dictionary<Type, MethodInfo>();
|
||||||
private Dictionary<FieldInfo, VersionAttribute> attributeCache = new Dictionary<FieldInfo, VersionAttribute>();
|
private Dictionary<FieldInfo, VersionAttribute> attributeCache = new Dictionary<FieldInfo, VersionAttribute>();
|
||||||
|
|
||||||
public BinaryStream(Stream input)
|
public BinaryStream(Stream input)
|
||||||
|
@ -23,6 +24,7 @@ namespace Il2CppDumper
|
||||||
reader = new BinaryReader(stream, Encoding.UTF8, true);
|
reader = new BinaryReader(stream, Encoding.UTF8, true);
|
||||||
writer = new BinaryWriter(stream, Encoding.UTF8, true);
|
writer = new BinaryWriter(stream, Encoding.UTF8, true);
|
||||||
readClass = GetType().GetMethod("ReadClass", Type.EmptyTypes);
|
readClass = GetType().GetMethod("ReadClass", Type.EmptyTypes);
|
||||||
|
readClassArray = GetType().GetMethod("ReadClassArray", new[] { typeof(long) });
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ReadBoolean() => reader.ReadBoolean();
|
public bool ReadBoolean() => reader.ReadBoolean();
|
||||||
|
@ -101,7 +103,7 @@ namespace Il2CppDumper
|
||||||
case "UInt64":
|
case "UInt64":
|
||||||
return ReadUInt64();
|
return ReadUInt64();
|
||||||
default:
|
default:
|
||||||
return null;
|
throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +129,7 @@ namespace Il2CppDumper
|
||||||
{
|
{
|
||||||
if (Attribute.IsDefined(i, typeof(VersionAttribute)))
|
if (Attribute.IsDefined(i, typeof(VersionAttribute)))
|
||||||
{
|
{
|
||||||
versionAttribute = (VersionAttribute)Attribute.GetCustomAttribute(i, typeof(VersionAttribute));
|
versionAttribute = i.GetCustomAttribute<VersionAttribute>();
|
||||||
attributeCache.Add(i, versionAttribute);
|
attributeCache.Add(i, versionAttribute);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,16 +142,24 @@ namespace Il2CppDumper
|
||||||
{
|
{
|
||||||
i.SetValue(t, ReadPrimitive(i.FieldType));
|
i.SetValue(t, ReadPrimitive(i.FieldType));
|
||||||
}
|
}
|
||||||
|
else if (i.FieldType.IsArray)
|
||||||
|
{
|
||||||
|
var arrayLengthAttribute = i.GetCustomAttribute<ArrayLengthAttribute>();
|
||||||
|
if (!genericMethodCache.TryGetValue(i.FieldType, out var methodInfo))
|
||||||
|
{
|
||||||
|
methodInfo = readClassArray.MakeGenericMethod(i.FieldType.GetElementType());
|
||||||
|
genericMethodCache.Add(i.FieldType, methodInfo);
|
||||||
|
}
|
||||||
|
i.SetValue(t, methodInfo.Invoke(this, new object[] { arrayLengthAttribute.Length }));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!readClassCache.TryGetValue(i.FieldType, out var methodInfo))
|
if (!genericMethodCache.TryGetValue(i.FieldType, out var methodInfo))
|
||||||
{
|
{
|
||||||
methodInfo = readClass.MakeGenericMethod(i.FieldType);
|
methodInfo = readClass.MakeGenericMethod(i.FieldType);
|
||||||
readClassCache.Add(i.FieldType, methodInfo);
|
genericMethodCache.Add(i.FieldType, methodInfo);
|
||||||
}
|
}
|
||||||
var value = methodInfo.Invoke(this, null);
|
i.SetValue(t, methodInfo.Invoke(this, null));
|
||||||
i.SetValue(t, value);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return t;
|
return t;
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="Attributes\ArrayLengthAttribute.cs" />
|
||||||
<Compile Include="Extensions\BoyerMooreHorspool.cs" />
|
<Compile Include="Extensions\BoyerMooreHorspool.cs" />
|
||||||
<Compile Include="ExecutableFormats\ElfConstants.cs" />
|
<Compile Include="ExecutableFormats\ElfConstants.cs" />
|
||||||
<Compile Include="Extensions\HexExtensions.cs" />
|
<Compile Include="Extensions\HexExtensions.cs" />
|
||||||
|
|
|
@ -514,7 +514,6 @@ namespace Il2CppDumper
|
||||||
var pointer = metadata.GetDefaultValueFromIndex(dataIndex);
|
var pointer = metadata.GetDefaultValueFromIndex(dataIndex);
|
||||||
var defaultValueType = il2Cpp.types[typeIndex];
|
var defaultValueType = il2Cpp.types[typeIndex];
|
||||||
metadata.Position = pointer;
|
metadata.Position = pointer;
|
||||||
value = null;
|
|
||||||
switch (defaultValueType.type)
|
switch (defaultValueType.type)
|
||||||
{
|
{
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN:
|
case Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN:
|
||||||
|
|
Loading…
Reference in a new issue