mirror of
https://github.com/Perfare/Il2CppDumper.git
synced 2025-01-09 11:17:35 -03:00
初始化提交
This commit is contained in:
parent
8bde61638d
commit
ef9e9de713
14 changed files with 1656 additions and 0 deletions
63
.gitattributes
vendored
Normal file
63
.gitattributes
vendored
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
###############################################################################
|
||||||
|
# Set default behavior to automatically normalize line endings.
|
||||||
|
###############################################################################
|
||||||
|
* text=auto
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Set default behavior for command prompt diff.
|
||||||
|
#
|
||||||
|
# This is need for earlier builds of msysgit that does not have it on by
|
||||||
|
# default for csharp files.
|
||||||
|
# Note: This is only used by command line
|
||||||
|
###############################################################################
|
||||||
|
#*.cs diff=csharp
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Set the merge driver for project and solution files
|
||||||
|
#
|
||||||
|
# Merging from the command prompt will add diff markers to the files if there
|
||||||
|
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||||
|
# the diff markers are never inserted). Diff markers may cause the following
|
||||||
|
# file extensions to fail to load in VS. An alternative would be to treat
|
||||||
|
# these files as binary and thus will always conflict and require user
|
||||||
|
# intervention with every merge. To do so, just uncomment the entries below
|
||||||
|
###############################################################################
|
||||||
|
#*.sln merge=binary
|
||||||
|
#*.csproj merge=binary
|
||||||
|
#*.vbproj merge=binary
|
||||||
|
#*.vcxproj merge=binary
|
||||||
|
#*.vcproj merge=binary
|
||||||
|
#*.dbproj merge=binary
|
||||||
|
#*.fsproj merge=binary
|
||||||
|
#*.lsproj merge=binary
|
||||||
|
#*.wixproj merge=binary
|
||||||
|
#*.modelproj merge=binary
|
||||||
|
#*.sqlproj merge=binary
|
||||||
|
#*.wwaproj merge=binary
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# behavior for image files
|
||||||
|
#
|
||||||
|
# image files are treated as binary by default.
|
||||||
|
###############################################################################
|
||||||
|
#*.jpg binary
|
||||||
|
#*.png binary
|
||||||
|
#*.gif binary
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# diff behavior for common document formats
|
||||||
|
#
|
||||||
|
# Convert binary document formats to text before diffing them. This feature
|
||||||
|
# is only available from the command line. Turn it on by uncommenting the
|
||||||
|
# entries below.
|
||||||
|
###############################################################################
|
||||||
|
#*.doc diff=astextplain
|
||||||
|
#*.DOC diff=astextplain
|
||||||
|
#*.docx diff=astextplain
|
||||||
|
#*.DOCX diff=astextplain
|
||||||
|
#*.dot diff=astextplain
|
||||||
|
#*.DOT diff=astextplain
|
||||||
|
#*.pdf diff=astextplain
|
||||||
|
#*.PDF diff=astextplain
|
||||||
|
#*.rtf diff=astextplain
|
||||||
|
#*.RTF diff=astextplain
|
242
.gitignore
vendored
Normal file
242
.gitignore
vendored
Normal file
|
@ -0,0 +1,242 @@
|
||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
[Xx]64/
|
||||||
|
[Xx]86/
|
||||||
|
[Bb]uild/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
|
||||||
|
# Visual Studio 2015 cache/options directory
|
||||||
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUNIT
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# DNX
|
||||||
|
project.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_i.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# JustCode is a .NET coding add-in
|
||||||
|
.JustCode
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
|
||||||
|
# TODO: Un-comment the next line if you do not want to checkin
|
||||||
|
# your web deploy settings because they may include unencrypted
|
||||||
|
# passwords
|
||||||
|
#*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/packages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/packages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/packages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignoreable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directory
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
[Ss]tyle[Cc]op.*
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
node_modules/
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# LightSwitch generated files
|
||||||
|
GeneratedArtifacts/
|
||||||
|
ModelManifest.xml
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
22
Il2CppDumper.sln
Normal file
22
Il2CppDumper.sln
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio 14
|
||||||
|
VisualStudioVersion = 14.0.25420.1
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Il2CppDumper", "Il2CppDumper\Il2CppDumper.csproj", "{379715D4-4B7B-41F2-B78A-8B18D86320E2}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{379715D4-4B7B-41F2-B78A-8B18D86320E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{379715D4-4B7B-41F2-B78A-8B18D86320E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{379715D4-4B7B-41F2-B78A-8B18D86320E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{379715D4-4B7B-41F2-B78A-8B18D86320E2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
20
Il2CppDumper/DefineConstants.cs
Normal file
20
Il2CppDumper/DefineConstants.cs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
internal static class DefineConstants
|
||||||
|
{
|
||||||
|
public const int FIELD_ATTRIBUTE_PRIVATE = 0x0001;
|
||||||
|
public const int FIELD_ATTRIBUTE_PUBLIC = 0x0006;
|
||||||
|
public const int FIELD_ATTRIBUTE_STATIC = 0x0010;
|
||||||
|
public const int FIELD_ATTRIBUTE_INIT_ONLY = 0x0020;
|
||||||
|
public const int METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK = 0x0007;
|
||||||
|
public const int METHOD_ATTRIBUTE_PRIVATE = 0x0001;
|
||||||
|
public const int METHOD_ATTRIBUTE_PUBLIC = 0x0006;
|
||||||
|
public const int METHOD_ATTRIBUTE_STATIC = 0x0010;
|
||||||
|
public const int METHOD_ATTRIBUTE_VIRTUAL = 0x0040;
|
||||||
|
public const int TYPE_ATTRIBUTE_VISIBILITY_MASK = 0x00000007;
|
||||||
|
public const int TYPE_ATTRIBUTE_PUBLIC = 0x00000001;
|
||||||
|
public const int TYPE_ATTRIBUTE_INTERFACE = 0x00000020;
|
||||||
|
public const int TYPE_ATTRIBUTE_ABSTRACT = 0x00000080;
|
||||||
|
public const int TYPE_ATTRIBUTE_SEALED = 0x00000100;
|
||||||
|
public const int TYPE_ATTRIBUTE_SERIALIZABLE = 0x00002000;
|
||||||
|
public const int PARAM_ATTRIBUTE_OUT = 0x0002;
|
||||||
|
public const int PARAM_ATTRIBUTE_OPTIONAL = 0x0010;
|
||||||
|
}
|
130
Il2CppDumper/Elf.cs
Normal file
130
Il2CppDumper/Elf.cs
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Il2CppDumper
|
||||||
|
{
|
||||||
|
class Elf : MyBinaryReader
|
||||||
|
{
|
||||||
|
public elf_header elf_header;
|
||||||
|
public Dictionary<string, elf_32_shdr> sectionWithName;
|
||||||
|
List<elf_32_shdr> sections;
|
||||||
|
|
||||||
|
public Elf(Stream stream) : base(stream)
|
||||||
|
{
|
||||||
|
elf_header = new elf_header();
|
||||||
|
elf_header.m_dwFormat = ReadUInt32();
|
||||||
|
if (elf_header.m_dwFormat != 0x464c457f)
|
||||||
|
{
|
||||||
|
throw new Exception("ERROR: il2cpp lib provided is not a valid ELF file.");
|
||||||
|
}
|
||||||
|
elf_header.m_arch = ReadByte();
|
||||||
|
elf_header.m_endian = ReadByte();
|
||||||
|
elf_header.m_version = ReadByte();
|
||||||
|
elf_header.m_osabi = ReadByte();
|
||||||
|
elf_header.m_osabi_ver = ReadByte();
|
||||||
|
elf_header.e_pad = ReadBytes(7);
|
||||||
|
elf_header.e_type = ReadUInt16();
|
||||||
|
elf_header.e_machine = ReadUInt16();
|
||||||
|
elf_header.e_version = ReadUInt32();
|
||||||
|
if (elf_header.m_arch == 1)//32
|
||||||
|
{
|
||||||
|
elf_header.e_entry = ReadUInt32();
|
||||||
|
elf_header.e_phoff = ReadUInt32();
|
||||||
|
elf_header.e_shoff = ReadUInt32();
|
||||||
|
elf_header.e_flags = ReadUInt32();
|
||||||
|
elf_header.e_ehsize = ReadUInt16();
|
||||||
|
elf_header.e_phentsize = ReadUInt16();
|
||||||
|
elf_header.e_phnum = ReadUInt16();
|
||||||
|
elf_header.e_shentsize = ReadUInt16();
|
||||||
|
elf_header.e_shnum = ReadUInt16();
|
||||||
|
elf_header.e_shtrndx = ReadUInt16();
|
||||||
|
}
|
||||||
|
else//64
|
||||||
|
{
|
||||||
|
elf_header.e_entry = ReadUInt64();
|
||||||
|
elf_header.e_phoff = ReadUInt64();
|
||||||
|
elf_header.e_shoff = ReadUInt64();
|
||||||
|
elf_header.e_flags = ReadUInt32();
|
||||||
|
elf_header.e_ehsize = ReadUInt16();
|
||||||
|
elf_header.e_phentsize = ReadUInt16();
|
||||||
|
elf_header.e_phnum = ReadUInt16();
|
||||||
|
elf_header.e_shentsize = ReadUInt16();
|
||||||
|
elf_header.e_shnum = ReadUInt16();
|
||||||
|
elf_header.e_shtrndx = ReadUInt16();
|
||||||
|
}
|
||||||
|
GetSectionWithName();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GetSectionWithName()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var section_name_block_off = (int)elf_header.e_shoff + (elf_header.e_shentsize * elf_header.e_shtrndx);
|
||||||
|
if (elf_header.m_arch == 1)//32
|
||||||
|
{
|
||||||
|
Position = section_name_block_off + 2 * 4 + 4 + 4;
|
||||||
|
section_name_block_off = ReadInt32();
|
||||||
|
}
|
||||||
|
else//Hmm...
|
||||||
|
{
|
||||||
|
Position = section_name_block_off + 2 * 4 + 8 + 8;
|
||||||
|
section_name_block_off = ReadInt32();
|
||||||
|
}
|
||||||
|
var sectionWithNametmp = new Dictionary<string, elf_32_shdr>();
|
||||||
|
var sectionstmp = new List<elf_32_shdr>();
|
||||||
|
for (int i = 0; i < elf_header.e_shnum; i++)
|
||||||
|
{
|
||||||
|
var section = GetSection(i);
|
||||||
|
sectionWithNametmp.Add(ReadStringToNull(section_name_block_off + section.sh_name), section);
|
||||||
|
sectionstmp.Add(section);
|
||||||
|
}
|
||||||
|
sectionWithName = sectionWithNametmp;
|
||||||
|
sections = sectionstmp;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Console.WriteLine("ERROR: Unable to get section.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private elf_32_shdr GetSection(int iSection)
|
||||||
|
{
|
||||||
|
return ReadClass<elf_32_shdr>((int)elf_header.e_shoff + (elf_header.e_shentsize * iSection));
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint MapVATR(uint uiAddr)
|
||||||
|
{
|
||||||
|
if (sections == null)
|
||||||
|
return uiAddr;
|
||||||
|
elf_32_shdr pFirstSec = sections[0];
|
||||||
|
if (uiAddr < pFirstSec.sh_addr)
|
||||||
|
return 0;
|
||||||
|
for (int i = 1; i < elf_header.e_shnum; ++i)
|
||||||
|
{
|
||||||
|
elf_32_shdr pSection = sections[i];
|
||||||
|
if (pSection.sh_addr > uiAddr)
|
||||||
|
{
|
||||||
|
elf_32_shdr pRetSec = sections[i - 1];
|
||||||
|
uint uiResOffset = uiAddr - pRetSec.sh_addr;
|
||||||
|
return pRetSec.sh_offset + uiResOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elf_32_shdr pRetSec2 = sections[elf_header.e_shnum - 1];
|
||||||
|
uint uiResOffset2 = uiAddr - pRetSec2.sh_addr;
|
||||||
|
return pRetSec2.sh_offset + uiResOffset2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T MapVATR<T>(uint uiAddr) where T : new()
|
||||||
|
{
|
||||||
|
return ReadClass<T>(MapVATR(uiAddr));
|
||||||
|
}
|
||||||
|
|
||||||
|
public T[] MapVATR<T>(uint uiAddr, int count) where T : new()
|
||||||
|
{
|
||||||
|
return ReadClassArray<T>(MapVATR(uiAddr), count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
71
Il2CppDumper/ElfClass.cs
Normal file
71
Il2CppDumper/ElfClass.cs
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Il2CppDumper
|
||||||
|
{
|
||||||
|
class elf_header
|
||||||
|
{
|
||||||
|
// 0x7f followed by ELF in ascii
|
||||||
|
public uint m_dwFormat;
|
||||||
|
|
||||||
|
// 1 - 32 bit
|
||||||
|
// 2 - 64 bit
|
||||||
|
public byte m_arch;
|
||||||
|
|
||||||
|
// 1 - little endian
|
||||||
|
// 2 - big endian
|
||||||
|
public byte m_endian;
|
||||||
|
|
||||||
|
// 1 is original elf format
|
||||||
|
public byte m_version;
|
||||||
|
|
||||||
|
// set based on OS, refer to OSABI enum
|
||||||
|
public byte m_osabi;
|
||||||
|
|
||||||
|
// refer to elf documentation
|
||||||
|
public byte m_osabi_ver;
|
||||||
|
|
||||||
|
// unused
|
||||||
|
public byte[] e_pad;//byte[7]
|
||||||
|
|
||||||
|
// 1 - relocatable
|
||||||
|
// 2 - executable
|
||||||
|
// 3 - shared
|
||||||
|
// 4 - core
|
||||||
|
public ushort e_type;
|
||||||
|
|
||||||
|
// refer to isa enum
|
||||||
|
public ushort e_machine;
|
||||||
|
|
||||||
|
public uint e_version;
|
||||||
|
|
||||||
|
//全部定义为64位
|
||||||
|
public ulong e_entry;
|
||||||
|
public ulong e_phoff;
|
||||||
|
public ulong e_shoff;
|
||||||
|
public uint e_flags;
|
||||||
|
public ushort e_ehsize;
|
||||||
|
public ushort e_phentsize;
|
||||||
|
public ushort e_phnum;
|
||||||
|
public ushort e_shentsize;
|
||||||
|
public ushort e_shnum;
|
||||||
|
public ushort e_shtrndx;
|
||||||
|
}
|
||||||
|
|
||||||
|
class elf_32_shdr
|
||||||
|
{
|
||||||
|
public uint sh_name;
|
||||||
|
public uint sh_type;
|
||||||
|
public uint sh_flags;
|
||||||
|
public uint sh_addr;
|
||||||
|
public uint sh_offset;
|
||||||
|
public uint sh_size;
|
||||||
|
public uint sh_link;
|
||||||
|
public uint sh_info;
|
||||||
|
public uint sh_addralign;
|
||||||
|
public uint sh_entsize;
|
||||||
|
}
|
||||||
|
}
|
118
Il2CppDumper/Il2Cpp.cs
Normal file
118
Il2CppDumper/Il2Cpp.cs
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Il2CppDumper
|
||||||
|
{
|
||||||
|
class Il2Cpp : Elf
|
||||||
|
{
|
||||||
|
Il2CppMetadataRegistration pMetadataRegistration;
|
||||||
|
public Il2CppCodeRegistration pCodeRegistration;
|
||||||
|
|
||||||
|
public Il2Cpp(Stream stream) : base(stream)
|
||||||
|
{
|
||||||
|
if (!Auto())
|
||||||
|
{
|
||||||
|
throw new Exception("ERROR: Unable to process file automatically, try to use manual mode.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Il2Cpp(Stream stream, uint codeRegistration, uint metadataRegistration) : base(stream)
|
||||||
|
{
|
||||||
|
Init(codeRegistration, metadataRegistration);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Init(uint codeRegistration, uint metadataRegistration)
|
||||||
|
{
|
||||||
|
pCodeRegistration = MapVATR<Il2CppCodeRegistration>(codeRegistration);
|
||||||
|
pMetadataRegistration = MapVATR<Il2CppMetadataRegistration>(metadataRegistration);
|
||||||
|
pCodeRegistration.methodPointers = MapVATR<uint>(pCodeRegistration.pmethodPointers, (int)pCodeRegistration.methodPointersCount);
|
||||||
|
pMetadataRegistration.fieldOffsets = MapVATR<int>(pMetadataRegistration.pfieldOffsets, pMetadataRegistration.fieldOffsetsCount);
|
||||||
|
var types = MapVATR<uint>(pMetadataRegistration.ptypes, pMetadataRegistration.typesCount);
|
||||||
|
pMetadataRegistration.types = new Il2CppType[pMetadataRegistration.typesCount];
|
||||||
|
for (int i = 0; i < pMetadataRegistration.typesCount; ++i)
|
||||||
|
{
|
||||||
|
pMetadataRegistration.types[i] = MapVATR<Il2CppType>(types[i]);
|
||||||
|
pMetadataRegistration.types[i].Init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Il2CppType GetTypeFromTypeIndex(int idx)
|
||||||
|
{
|
||||||
|
return pMetadataRegistration.types[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetFieldOffsetFromIndex(int typeIndex, int fieldIndexInType)
|
||||||
|
{
|
||||||
|
var ptr = pMetadataRegistration.fieldOffsets[typeIndex];
|
||||||
|
Position = ptr + 4 * fieldIndexInType;
|
||||||
|
return ReadInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Auto()
|
||||||
|
{
|
||||||
|
if (sectionWithName != null)
|
||||||
|
{
|
||||||
|
var bytes = new byte[] { 0x1c, 0x0, 0x9f, 0xe5, 0x1c, 0x10, 0x9f, 0xe5, 0x1c, 0x20, 0x9f, 0xe5 };
|
||||||
|
//判断必要的section是否都在
|
||||||
|
if (sectionWithName.ContainsKey(".got") && sectionWithName.ContainsKey(".init_array") && sectionWithName.ContainsKey(".dynamic"))
|
||||||
|
{
|
||||||
|
var dynamic = sectionWithName[".dynamic"];
|
||||||
|
var got = sectionWithName[".got"];
|
||||||
|
//从.dynamic获取_GLOBAL_OFFSET_TABLE_
|
||||||
|
uint _GLOBAL_OFFSET_TABLE_ = 0;
|
||||||
|
Position = dynamic.sh_offset;
|
||||||
|
var dynamicend = dynamic.sh_offset + dynamic.sh_size;
|
||||||
|
var gotend = got.sh_offset + got.sh_size;
|
||||||
|
while (Position < dynamicend)
|
||||||
|
{
|
||||||
|
var tag = ReadInt32();
|
||||||
|
if (tag == 3)
|
||||||
|
{
|
||||||
|
var tmp = ReadUInt32();
|
||||||
|
if (tmp >= got.sh_offset && tmp <= gotend)
|
||||||
|
{
|
||||||
|
_GLOBAL_OFFSET_TABLE_ = tmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Position += 4;
|
||||||
|
}
|
||||||
|
//从.init_array获取函数
|
||||||
|
var init_array = sectionWithName[".init_array"];
|
||||||
|
var addrs = ReadClassArray<uint>(init_array.sh_offset, (int)init_array.sh_size / 4);
|
||||||
|
foreach (var i in addrs)
|
||||||
|
{
|
||||||
|
if (i != 0)
|
||||||
|
{
|
||||||
|
Position = i;
|
||||||
|
var buff = ReadBytes(12);
|
||||||
|
if (bytes.SequenceEqual(buff))
|
||||||
|
{
|
||||||
|
Position = i + 0x2c;
|
||||||
|
var subaddr = ReadUInt32() + _GLOBAL_OFFSET_TABLE_;
|
||||||
|
Position = subaddr + 0x28;
|
||||||
|
var codeRegistration = ReadUInt32() + _GLOBAL_OFFSET_TABLE_;
|
||||||
|
Console.WriteLine("CodeRegistration : {0:x}", codeRegistration);
|
||||||
|
Position = subaddr + 0x2C;
|
||||||
|
var ptr = ReadUInt32() + _GLOBAL_OFFSET_TABLE_;
|
||||||
|
Position = MapVATR(ptr);
|
||||||
|
var metadataRegistration = ReadUInt32();
|
||||||
|
Console.WriteLine("MetadataRegistration : {0:x}", metadataRegistration);
|
||||||
|
Init(codeRegistration, metadataRegistration);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("ERROR: The necessary section is missing.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
208
Il2CppDumper/Il2CppClass.cs
Normal file
208
Il2CppDumper/Il2CppClass.cs
Normal file
|
@ -0,0 +1,208 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Il2CppDumper
|
||||||
|
{
|
||||||
|
public class Il2CppCodeRegistration
|
||||||
|
{
|
||||||
|
public uint methodPointersCount;
|
||||||
|
public uint pmethodPointers;
|
||||||
|
public uint delegateWrappersFromNativeToManagedCount;
|
||||||
|
public uint delegateWrappersFromNativeToManaged; // note the double indirection to handle different calling conventions
|
||||||
|
public uint delegateWrappersFromManagedToNativeCount;
|
||||||
|
public uint delegateWrappersFromManagedToNative;
|
||||||
|
public uint marshalingFunctionsCount;
|
||||||
|
public uint marshalingFunctions;
|
||||||
|
public uint ccwMarshalingFunctionsCount;
|
||||||
|
public uint ccwMarshalingFunctions;
|
||||||
|
public uint genericMethodPointersCount;
|
||||||
|
public uint genericMethodPointers;
|
||||||
|
public uint invokerPointersCount;
|
||||||
|
public uint invokerPointers;
|
||||||
|
public int customAttributeCount;
|
||||||
|
public uint customAttributeGenerators;
|
||||||
|
public int guidCount;
|
||||||
|
public uint guids; // Il2CppGuid
|
||||||
|
|
||||||
|
public uint[] methodPointers
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Il2CppMetadataRegistration
|
||||||
|
{
|
||||||
|
public int genericClassesCount;
|
||||||
|
public uint genericClasses;
|
||||||
|
public int genericInstsCount;
|
||||||
|
public uint genericInsts;
|
||||||
|
public int genericMethodTableCount;
|
||||||
|
public uint genericMethodTable; // Il2CppGenericMethodFunctionsDefinitions
|
||||||
|
public int typesCount;
|
||||||
|
public uint ptypes;
|
||||||
|
public int methodSpecsCount;
|
||||||
|
public uint methodSpecs;
|
||||||
|
|
||||||
|
public int fieldOffsetsCount;
|
||||||
|
public uint pfieldOffsets;
|
||||||
|
|
||||||
|
public int typeDefinitionsSizesCount;
|
||||||
|
public uint typeDefinitionsSizes;
|
||||||
|
public uint metadataUsagesCount;
|
||||||
|
public uint metadataUsages;
|
||||||
|
|
||||||
|
public int[] fieldOffsets
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Il2CppType[] types
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Il2CppTypeEnum
|
||||||
|
{
|
||||||
|
IL2CPP_TYPE_END = 0x00, /* End of List */
|
||||||
|
IL2CPP_TYPE_VOID = 0x01,
|
||||||
|
IL2CPP_TYPE_BOOLEAN = 0x02,
|
||||||
|
IL2CPP_TYPE_CHAR = 0x03,
|
||||||
|
IL2CPP_TYPE_I1 = 0x04,
|
||||||
|
IL2CPP_TYPE_U1 = 0x05,
|
||||||
|
IL2CPP_TYPE_I2 = 0x06,
|
||||||
|
IL2CPP_TYPE_U2 = 0x07,
|
||||||
|
IL2CPP_TYPE_I4 = 0x08,
|
||||||
|
IL2CPP_TYPE_U4 = 0x09,
|
||||||
|
IL2CPP_TYPE_I8 = 0x0a,
|
||||||
|
IL2CPP_TYPE_U8 = 0x0b,
|
||||||
|
IL2CPP_TYPE_R4 = 0x0c,
|
||||||
|
IL2CPP_TYPE_R8 = 0x0d,
|
||||||
|
IL2CPP_TYPE_STRING = 0x0e,
|
||||||
|
IL2CPP_TYPE_PTR = 0x0f, /* arg: <type> token */
|
||||||
|
IL2CPP_TYPE_BYREF = 0x10, /* arg: <type> token */
|
||||||
|
IL2CPP_TYPE_VALUETYPE = 0x11, /* arg: <type> token */
|
||||||
|
IL2CPP_TYPE_CLASS = 0x12, /* arg: <type> token */
|
||||||
|
IL2CPP_TYPE_VAR = 0x13, /* Generic parameter in a generic type definition, represented as number (compressed unsigned integer) number */
|
||||||
|
IL2CPP_TYPE_ARRAY = 0x14, /* type, rank, boundsCount, bound1, loCount, lo1 */
|
||||||
|
IL2CPP_TYPE_GENERICINST = 0x15, /* <type> <type-arg-count> <type-1> \x{2026} <type-n> */
|
||||||
|
IL2CPP_TYPE_TYPEDBYREF = 0x16,
|
||||||
|
IL2CPP_TYPE_I = 0x18,
|
||||||
|
IL2CPP_TYPE_U = 0x19,
|
||||||
|
IL2CPP_TYPE_FNPTR = 0x1b, /* arg: full method signature */
|
||||||
|
IL2CPP_TYPE_OBJECT = 0x1c,
|
||||||
|
IL2CPP_TYPE_SZARRAY = 0x1d, /* 0-based one-dim-array */
|
||||||
|
IL2CPP_TYPE_MVAR = 0x1e, /* Generic parameter in a generic method definition, represented as number (compressed unsigned integer) */
|
||||||
|
IL2CPP_TYPE_CMOD_REQD = 0x1f, /* arg: typedef or typeref token */
|
||||||
|
IL2CPP_TYPE_CMOD_OPT = 0x20, /* optional arg: typedef or typref token */
|
||||||
|
IL2CPP_TYPE_INTERNAL = 0x21, /* CLR internal type */
|
||||||
|
|
||||||
|
IL2CPP_TYPE_MODIFIER = 0x40, /* Or with the following types */
|
||||||
|
IL2CPP_TYPE_SENTINEL = 0x41, /* Sentinel for varargs method signature */
|
||||||
|
IL2CPP_TYPE_PINNED = 0x45, /* Local var that points to pinned object */
|
||||||
|
|
||||||
|
IL2CPP_TYPE_ENUM = 0x55 /* an enumeration */
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Il2CppType
|
||||||
|
{
|
||||||
|
public uint datapoint;
|
||||||
|
public Anonymous data { get; set; }
|
||||||
|
public uint bits;
|
||||||
|
public uint attrs { get; set; }
|
||||||
|
public Il2CppTypeEnum type { get; set; }
|
||||||
|
public uint num_mods { get; set; }
|
||||||
|
public uint byref { get; set; }
|
||||||
|
public uint pinned { get; set; }
|
||||||
|
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
var str = System.Convert.ToString(bits, 2);
|
||||||
|
if (str.Length != 32)
|
||||||
|
{
|
||||||
|
str = new string(Enumerable.Repeat('0', 32 - str.Length).Concat(str.ToCharArray()).ToArray());
|
||||||
|
}
|
||||||
|
attrs = Convert.ToUInt32(str.Substring(16, 16), 2);
|
||||||
|
type = (Il2CppTypeEnum)Convert.ToInt32(str.Substring(8, 8), 2);
|
||||||
|
num_mods = Convert.ToUInt32(str.Substring(2, 6), 2);
|
||||||
|
byref = Convert.ToUInt32(str.Substring(1, 1), 2);
|
||||||
|
pinned = Convert.ToUInt32(str.Substring(0, 1), 2);
|
||||||
|
data = new Anonymous() { dummy = datapoint };
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Anonymous
|
||||||
|
{
|
||||||
|
public uint dummy;
|
||||||
|
public int klassIndex
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (int)dummy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public uint type
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return dummy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public uint array
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return dummy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public int genericParameterIndex
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (int)dummy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public uint generic_class
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return dummy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Il2CppGenericClass
|
||||||
|
{
|
||||||
|
public int typeDefinitionIndex; /* the generic type definition */
|
||||||
|
public Il2CppGenericContext context; /* a context that contains the type instantiation doesn't contain any method instantiation */
|
||||||
|
public uint cached_class; /* if present, the Il2CppClass corresponding to the instantiation. */
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Il2CppGenericContext
|
||||||
|
{
|
||||||
|
/* The instantiation corresponding to the class generic parameters */
|
||||||
|
public uint class_inst;
|
||||||
|
/* The instantiation corresponding to the method generic parameters */
|
||||||
|
public uint method_inst;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class Il2CppGenericInst
|
||||||
|
{
|
||||||
|
public uint type_argc;
|
||||||
|
public uint type_argv;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Il2CppArrayType
|
||||||
|
{
|
||||||
|
public uint etype;
|
||||||
|
public byte rank;
|
||||||
|
public byte numsizes;
|
||||||
|
public byte numlobounds;
|
||||||
|
public uint sizes;
|
||||||
|
public uint lobounds;
|
||||||
|
}
|
||||||
|
}
|
63
Il2CppDumper/Il2CppDumper.csproj
Normal file
63
Il2CppDumper/Il2CppDumper.csproj
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProjectGuid>{379715D4-4B7B-41F2-B78A-8B18D86320E2}</ProjectGuid>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>Il2CppDumper</RootNamespace>
|
||||||
|
<AssemblyName>Il2CppDumper</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="DefineConstants.cs" />
|
||||||
|
<Compile Include="Elf.cs" />
|
||||||
|
<Compile Include="ElfClass.cs" />
|
||||||
|
<Compile Include="Il2Cpp.cs" />
|
||||||
|
<Compile Include="Il2CppClass.cs" />
|
||||||
|
<Compile Include="Metadata.cs" />
|
||||||
|
<Compile Include="MetadataClass.cs" />
|
||||||
|
<Compile Include="MyBinaryReader.cs" />
|
||||||
|
<Compile Include="Program.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
85
Il2CppDumper/Metadata.cs
Normal file
85
Il2CppDumper/Metadata.cs
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Il2CppDumper
|
||||||
|
{
|
||||||
|
class Metadata : MyBinaryReader
|
||||||
|
{
|
||||||
|
Il2CppGlobalMetadataHeader pMetadataHdr;
|
||||||
|
public int uiImageCount;
|
||||||
|
public int uiNumTypes;
|
||||||
|
public Il2CppImageDefinition[] imageDefs;
|
||||||
|
public Il2CppTypeDefinition[] typeDefs;
|
||||||
|
public Il2CppMethodDefinition[] methodDefs;
|
||||||
|
public Il2CppParameterDefinition[] parameterDefs;
|
||||||
|
public Il2CppFieldDefinition[] fieldDefs;
|
||||||
|
public Il2CppFieldDefaultValue[] fieldDefaultValues;
|
||||||
|
|
||||||
|
public Metadata(Stream stream) : base(stream)
|
||||||
|
{
|
||||||
|
pMetadataHdr = ReadClass<Il2CppGlobalMetadataHeader>();
|
||||||
|
if (pMetadataHdr.sanity != 0xFAB11BAF)
|
||||||
|
{
|
||||||
|
throw new Exception("ERROR: Metadata file supplied is not valid metadata file.");
|
||||||
|
}
|
||||||
|
if (pMetadataHdr.version != 21 && pMetadataHdr.version != 22)
|
||||||
|
{
|
||||||
|
throw new Exception($"ERROR: Metadata file supplied is not a supported version[{pMetadataHdr.version}].");
|
||||||
|
}
|
||||||
|
uiImageCount = pMetadataHdr.imagesCount / MySizeOf(typeof(Il2CppImageDefinition));
|
||||||
|
uiNumTypes = pMetadataHdr.typeDefinitionsCount / MySizeOf(typeof(Il2CppTypeDefinition));
|
||||||
|
imageDefs = ReadClassArray<Il2CppImageDefinition>(pMetadataHdr.imagesOffset, uiImageCount);
|
||||||
|
//GetTypeDefFromIndex
|
||||||
|
typeDefs = ReadClassArray<Il2CppTypeDefinition>(pMetadataHdr.typeDefinitionsOffset, uiNumTypes);
|
||||||
|
//GetMethodDefinition
|
||||||
|
methodDefs = ReadClassArray<Il2CppMethodDefinition>(pMetadataHdr.methodsOffset, pMetadataHdr.methodsCount / MySizeOf(typeof(Il2CppMethodDefinition)));
|
||||||
|
//GetParameterFromIndex
|
||||||
|
parameterDefs = ReadClassArray<Il2CppParameterDefinition>(pMetadataHdr.parametersOffset, pMetadataHdr.parametersCount / MySizeOf(typeof(Il2CppParameterDefinition)));
|
||||||
|
//GetFieldDefFromIndex
|
||||||
|
fieldDefs = ReadClassArray<Il2CppFieldDefinition>(pMetadataHdr.fieldsOffset, pMetadataHdr.fieldsCount / MySizeOf(typeof(Il2CppFieldDefinition)));
|
||||||
|
//GetFieldDefaultFromIndex
|
||||||
|
fieldDefaultValues = ReadClassArray<Il2CppFieldDefaultValue>(pMetadataHdr.fieldDefaultValuesOffset, pMetadataHdr.fieldDefaultValuesCount / MySizeOf(typeof(Il2CppFieldDefaultValue)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Il2CppFieldDefaultValue GetFieldDefaultFromIndex(int idx)
|
||||||
|
{
|
||||||
|
return fieldDefaultValues.FirstOrDefault(x => x.fieldIndex == idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetDefaultValueFromIndex(int idx)
|
||||||
|
{
|
||||||
|
return pMetadataHdr.fieldAndParameterDefaultValueDataOffset + idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetString(int idx)
|
||||||
|
{
|
||||||
|
return ReadStringToNull(pMetadataHdr.stringOffset + idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int MySizeOf(Type type)
|
||||||
|
{
|
||||||
|
int size = 0;
|
||||||
|
foreach (var i in type.GetFields())
|
||||||
|
{
|
||||||
|
if (i.FieldType == typeof(int))
|
||||||
|
{
|
||||||
|
size += 4;
|
||||||
|
}
|
||||||
|
else if (i.FieldType == typeof(uint))
|
||||||
|
{
|
||||||
|
size += 4;
|
||||||
|
}
|
||||||
|
else if (i.FieldType == typeof(short))
|
||||||
|
{
|
||||||
|
size += 2;
|
||||||
|
}
|
||||||
|
else if (i.FieldType == typeof(ushort))
|
||||||
|
{
|
||||||
|
size += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
180
Il2CppDumper/MetadataClass.cs
Normal file
180
Il2CppDumper/MetadataClass.cs
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Il2CppDumper
|
||||||
|
{
|
||||||
|
class Il2CppGlobalMetadataHeader
|
||||||
|
{
|
||||||
|
public uint sanity;
|
||||||
|
public int version;
|
||||||
|
public int stringLiteralOffset; // string data for managed code
|
||||||
|
public int stringLiteralCount;
|
||||||
|
public int stringLiteralDataOffset;
|
||||||
|
public int stringLiteralDataCount;
|
||||||
|
public int stringOffset; // string data for metadata
|
||||||
|
public int stringCount;
|
||||||
|
public int eventsOffset; // Il2CppEventDefinition
|
||||||
|
public int eventsCount;
|
||||||
|
public int propertiesOffset; // Il2CppPropertyDefinition
|
||||||
|
public int propertiesCount;
|
||||||
|
public int methodsOffset; // Il2CppMethodDefinition
|
||||||
|
public int methodsCount;
|
||||||
|
public int parameterDefaultValuesOffset; // Il2CppParameterDefaultValue
|
||||||
|
public int parameterDefaultValuesCount;
|
||||||
|
public int fieldDefaultValuesOffset; // Il2CppFieldDefaultValue
|
||||||
|
public int fieldDefaultValuesCount;
|
||||||
|
public int fieldAndParameterDefaultValueDataOffset; // uint8_t
|
||||||
|
public int fieldAndParameterDefaultValueDataCount;
|
||||||
|
public int fieldMarshaledSizesOffset; // Il2CppFieldMarshaledSize
|
||||||
|
public int fieldMarshaledSizesCount;
|
||||||
|
public int parametersOffset; // Il2CppParameterDefinition
|
||||||
|
public int parametersCount;
|
||||||
|
public int fieldsOffset; // Il2CppFieldDefinition
|
||||||
|
public int fieldsCount;
|
||||||
|
public int genericParametersOffset; // Il2CppGenericParameter
|
||||||
|
public int genericParametersCount;
|
||||||
|
public int genericParameterConstraintsOffset; // TypeIndex
|
||||||
|
public int genericParameterConstraintsCount;
|
||||||
|
public int genericContainersOffset; // Il2CppGenericContainer
|
||||||
|
public int genericContainersCount;
|
||||||
|
public int nestedTypesOffset; // TypeDefinitionIndex
|
||||||
|
public int nestedTypesCount;
|
||||||
|
public int interfacesOffset; // TypeIndex
|
||||||
|
public int interfacesCount;
|
||||||
|
public int vtableMethodsOffset; // EncodedMethodIndex
|
||||||
|
public int vtableMethodsCount;
|
||||||
|
public int interfaceOffsetsOffset; // Il2CppInterfaceOffsetPair
|
||||||
|
public int interfaceOffsetsCount;
|
||||||
|
public int typeDefinitionsOffset; // Il2CppTypeDefinition
|
||||||
|
public int typeDefinitionsCount;
|
||||||
|
public int rgctxEntriesOffset; // Il2CppRGCTXDefinition
|
||||||
|
public int rgctxEntriesCount;
|
||||||
|
public int imagesOffset; // Il2CppImageDefinition
|
||||||
|
public int imagesCount;
|
||||||
|
public int assembliesOffset; // Il2CppAssemblyDefinition
|
||||||
|
public int assembliesCount;
|
||||||
|
public int metadataUsageListsOffset; // Il2CppMetadataUsageList
|
||||||
|
public int metadataUsageListsCount;
|
||||||
|
public int metadataUsagePairsOffset; // Il2CppMetadataUsagePair
|
||||||
|
public int metadataUsagePairsCount;
|
||||||
|
public int fieldRefsOffset; // Il2CppFieldRef
|
||||||
|
public int fieldRefsCount;
|
||||||
|
public int referencedAssembliesOffset; // int
|
||||||
|
public int referencedAssembliesCount;
|
||||||
|
public int attributesInfoOffset; // Il2CppCustomAttributeTypeRange
|
||||||
|
public int attributesInfoCount;
|
||||||
|
public int attributeTypesOffset; // TypeIndex
|
||||||
|
public int attributeTypesCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Il2CppImageDefinition
|
||||||
|
{
|
||||||
|
public int nameIndex;
|
||||||
|
public int assemblyIndex;
|
||||||
|
|
||||||
|
public int typeStart;
|
||||||
|
public uint typeCount;
|
||||||
|
|
||||||
|
public int entryPointIndex;
|
||||||
|
public uint token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Il2CppTypeDefinition
|
||||||
|
{
|
||||||
|
public int nameIndex;
|
||||||
|
public int namespaceIndex;
|
||||||
|
public int customAttributeIndex;
|
||||||
|
public int byvalTypeIndex;
|
||||||
|
public int byrefTypeIndex;
|
||||||
|
|
||||||
|
public int declaringTypeIndex;
|
||||||
|
public int parentIndex;
|
||||||
|
public int elementTypeIndex; // we can probably remove this one. Only used for enums
|
||||||
|
|
||||||
|
public int rgctxStartIndex;
|
||||||
|
public int rgctxCount;
|
||||||
|
|
||||||
|
public int genericContainerIndex;
|
||||||
|
|
||||||
|
public int delegateWrapperFromManagedToNativeIndex;
|
||||||
|
public int marshalingFunctionsIndex;
|
||||||
|
public int ccwFunctionIndex;
|
||||||
|
public int guidIndex;
|
||||||
|
|
||||||
|
public uint flags;
|
||||||
|
|
||||||
|
public int fieldStart;
|
||||||
|
public int methodStart;
|
||||||
|
public int eventStart;
|
||||||
|
public int propertyStart;
|
||||||
|
public int nestedTypesStart;
|
||||||
|
public int interfacesStart;
|
||||||
|
public int vtableStart;
|
||||||
|
public int interfaceOffsetsStart;
|
||||||
|
|
||||||
|
public ushort method_count;
|
||||||
|
public ushort property_count;
|
||||||
|
public ushort field_count;
|
||||||
|
public ushort event_count;
|
||||||
|
public ushort nested_type_count;
|
||||||
|
public ushort vtable_count;
|
||||||
|
public ushort interfaces_count;
|
||||||
|
public ushort interface_offsets_count;
|
||||||
|
|
||||||
|
// bitfield to portably encode boolean values as single bits
|
||||||
|
// 01 - valuetype;
|
||||||
|
// 02 - enumtype;
|
||||||
|
// 03 - has_finalize;
|
||||||
|
// 04 - has_cctor;
|
||||||
|
// 05 - is_blittable;
|
||||||
|
// 06 - is_import;
|
||||||
|
// 07-10 - One of nine possible PackingSize values (0, 1, 2, 4, 8, 16, 32, 64, or 128)
|
||||||
|
public uint bitfield;
|
||||||
|
public uint token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Il2CppMethodDefinition
|
||||||
|
{
|
||||||
|
public int nameIndex;
|
||||||
|
public int declaringType;
|
||||||
|
public int returnType;
|
||||||
|
public int parameterStart;
|
||||||
|
public int customAttributeIndex;
|
||||||
|
public int genericContainerIndex;
|
||||||
|
public int methodIndex;
|
||||||
|
public int invokerIndex;
|
||||||
|
public int delegateWrapperIndex;
|
||||||
|
public int rgctxStartIndex;
|
||||||
|
public int rgctxCount;
|
||||||
|
public uint token;
|
||||||
|
public ushort flags;
|
||||||
|
public ushort iflags;
|
||||||
|
public ushort slot;
|
||||||
|
public ushort parameterCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Il2CppParameterDefinition
|
||||||
|
{
|
||||||
|
public int nameIndex;
|
||||||
|
public uint token;
|
||||||
|
public int customAttributeIndex;
|
||||||
|
public int typeIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Il2CppFieldDefinition
|
||||||
|
{
|
||||||
|
public int nameIndex;
|
||||||
|
public int typeIndex;
|
||||||
|
public int customAttributeIndex;
|
||||||
|
public uint token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Il2CppFieldDefaultValue
|
||||||
|
{
|
||||||
|
public int fieldIndex;
|
||||||
|
public int typeIndex;
|
||||||
|
public int dataIndex;
|
||||||
|
}
|
||||||
|
}
|
139
Il2CppDumper/MyBinaryReader.cs
Normal file
139
Il2CppDumper/MyBinaryReader.cs
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace Il2CppDumper
|
||||||
|
{
|
||||||
|
class MyBinaryReader : BinaryReader
|
||||||
|
{
|
||||||
|
public MyBinaryReader(Stream stream) : base(stream) { }
|
||||||
|
|
||||||
|
public long Position
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return BaseStream.Position;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
BaseStream.Position = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public T ReadClass<T>(long addr) where T : new()
|
||||||
|
{
|
||||||
|
BaseStream.Position = addr;
|
||||||
|
return ReadClass<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T ReadClass<T>() where T : new()
|
||||||
|
{
|
||||||
|
var type = typeof(T);
|
||||||
|
if (type.IsPrimitive)
|
||||||
|
{
|
||||||
|
if (type == typeof(int))
|
||||||
|
{
|
||||||
|
return (T)(object)ReadInt32();
|
||||||
|
}
|
||||||
|
else if (type == typeof(uint))
|
||||||
|
{
|
||||||
|
return (T)(object)ReadUInt32();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return default(T);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
T t = new T();
|
||||||
|
foreach (var i in t.GetType().GetFields())
|
||||||
|
{
|
||||||
|
if (i.FieldType == typeof(int))
|
||||||
|
{
|
||||||
|
i.SetValue(t, ReadInt32());
|
||||||
|
}
|
||||||
|
else if (i.FieldType == typeof(uint))
|
||||||
|
{
|
||||||
|
i.SetValue(t, ReadUInt32());
|
||||||
|
}
|
||||||
|
else if (i.FieldType == typeof(short))
|
||||||
|
{
|
||||||
|
i.SetValue(t, ReadInt16());
|
||||||
|
}
|
||||||
|
else if (i.FieldType == typeof(ushort))
|
||||||
|
{
|
||||||
|
i.SetValue(t, ReadUInt16());
|
||||||
|
}
|
||||||
|
else if (i.FieldType == typeof(byte))
|
||||||
|
{
|
||||||
|
i.SetValue(t, ReadByte());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var mi = GetType().GetMethod("ReadClass", Type.EmptyTypes);
|
||||||
|
var mi2 = mi.MakeGenericMethod(i.FieldType);
|
||||||
|
var o = mi2.Invoke(this, null);
|
||||||
|
i.SetValue(t, o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public T[] ReadClassArray<T>(long addr, int count) where T : new()
|
||||||
|
{
|
||||||
|
BaseStream.Position = addr;
|
||||||
|
var type = typeof(T);
|
||||||
|
if (type.IsPrimitive)
|
||||||
|
{
|
||||||
|
if (type == typeof(int))
|
||||||
|
{
|
||||||
|
int[] t = new int[count];
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
t[i] = ReadInt32();
|
||||||
|
}
|
||||||
|
return t as T[];
|
||||||
|
}
|
||||||
|
else if (type == typeof(uint))
|
||||||
|
{
|
||||||
|
uint[] t = new uint[count];
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
t[i] = ReadUInt32();
|
||||||
|
}
|
||||||
|
return t as T[];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
T[] t = new T[count];
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
t[i] = ReadClass<T>();
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ReadStringToNull(long addr)
|
||||||
|
{
|
||||||
|
BaseStream.Position = addr;
|
||||||
|
string result = "";
|
||||||
|
char c;
|
||||||
|
for (int i = 0; i < base.BaseStream.Length; i++)
|
||||||
|
{
|
||||||
|
if ((c = (char)base.ReadByte()) == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
result += c.ToString();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
279
Il2CppDumper/Program.cs
Normal file
279
Il2CppDumper/Program.cs
Normal file
|
@ -0,0 +1,279 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Il2CppDumper
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static Metadata metadata;
|
||||||
|
static Il2Cpp il2cpp;
|
||||||
|
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Select Mode: 1. Manual 2.Auto");
|
||||||
|
var key = Console.ReadKey(true);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (key.KeyChar == '2')
|
||||||
|
{
|
||||||
|
metadata = new Metadata(new MemoryStream(File.ReadAllBytes("global-metadata.dat")));
|
||||||
|
il2cpp = new Il2Cpp(new MemoryStream(File.ReadAllBytes("libil2cpp.so")));
|
||||||
|
}
|
||||||
|
else if (key.KeyChar == '1')
|
||||||
|
{
|
||||||
|
Console.Write("Input CodeRegistration(R0): ");
|
||||||
|
var codeRegistration = Convert.ToUInt32(Console.ReadLine(), 16);
|
||||||
|
Console.Write("Input MetadataRegistration(R1): ");
|
||||||
|
var metadataRegistration = Convert.ToUInt32(Console.ReadLine(), 16);
|
||||||
|
metadata = new Metadata(new MemoryStream(File.ReadAllBytes("global-metadata.dat")));
|
||||||
|
il2cpp = new Il2Cpp(new MemoryStream(File.ReadAllBytes("libil2cpp.so")), codeRegistration, metadataRegistration);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var writer = new StreamWriter(new FileStream("dump.cs", FileMode.Create));
|
||||||
|
Console.WriteLine("Dumping...");
|
||||||
|
//dump_image();
|
||||||
|
for (int imageIndex = 0; imageIndex < metadata.uiImageCount; imageIndex++)
|
||||||
|
{
|
||||||
|
var imageDef = metadata.imageDefs[imageIndex];
|
||||||
|
writer.Write($"// Image {imageIndex}: {metadata.GetString(imageDef.nameIndex)} - {imageDef.typeStart}\n");
|
||||||
|
}
|
||||||
|
for (int idx = 0; idx < metadata.uiNumTypes; ++idx)
|
||||||
|
{
|
||||||
|
//dump_class(i);
|
||||||
|
var typeDef = metadata.typeDefs[idx];
|
||||||
|
writer.Write($"// Namespace: {metadata.GetString(typeDef.namespaceIndex)}\n");
|
||||||
|
if ((typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_SERIALIZABLE) != 0)
|
||||||
|
writer.Write("[Serializable]\n");
|
||||||
|
if ((typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_VISIBILITY_MASK) == DefineConstants.TYPE_ATTRIBUTE_PUBLIC)
|
||||||
|
writer.Write("public ");
|
||||||
|
if ((typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_ABSTRACT) != 0)
|
||||||
|
writer.Write("abstract ");
|
||||||
|
if ((typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_SEALED) != 0)
|
||||||
|
writer.Write("sealed ");
|
||||||
|
if ((typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_INTERFACE) != 0)
|
||||||
|
writer.Write("interface ");
|
||||||
|
else
|
||||||
|
writer.Write("class ");
|
||||||
|
writer.Write($"{metadata.GetString(typeDef.nameIndex)} // TypeDefIndex: {idx}\n{{\n");
|
||||||
|
writer.Write("\t// Fields\n");
|
||||||
|
var fieldEnd = typeDef.fieldStart + typeDef.field_count;
|
||||||
|
for (int i = typeDef.fieldStart; i < fieldEnd; ++i)
|
||||||
|
{
|
||||||
|
//dump_field(i, idx, i - typeDef.fieldStart);
|
||||||
|
var pField = metadata.fieldDefs[i];
|
||||||
|
var pType = il2cpp.GetTypeFromTypeIndex(pField.typeIndex);
|
||||||
|
var pDefault = metadata.GetFieldDefaultFromIndex(i);
|
||||||
|
writer.Write("\t");
|
||||||
|
if ((pType.attrs & DefineConstants.FIELD_ATTRIBUTE_PRIVATE) == DefineConstants.FIELD_ATTRIBUTE_PRIVATE)
|
||||||
|
writer.Write("private ");
|
||||||
|
if ((pType.attrs & DefineConstants.FIELD_ATTRIBUTE_PUBLIC) == DefineConstants.FIELD_ATTRIBUTE_PUBLIC)
|
||||||
|
writer.Write("public ");
|
||||||
|
if ((pType.attrs & DefineConstants.FIELD_ATTRIBUTE_STATIC) != 0)
|
||||||
|
writer.Write("static ");
|
||||||
|
if ((pType.attrs & DefineConstants.FIELD_ATTRIBUTE_INIT_ONLY) != 0)
|
||||||
|
writer.Write("readonly ");
|
||||||
|
writer.Write($"{get_type_name(pType)} {metadata.GetString(pField.nameIndex)}");
|
||||||
|
if (pDefault != null && pDefault.dataIndex != -1)
|
||||||
|
{
|
||||||
|
var pointer = metadata.GetDefaultValueFromIndex(pDefault.dataIndex);
|
||||||
|
Il2CppType pTypeToUse = il2cpp.GetTypeFromTypeIndex(pDefault.typeIndex);
|
||||||
|
if (pointer > 0)
|
||||||
|
{
|
||||||
|
metadata.Position = pointer;
|
||||||
|
object multi = null;
|
||||||
|
switch (pTypeToUse.type)
|
||||||
|
{
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN:
|
||||||
|
multi = metadata.ReadBoolean();
|
||||||
|
break;
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_U1:
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_I1:
|
||||||
|
multi = metadata.ReadByte();
|
||||||
|
break;
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_CHAR:
|
||||||
|
multi = metadata.ReadChar();
|
||||||
|
break;
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_U2:
|
||||||
|
multi = metadata.ReadUInt16();
|
||||||
|
break;
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_I2:
|
||||||
|
multi = metadata.ReadInt16();
|
||||||
|
break;
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_U4:
|
||||||
|
multi = metadata.ReadUInt32();
|
||||||
|
break;
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_I4:
|
||||||
|
multi = metadata.ReadInt32();
|
||||||
|
break;
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_U8:
|
||||||
|
multi = metadata.ReadUInt64();
|
||||||
|
break;
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_I8:
|
||||||
|
multi = metadata.ReadInt64();
|
||||||
|
break;
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_R4:
|
||||||
|
multi = metadata.ReadSingle();
|
||||||
|
break;
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_R8:
|
||||||
|
multi = metadata.ReadDouble();
|
||||||
|
break;
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_STRING:
|
||||||
|
var uiLen = metadata.ReadInt32();
|
||||||
|
multi = Encoding.UTF8.GetString(metadata.ReadBytes(uiLen));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (multi is string)
|
||||||
|
writer.Write($" = \"{multi}\"");
|
||||||
|
else if (multi != null)
|
||||||
|
writer.Write($" = {multi}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writer.Write("; // 0x{0:x}\n", il2cpp.GetFieldOffsetFromIndex(idx, i - typeDef.fieldStart));
|
||||||
|
}
|
||||||
|
writer.Write("\t// Methods\n");
|
||||||
|
var methodEnd = typeDef.methodStart + typeDef.method_count;
|
||||||
|
for (int i = typeDef.methodStart; i < methodEnd; ++i)
|
||||||
|
{
|
||||||
|
//dump_method(i);
|
||||||
|
var methodDef = metadata.methodDefs[i];
|
||||||
|
writer.Write("\t");
|
||||||
|
Il2CppType pReturnType = il2cpp.GetTypeFromTypeIndex(methodDef.returnType);
|
||||||
|
if ((methodDef.flags & DefineConstants.METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == DefineConstants.METHOD_ATTRIBUTE_PRIVATE)
|
||||||
|
writer.Write("private ");
|
||||||
|
if ((methodDef.flags & DefineConstants.METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == DefineConstants.METHOD_ATTRIBUTE_PUBLIC)
|
||||||
|
writer.Write("public ");
|
||||||
|
if ((methodDef.flags & DefineConstants.METHOD_ATTRIBUTE_VIRTUAL) != 0)
|
||||||
|
writer.Write("virtual ");
|
||||||
|
if ((methodDef.flags & DefineConstants.METHOD_ATTRIBUTE_STATIC) != 0)
|
||||||
|
writer.Write("static ");
|
||||||
|
|
||||||
|
writer.Write($"{get_type_name(pReturnType)} {metadata.GetString(methodDef.nameIndex)}(");
|
||||||
|
for (int j = 0; j < methodDef.parameterCount; ++j)
|
||||||
|
{
|
||||||
|
Il2CppParameterDefinition pParam = metadata.parameterDefs[methodDef.parameterStart + j];
|
||||||
|
string szParamName = metadata.GetString(pParam.nameIndex);
|
||||||
|
Il2CppType pType = il2cpp.GetTypeFromTypeIndex(pParam.typeIndex);
|
||||||
|
string szTypeName = get_type_name(pType);
|
||||||
|
if ((pType.attrs & DefineConstants.PARAM_ATTRIBUTE_OPTIONAL) != 0)
|
||||||
|
writer.Write("optional ");
|
||||||
|
if ((pType.attrs & DefineConstants.PARAM_ATTRIBUTE_OUT) != 0)
|
||||||
|
writer.Write("out ");
|
||||||
|
if (j != methodDef.parameterCount - 1)
|
||||||
|
{
|
||||||
|
writer.Write($"{szTypeName} {szParamName}, ");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writer.Write($"{szTypeName} {szParamName}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (methodDef.methodIndex >= 0)
|
||||||
|
writer.Write("); // {0:x} - {1}\n", il2cpp.pCodeRegistration.methodPointers[methodDef.methodIndex], methodDef.methodIndex);
|
||||||
|
else
|
||||||
|
writer.Write("); // 0 - -1\n");
|
||||||
|
}
|
||||||
|
writer.Write("}\n");
|
||||||
|
}
|
||||||
|
writer.Close();
|
||||||
|
Console.WriteLine("Done !");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e.Message);
|
||||||
|
}
|
||||||
|
Console.WriteLine("Press any key to exit...");
|
||||||
|
Console.ReadKey(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string get_type_name(Il2CppType pType)
|
||||||
|
{
|
||||||
|
string ret;
|
||||||
|
if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_CLASS || pType.type == Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE)
|
||||||
|
{
|
||||||
|
Il2CppTypeDefinition klass = metadata.typeDefs[pType.data.klassIndex];
|
||||||
|
ret = metadata.GetString(klass.nameIndex);
|
||||||
|
}
|
||||||
|
else if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST)
|
||||||
|
{
|
||||||
|
Il2CppGenericClass generic_class = il2cpp.MapVATR<Il2CppGenericClass>(pType.data.generic_class);
|
||||||
|
Il2CppTypeDefinition pMainDef = metadata.typeDefs[generic_class.typeDefinitionIndex];
|
||||||
|
ret = metadata.GetString(pMainDef.nameIndex);
|
||||||
|
var typeNames = new List<string>();
|
||||||
|
Il2CppGenericInst pInst = il2cpp.MapVATR<Il2CppGenericInst>(generic_class.context.class_inst);
|
||||||
|
var pointers = il2cpp.MapVATR<uint>(pInst.type_argv, (int)pInst.type_argc);
|
||||||
|
for (int i = 0; i < pInst.type_argc; ++i)
|
||||||
|
{
|
||||||
|
var pOriType = il2cpp.MapVATR<Il2CppType>(pointers[i]);
|
||||||
|
pOriType.Init();
|
||||||
|
typeNames.Add(get_type_name(pOriType));
|
||||||
|
}
|
||||||
|
ret += $"<{string.Join(", ", typeNames)}>";
|
||||||
|
}
|
||||||
|
else if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_ARRAY)
|
||||||
|
{
|
||||||
|
Il2CppArrayType arrayType = il2cpp.MapVATR<Il2CppArrayType>(pType.data.array);
|
||||||
|
var type = il2cpp.MapVATR<Il2CppType>(arrayType.etype);
|
||||||
|
type.Init();
|
||||||
|
ret = $"{get_type_name(type)}[]";
|
||||||
|
}
|
||||||
|
else if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY)
|
||||||
|
{
|
||||||
|
var type = il2cpp.MapVATR<Il2CppType>(pType.data.type);
|
||||||
|
type.Init();
|
||||||
|
ret = $"{get_type_name(type)}[]";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((int)pType.type >= szTypeString.Length)
|
||||||
|
ret = "unknow";
|
||||||
|
else
|
||||||
|
ret = szTypeString[(int)pType.type];
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static string[] szTypeString =
|
||||||
|
{
|
||||||
|
"END",
|
||||||
|
"void",
|
||||||
|
"bool",
|
||||||
|
"char",
|
||||||
|
"sbyte",
|
||||||
|
"byte",
|
||||||
|
"short",
|
||||||
|
"ushort",
|
||||||
|
"int",
|
||||||
|
"uint",
|
||||||
|
"long",
|
||||||
|
"ulong",
|
||||||
|
"float",
|
||||||
|
"double",
|
||||||
|
"string",
|
||||||
|
"PTR",//eg. void*
|
||||||
|
"BYREF",
|
||||||
|
"VALUETYPE",
|
||||||
|
"CLASS",
|
||||||
|
"T",
|
||||||
|
"ARRAY",
|
||||||
|
"GENERICINST",
|
||||||
|
"TYPEDBYREF",
|
||||||
|
"None",
|
||||||
|
"IntPtr",
|
||||||
|
"UIntPtr",
|
||||||
|
"None",
|
||||||
|
"FNPTR",
|
||||||
|
"object",
|
||||||
|
"SZARRAY",
|
||||||
|
"T",
|
||||||
|
"CMOD_REQD",
|
||||||
|
"CMOD_OPT",
|
||||||
|
"INTERNAL",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
36
Il2CppDumper/Properties/AssemblyInfo.cs
Normal file
36
Il2CppDumper/Properties/AssemblyInfo.cs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// 有关程序集的一般信息由以下
|
||||||
|
// 控制。更改这些特性值可修改
|
||||||
|
// 与程序集关联的信息。
|
||||||
|
[assembly: AssemblyTitle("Il2CppDumper")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("Il2CppDumper")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2016")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
//将 ComVisible 设置为 false 将使此程序集中的类型
|
||||||
|
//对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
|
||||||
|
//请将此类型的 ComVisible 特性设置为 true。
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
||||||
|
[assembly: Guid("379715d4-4b7b-41f2-b78a-8b18d86320e2")]
|
||||||
|
|
||||||
|
// 程序集的版本信息由下列四个值组成:
|
||||||
|
//
|
||||||
|
// 主版本
|
||||||
|
// 次版本
|
||||||
|
// 生成号
|
||||||
|
// 修订号
|
||||||
|
//
|
||||||
|
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
|
||||||
|
// 方法是按如下所示使用“*”: :
|
||||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
Loading…
Reference in a new issue