Showing preview only (475K chars total). Download the full file or copy to clipboard to get everything.
Repository: Perfare/Il2CppDumper
Branch: master
Commit: 4741d46ba9cd
Files: 74
Total size: 450.9 KB
Directory structure:
gitextract_h0jok5q9/
├── .gitattributes
├── .github/
│ └── ISSUE_TEMPLATE/
│ ├── config.yml
│ ├── problem_report.md
│ └── problem_report_cn.md
├── .gitignore
├── Il2CppDumper/
│ ├── Attributes/
│ │ ├── ArrayLengthAttribute.cs
│ │ └── VersionAttribute.cs
│ ├── Config.cs
│ ├── ExecutableFormats/
│ │ ├── Elf.cs
│ │ ├── Elf64.cs
│ │ ├── ElfBase.cs
│ │ ├── ElfClass.cs
│ │ ├── Macho.cs
│ │ ├── Macho64.cs
│ │ ├── MachoClass.cs
│ │ ├── MachoFat.cs
│ │ ├── NSO.cs
│ │ ├── NSOClass.cs
│ │ ├── PE.cs
│ │ ├── PEClass.cs
│ │ ├── WebAssembly.cs
│ │ ├── WebAssemblyClass.cs
│ │ └── WebAssemblyMemory.cs
│ ├── Extensions/
│ │ ├── BinaryReaderExtensions.cs
│ │ ├── BoyerMooreHorspool.cs
│ │ ├── HexExtensions.cs
│ │ └── StringExtensions.cs
│ ├── IO/
│ │ ├── BinaryStream.cs
│ │ └── Lz4DecoderStream.cs
│ ├── Il2Cpp/
│ │ ├── Il2Cpp.cs
│ │ ├── Il2CppClass.cs
│ │ ├── Metadata.cs
│ │ └── MetadataClass.cs
│ ├── Il2CppBinaryNinja/
│ │ ├── __init__.py
│ │ └── plugin.json
│ ├── Il2CppDumper.csproj
│ ├── Outputs/
│ │ ├── DummyAssemblyExporter.cs
│ │ ├── HeaderConstants.cs
│ │ ├── Il2CppConstants.cs
│ │ ├── Il2CppDecompiler.cs
│ │ ├── ScriptJson.cs
│ │ ├── StructGenerator.cs
│ │ └── StructInfo.cs
│ ├── Program.cs
│ ├── Resource1.Designer.cs
│ ├── Resource1.resx
│ ├── Utils/
│ │ ├── ArmUtils.cs
│ │ ├── AttributeArgument.cs
│ │ ├── BlobValue.cs
│ │ ├── CustomAttributeDataReader.cs
│ │ ├── CustomAttributeReaderVisitor.cs
│ │ ├── DummyAssemblyGenerator.cs
│ │ ├── FileDialogNative.cs
│ │ ├── Il2CppExecutor.cs
│ │ ├── MyAssemblyResolver.cs
│ │ ├── OpenFileDialog.cs
│ │ ├── PELoader.cs
│ │ ├── SearchSection.cs
│ │ └── SectionHelper.cs
│ ├── config.json
│ ├── ghidra.py
│ ├── ghidra_wasm.py
│ ├── ghidra_with_struct.py
│ ├── hopper-py3.py
│ ├── ida.py
│ ├── ida_py3.py
│ ├── ida_with_struct.py
│ ├── ida_with_struct_py3.py
│ ├── il2cpp_header_to_binja.py
│ └── il2cpp_header_to_ghidra.py
├── Il2CppDumper.sln
├── LICENSE
├── README.md
└── README.zh-CN.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
###############################################################################
# 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
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
================================================
FILE: .github/ISSUE_TEMPLATE/problem_report.md
================================================
---
name: Problem report
about: Problem report
title: ''
labels: ''
assignees: ''
---
Note: if you do not provide all of the following information I will directly ignore and close this issue
- Il2CppDumper version
- Target Unity version (optional)
- Describe the issue
- Upload executable file and global-metadata.dat
================================================
FILE: .github/ISSUE_TEMPLATE/problem_report_cn.md
================================================
---
name: 问题报告
about: 中文问题报告
title: ''
labels: ''
assignees: ''
---
请注意:如果你没有提供以下所有信息我将会直接无视并关闭这个issue
- Il2CppDumper版本
- 目标Unity版本 (可以不填)
- 问题描述
- 上传可执行文件和global-metadata.dat
================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Oo]ut/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# 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
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# 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/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# 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
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
================================================
FILE: Il2CppDumper/Attributes/ArrayLengthAttribute.cs
================================================
using System;
namespace Il2CppDumper
{
[AttributeUsage(AttributeTargets.Field)]
class ArrayLengthAttribute : Attribute
{
public int Length { get; set; }
}
}
================================================
FILE: Il2CppDumper/Attributes/VersionAttribute.cs
================================================
using System;
namespace Il2CppDumper
{
[AttributeUsage(AttributeTargets.Field, AllowMultiple = true)]
class VersionAttribute : Attribute
{
public double Min { get; set; } = 0;
public double Max { get; set; } = 99;
}
}
================================================
FILE: Il2CppDumper/Config.cs
================================================
namespace Il2CppDumper
{
public class Config
{
public bool DumpMethod { get; set; } = true;
public bool DumpField { get; set; } = true;
public bool DumpProperty { get; set; } = false;
public bool DumpAttribute { get; set; } = false;
public bool DumpFieldOffset { get; set; } = true;
public bool DumpMethodOffset { get; set; } = true;
public bool DumpTypeDefIndex { get; set; } = true;
public bool GenerateDummyDll { get; set; } = true;
public bool GenerateStruct { get; set; } = true;
public bool DummyDllAddToken { get; set; } = true;
public bool RequireAnyKey { get; set; } = true;
public bool ForceIl2CppVersion { get; set; } = false;
public double ForceVersion { get; set; } = 24.3;
public bool ForceDump { get; set; } = false;
public bool NoRedirectedPointer { get; set; } = false;
}
}
================================================
FILE: Il2CppDumper/ExecutableFormats/Elf.cs
================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using static Il2CppDumper.ElfConstants;
namespace Il2CppDumper
{
public sealed class Elf : ElfBase
{
private Elf32_Ehdr elfHeader;
private Elf32_Phdr[] programSegment;
private Elf32_Dyn[] dynamicSection;
private Elf32_Sym[] symbolTable;
private Elf32_Shdr[] sectionTable;
private Elf32_Phdr pt_dynamic;
/*
* LDR R1, [X]
* ADD R0, X, X
* ADD R2, X, X
*/
private static readonly string ARMFeatureBytes = "? 0x10 ? 0xE7 ? 0x00 ? 0xE0 ? 0x20 ? 0xE0";
private static readonly string X86FeatureBytes = "? 0x10 ? 0xE7 ? 0x00 ? 0xE0 ? 0x20 ? 0xE0"; //TODO
public Elf(Stream stream) : base(stream)
{
Is32Bit = true;
Load();
}
protected override void Load()
{
elfHeader = ReadClass<Elf32_Ehdr>(0);
programSegment = ReadClassArray<Elf32_Phdr>(elfHeader.e_phoff, elfHeader.e_phnum);
if (IsDumped)
{
FixedProgramSegment();
}
pt_dynamic = programSegment.First(x => x.p_type == PT_DYNAMIC);
dynamicSection = ReadClassArray<Elf32_Dyn>(pt_dynamic.p_offset, pt_dynamic.p_filesz / 8u);
if (IsDumped)
{
FixedDynamicSection();
}
ReadSymbol();
if (!IsDumped)
{
RelocationProcessing();
if (CheckProtection())
{
Console.WriteLine("ERROR: This file may be protected.");
}
}
}
protected override bool CheckSection()
{
try
{
var names = new List<string>();
sectionTable = ReadClassArray<Elf32_Shdr>(elfHeader.e_shoff, elfHeader.e_shnum);
var shstrndx = sectionTable[elfHeader.e_shstrndx].sh_offset;
foreach (var section in sectionTable)
{
names.Add(ReadStringToNull(shstrndx + section.sh_name));
}
if (!names.Contains(".text"))
{
return false;
}
return true;
}
catch
{
return false;
}
}
public override ulong MapVATR(ulong addr)
{
var phdr = programSegment.First(x => addr >= x.p_vaddr && addr <= x.p_vaddr + x.p_memsz);
return addr - phdr.p_vaddr + phdr.p_offset;
}
public override ulong MapRTVA(ulong addr)
{
var phdr = programSegment.FirstOrDefault(x => addr >= x.p_offset && addr <= x.p_offset + x.p_filesz);
if (phdr == null)
{
return 0;
}
return addr - phdr.p_offset + phdr.p_vaddr;
}
public override bool Search()
{
var _GLOBAL_OFFSET_TABLE_ = dynamicSection.First(x => x.d_tag == DT_PLTGOT).d_un;
var execs = programSegment.Where(x => x.p_type == PT_LOAD && (x.p_flags & PF_X) == 1).ToArray();
var resultList = new List<int>();
var featureBytes = elfHeader.e_machine == EM_ARM ? ARMFeatureBytes : X86FeatureBytes;
foreach (var exec in execs)
{
Position = exec.p_offset;
var buff = ReadBytes((int)exec.p_filesz);
foreach (var temp in buff.Search(featureBytes))
{
var bin = buff[temp + 2].HexToBin();
if (bin[3] == '1') //LDR
{
resultList.Add(temp);
}
}
}
if (resultList.Count == 1)
{
uint codeRegistration = 0;
uint metadataRegistration = 0;
var result = (uint)resultList[0];
if (Version < 24)
{
if (elfHeader.e_machine == EM_ARM)
{
Position = result + 0x14;
codeRegistration = ReadUInt32() + _GLOBAL_OFFSET_TABLE_;
Position = result + 0x18;
var ptr = ReadUInt32() + _GLOBAL_OFFSET_TABLE_;
Position = MapVATR(ptr);
metadataRegistration = ReadUInt32();
}
}
else if (Version >= 24)
{
if (elfHeader.e_machine == EM_ARM)
{
Position = result + 0x14;
codeRegistration = ReadUInt32() + result + 0xcu + (uint)ImageBase;
Position = result + 0x10;
var ptr = ReadUInt32() + result + 0x8;
Position = MapVATR(ptr + ImageBase);
metadataRegistration = ReadUInt32();
}
}
Console.WriteLine("CodeRegistration : {0:x}", codeRegistration);
Console.WriteLine("MetadataRegistration : {0:x}", metadataRegistration);
Init(codeRegistration, metadataRegistration);
return true;
}
return false;
}
public override bool PlusSearch(int methodCount, int typeDefinitionsCount, int imageCount)
{
var sectionHelper = GetSectionHelper(methodCount, typeDefinitionsCount, imageCount);
var codeRegistration = sectionHelper.FindCodeRegistration();
var metadataRegistration = sectionHelper.FindMetadataRegistration();
return AutoPlusInit(codeRegistration, metadataRegistration);
}
public override bool SymbolSearch()
{
uint codeRegistration = 0;
uint metadataRegistration = 0;
var dynstrOffset = MapVATR(dynamicSection.First(x => x.d_tag == DT_STRTAB).d_un);
foreach (var symbol in symbolTable)
{
var name = ReadStringToNull(dynstrOffset + symbol.st_name);
switch (name)
{
case "g_CodeRegistration":
codeRegistration = symbol.st_value;
break;
case "g_MetadataRegistration":
metadataRegistration = symbol.st_value;
break;
}
}
if (codeRegistration > 0 && metadataRegistration > 0)
{
Console.WriteLine("Detected Symbol !");
Console.WriteLine("CodeRegistration : {0:x}", codeRegistration);
Console.WriteLine("MetadataRegistration : {0:x}", metadataRegistration);
Init(codeRegistration, metadataRegistration);
return true;
}
Console.WriteLine("ERROR: No symbol is detected");
return false;
}
private void ReadSymbol()
{
try
{
var symbolCount = 0u;
var hash = dynamicSection.FirstOrDefault(x => x.d_tag == DT_HASH);
if (hash != null)
{
var addr = MapVATR(hash.d_un);
Position = addr;
var nbucket = ReadUInt32();
var nchain = ReadUInt32();
symbolCount = nchain;
}
else
{
hash = dynamicSection.First(x => x.d_tag == DT_GNU_HASH);
var addr = MapVATR(hash.d_un);
Position = addr;
var nbuckets = ReadUInt32();
var symoffset = ReadUInt32();
var bloom_size = ReadUInt32();
var bloom_shift = ReadUInt32();
var buckets_address = addr + 16 + (4 * bloom_size);
var buckets = ReadClassArray<uint>(buckets_address, nbuckets);
var last_symbol = buckets.Max();
if (last_symbol < symoffset)
{
symbolCount = symoffset;
}
else
{
var chains_base_address = buckets_address + 4 * nbuckets;
Position = chains_base_address + (last_symbol - symoffset) * 4;
while (true)
{
var chain_entry = ReadUInt32();
++last_symbol;
if ((chain_entry & 1) != 0)
break;
}
symbolCount = last_symbol;
}
}
var dynsymOffset = MapVATR(dynamicSection.First(x => x.d_tag == DT_SYMTAB).d_un);
symbolTable = ReadClassArray<Elf32_Sym>(dynsymOffset, symbolCount);
}
catch
{
// ignored
}
}
private void RelocationProcessing()
{
Console.WriteLine("Applying relocations...");
try
{
var reldynOffset = MapVATR(dynamicSection.First(x => x.d_tag == DT_REL).d_un);
var reldynSize = dynamicSection.First(x => x.d_tag == DT_RELSZ).d_un;
var relTable = ReadClassArray<Elf32_Rel>(reldynOffset, reldynSize / 8);
var isx86 = elfHeader.e_machine == 0x3;
foreach (var rel in relTable)
{
var type = rel.r_info & 0xff;
var sym = rel.r_info >> 8;
switch (type)
{
case R_386_32 when isx86:
case R_ARM_ABS32 when !isx86:
{
var symbol = symbolTable[sym];
Position = MapVATR(rel.r_offset);
Write(symbol.st_value);
break;
}
}
}
}
catch
{
// ignored
}
}
private bool CheckProtection()
{
try
{
//.init_proc
if (dynamicSection.Any(x => x.d_tag == DT_INIT))
{
Console.WriteLine("WARNING: find .init_proc");
return true;
}
//JNI_OnLoad
var dynstrOffset = MapVATR(dynamicSection.First(x => x.d_tag == DT_STRTAB).d_un);
foreach (var symbol in symbolTable)
{
var name = ReadStringToNull(dynstrOffset + symbol.st_name);
switch (name)
{
case "JNI_OnLoad":
Console.WriteLine("WARNING: find JNI_OnLoad");
return true;
}
}
if (sectionTable != null && sectionTable.Any(x => x.sh_type == SHT_LOUSER))
{
Console.WriteLine("WARNING: find SHT_LOUSER section");
return true;
}
}
catch
{
// ignored
}
return false;
}
public override ulong GetRVA(ulong pointer)
{
if (IsDumped)
{
return pointer - ImageBase;
}
return pointer;
}
private void FixedProgramSegment()
{
for (uint i = 0; i < programSegment.Length; i++)
{
Position = elfHeader.e_phoff + i * 32u + 4u;
var phdr = programSegment[i];
phdr.p_offset = phdr.p_vaddr;
Write(phdr.p_offset);
phdr.p_vaddr += (uint)ImageBase;
Write(phdr.p_vaddr);
Position += 4;
phdr.p_filesz = phdr.p_memsz;
Write(phdr.p_filesz);
}
}
private void FixedDynamicSection()
{
for (uint i = 0; i < dynamicSection.Length; i++)
{
Position = pt_dynamic.p_offset + i * 8 + 4;
var dyn = dynamicSection[i];
switch (dyn.d_tag)
{
case DT_PLTGOT:
case DT_HASH:
case DT_STRTAB:
case DT_SYMTAB:
case DT_RELA:
case DT_INIT:
case DT_FINI:
case DT_REL:
case DT_JMPREL:
case DT_INIT_ARRAY:
case DT_FINI_ARRAY:
dyn.d_un += (uint)ImageBase;
Write(dyn.d_un);
break;
}
}
}
public override SectionHelper GetSectionHelper(int methodCount, int typeDefinitionsCount, int imageCount)
{
var dataList = new List<Elf32_Phdr>();
var execList = new List<Elf32_Phdr>();
foreach (var phdr in programSegment)
{
if (phdr.p_memsz != 0ul)
{
switch (phdr.p_flags)
{
case 1u: //PF_X
case 3u:
case 5u:
case 7u:
execList.Add(phdr);
break;
case 2u: //PF_W && PF_R
case 4u:
case 6u:
dataList.Add(phdr);
break;
}
}
}
var data = dataList.ToArray();
var exec = execList.ToArray();
var sectionHelper = new SectionHelper(this, methodCount, typeDefinitionsCount, metadataUsagesCount, imageCount);
sectionHelper.SetSection(SearchSectionType.Exec, exec);
sectionHelper.SetSection(SearchSectionType.Data, data);
sectionHelper.SetSection(SearchSectionType.Bss, data);
return sectionHelper;
}
}
}
================================================
FILE: Il2CppDumper/ExecutableFormats/Elf64.cs
================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using static Il2CppDumper.ElfConstants;
namespace Il2CppDumper
{
public sealed class Elf64 : ElfBase
{
private Elf64_Ehdr elfHeader;
private Elf64_Phdr[] programSegment;
private Elf64_Dyn[] dynamicSection;
private Elf64_Sym[] symbolTable;
private Elf64_Shdr[] sectionTable;
private Elf64_Phdr pt_dynamic;
public Elf64(Stream stream) : base(stream)
{
Load();
}
protected override void Load()
{
elfHeader = ReadClass<Elf64_Ehdr>(0);
programSegment = ReadClassArray<Elf64_Phdr>(elfHeader.e_phoff, elfHeader.e_phnum);
if (IsDumped)
{
FixedProgramSegment();
}
pt_dynamic = programSegment.First(x => x.p_type == PT_DYNAMIC);
dynamicSection = ReadClassArray<Elf64_Dyn>(pt_dynamic.p_offset, pt_dynamic.p_filesz / 16L);
if (IsDumped)
{
FixedDynamicSection();
}
ReadSymbol();
if (!IsDumped)
{
RelocationProcessing();
if (CheckProtection())
{
Console.WriteLine("ERROR: This file may be protected.");
}
}
}
protected override bool CheckSection()
{
try
{
var names = new List<string>();
sectionTable = ReadClassArray<Elf64_Shdr>(elfHeader.e_shoff, elfHeader.e_shnum);
var shstrndx = sectionTable[elfHeader.e_shstrndx].sh_offset;
foreach (var section in sectionTable)
{
names.Add(ReadStringToNull(shstrndx + section.sh_name));
}
if (!names.Contains(".text"))
{
return false;
}
return true;
}
catch
{
return false;
}
}
public override ulong MapVATR(ulong addr)
{
var phdr = programSegment.First(x => addr >= x.p_vaddr && addr <= x.p_vaddr + x.p_memsz);
return addr - phdr.p_vaddr + phdr.p_offset;
}
public override ulong MapRTVA(ulong addr)
{
var phdr = programSegment.FirstOrDefault(x => addr >= x.p_offset && addr <= x.p_offset + x.p_filesz);
if (phdr == null)
{
return 0;
}
return addr - phdr.p_offset + phdr.p_vaddr;
}
public override bool Search()
{
return false;
}
public override bool PlusSearch(int methodCount, int typeDefinitionsCount, int imageCount)
{
var sectionHelper = GetSectionHelper(methodCount, typeDefinitionsCount, imageCount);
var codeRegistration = sectionHelper.FindCodeRegistration();
var metadataRegistration = sectionHelper.FindMetadataRegistration();
return AutoPlusInit(codeRegistration, metadataRegistration);
}
public override bool SymbolSearch()
{
ulong codeRegistration = 0ul;
ulong metadataRegistration = 0ul;
ulong dynstrOffset = MapVATR(dynamicSection.First(x => x.d_tag == DT_STRTAB).d_un);
foreach (var symbol in symbolTable)
{
var name = ReadStringToNull(dynstrOffset + symbol.st_name);
switch (name)
{
case "g_CodeRegistration":
codeRegistration = symbol.st_value;
break;
case "g_MetadataRegistration":
metadataRegistration = symbol.st_value;
break;
}
}
if (codeRegistration > 0 && metadataRegistration > 0)
{
Console.WriteLine("Detected Symbol !");
Console.WriteLine("CodeRegistration : {0:x}", codeRegistration);
Console.WriteLine("MetadataRegistration : {0:x}", metadataRegistration);
Init(codeRegistration, metadataRegistration);
return true;
}
Console.WriteLine("ERROR: No symbol is detected");
return false;
}
private void ReadSymbol()
{
try
{
var symbolCount = 0u;
var hash = dynamicSection.FirstOrDefault(x => x.d_tag == DT_HASH);
if (hash != null)
{
var addr = MapVATR(hash.d_un);
Position = addr;
var nbucket = ReadUInt32();
var nchain = ReadUInt32();
symbolCount = nchain;
}
else
{
hash = dynamicSection.First(x => x.d_tag == DT_GNU_HASH);
var addr = MapVATR(hash.d_un);
Position = addr;
var nbuckets = ReadUInt32();
var symoffset = ReadUInt32();
var bloom_size = ReadUInt32();
var bloom_shift = ReadUInt32();
var buckets_address = addr + 16 + (8 * bloom_size);
var buckets = ReadClassArray<uint>(buckets_address, nbuckets);
var last_symbol = buckets.Max();
if (last_symbol < symoffset)
{
symbolCount = symoffset;
}
else
{
var chains_base_address = buckets_address + 4 * nbuckets;
Position = chains_base_address + (last_symbol - symoffset) * 4;
while (true)
{
var chain_entry = ReadUInt32();
++last_symbol;
if ((chain_entry & 1) != 0)
break;
}
symbolCount = last_symbol;
}
}
var dynsymOffset = MapVATR(dynamicSection.First(x => x.d_tag == DT_SYMTAB).d_un);
symbolTable = ReadClassArray<Elf64_Sym>(dynsymOffset, symbolCount);
}
catch
{
// ignored
}
}
private void RelocationProcessing()
{
Console.WriteLine("Applying relocations...");
try
{
var relaOffset = MapVATR(dynamicSection.First(x => x.d_tag == DT_RELA).d_un);
var relaSize = dynamicSection.First(x => x.d_tag == DT_RELASZ).d_un;
var relaTable = ReadClassArray<Elf64_Rela>(relaOffset, relaSize / 24L);
foreach (var rela in relaTable)
{
var type = rela.r_info & 0xffffffff;
var sym = rela.r_info >> 32;
(ulong value, bool recognized) result = (type, elfHeader.e_machine) switch
{
(R_AARCH64_ABS64, EM_AARCH64) => (symbolTable[sym].st_value + rela.r_addend, true),
(R_AARCH64_RELATIVE, EM_AARCH64) => (rela.r_addend, true),
(R_X86_64_64, EM_X86_64) => (symbolTable[sym].st_value + rela.r_addend, true),
(R_X86_64_RELATIVE, EM_X86_64) => (rela.r_addend, true),
_ => (0, false)
};
if (result.recognized)
{
Position = MapVATR(rela.r_offset);
Write(result.value);
}
}
}
catch
{
// ignored
}
}
private bool CheckProtection()
{
try
{
//.init_proc
if (dynamicSection.Any(x => x.d_tag == DT_INIT))
{
Console.WriteLine("WARNING: find .init_proc");
return true;
}
//JNI_OnLoad
ulong dynstrOffset = MapVATR(dynamicSection.First(x => x.d_tag == DT_STRTAB).d_un);
foreach (var symbol in symbolTable)
{
var name = ReadStringToNull(dynstrOffset + symbol.st_name);
switch (name)
{
case "JNI_OnLoad":
Console.WriteLine("WARNING: find JNI_OnLoad");
return true;
}
}
if (sectionTable != null && sectionTable.Any(x => x.sh_type == SHT_LOUSER))
{
Console.WriteLine("WARNING: find SHT_LOUSER section");
return true;
}
}
catch
{
// ignored
}
return false;
}
public override ulong GetRVA(ulong pointer)
{
if (IsDumped)
{
return pointer - ImageBase;
}
return pointer;
}
private void FixedProgramSegment()
{
for (uint i = 0; i < programSegment.Length; i++)
{
Position = elfHeader.e_phoff + i * 56u + 8u;
var phdr = programSegment[i];
phdr.p_offset = phdr.p_vaddr;
Write(phdr.p_offset);
phdr.p_vaddr += ImageBase;
Write(phdr.p_vaddr);
Position += 8;
phdr.p_filesz = phdr.p_memsz;
Write(phdr.p_filesz);
}
}
private void FixedDynamicSection()
{
for (uint i = 0; i < dynamicSection.Length; i++)
{
Position = pt_dynamic.p_offset + i * 16 + 8;
var dyn = dynamicSection[i];
switch (dyn.d_tag)
{
case DT_PLTGOT:
case DT_HASH:
case DT_STRTAB:
case DT_SYMTAB:
case DT_RELA:
case DT_INIT:
case DT_FINI:
case DT_REL:
case DT_JMPREL:
case DT_INIT_ARRAY:
case DT_FINI_ARRAY:
dyn.d_un += ImageBase;
Write(dyn.d_un);
break;
}
}
}
public override SectionHelper GetSectionHelper(int methodCount, int typeDefinitionsCount, int imageCount)
{
var dataList = new List<Elf64_Phdr>();
var execList = new List<Elf64_Phdr>();
foreach (var phdr in programSegment)
{
if (phdr.p_memsz != 0ul)
{
switch (phdr.p_flags)
{
case 1u: //PF_X
case 3u:
case 5u:
case 7u:
execList.Add(phdr);
break;
case 2u: //PF_W && PF_R
case 4u:
case 6u:
dataList.Add(phdr);
break;
}
}
}
var data = dataList.ToArray();
var exec = execList.ToArray();
var sectionHelper = new SectionHelper(this, methodCount, typeDefinitionsCount, metadataUsagesCount, imageCount);
sectionHelper.SetSection(SearchSectionType.Exec, exec);
sectionHelper.SetSection(SearchSectionType.Data, data);
sectionHelper.SetSection(SearchSectionType.Bss, data);
return sectionHelper;
}
}
}
================================================
FILE: Il2CppDumper/ExecutableFormats/ElfBase.cs
================================================
using System.IO;
namespace Il2CppDumper
{
public abstract class ElfBase : Il2Cpp
{
protected ElfBase(Stream stream) : base(stream) { }
protected abstract void Load();
protected abstract bool CheckSection();
public override bool CheckDump() => !CheckSection();
public void Reload() => Load();
}
}
================================================
FILE: Il2CppDumper/ExecutableFormats/ElfClass.cs
================================================
namespace Il2CppDumper
{
public class Elf32_Ehdr
{
public uint ei_mag;
public byte ei_class;
public byte ei_data;
public byte ei_version;
public byte ei_osabi;
public byte ei_abiversion;
[ArrayLength(Length = 7)]
public byte[] ei_pad;
public ushort e_type;
public ushort e_machine;
public uint e_version;
public uint e_entry;
public uint e_phoff;
public uint 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_shstrndx;
}
public class Elf32_Phdr
{
public uint p_type;
public uint p_offset;
public uint p_vaddr;
public uint p_paddr;
public uint p_filesz;
public uint p_memsz;
public uint p_flags;
public uint p_align;
}
public class Elf32_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;
}
public class Elf32_Sym
{
public uint st_name;
public uint st_value;
public uint st_size;
public byte st_info;
public byte st_other;
public ushort st_shndx;
}
public class Elf32_Dyn
{
public int d_tag;
public uint d_un;
}
public class Elf32_Rel
{
public uint r_offset;
public uint r_info;
}
public class Elf64_Ehdr
{
public uint ei_mag;
public byte ei_class;
public byte ei_data;
public byte ei_version;
public byte ei_osabi;
public byte ei_abiversion;
[ArrayLength(Length = 7)]
public byte[] ei_pad;
public ushort e_type;
public ushort e_machine;
public uint e_version;
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_shstrndx;
}
public class Elf64_Phdr
{
public uint p_type;
public uint p_flags;
public ulong p_offset;
public ulong p_vaddr;
public ulong p_paddr;
public ulong p_filesz;
public ulong p_memsz;
public ulong p_align;
}
public class Elf64_Shdr
{
public uint sh_name;
public uint sh_type;
public ulong sh_flags;
public ulong sh_addr;
public ulong sh_offset;
public ulong sh_size;
public uint sh_link;
public uint sh_info;
public ulong sh_addralign;
public ulong sh_entsize;
}
public class Elf64_Sym
{
public uint st_name;
public byte st_info;
public byte st_other;
public ushort st_shndx;
public ulong st_value;
public ulong st_size;
}
public class Elf64_Dyn
{
public long d_tag;
public ulong d_un;
}
public class Elf64_Rela
{
public ulong r_offset;
public ulong r_info;
public ulong r_addend;
}
public static class ElfConstants
{
//e_machine
public const int EM_386 = 3;
public const int EM_ARM = 40;
public const int EM_X86_64 = 62;
public const int EM_AARCH64 = 183;
//p_type
public const int PT_LOAD = 1;
public const int PT_DYNAMIC = 2;
//p_flags
public const int PF_X = 1;
//d_tag
public const int DT_PLTGOT = 3;
public const int DT_HASH = 4;
public const int DT_STRTAB = 5;
public const int DT_SYMTAB = 6;
public const int DT_RELA = 7;
public const int DT_RELASZ = 8;
public const int DT_INIT = 12;
public const int DT_FINI = 13;
public const int DT_REL = 17;
public const int DT_RELSZ = 18;
public const int DT_JMPREL = 23;
public const int DT_INIT_ARRAY = 25;
public const int DT_FINI_ARRAY = 26;
public const int DT_GNU_HASH = 0x6ffffef5;
//sh_type
public const uint SHT_LOUSER = 0x80000000;
//ARM relocs
public const int R_ARM_ABS32 = 2;
//i386 relocs
public const int R_386_32 = 1;
//AArch64 relocs
public const int R_AARCH64_ABS64 = 257;
public const int R_AARCH64_RELATIVE = 1027;
//AMD x86-64 relocations
public const int R_X86_64_64 = 1;
public const int R_X86_64_RELATIVE = 8;
}
}
================================================
FILE: Il2CppDumper/ExecutableFormats/Macho.cs
================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using static Il2CppDumper.ArmUtils;
namespace Il2CppDumper
{
public sealed class Macho : Il2Cpp
{
private static readonly byte[] FeatureBytes1 = { 0x0, 0x22 };//MOVS R2, #0
private static readonly byte[] FeatureBytes2 = { 0x78, 0x44, 0x79, 0x44 };//ADD R0, PC and ADD R1, PC
private readonly List<MachoSection> sections = new();
private readonly ulong vmaddr;
public Macho(Stream stream) : base(stream)
{
Is32Bit = true;
Position += 16; //skip magic, cputype, cpusubtype, filetype
var ncmds = ReadUInt32();
Position += 8; //skip sizeofcmds, flags
for (var i = 0; i < ncmds; i++)
{
var pos = Position;
var cmd = ReadUInt32();
var cmdsize = ReadUInt32();
switch (cmd)
{
case 1: //LC_SEGMENT
var segname = Encoding.UTF8.GetString(ReadBytes(16)).TrimEnd('\0');
if (segname == "__TEXT") //__PAGEZERO
{
vmaddr = ReadUInt32();
}
else
{
Position += 4;
}
Position += 20; //skip vmsize, fileoff, filesize, maxprot, initprot
var nsects = ReadUInt32();
Position += 4; //skip flags
for (var j = 0; j < nsects; j++)
{
var section = new MachoSection();
sections.Add(section);
section.sectname = Encoding.UTF8.GetString(ReadBytes(16)).TrimEnd('\0');
Position += 16; //skip segname
section.addr = ReadUInt32();
section.size = ReadUInt32();
section.offset = ReadUInt32();
Position += 12; //skip align, reloff, nreloc
section.flags = ReadUInt32();
Position += 8; //skip reserved1, reserved2
}
break;
case 0x21: //LC_ENCRYPTION_INFO
Position += 8;
var cryptID = ReadUInt32();
if (cryptID != 0)
{
Console.WriteLine("ERROR: This Mach-O executable is encrypted and cannot be processed.");
}
break;
}
Position = pos + cmdsize;//next
}
}
public override void Init(ulong codeRegistration, ulong metadataRegistration)
{
base.Init(codeRegistration, metadataRegistration);
methodPointers = methodPointers.Select(x => x - 1).ToArray();
customAttributeGenerators = customAttributeGenerators.Select(x => x - 1).ToArray();
}
public override ulong MapVATR(ulong addr)
{
var section = sections.First(x => addr >= x.addr && addr <= x.addr + x.size);
return addr - section.addr + section.offset;
}
public override ulong MapRTVA(ulong addr)
{
var section = sections.FirstOrDefault(x => addr >= x.offset && addr <= x.offset + x.size);
if (section == null)
{
return 0;
}
return addr - section.offset + section.addr;
}
public override bool Search()
{
if (Version < 21)
{
var __mod_init_func = sections.First(x => x.sectname == "__mod_init_func");
var addrs = ReadClassArray<uint>(__mod_init_func.offset, __mod_init_func.size / 4u);
foreach (var a in addrs)
{
if (a > 0)
{
var i = a - 1;
Position = MapVATR(i);
Position += 4;
var buff = ReadBytes(2);
if (FeatureBytes1.SequenceEqual(buff))
{
Position += 12;
buff = ReadBytes(4);
if (FeatureBytes2.SequenceEqual(buff))
{
Position = MapVATR(i) + 10;
var subaddr = DecodeMov(ReadBytes(8)) + i + 24u - 1u;
var rsubaddr = MapVATR(subaddr);
Position = rsubaddr;
var ptr = DecodeMov(ReadBytes(8)) + subaddr + 16u;
Position = MapVATR(ptr);
var metadataRegistration = ReadUInt32();
Position = rsubaddr + 8;
buff = ReadBytes(4);
Position = rsubaddr + 14;
buff = buff.Concat(ReadBytes(4)).ToArray();
var codeRegistration = DecodeMov(buff) + subaddr + 22u;
Console.WriteLine("CodeRegistration : {0:x}", codeRegistration);
Console.WriteLine("MetadataRegistration : {0:x}", metadataRegistration);
Init(codeRegistration, metadataRegistration);
return true;
}
}
}
}
return false;
}
else
{
var __mod_init_func = sections.First(x => x.sectname == "__mod_init_func");
var addrs = ReadClassArray<uint>(__mod_init_func.offset, __mod_init_func.size / 4u);
foreach (var a in addrs)
{
if (a > 0)
{
var i = a - 1;
Position = MapVATR(i);
Position += 4;
var buff = ReadBytes(2);
if (FeatureBytes1.SequenceEqual(buff))
{
Position += 12;
buff = ReadBytes(4);
if (FeatureBytes2.SequenceEqual(buff))
{
Position = MapVATR(i) + 10;
var subaddr = DecodeMov(ReadBytes(8)) + i + 24u - 1u;
var rsubaddr = MapVATR(subaddr);
Position = rsubaddr;
var ptr = DecodeMov(ReadBytes(8)) + subaddr + 16u;
Position = MapVATR(ptr);
var metadataRegistration = ReadUInt32();
Position = rsubaddr + 8;
buff = ReadBytes(4);
Position = rsubaddr + 14;
buff = buff.Concat(ReadBytes(4)).ToArray();
var codeRegistration = DecodeMov(buff) + subaddr + 26u;
Console.WriteLine("CodeRegistration : {0:x}", codeRegistration);
Console.WriteLine("MetadataRegistration : {0:x}", metadataRegistration);
Init(codeRegistration, metadataRegistration);
return true;
}
}
}
}
return false;
}
}
public override bool PlusSearch(int methodCount, int typeDefinitionsCount, int imageCount)
{
var sectionHelper = GetSectionHelper(methodCount, typeDefinitionsCount, imageCount);
var codeRegistration = sectionHelper.FindCodeRegistration();
var metadataRegistration = sectionHelper.FindMetadataRegistration();
return AutoPlusInit(codeRegistration, metadataRegistration);
}
public override bool SymbolSearch()
{
return false;
}
public override ulong GetRVA(ulong pointer)
{
return pointer - vmaddr;
}
public override SectionHelper GetSectionHelper(int methodCount, int typeDefinitionsCount, int imageCount)
{
var data = sections.Where(x => x.sectname == "__const").ToArray();
var code = sections.Where(x => x.flags == 0x80000400).ToArray();
var bss = sections.Where(x => x.flags == 1u).ToArray();
var sectionHelper = new SectionHelper(this, methodCount, typeDefinitionsCount, metadataUsagesCount, imageCount);
sectionHelper.SetSection(SearchSectionType.Exec, code);
sectionHelper.SetSection(SearchSectionType.Data, data);
sectionHelper.SetSection(SearchSectionType.Bss, bss);
return sectionHelper;
}
public override bool CheckDump() => false;
}
}
================================================
FILE: Il2CppDumper/ExecutableFormats/Macho64.cs
================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using static Il2CppDumper.ArmUtils;
namespace Il2CppDumper
{
public sealed class Macho64 : Il2Cpp
{
private static readonly byte[] FeatureBytes1 = { 0x2, 0x0, 0x80, 0xD2 };//MOV X2, #0
private static readonly byte[] FeatureBytes2 = { 0x3, 0x0, 0x80, 0x52 };//MOV W3, #0
private readonly List<MachoSection64Bit> sections = new();
private readonly ulong vmaddr;
public Macho64(Stream stream) : base(stream)
{
Position += 16; //skip magic, cputype, cpusubtype, filetype
var ncmds = ReadUInt32();
Position += 12; //skip sizeofcmds, flags, reserved
for (var i = 0; i < ncmds; i++)
{
var pos = Position;
var cmd = ReadUInt32();
var cmdsize = ReadUInt32();
switch (cmd)
{
case 0x19: //LC_SEGMENT_64
var segname = Encoding.UTF8.GetString(ReadBytes(16)).TrimEnd('\0');
if (segname == "__TEXT") //__PAGEZERO
{
vmaddr = ReadUInt64();
}
else
{
Position += 8;
}
Position += 32; //skip vmsize, fileoff, filesize, maxprot, initprot
var nsects = ReadUInt32();
Position += 4; //skip flags
for (var j = 0; j < nsects; j++)
{
var section = new MachoSection64Bit();
sections.Add(section);
section.sectname = Encoding.UTF8.GetString(ReadBytes(16)).TrimEnd('\0');
Position += 16; //skip segname
section.addr = ReadUInt64();
section.size = ReadUInt64();
section.offset = ReadUInt32();
Position += 12; //skip align, reloff, nreloc
section.flags = ReadUInt32();
Position += 12; //skip reserved1, reserved2, reserved3
}
break;
case 0x2C: //LC_ENCRYPTION_INFO_64
Position += 8;
var cryptID = ReadUInt32();
if (cryptID != 0)
{
Console.WriteLine("ERROR: This Mach-O executable is encrypted and cannot be processed.");
}
break;
}
Position = pos + cmdsize;//skip
}
}
public override ulong MapVATR(ulong addr)
{
var section = sections.First(x => addr >= x.addr && addr <= x.addr + x.size);
if (section.sectname == "__bss")
{
throw new Exception();
}
return addr - section.addr + section.offset;
}
public override ulong MapRTVA(ulong addr)
{
var section = sections.FirstOrDefault(x => addr >= x.offset && addr <= x.offset + x.size);
if (section == null)
{
return 0;
}
if (section.sectname == "__bss")
{
throw new Exception();
}
return addr - section.offset + section.addr;
}
public override bool Search()
{
var codeRegistration = 0ul;
var metadataRegistration = 0ul;
if (Version < 23)
{
var __mod_init_func = sections.First(x => x.sectname == "__mod_init_func");
var addrs = ReadClassArray<ulong>(__mod_init_func.offset, __mod_init_func.size / 8);
foreach (var i in addrs)
{
if (i > 0)
{
var flag = false;
var subaddr = 0ul;
Position = MapVATR(i);
var buff = ReadBytes(4);
if (FeatureBytes1.SequenceEqual(buff))
{
buff = ReadBytes(4);
if (FeatureBytes2.SequenceEqual(buff))
{
Position += 8;
var inst = ReadBytes(4);
if (IsAdr(inst))
{
subaddr = DecodeAdr(i + 16, inst);
flag = true;
}
}
}
else
{
Position += 0xc;
buff = ReadBytes(4);
if (FeatureBytes2.SequenceEqual(buff))
{
buff = ReadBytes(4);
if (FeatureBytes1.SequenceEqual(buff))
{
Position -= 0x10;
var inst = ReadBytes(4);
if (IsAdr(inst))
{
subaddr = DecodeAdr(i + 8, inst);
flag = true;
}
}
}
}
if (flag)
{
var rsubaddr = MapVATR(subaddr);
Position = rsubaddr;
codeRegistration = DecodeAdrp(subaddr, ReadBytes(4));
codeRegistration += DecodeAdd(ReadBytes(4));
Position = rsubaddr + 8;
metadataRegistration = DecodeAdrp(subaddr + 8, ReadBytes(4));
metadataRegistration += DecodeAdd(ReadBytes(4));
}
}
}
}
if (Version == 23)
{
/* ADRP X0, unk
* ADD X0, X0, unk
* ADR X1, sub
* NOP
* MOV X2, #0
* MOV W3, #0
* B sub
*/
var __mod_init_func = sections.First(x => x.sectname == "__mod_init_func");
var addrs = ReadClassArray<ulong>(__mod_init_func.offset, __mod_init_func.size / 8);
foreach (var i in addrs)
{
if (i > 0)
{
Position = MapVATR(i) + 16;
var buff = ReadBytes(4);
if (FeatureBytes1.SequenceEqual(buff))
{
buff = ReadBytes(4);
if (FeatureBytes2.SequenceEqual(buff))
{
Position -= 16;
var subaddr = DecodeAdr(i + 8, ReadBytes(4));
var rsubaddr = MapVATR(subaddr);
Position = rsubaddr;
codeRegistration = DecodeAdrp(subaddr, ReadBytes(4));
codeRegistration += DecodeAdd(ReadBytes(4));
Position = rsubaddr + 8;
metadataRegistration = DecodeAdrp(subaddr + 8, ReadBytes(4));
metadataRegistration += DecodeAdd(ReadBytes(4));
}
}
}
}
}
if (Version >= 24)
{
/* ADRP X0, unk
* ADD X0, X0, unk
* ADR X1, sub
* NOP
* MOV W3, #0
* MOV X2, #0
* B sub
*/
var __mod_init_func = sections.First(x => x.sectname == "__mod_init_func");
var addrs = ReadClassArray<ulong>(__mod_init_func.offset, __mod_init_func.size / 8);
foreach (var i in addrs)
{
if (i > 0)
{
Position = MapVATR(i) + 16;
var buff = ReadBytes(4);
if (FeatureBytes2.SequenceEqual(buff))
{
buff = ReadBytes(4);
if (FeatureBytes1.SequenceEqual(buff))
{
Position -= 16;
var subaddr = DecodeAdr(i + 8, ReadBytes(4));
var rsubaddr = MapVATR(subaddr);
Position = rsubaddr;
codeRegistration = DecodeAdrp(subaddr, ReadBytes(4));
codeRegistration += DecodeAdd(ReadBytes(4));
Position = rsubaddr + 8;
metadataRegistration = DecodeAdrp(subaddr + 8, ReadBytes(4));
metadataRegistration += DecodeAdd(ReadBytes(4));
}
}
}
}
}
if (codeRegistration != 0 && metadataRegistration != 0)
{
Console.WriteLine("CodeRegistration : {0:x}", codeRegistration);
Console.WriteLine("MetadataRegistration : {0:x}", metadataRegistration);
Init(codeRegistration, metadataRegistration);
return true;
}
return false;
}
public override bool PlusSearch(int methodCount, int typeDefinitionsCount, int imageCount)
{
var sectionHelper = GetSectionHelper(methodCount, typeDefinitionsCount, imageCount);
var codeRegistration = sectionHelper.FindCodeRegistration();
var metadataRegistration = sectionHelper.FindMetadataRegistration();
return AutoPlusInit(codeRegistration, metadataRegistration);
}
public override bool SymbolSearch()
{
return false;
}
public override ulong GetRVA(ulong pointer)
{
return pointer - vmaddr;
}
public override SectionHelper GetSectionHelper(int methodCount, int typeDefinitionsCount, int imageCount)
{
var data = sections.Where(x => x.sectname == "__const" || x.sectname == "__cstring" || x.sectname == "__data").ToArray();
var code = sections.Where(x => x.flags == 0x80000400).ToArray();
var bss = sections.Where(x => x.flags == 1u).ToArray();
var sectionHelper = new SectionHelper(this, methodCount, typeDefinitionsCount, metadataUsagesCount, imageCount);
sectionHelper.SetSection(SearchSectionType.Exec, code);
sectionHelper.SetSection(SearchSectionType.Data, data);
sectionHelper.SetSection(SearchSectionType.Bss, bss);
return sectionHelper;
}
public override bool CheckDump() => false;
public override ulong ReadUIntPtr()
{
var pointer = ReadUInt64();
if (pointer > vmaddr + 0xFFFFFFFF)
{
var addr = Position;
var section = sections.First(x => addr >= x.offset && addr <= x.offset + x.size);
if (section.sectname == "__const" || section.sectname == "__data")
{
var rva = pointer - vmaddr;
rva &= 0xFFFFFFFF;
pointer = rva + vmaddr;
}
}
return pointer;
}
}
}
================================================
FILE: Il2CppDumper/ExecutableFormats/MachoClass.cs
================================================
namespace Il2CppDumper
{
public class MachoSection
{
public string sectname;
public uint addr;
public uint size;
public uint offset;
public uint flags;
}
public class MachoSection64Bit
{
public string sectname;
public ulong addr;
public ulong size;
public ulong offset;
public uint flags;
}
public class Fat
{
public uint offset;
public uint size;
public uint magic;
}
}
================================================
FILE: Il2CppDumper/ExecutableFormats/MachoFat.cs
================================================
using System.Buffers.Binary;
using System.IO;
namespace Il2CppDumper
{
public sealed class MachoFat : BinaryStream
{
public Fat[] fats;
public MachoFat(Stream stream) : base(stream)
{
Position += 4;
var size = BinaryPrimitives.ReadInt32BigEndian(ReadBytes(4));
fats = new Fat[size];
for (var i = 0; i < size; i++)
{
Position += 8;
fats[i] = new Fat
{
offset = BinaryPrimitives.ReadUInt32BigEndian(ReadBytes(4)),
size = BinaryPrimitives.ReadUInt32BigEndian(ReadBytes(4))
};
Position += 4;
}
for (var i = 0; i < size; i++)
{
Position = fats[i].offset;
fats[i].magic = ReadUInt32();
}
}
public byte[] GetMacho(int index)
{
Position = fats[index].offset;
return ReadBytes((int)fats[index].size);
}
}
}
================================================
FILE: Il2CppDumper/ExecutableFormats/NSO.cs
================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using static Il2CppDumper.ElfConstants;
namespace Il2CppDumper
{
public sealed class NSO : Il2Cpp
{
private readonly NSOHeader header;
private readonly bool isTextCompressed;
private readonly bool isRoDataCompressed;
private readonly bool isDataCompressed;
private readonly List<NSOSegmentHeader> segments = new();
private Elf64_Sym[] symbolTable;
private readonly List<Elf64_Dyn> dynamicSection = new();
private bool IsCompressed => isTextCompressed || isRoDataCompressed || isDataCompressed;
public NSO(Stream stream) : base(stream)
{
header = new NSOHeader
{
Magic = ReadUInt32(),
Version = ReadUInt32(),
Reserved = ReadUInt32(),
Flags = ReadUInt32()
};
isTextCompressed = (header.Flags & 1) != 0;
isRoDataCompressed = (header.Flags & 2) != 0;
isDataCompressed = (header.Flags & 4) != 0;
header.TextSegment = new NSOSegmentHeader
{
FileOffset = ReadUInt32(),
MemoryOffset = ReadUInt32(),
DecompressedSize = ReadUInt32()
};
segments.Add(header.TextSegment);
header.ModuleOffset = ReadUInt32();
header.RoDataSegment = new NSOSegmentHeader
{
FileOffset = ReadUInt32(),
MemoryOffset = ReadUInt32(),
DecompressedSize = ReadUInt32()
};
segments.Add(header.RoDataSegment);
header.ModuleFileSize = ReadUInt32();
header.DataSegment = new NSOSegmentHeader
{
FileOffset = ReadUInt32(),
MemoryOffset = ReadUInt32(),
DecompressedSize = ReadUInt32()
};
segments.Add(header.DataSegment);
header.BssSize = ReadUInt32();
header.DigestBuildID = ReadBytes(0x20);
header.TextCompressedSize = ReadUInt32();
header.RoDataCompressedSize = ReadUInt32();
header.DataCompressedSize = ReadUInt32();
header.Padding = ReadBytes(0x1C);
header.APIInfo = new NSORelativeExtent
{
RegionRoDataOffset = ReadUInt32(),
RegionSize = ReadUInt32()
};
header.DynStr = new NSORelativeExtent
{
RegionRoDataOffset = ReadUInt32(),
RegionSize = ReadUInt32()
};
header.DynSym = new NSORelativeExtent
{
RegionRoDataOffset = ReadUInt32(),
RegionSize = ReadUInt32()
};
header.TextHash = ReadBytes(0x20);
header.RoDataHash = ReadBytes(0x20);
header.DataHash = ReadBytes(0x20);
if (!IsCompressed)
{
Position = header.TextSegment.FileOffset + 4;
var modOffset = ReadUInt32();
Position = header.TextSegment.FileOffset + modOffset + 4;
var dynamicOffset = ReadUInt32() + modOffset;
var bssStart = ReadUInt32();
var bssEnd = ReadUInt32();
header.BssSegment = new NSOSegmentHeader
{
FileOffset = bssStart,
MemoryOffset = bssStart,
DecompressedSize = bssEnd - bssStart
};
var maxSize = (header.DataSegment.MemoryOffset + header.DataSegment.DecompressedSize - dynamicOffset) / 16;
Position = MapVATR(dynamicOffset);
for (int i = 0; i < maxSize; i++)
{
var dynamic = ReadClass<Elf64_Dyn>();
if (dynamic.d_tag == 0)
{
break;
}
else
{
dynamicSection.Add(dynamic);
}
}
ReadSymbol();
RelocationProcessing();
}
}
private void ReadSymbol()
{
try
{
var symbolCount = 0u;
var hash = dynamicSection.FirstOrDefault(x => x.d_tag == DT_HASH);
if (hash != null)
{
var addr = MapVATR(hash.d_un);
Position = addr;
var nbucket = ReadUInt32();
var nchain = ReadUInt32();
symbolCount = nchain;
}
else
{
hash = dynamicSection.First(x => x.d_tag == DT_GNU_HASH);
var addr = MapVATR(hash.d_un);
Position = addr;
var nbuckets = ReadUInt32();
var symoffset = ReadUInt32();
var bloom_size = ReadUInt32();
var bloom_shift = ReadUInt32();
var buckets_address = addr + 16 + (8 * bloom_size);
var buckets = ReadClassArray<uint>(buckets_address, nbuckets);
var last_symbol = buckets.Max();
if (last_symbol < symoffset)
{
symbolCount = symoffset;
}
else
{
var chains_base_address = buckets_address + 4 * nbuckets;
Position = chains_base_address + (last_symbol - symoffset) * 4;
while (true)
{
var chain_entry = ReadUInt32();
++last_symbol;
if ((chain_entry & 1) != 0)
break;
}
symbolCount = last_symbol;
}
}
var dynsymOffset = MapVATR(dynamicSection.First(x => x.d_tag == DT_SYMTAB).d_un);
symbolTable = ReadClassArray<Elf64_Sym>(dynsymOffset, symbolCount);
}
catch
{
// ignored
}
}
private void RelocationProcessing()
{
Console.WriteLine("Applying relocations...");
try
{
var relaOffset = MapVATR(dynamicSection.First(x => x.d_tag == DT_RELA).d_un);
var relaSize = dynamicSection.First(x => x.d_tag == DT_RELASZ).d_un;
var relaTable = ReadClassArray<Elf64_Rela>(relaOffset, relaSize / 24L);
foreach (var rela in relaTable)
{
var type = rela.r_info & 0xffffffff;
var sym = rela.r_info >> 32;
switch (type)
{
case R_AARCH64_ABS64:
{
var symbol = symbolTable[sym];
Position = MapVATR(rela.r_offset);
Write(symbol.st_value + (ulong)rela.r_addend);
break;
}
case R_AARCH64_RELATIVE:
{
Position = MapVATR(rela.r_offset);
Write(rela.r_addend);
break;
}
}
}
}
catch
{
// ignored
}
}
public override ulong MapVATR(ulong addr)
{
var segment = segments.First(x => addr >= x.MemoryOffset && addr <= x.MemoryOffset + x.DecompressedSize);
return addr - segment.MemoryOffset + segment.FileOffset;
}
public override ulong MapRTVA(ulong addr)
{
var segment = segments.FirstOrDefault(x => addr >= x.FileOffset && addr <= x.FileOffset + x.DecompressedSize);
if (segment == null)
{
return 0;
}
return addr - segment.FileOffset + segment.MemoryOffset;
}
public override bool Search()
{
return false;
}
public override bool PlusSearch(int methodCount, int typeDefinitionsCount, int imageCount)
{
var sectionHelper = GetSectionHelper(methodCount, typeDefinitionsCount, imageCount);
var codeRegistration = sectionHelper.FindCodeRegistration();
var metadataRegistration = sectionHelper.FindMetadataRegistration();
return AutoPlusInit(codeRegistration, metadataRegistration);
}
public override bool SymbolSearch()
{
return false;
}
public NSO UnCompress()
{
if (isTextCompressed || isRoDataCompressed || isDataCompressed)
{
var unCompressedStream = new MemoryStream();
var writer = new BinaryWriter(unCompressedStream);
writer.Write(header.Magic);
writer.Write(header.Version);
writer.Write(header.Reserved);
writer.Write(0); //Flags
writer.Write(header.TextSegment.FileOffset);
writer.Write(header.TextSegment.MemoryOffset);
writer.Write(header.TextSegment.DecompressedSize);
writer.Write(header.ModuleOffset);
var roOffset = header.TextSegment.FileOffset + header.TextSegment.DecompressedSize;
writer.Write(roOffset); //header.RoDataSegment.FileOffset
writer.Write(header.RoDataSegment.MemoryOffset);
writer.Write(header.RoDataSegment.DecompressedSize);
writer.Write(header.ModuleFileSize);
writer.Write(roOffset + header.RoDataSegment.DecompressedSize); //header.DataSegment.FileOffset
writer.Write(header.DataSegment.MemoryOffset);
writer.Write(header.DataSegment.DecompressedSize);
writer.Write(header.BssSize);
writer.Write(header.DigestBuildID);
writer.Write(header.TextCompressedSize);
writer.Write(header.RoDataCompressedSize);
writer.Write(header.DataCompressedSize);
writer.Write(header.Padding);
writer.Write(header.APIInfo.RegionRoDataOffset);
writer.Write(header.APIInfo.RegionSize);
writer.Write(header.DynStr.RegionRoDataOffset);
writer.Write(header.DynStr.RegionSize);
writer.Write(header.DynSym.RegionRoDataOffset);
writer.Write(header.DynSym.RegionSize);
writer.Write(header.TextHash);
writer.Write(header.RoDataHash);
writer.Write(header.DataHash);
writer.BaseStream.Position = header.TextSegment.FileOffset;
Position = header.TextSegment.FileOffset;
var textBytes = ReadBytes((int)header.TextCompressedSize);
if (isTextCompressed)
{
var unCompressedData = new byte[header.TextSegment.DecompressedSize];
using (var decoder = new Lz4DecoderStream(new MemoryStream(textBytes)))
{
decoder.Read(unCompressedData, 0, unCompressedData.Length);
}
writer.Write(unCompressedData);
}
else
{
writer.Write(textBytes);
}
var roDataBytes = ReadBytes((int)header.RoDataCompressedSize);
if (isRoDataCompressed)
{
var unCompressedData = new byte[header.RoDataSegment.DecompressedSize];
using (var decoder = new Lz4DecoderStream(new MemoryStream(roDataBytes)))
{
decoder.Read(unCompressedData, 0, unCompressedData.Length);
}
writer.Write(unCompressedData);
}
else
{
writer.Write(roDataBytes);
}
var dataBytes = ReadBytes((int)header.DataCompressedSize);
if (isDataCompressed)
{
var unCompressedData = new byte[header.DataSegment.DecompressedSize];
using (var decoder = new Lz4DecoderStream(new MemoryStream(dataBytes)))
{
decoder.Read(unCompressedData, 0, unCompressedData.Length);
}
writer.Write(unCompressedData);
}
else
{
writer.Write(dataBytes);
}
writer.Flush();
unCompressedStream.Position = 0;
return new NSO(unCompressedStream);
}
return this;
}
public override SectionHelper GetSectionHelper(int methodCount, int typeDefinitionsCount, int imageCount)
{
var sectionHelper = new SectionHelper(this, methodCount, typeDefinitionsCount, metadataUsagesCount, imageCount);
sectionHelper.SetSection(SearchSectionType.Exec, header.TextSegment);
sectionHelper.SetSection(SearchSectionType.Data, header.DataSegment, header.RoDataSegment);
sectionHelper.SetSection(SearchSectionType.Bss, header.BssSegment);
return sectionHelper;
}
public override bool CheckDump() => false;
}
}
================================================
FILE: Il2CppDumper/ExecutableFormats/NSOClass.cs
================================================
namespace Il2CppDumper
{
public class NSOHeader
{
public uint Magic;
public uint Version;
public uint Reserved;
public uint Flags;
public NSOSegmentHeader TextSegment;
public uint ModuleOffset;
public NSOSegmentHeader RoDataSegment;
public uint ModuleFileSize;
public NSOSegmentHeader DataSegment;
public uint BssSize;
public byte[] DigestBuildID;
public uint TextCompressedSize;
public uint RoDataCompressedSize;
public uint DataCompressedSize;
public byte[] Padding;
public NSORelativeExtent APIInfo;
public NSORelativeExtent DynStr;
public NSORelativeExtent DynSym;
public byte[] TextHash;
public byte[] RoDataHash;
public byte[] DataHash;
public NSOSegmentHeader BssSegment;
}
public class NSOSegmentHeader
{
public uint FileOffset;
public uint MemoryOffset;
public uint DecompressedSize;
}
public class NSORelativeExtent
{
public uint RegionRoDataOffset;
public uint RegionSize;
}
}
================================================
FILE: Il2CppDumper/ExecutableFormats/PE.cs
================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Il2CppDumper
{
public sealed class PE : Il2Cpp
{
private readonly SectionHeader[] sections;
public PE(Stream stream) : base(stream)
{
var dosHeader = ReadClass<DosHeader>();
if (dosHeader.Magic != 0x5A4D)
{
throw new InvalidDataException("ERROR: Invalid PE file");
}
Position = dosHeader.Lfanew;
if (ReadUInt32() != 0x4550u) //Signature
{
throw new InvalidDataException("ERROR: Invalid PE file");
}
var fileHeader = ReadClass<FileHeader>();
var pos = Position;
var magic = ReadUInt16();
Position -= 2;
if (magic == 0x10b)
{
Is32Bit = true;
var optionalHeader = ReadClass<OptionalHeader>();
ImageBase = optionalHeader.ImageBase;
}
else if (magic == 0x20b)
{
var optionalHeader = ReadClass<OptionalHeader64>();
ImageBase = optionalHeader.ImageBase;
}
else
{
throw new NotSupportedException($"Invalid Optional header magic {magic}");
}
Position = pos + fileHeader.SizeOfOptionalHeader;
sections = ReadClassArray<SectionHeader>(fileHeader.NumberOfSections);
}
public void LoadFromMemory(ulong addr)
{
ImageBase = addr;
foreach (var section in sections)
{
section.PointerToRawData = section.VirtualAddress;
section.SizeOfRawData = section.VirtualSize;
}
}
public override ulong MapVATR(ulong absAddr)
{
var addr = absAddr - ImageBase;
var section = sections.FirstOrDefault(x => addr >= x.VirtualAddress && addr <= x.VirtualAddress + x.VirtualSize);
if (section == null)
{
return 0ul;
}
return addr - section.VirtualAddress + section.PointerToRawData;
}
public override ulong MapRTVA(ulong addr)
{
var section = sections.FirstOrDefault(x => addr >= x.PointerToRawData && addr <= x.PointerToRawData + x.SizeOfRawData);
if (section == null)
{
return 0ul;
}
return addr - section.PointerToRawData + section.VirtualAddress + ImageBase;
}
public override bool Search()
{
return false;
}
public override bool PlusSearch(int methodCount, int typeDefinitionsCount, int imageCount)
{
var sectionHelper = GetSectionHelper(methodCount, typeDefinitionsCount, imageCount);
var codeRegistration = sectionHelper.FindCodeRegistration();
var metadataRegistration = sectionHelper.FindMetadataRegistration();
return AutoPlusInit(codeRegistration, metadataRegistration);
}
public override bool SymbolSearch()
{
return false;
}
public override ulong GetRVA(ulong pointer)
{
return pointer - ImageBase;
}
public override SectionHelper GetSectionHelper(int methodCount, int typeDefinitionsCount, int imageCount)
{
var execList = new List<SectionHeader>();
var dataList = new List<SectionHeader>();
foreach (var section in sections)
{
switch (section.Characteristics)
{
case 0x60000020:
execList.Add(section);
break;
case 0x40000040:
case 0xC0000040:
dataList.Add(section);
break;
}
}
var sectionHelper = new SectionHelper(this, methodCount, typeDefinitionsCount, metadataUsagesCount, imageCount);
var data = dataList.ToArray();
var exec = execList.ToArray();
sectionHelper.SetSection(SearchSectionType.Exec, ImageBase, exec);
sectionHelper.SetSection(SearchSectionType.Data, ImageBase, data);
sectionHelper.SetSection(SearchSectionType.Bss, ImageBase, data);
return sectionHelper;
}
public override bool CheckDump()
{
if (Is32Bit)
{
return ImageBase != 0x10000000;
}
else
{
return ImageBase != 0x180000000;
}
}
}
}
================================================
FILE: Il2CppDumper/ExecutableFormats/PEClass.cs
================================================
using System;
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 ushort Machine;
public ushort NumberOfSections;
public uint TimeDateStamp;
public uint PointerToSymbolTable;
public uint NumberOfSymbols;
public ushort SizeOfOptionalHeader;
public ushort Characteristics;
}
public class OptionalHeader
{
public ushort Magic;
public byte MajorLinkerVersion;
public byte MinorLinkerVersion;
public uint SizeOfCode;
public uint SizeOfInitializedData;
public uint SizeOfUninitializedData;
public uint AddressOfEntryPoint;
public uint BaseOfCode;
public uint BaseOfData;
public uint ImageBase;
public uint SectionAlignment;
public uint FileAlignment;
public ushort MajorOperatingSystemVersion;
public ushort MinorOperatingSystemVersion;
public ushort MajorImageVersion;
public ushort MinorImageVersion;
public ushort MajorSubsystemVersion;
public ushort MinorSubsystemVersion;
public uint Win32VersionValue;
public uint SizeOfImage;
public uint SizeOfHeaders;
public uint CheckSum;
public ushort Subsystem;
public ushort DllCharacteristics;
public uint SizeOfStackReserve;
public uint SizeOfStackCommit;
public uint SizeOfHeapReserve;
public uint SizeOfHeapCommit;
public uint LoaderFlags;
public uint NumberOfRvaAndSizes;
//public DataDirectory[] DataDirectory;
}
public class OptionalHeader64
{
public ushort Magic;
public byte MajorLinkerVersion;
public byte MinorLinkerVersion;
public uint SizeOfCode;
public uint SizeOfInitializedData;
public uint SizeOfUninitializedData;
public uint AddressOfEntryPoint;
public uint BaseOfCode;
public ulong ImageBase;
public uint SectionAlignment;
public uint FileAlignment;
public ushort MajorOperatingSystemVersion;
public ushort MinorOperatingSystemVersion;
public ushort MajorImageVersion;
public ushort MinorImageVersion;
public ushort MajorSubsystemVersion;
public ushort MinorSubsystemVersion;
public uint Win32VersionValue;
public uint SizeOfImage;
public uint SizeOfHeaders;
public uint CheckSum;
public ushort Subsystem;
public ushort DllCharacteristics;
public ulong SizeOfStackReserve;
public ulong SizeOfStackCommit;
public ulong SizeOfHeapReserve;
public ulong SizeOfHeapCommit;
public uint LoaderFlags;
public uint NumberOfRvaAndSizes;
//public DataDirectory[] DataDirectory;
}
/*public class DataDirectory
{
public uint VirtualAddress;
public uint Size;
}*/
public class SectionHeader
{
[ArrayLength(Length = 8)]
public byte[] Name;
public uint VirtualSize;
public uint VirtualAddress;
public uint SizeOfRawData;
public uint PointerToRawData;
public uint PointerToRelocations;
public uint PointerToLinenumbers;
public ushort NumberOfRelocations;
public ushort NumberOfLinenumbers;
public uint Characteristics;
}
[Flags]
public enum SectionCharacteristics : uint
{
IMAGE_SCN_MEM_EXECUTE = 0x20000000,
IMAGE_SCN_MEM_READ = 0x40000000,
IMAGE_SCN_MEM_WRITE = 0x80000000
}
}
================================================
FILE: Il2CppDumper/ExecutableFormats/WebAssembly.cs
================================================
using System;
using System.IO;
namespace Il2CppDumper
{
public sealed class WebAssembly : BinaryStream
{
private readonly DataSection[] dataSections;
public WebAssembly(Stream stream) : base(stream)
{
Is32Bit = true;
var magic = ReadUInt32();
var version = ReadInt32();
while (Position < Length)
{
var id = ReadULeb128();
var len = ReadULeb128();
if (id == 11)
{
var count = ReadULeb128();
dataSections = new DataSection[count];
for (int i = 0; i < count; i++)
{
var dataSection = new DataSection();
dataSections[i] = dataSection;
dataSection.Index = ReadULeb128();
var opCode = ReadByte();
if (opCode != 0x41) //i32.const
{
throw new InvalidOperationException();
}
dataSection.Offset = ReadULeb128();
opCode = ReadByte();
if (opCode != 0xB) //end
{
throw new InvalidOperationException();
}
dataSection.Data = ReadBytes((int)ReadULeb128());
}
break;
}
Position += len;
}
}
public WebAssemblyMemory CreateMemory()
{
var last = dataSections[^1];
var bssStart = last.Offset + (uint)last.Data.Length;
var stream = new MemoryStream(new byte[Length]);
foreach (var dataSection in dataSections)
{
stream.Position = dataSection.Offset;
stream.Write(dataSection.Data, 0, dataSection.Data.Length);
}
return new WebAssemblyMemory(stream, bssStart);
}
}
}
================================================
FILE: Il2CppDumper/ExecutableFormats/WebAssemblyClass.cs
================================================
namespace Il2CppDumper
{
public class DataSection
{
public uint Index;
public uint Offset;
public byte[] Data;
}
}
================================================
FILE: Il2CppDumper/ExecutableFormats/WebAssemblyMemory.cs
================================================
using System.IO;
namespace Il2CppDumper
{
public sealed class WebAssemblyMemory : Il2Cpp
{
private readonly uint bssStart;
public WebAssemblyMemory(Stream stream, uint bssStart) : base(stream)
{
Is32Bit = true;
this.bssStart = bssStart;
}
public override ulong MapVATR(ulong addr)
{
return addr;
}
public override ulong MapRTVA(ulong addr)
{
return addr;
}
public override bool PlusSearch(int methodCount, int typeDefinitionsCount, int imageCount)
{
var sectionHelper = GetSectionHelper(methodCount, typeDefinitionsCount, imageCount);
var codeRegistration = sectionHelper.FindCodeRegistration();
var metadataRegistration = sectionHelper.FindMetadataRegistration();
return AutoPlusInit(codeRegistration, metadataRegistration);
}
public override bool Search()
{
return false;
}
public override bool SymbolSearch()
{
return false;
}
public override SectionHelper GetSectionHelper(int methodCount, int typeDefinitionsCount, int imageCount)
{
var exec = new SearchSection
{
offset = 0,
offsetEnd = (ulong)methodCount, //hack
address = 0,
addressEnd = (ulong)methodCount //hack
};
var data = new SearchSection
{
offset = 1024,
offsetEnd = Length,
address = 1024,
addressEnd = Length
};
var bss = new SearchSection
{
offset = bssStart,
offsetEnd = long.MaxValue, //hack
address = bssStart,
addressEnd = long.MaxValue //hack
};
var sectionHelper = new SectionHelper(this, methodCount, typeDefinitionsCount, metadataUsagesCount, imageCount);
sectionHelper.SetSection(SearchSectionType.Exec, exec);
sectionHelper.SetSection(SearchSectionType.Data, data);
sectionHelper.SetSection(SearchSectionType.Bss, bss);
return sectionHelper;
}
public override bool CheckDump() => false;
}
}
================================================
FILE: Il2CppDumper/Extensions/BinaryReaderExtensions.cs
================================================
using System;
using System.IO;
using System.Text;
namespace Il2CppDumper
{
public static class BinaryReaderExtensions
{
public static string ReadString(this BinaryReader reader, int numChars)
{
var start = reader.BaseStream.Position;
// UTF8 takes up to 4 bytes per character
var str = Encoding.UTF8.GetString(reader.ReadBytes(numChars * 4))[..numChars];
// make our position what it would have been if we'd known the exact number of bytes needed.
reader.BaseStream.Position = start;
reader.ReadBytes(Encoding.UTF8.GetByteCount(str));
return str;
}
public static uint ReadULeb128(this BinaryReader reader)
{
uint value = reader.ReadByte();
if (value >= 0x80)
{
var bitshift = 0;
value &= 0x7f;
while (true)
{
var b = reader.ReadByte();
bitshift += 7;
value |= (uint)((b & 0x7f) << bitshift);
if (b < 0x80)
break;
}
}
return value;
}
public static uint ReadCompressedUInt32(this BinaryReader reader)
{
uint val;
var read = reader.ReadByte();
if ((read & 0x80) == 0)
{
// 1 byte written
val = read;
}
else if ((read & 0xC0) == 0x80)
{
// 2 bytes written
val = (read & ~0x80u) << 8;
val |= reader.ReadByte();
}
else if ((read & 0xE0) == 0xC0)
{
// 4 bytes written
val = (read & ~0xC0u) << 24;
val |= ((uint)reader.ReadByte() << 16);
val |= ((uint)reader.ReadByte() << 8);
val |= reader.ReadByte();
}
else if (read == 0xF0)
{
// 5 bytes written, we had a really large int32!
val = reader.ReadUInt32();
}
else if (read == 0xFE)
{
// Special encoding for Int32.MaxValue
val = uint.MaxValue - 1;
}
else if (read == 0xFF)
{
// Yes we treat UInt32.MaxValue (and Int32.MinValue, see ReadCompressedInt32) specially
val = uint.MaxValue;
}
else
{
throw new Exception("Invalid compressed integer format");
}
return val;
}
public static int ReadCompressedInt32(this BinaryReader reader)
{
var encoded = reader.ReadCompressedUInt32();
// -UINT32_MAX can't be represted safely in an int32_t, so we treat it specially
if (encoded == uint.MaxValue)
return int.MinValue;
bool isNegative = (encoded & 1) != 0;
encoded >>= 1;
if (isNegative)
return -(int)(encoded + 1);
return (int)encoded;
}
}
}
================================================
FILE: Il2CppDumper/Extensions/BoyerMooreHorspool.cs
================================================
using System;
using System.Collections.Generic;
namespace Il2CppDumper
{
static class BoyerMooreHorspool
{
public static IEnumerable<int> Search(this byte[] source, byte[] pattern)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
if (pattern == null)
{
throw new ArgumentNullException(nameof(pattern));
}
int valueLength = source.Length;
int patternLength = pattern.Length;
if (valueLength == 0 || patternLength == 0 || patternLength > valueLength)
{
yield break;
}
var badCharacters = new int[256];
for (var i = 0; i < 256; i++)
{
badCharacters[i] = patternLength;
}
var lastPatternByte = patternLength - 1;
for (int i = 0; i < lastPatternByte; i++)
{
badCharacters[pattern[i]] = lastPatternByte - i;
}
int index = 0;
while (index <= valueLength - patternLength)
{
for (var i = lastPatternByte; source[index + i] == pattern[i]; i--)
{
if (i == 0)
{
yield return index;
break;
}
}
index += badCharacters[source[index + lastPatternByte]];
}
}
public static IEnumerable<int> Search(this byte[] source, string stringPattern)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
if (stringPattern == null)
{
throw new ArgumentNullException(nameof(stringPattern));
}
var pattern = stringPattern.Split(' ');
int valueLength = source.Length;
int patternLength = pattern.Length;
if (valueLength == 0 || patternLength == 0 || patternLength > valueLength)
{
yield break;
}
var badCharacters = new int[256];
for (var i = 0; i < 256; i++)
{
badCharacters[i] = patternLength;
}
var lastPatternByte = patternLength - 1;
for (int i = 0; i < lastPatternByte; i++)
{
if (pattern[i] != "?")
{
var result = Convert.ToInt32(pattern[i], 16);
badCharacters[result] = lastPatternByte - i;
}
}
int index = 0;
while (index <= valueLength - patternLength)
{
for (var i = lastPatternByte; CheckEqual(source, pattern, index, i); i--)
{
if (i == 0)
{
yield return index;
break;
}
}
index += badCharacters[source[index + lastPatternByte]];
}
}
private static bool CheckEqual(byte[] source, string[] pattern, int index, int i)
{
if (pattern[i] != "?")
{
var result = Convert.ToInt32(pattern[i], 16);
return source[index + i] == result;
}
return true;
}
}
}
================================================
FILE: Il2CppDumper/Extensions/HexExtensions.cs
================================================
using System;
using System.Text;
namespace Il2CppDumper
{
static class HexExtensions
{
public static string HexToBin(this byte b)
{
return Convert.ToString(b, 2).PadLeft(8, '0');
}
public static string HexToBin(this byte[] bytes)
{
var result = new StringBuilder(bytes.Length * 8);
foreach (var b in bytes)
{
result.Insert(0, b.HexToBin());
}
return result.ToString();
}
}
}
================================================
FILE: Il2CppDumper/Extensions/StringExtensions.cs
================================================
using System.Text;
namespace Il2CppDumper
{
public static class StringExtensions
{
public static string ToEscapedString(this string s)
{
var re = new StringBuilder(s.Length);
foreach (var c in s)
{
switch (c)
{
case '\'':
re.Append(@"\'");
break;
case '"':
re.Append(@"\""");
break;
case '\\':
re.Append(@"\\");
break;
case '\0':
re.Append(@"\0");
break;
case '\a':
re.Append(@"\a");
break;
case '\b':
re.Append(@"\b");
break;
case '\f':
re.Append(@"\f");
break;
case '\n':
re.Append(@"\n");
break;
case '\r':
re.Append(@"\r");
break;
case '\t':
re.Append(@"\t");
break;
case '\v':
re.Append(@"\v");
break;
case '\u0085':
re.Append(@"\u0085");
break;
case '\u2028':
re.Append(@"\u2028");
break;
case '\u2029':
re.Append(@"\u2029");
break;
default:
re.Append(c);
break;
}
}
return re.ToString();
}
}
}
================================================
FILE: Il2CppDumper/IO/BinaryStream.cs
================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
namespace Il2CppDumper
{
public class BinaryStream : IDisposable
{
public double Version;
public bool Is32Bit;
public ulong ImageBase;
private readonly Stream stream;
private readonly BinaryReader reader;
private readonly BinaryWriter writer;
private readonly MethodInfo readClass;
private readonly MethodInfo readClassArray;
private readonly Dictionary<Type, MethodInfo> genericMethodCache;
private readonly Dictionary<FieldInfo, VersionAttribute[]> attributeCache;
public BinaryStream(Stream input)
{
stream = input;
reader = new BinaryReader(stream, Encoding.UTF8, true);
writer = new BinaryWriter(stream, Encoding.UTF8, true);
readClass = GetType().GetMethod("ReadClass", Type.EmptyTypes);
readClassArray = GetType().GetMethod("ReadClassArray", new[] { typeof(long) });
genericMethodCache = new();
attributeCache = new();
}
public bool ReadBoolean() => reader.ReadBoolean();
public byte ReadByte() => reader.ReadByte();
public byte[] ReadBytes(int count) => reader.ReadBytes(count);
public sbyte ReadSByte() => reader.ReadSByte();
public short ReadInt16() => reader.ReadInt16();
public ushort ReadUInt16() => reader.ReadUInt16();
public int ReadInt32() => reader.ReadInt32();
public uint ReadUInt32() => reader.ReadUInt32();
public long ReadInt64() => reader.ReadInt64();
public ulong ReadUInt64() => reader.ReadUInt64();
public float ReadSingle() => reader.ReadSingle();
public double ReadDouble() => reader.ReadDouble();
public uint ReadCompressedUInt32() => reader.ReadCompressedUInt32();
public int ReadCompressedInt32() => reader.ReadCompressedInt32();
public uint ReadULeb128() => reader.ReadULeb128();
public void Write(bool value) => writer.Write(value);
public void Write(byte value) => writer.Write(value);
public void Write(sbyte value) => writer.Write(value);
public void Write(short value) => writer.Write(value);
public void Write(ushort value) => writer.Write(value);
public void Write(int value) => writer.Write(value);
public void Write(uint value) => writer.Write(value);
public void Write(long value) => writer.Write(value);
public void Write(ulong value) => writer.Write(value);
public void Write(float value) => writer.Write(value);
public void Write(double value) => writer.Write(value);
public ulong Position
{
get => (ulong)stream.Position;
set => stream.Position = (long)value;
}
public ulong Length => (ulong)stream.Length;
private object ReadPrimitive(Type type)
{
return type.Name switch
{
"Int32" => ReadInt32(),
"UInt32" => ReadUInt32(),
"Int16" => ReadInt16(),
"UInt16" => ReadUInt16(),
"Byte" => ReadByte(),
"Int64" => ReadIntPtr(),
"UInt64" => ReadUIntPtr(),
_ => throw new NotSupportedException()
};
}
public T ReadClass<T>(ulong addr) where T : new()
{
Position = addr;
return ReadClass<T>();
}
public T ReadClass<T>() where T : new()
{
var type = typeof(T);
if (type.IsPrimitive)
{
return (T)ReadPrimitive(type);
}
else
{
var t = new T();
foreach (var i in t.GetType().GetFields())
{
if (!attributeCache.TryGetValue(i, out var versionAttributes))
{
if (Attribute.IsDefined(i, typeof(VersionAttribute)))
{
versionAttributes = i.GetCustomAttributes<VersionAttribute>().ToArray();
attributeCache.Add(i, versionAttributes);
}
}
if (versionAttributes?.Length > 0)
{
var read = false;
foreach (var versionAttribute in versionAttributes)
{
if (Version >= versionAttribute.Min && Version <= versionAttribute.Max)
{
read = true;
break;
}
}
if (!read)
{
continue;
}
}
var fieldType = i.FieldType;
if (fieldType.IsPrimitive)
{
i.SetValue(t, ReadPrimitive(fieldType));
}
else if (fieldType.IsEnum)
{
var e = fieldType.GetField("value__").FieldType;
i.SetValue(t, ReadPrimitive(e));
}
else if (fieldType.IsArray)
{
var arrayLengthAttribute = i.GetCustomAttribute<ArrayLengthAttribute>();
if (!genericMethodCache.TryGetValue(fieldType, out var methodInfo))
{
methodInfo = readClassArray.MakeGenericMethod(fieldType.GetElementType());
genericMethodCache.Add(fieldType, methodInfo);
}
i.SetValue(t, methodInfo.Invoke(this, new object[] { arrayLengthAttribute.Length }));
}
else
{
if (!genericMethodCache.TryGetValue(fieldType, out var methodInfo))
{
methodInfo = readClass.MakeGenericMethod(fieldType);
genericMethodCache.Add(fieldType, methodInfo);
}
i.SetValue(t, methodInfo.Invoke(this, null));
}
}
return t;
}
}
public T[] ReadClassArray<T>(long count) where T : new()
{
var t = new T[count];
for (var i = 0; i < count; i++)
{
t[i] = ReadClass<T>();
}
return t;
}
public T[] ReadClassArray<T>(ulong addr, ulong count) where T : new()
{
return ReadClassArray<T>(addr, (long)count);
}
public T[] ReadClassArray<T>(ulong addr, long count) where T : new()
{
Position = addr;
return ReadClassArray<T>(count);
}
public string ReadStringToNull(ulong addr)
{
Position = addr;
var bytes = new List<byte>();
byte b;
while ((b = ReadByte()) != 0)
bytes.Add(b);
return Encoding.UTF8.GetString(bytes.ToArray());
}
public long ReadIntPtr()
{
return Is32Bit ? ReadInt32() : ReadInt64();
}
public virtual ulong ReadUIntPtr()
{
return Is32Bit ? ReadUInt32() : ReadUInt64();
}
public ulong PointerSize
{
get => Is32Bit ? 4ul : 8ul;
}
public BinaryReader Reader => reader;
public BinaryWriter Writer => writer;
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
reader.Dispose();
writer.Dispose();
stream.Close();
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}
================================================
FILE: Il2CppDumper/IO/Lz4DecoderStream.cs
================================================
#define CHECK_ARGS
#define CHECK_EOF
//#define LOCAL_SHADOW
using System;
using System.IO;
namespace Il2CppDumper
{
public class Lz4DecoderStream : Stream
{
public Lz4DecoderStream(Stream input, long inputLength = long.MaxValue)
{
Reset(input, inputLength);
}
private void Reset(Stream input, long inputLength = long.MaxValue)
{
this.inputLength = inputLength;
this.input = input;
phase = DecodePhase.ReadToken;
decodeBufferPos = 0;
litLen = 0;
matLen = 0;
matDst = 0;
inBufPos = DecBufLen;
inBufEnd = DecBufLen;
}
protected override void Dispose(bool disposing)
{
try
{
if (disposing && input != null)
{
input.Close();
}
input = null;
decodeBuffer = null;
}
finally
{
base.Dispose(disposing);
}
}
private long inputLength;
private Stream input;
//because we might not be able to match back across invocations,
//we have to keep the last window's worth of bytes around for reuse
//we use a circular buffer for this - every time we write into this
//buffer, we also write the same into our output buffer
private const int DecBufLen = 0x10000;
private const int DecBufMask = 0xFFFF;
private const int InBufLen = 128;
private byte[] decodeBuffer = new byte[DecBufLen + InBufLen];
private int decodeBufferPos, inBufPos, inBufEnd;
//we keep track of which phase we're in so that we can jump right back
//into the correct part of decoding
private DecodePhase phase;
private enum DecodePhase
{
ReadToken,
ReadExLiteralLength,
CopyLiteral,
ReadOffset,
ReadExMatchLength,
CopyMatch,
}
//state within interruptable phases and across phase boundaries is
//kept here - again, so that we can punt out and restart freely
private int litLen, matLen, matDst;
public override int Read(byte[] buffer, int offset, int count)
{
#if CHECK_ARGS
if (buffer == null)
throw new ArgumentNullException("buffer");
if (offset < 0 || count < 0 || buffer.Length - count < offset)
throw new ArgumentOutOfRangeException();
if (input == null)
throw new InvalidOperationException();
#endif
int nRead, nToRead = count;
var decBuf = decodeBuffer;
//the stringy gotos are obnoxious, but their purpose is to
//make it *blindingly* obvious how the state machine transitions
//back and forth as it reads - remember, we can yield out of
//this routine in several places, and we must be able to re-enter
//and pick up where we left off!
#if LOCAL_SHADOW
var phase = this.phase;
var inBufPos = this.inBufPos;
var inBufEnd = this.inBufEnd;
#endif
switch (phase)
{
case DecodePhase.ReadToken:
goto readToken;
case DecodePhase.ReadExLiteralLength:
goto readExLiteralLength;
case DecodePhase.CopyLiteral:
goto copyLiteral;
case DecodePhase.ReadOffset:
goto readOffset;
case DecodePhase.ReadExMatchLength:
goto readExMatchLength;
case DecodePhase.CopyMatch:
goto copyMatch;
}
readToken:
int tok;
if (inBufPos < inBufEnd)
{
tok = decBuf[inBufPos++];
}
else
{
#if LOCAL_SHADOW
this.inBufPos = inBufPos;
#endif
tok = ReadByteCore();
#if LOCAL_SHADOW
inBufPos = this.inBufPos;
inBufEnd = this.inBufEnd;
#endif
#if CHECK_EOF
if (tok == -1)
goto finish;
#endif
}
litLen = tok >> 4;
matLen = (tok & 0xF) + 4;
switch (litLen)
{
case 0:
phase = DecodePhase.ReadOffset;
goto readOffset;
case 0xF:
phase = DecodePhase.ReadExLiteralLength;
goto readExLiteralLength;
default:
phase = DecodePhase.CopyLiteral;
goto copyLiteral;
}
readExLiteralLength:
int exLitLen;
if (inBufPos < inBufEnd)
{
exLitLen = decBuf[inBufPos++];
}
else
{
#if LOCAL_SHADOW
this.inBufPos = inBufPos;
#endif
exLitLen = ReadByteCore();
#if LOCAL_SHADOW
inBufPos = this.inBufPos;
inBufEnd = this.inBufEnd;
#endif
#if CHECK_EOF
if (exLitLen == -1)
goto finish;
#endif
}
litLen += exLitLen;
if (exLitLen == 255)
goto readExLiteralLength;
phase = DecodePhase.CopyLiteral;
goto copyLiteral;
copyLiteral:
int nReadLit = litLen < nToRead ? litLen : nToRead;
if (nReadLit != 0)
{
if (inBufPos + nReadLit <= inBufEnd)
{
int ofs = offset;
for (int c = nReadLit; c-- != 0;)
buffer[ofs++] = decBuf[inBufPos++];
nRead = nReadLit;
}
else
{
#if LOCAL_SHADOW
this.inBufPos = inBufPos;
#endif
nRead = ReadCore(buffer, offset, nReadLit);
#if LOCAL_SHADOW
inBufPos = this.inBufPos;
inBufEnd = this.inBufEnd;
#endif
#if CHECK_EOF
if (nRead == 0)
goto finish;
#endif
}
offset += nRead;
nToRead -= nRead;
litLen -= nRead;
if (litLen != 0)
goto copyLiteral;
}
if (nToRead == 0)
goto finish;
phase = DecodePhase.ReadOffset;
goto readOffset;
readOffset:
if (inBufPos + 1 < inBufEnd)
{
matDst = (decBuf[inBufPos + 1] << 8) | decBuf[inBufPos];
inBufPos += 2;
}
else
{
#if LOCAL_SHADOW
this.inBufPos = inBufPos;
#endif
matDst = ReadOffsetCore();
#if LOCAL_SHADOW
inBufPos = this.inBufPos;
inBufEnd = this.inBufEnd;
#endif
#if CHECK_EOF
if (matDst == -1)
goto finish;
#endif
}
if (matLen == 15 + 4)
{
phase = DecodePhase.ReadExMatchLength;
goto readExMatchLength;
}
else
{
phase = DecodePhase.CopyMatch;
goto copyMatch;
}
readExMatchLength:
int exMatLen;
if (inBufPos < inBufEnd)
{
exMatLen = decBuf[inBufPos++];
}
else
{
#if LOCAL_SHADOW
this.inBufPos = inBufPos;
#endif
exMatLen = ReadByteCore();
#if LOCAL_SHADOW
inBufPos = this.inBufPos;
inBufEnd = this.inBufEnd;
#endif
#if CHECK_EOF
if (exMatLen == -1)
goto finish;
#endif
}
matLen += exMatLen;
if (exMatLen == 255)
goto readExMatchLength;
phase = DecodePhase.CopyMatch;
goto copyMatch;
copyMatch:
int nCpyMat = matLen < nToRead ? matLen : nToRead;
if (nCpyMat != 0)
{
nRead = count - nToRead;
int bufDst = matDst - nRead;
if (bufDst > 0)
{
//offset is fairly far back, we need to pull from the buffer
int bufSrc = decodeBufferPos - bufDst;
if (bufSrc < 0)
bufSrc += DecBufLen;
int bufCnt = bufDst < nCpyMat ? bufDst : nCpyMat;
for (int c = bufCnt; c-- != 0;)
buffer[offset++] = decBuf[bufSrc++ & DecBufMask];
}
else
{
bufDst = 0;
}
int sOfs = offset - matDst;
for (int i = bufDst; i < nCpyMat; i++)
buffer[offset++] = buffer[sOfs++];
nToRead -= nCpyMat;
matLen -= nCpyMat;
}
if (nToRead == 0)
goto finish;
phase = DecodePhase.ReadToken;
goto readToken;
finish:
nRead = count - nToRead;
int nToBuf = nRead < DecBufLen ? nRead : DecBufLen;
int repPos = offset - nToBuf;
if (nToBuf == DecBufLen)
{
Buffer.BlockCopy(buffer, repPos, decBuf, 0, DecBufLen);
decodeBufferPos = 0;
}
else
{
int decPos = decodeBufferPos;
while (nToBuf-- != 0)
decBuf[decPos++ & DecBufMask] = buffer[repPos++];
decodeBufferPos = decPos & DecBufMask;
}
#if LOCAL_SHADOW
this.phase = phase;
this.inBufPos = inBufPos;
#endif
return nRead;
}
private int ReadByteCore()
{
var buf = decodeBuffer;
if (inBufPos == inBufEnd)
{
int nRead = input.Read(buf, DecBufLen,
InBufLen < inputLength ? InBufLen : (int)inputLength);
#if CHECK_EOF
if (nRead == 0)
return -1;
#endif
inputLength -= nRead;
inBufPos = DecBufLen;
inBufEnd = DecBufLen + nRead;
}
return buf[inBufPos++];
}
private int ReadOffsetCore()
{
var buf = decodeBuffer;
if (inBufPos == inBufEnd)
{
int nRead = input.Read(buf, DecBufLen,
InBufLen < inputLength ? InBufLen : (int)inputLength);
#if CHECK_EOF
if (nRead == 0)
return -1;
#endif
inputLength -= nRead;
inBufPos = DecBufLen;
inBufEnd = DecBufLen + nRead;
}
if (inBufEnd - inBufPos == 1)
{
buf[DecBufLen] = buf[inBufPos];
int nRead = input.Read(buf, DecBufLen + 1,
InBufLen - 1 < inputLength ? InBufLen - 1 : (int)inputLength);
#if CHECK_EOF
if (nRead == 0)
{
inBufPos = DecBufLen;
inBufEnd = DecBufLen + 1;
return -1;
}
#endif
inputLength -= nRead;
inBufPos = DecBufLen;
inBufEnd = DecBufLen + nRead + 1;
}
int ret = (buf[inBufPos + 1] << 8) | buf[inBufPos];
inBufPos += 2;
return ret;
}
private int ReadCore(byte[] buffer, int offset, int count)
{
int nToRead = count;
var buf = decodeBuffer;
int inBufLen = inBufEnd - inBufPos;
int fromBuf = nToRead < inBufLen ? nToRead : inBufLen;
if (fromBuf != 0)
{
var bufPos = inBufPos;
for (int c = fromBuf; c-- != 0;)
buffer[offset++] = buf[bufPos++];
inBufPos = bufPos;
nToRead -= fromBuf;
}
if (nToRead != 0)
{
int nRead;
if (nToRead >= InBufLen)
{
nRead = input.Read(buffer, offset,
nToRead < inputLength ? nToRead : (int)inputLength);
nToRead -= nRead;
}
else
{
nRead = input.Read(buf, DecBufLen,
InBufLen < inputLength ? InBufLen : (int)inputLength);
inBufPos = DecBufLen;
inBufEnd = DecBufLen + nRead;
fromBuf = nToRead < nRead ? nToRead : nRead;
var bufPos = inBufPos;
for (int c = fromBuf; c-- != 0;)
buffer[offset++] = buf[bufPos++];
inBufPos = bufPos;
nToRead -= fromBuf;
}
inputLength -= nRead;
}
return count - nToRead;
}
#region Stream internals
public override bool CanRead => true;
public override bool CanSeek => false;
public override bool CanWrite => false;
public override void Flush()
{
}
public override long Length => throw new NotSupportedException();
public override long Position
{
get => throw new NotSupportedException();
set => throw new NotSupportedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
#endregion
}
}
================================================
FILE: Il2CppDumper/Il2Cpp/Il2Cpp.cs
================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Il2CppDumper
{
public abstract class Il2Cpp : BinaryStream
{
private Il2CppMetadataRegistration pMetadataRegistration;
private Il2CppCodeRegistration pCodeRegistration;
public ulong[] methodPointers;
public ulong[] genericMethodPointers;
public ulong[] invokerPointers;
public ulong[] customAttributeGenerators;
public ulong[] reversePInvokeWrappers;
public ulong[] unresolvedVirtualCallPointers;
private ulong[] fieldOffsets;
public Il2CppType[] types;
private readonly Dictionary<ulong, Il2CppType> typeDic = new();
public ulong[] metadataUsages;
private Il2CppGenericMethodFunctionsDefinitions[] genericMethodTable;
public ulong[] genericInstPointers;
public Il2CppGenericInst[] genericInsts;
public Il2CppMethodSpec[] methodSpecs;
public Dictionary<int, List<Il2CppMethodSpec>> methodDefinitionMethodSpecs = new();
public Dictionary<Il2CppMethodSpec, ulong> methodSpecGenericMethodPointers = new();
private bool fieldOffsetsArePointers;
protected long metadataUsagesCount;
public Dictionary<string, Il2CppCodeGenModule> codeGenModules;
public Dictionary<string, ulong[]> codeGenModuleMethodPointers;
public Dictionary<string, Dictionary<uint, Il2CppRGCTXDefinition[]>> rgctxsDictionary;
public bool IsDumped;
public abstract ulong MapVATR(ulong addr);
public abstract ulong MapRTVA(ulong addr);
public abstract bool Search();
public abstract bool PlusSearch(int methodCount, int typeDefinitionsCount, int imageCount);
public abstract bool SymbolSearch();
public abstract SectionHelper GetSectionHelper(int methodCount, int typeDefinitionsCount, int imageCount);
public abstract bool CheckDump();
protected Il2Cpp(Stream stream) : base(stream) { }
public void SetProperties(double version, long metadataUsagesCount)
{
Version = version;
this.metadataUsagesCount = metadataUsagesCount;
}
protected bool AutoPlusInit(ulong codeRegistration, ulong metadataRegistration)
{
if (codeRegistration != 0)
{
var limit = this is WebAssemblyMemory ? 0x35000u : 0x50000u; //TODO
if (Version >= 24.2)
{
pCodeRegistration = MapVATR<Il2CppCodeRegistration>(codeRegistration);
if (Version == 31)
{
if (pCodeRegistration.genericMethodPointersCount > limit)
{
codeRegistration -= PointerSize * 2;
}
else
{
Version = 29;
Console.WriteLine($"Change il2cpp version to: {Version}");
}
}
if (Version == 29)
{
if (pCodeRegistration.genericMethodPointersCount > limit)
{
Version = 29.1;
codeRegistration -= PointerSize * 2;
Console.WriteLine($"Change il2cpp version to: {Version}");
}
}
if (Version == 27)
{
if (pCodeRegistration.reversePInvokeWrapperCount > limit)
{
Version = 27.1;
codeRegistration -= PointerSize;
Console.WriteLine($"Change il2cpp version to: {Version}");
}
}
if (Version == 24.4)
{
codeRegistration -= PointerSize * 2;
if (pCodeRegistration.reversePInvokeWrapperCount > limit)
{
Version = 24.5;
codeRegistration -= PointerSize;
Console.WriteLine($"Change il2cpp version to: {Version}");
}
}
if (Version == 24.2)
{
if (pCodeRegistration.interopDataCount == 0) //TODO
{
Version = 24.3;
codeRegistration -= PointerSize * 2;
Console.WriteLine($"Change il2cpp version to: {Version}");
}
}
}
}
Console.WriteLine("CodeRegistration : {0:x}", codeRegistration);
Console.WriteLine("MetadataRegistration : {0:x}", metadataRegistration);
if (codeRegistration != 0 && metadataRegistration != 0)
{
Init(codeRegistration, metadataRegistration);
return true;
}
return false;
}
public virtual void Init(ulong codeRegistration, ulong metadataRegistration)
{
pCodeRegistration = MapVATR<Il2CppCodeRegistration>(codeRegistration);
var limit = this is WebAssemblyMemory ? 0x35000u : 0x50000u; //TODO
if (Version == 27 && pCodeRegistration.invokerPointersCount > limit)
{
Version = 27.1;
Console.WriteLine($"Change il2cpp version to: {Version}");
pCodeRegistration = MapVATR<Il2CppCodeRegistration>(codeRegistration);
}
if (Version == 27.1)
{
var pCodeGenModules = MapVATR<ulong>(pCodeRegistration.codeGenModules, pCodeRegistration.codeGenModulesCount);
foreach (var pCodeGenModule in pCodeGenModules)
{
var codeGenModule = MapVATR<Il2CppCodeGenModule>(pCodeGenModule);
if (codeGenModule.rgctxsCount > 0)
{
var rgctxs = MapVATR<Il2CppRGCTXDefinition>(codeGenModule.rgctxs, codeGenModule.rgctxsCount);
if (rgctxs.All(x => x.data.rgctxDataDummy > limit))
{
Version = 27.2;
Console.WriteLine($"Change il2cpp version to: {Version}");
}
break;
}
}
}
if (Version == 24.4 && pCodeRegistration.invokerPointersCount > limit)
{
Version = 24.5;
Console.WriteLine($"Change il2cpp version to: {Version}");
pCodeRegistration = MapVATR<Il2CppCodeRegistration>(codeRegistration);
}
if (Version == 24.2 && pCodeRegistration.codeGenModules == 0) //TODO
{
Version = 24.3;
Console.WriteLine($"Change il2cpp version to: {Version}");
pCodeRegistration = MapVATR<Il2CppCodeRegistration>(codeRegistration);
}
pMetadataRegistration = MapVATR<Il2CppMetadataRegistration>(metadataRegistration);
genericMethodPointers = MapVATR<ulong>(pCodeRegistration.genericMethodPointers, pCodeRegistration.genericMethodPointersCount);
invokerPointers = MapVATR<ulong>(pCodeRegistration.invokerPointers, pCodeRegistration.invokerPointersCount);
if (Version < 27)
{
customAttributeGenerators = MapVATR<ulong>(pCodeRegistration.customAttributeGenerators, pCodeRegistration.customAttributeCount);
}
if (Version > 16 && Version < 27)
{
metadataUsages = MapVATR<ulong>(pMetadataRegistration.metadataUsages, metadataUsagesCount);
}
if (Version >= 22)
{
if (pCodeRegistration.reversePInvokeWrapperCount != 0)
reversePInvokeWrappers = MapVATR<ulong>(pCodeRegistration.reversePInvokeWrappers, pCodeRegistration.reversePInvokeWrapperCount);
if (pCodeRegistration.unresolvedVirtualCallCount != 0)
unresolvedVirtualCallPointers = MapVATR<ulong>(pCodeRegistration.unresolvedVirtualCallPointers, pCodeRegistration.unresolvedVirtualCallCount);
}
genericInstPointers = MapVATR<ulong>(pMetadataRegistration.genericInsts, pMetadataRegistration.genericInstsCount);
genericInsts = Array.ConvertAll(genericInstPointers, MapVATR<Il2CppGenericInst>);
fieldOffsetsArePointers = Version > 21;
if (Version == 21)
{
var fieldTest = MapVATR<uint>(pMetadataRegistration.fieldOffsets, 6);
fieldOffsetsArePointers = fieldTest[0] == 0 && fieldTest[1] == 0 && fieldTest[2] == 0 && fieldTest[3] == 0 && fieldTest[4] == 0 && fieldTest[5] > 0;
}
if (fieldOffsetsArePointers)
{
fieldOffsets = MapVATR<ulong>(pMetadataRegistration.fieldOffsets, pMetadataRegistration.fieldOffsetsCount);
}
else
{
fieldOffsets = Array.ConvertAll(MapVATR<uint>(pMetadataRegistration.fieldOffsets, pMetadataRegistration.fieldOffsetsCount), x => (ulong)x);
}
var pTypes = MapVATR<ulong>(pMetadataRegistration.types, pMetadataRegistration.typesCount);
types = new Il2CppType[pMetadataRegistration.typesCount];
for (var i = 0; i < pMetadataRegistration.typesCount; ++i)
{
types[i] = MapVATR<Il2CppType>(pTypes[i]);
types[i].Init(Version);
typeDic.Add(pTypes[i], types[i]);
}
if (Version >= 24.2)
{
var pCodeGenModules = MapVATR<ulong>(pCodeRegistration.codeGenModules, pCodeRegistration.codeGenModulesCount);
codeGenModules = new Dictionary<string, Il2CppCodeGenModule>(pCodeGenModules.Length, StringComparer.Ordinal);
codeGenModuleMethodPointers = new Dictionary<string, ulong[]>(pCodeGenModules.Length, StringComparer.Ordinal);
rgctxsDictionary = new Dictionary<string, Dictionary<uint, Il2CppRGCTXDefinition[]>>(pCodeGenModules.Length, StringComparer.Ordinal);
foreach (var pCodeGenModule in pCodeGenModules)
{
var codeGenModule = MapVATR<Il2CppCodeGenModule>(pCodeGenModule);
var moduleName = ReadStringToNull(MapVATR(codeGenModule.moduleName));
codeGenModules.Add(moduleName, codeGenModule);
ulong[] methodPointers;
try
{
methodPointers = MapVATR<ulong>(codeGenModule.methodPointers, codeGenModule.methodPointerCount);
}
catch
{
methodPointers = new ulong[codeGenModule.methodPointerCount];
}
codeGenModuleMethodPointers.Add(moduleName, methodPointers);
var rgctxsDefDictionary = new Dictionary<uint, Il2CppRGCTXDefinition[]>();
rgctxsDictionary.Add(moduleName, rgctxsDefDictionary);
if (codeGenModule.rgctxsCount > 0)
{
var rgctxs = MapVATR<Il2CppRGCTXDefinition>(codeGenModule.rgctxs, codeGenModule.rgctxsCount);
var rgctxRanges = MapVATR<Il2CppTokenRangePair>(codeGenModule.rgctxRanges, codeGenModule.rgctxRangesCount);
foreach (var rgctxRange in rgctxRanges)
{
var rgctxDefs = new Il2CppRGCTXDefinition[rgctxRange.range.length];
Array.Copy(rgctxs, rgctxRange.range.start, rgctxDefs, 0, rgctxRange.range.length);
rgctxsDefDictionary.Add(rgctxRange.token, rgctxDefs);
}
}
}
}
else
{
methodPointers = MapVATR<ulong>(pCodeRegistration.methodPointers, pCodeRegistration.methodPointersCount);
}
genericMethodTable = MapVATR<Il2CppGenericMethodFunctionsDefinitions>(pMetadataRegistration.genericMethodTable, pMetadataRegistration.genericMethodTableCount);
methodSpecs = MapVATR<Il2CppMethodSpec>(pMetadataRegistration.methodSpecs, pMetadataRegistration.methodSpecsCount);
foreach (var table in genericMethodTable)
{
var methodSpec = methodSpecs[table.genericMethodIndex];
var methodDefinitionIndex = methodSpec.methodDefinitionIndex;
if (!methodDefinitionMethodSpecs.TryGetValue(methodDefinitionIndex, out var list))
{
list = new List<Il2CppMethodSpec>();
methodDefinitionMethodSpecs.Add(methodDefinitionIndex, list);
}
list.Add(methodSpec);
methodSpecGenericMethodPointers.Add(methodSpec, genericMethodPointers[table.indices.methodIndex]);
}
}
public T MapVATR<T>(ulong addr) where T : new()
{
return ReadClass<T>(MapVATR(addr));
}
public T[] MapVATR<T>(ulong addr, ulong count) where T : new()
{
return ReadClassArray<T>(MapVATR(addr), count);
}
public T[] MapVATR<T>(ulong addr, long count) where T : new()
{
return ReadClassArray<T>(MapVATR(addr), count);
}
public int GetFieldOffsetFromIndex(int typeIndex, int fieldIndexInType, int fieldIndex, bool isValueType, bool isStatic)
{
try
{
var offset = -1;
if (fieldOffsetsArePointers)
{
var ptr = fieldOffsets[typeIndex];
if (ptr > 0)
{
Position = MapVATR(ptr) + 4ul * (ulong)fieldIndexInType;
offset = ReadInt32();
}
}
else
{
offset = (int)fieldOffsets[fieldIndex];
}
if (offset > 0)
{
if (isValueType && !isStatic)
{
if (Is32Bit)
{
offset -= 8;
}
else
{
offset -= 16;
}
}
}
return offset;
}
catch
{
return -1;
}
}
public Il2CppType GetIl2CppType(ulong pointer)
{
if (!typeDic.TryGetValue(pointer, out var type))
{
return null;
}
return type;
}
public ulong GetMethodPointer(string imageName, Il2CppMethodDefinition methodDef)
{
if (Version >= 24.2)
{
var methodToken = methodDef.token;
var ptrs = codeGenModuleMethodPointers[imageName];
var methodPointerIndex = methodToken & 0x00FFFFFFu;
return ptrs[methodPointerIndex - 1];
}
else
{
var methodIndex = methodDef.methodIndex;
if (methodIndex >= 0)
{
return methodPointers[methodIndex];
}
}
return 0;
}
public virtual ulong GetRVA(ulong pointer)
{
return pointer;
}
}
}
================================================
FILE: Il2CppDumper/Il2Cpp/Il2CppClass.cs
================================================
using System;
namespace Il2CppDumper
{
public class Il2CppCodeRegistration
{
[Version(Max = 24.1)]
public ulong methodPointersCount;
[Version(Max = 24.1)]
public ulong methodPointers;
[Version(Max = 21)]
public ulong delegateWrappersFromNativeToManagedCount;
[Version(Max = 21)]
public ulong delegateWrappersFromNativeToManaged; // note the double indirection to handle different calling conventions
[Version(Min = 22)]
public ulong reversePInvokeWrapperCount;
[Version(Min = 22)]
public ulong reversePInvokeWrappers;
[Version(Max = 22)]
public ulong delegateWrappersFromManagedToNativeCount;
[Version(Max = 22)]
public ulong delegateWrappersFromManagedToNative;
[Version(Max = 22)]
public ulong marshalingFunctionsCount;
[Version(Max = 22)]
public ulong marshalingFunctions;
[Version(Min = 21, Max = 22)]
public ulong ccwMarshalingFunctionsCount;
[Version(Min = 21, Max = 22)]
public ulong ccwMarshalingFunctions;
public ulong genericMethodPointersCount;
public ulong genericMethodPointers;
[Version(Min = 24.5, Max = 24.5)]
[Version(Min = 27.1)]
public ulong genericAdjustorThunks;
public ulong invokerPointersCount;
public ulong invokerPointers;
[Version(Max = 24.5)]
public ulong customAttributeCount;
[Version(Max = 24.5)]
public ulong customAttributeGenerators;
[Version(Min = 21, Max = 22)]
public ulong guidCount;
[Version(Min = 21, Max = 22)]
public ulong guids; // Il2CppGuid
[Version(Min = 22)]
public ulong unresolvedVirtualCallCount; //29.1 unresolvedIndirectCallCount;
[Version(Min = 22)]
public ulong unresolvedVirtualCallPointers;
[Version(Min = 29.1)]
public ulong unresolvedInstanceCallPointers;
[Version(Min = 29.1)]
public ulong unresolvedStaticCallPointers;
[Version(Min = 23)]
public ulong interopDataCount;
[Version(Min = 23)]
public ulong interopData;
[Version(Min = 24.3)]
public ulong windowsRuntimeFactoryCount;
[Version(Min = 24.3)]
public ulong windowsRuntimeFactoryTable;
[Version(Min = 24.2)]
public ulong codeGenModulesCount;
[Version(Min = 24.2)]
public ulong codeGenModules;
}
public class Il2CppMetadataRegistration
{
public long genericClassesCount;
public ulong genericClasses;
public long genericInstsCount;
public ulong genericInsts;
public long genericMethodTableCount;
public ulong genericMethodTable;
public long typesCount;
public ulong types;
public long methodSpecsCount;
public ulong methodSpecs;
[Version(Max = 16)]
public long methodReferencesCount;
[Version(Max = 16)]
public ulong methodReferences;
public long fieldOffsetsCount;
public ulong fieldOffsets;
public long typeDefinitionsSizesCount;
public ulong typeDefinitionsSizes;
[Version(Min = 19)]
public ulong metadataUsagesCount;
[Version(Min = 19)]
public ulong metadataUsages;
}
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 */
IL2CPP_TYPE_IL2CPP_TYPE_INDEX = 0xff /* an index into IL2CPP type metadata table */
}
public class Il2CppType
{
public ulong datapoint;
public uint bits;
public Union data { get; set; }
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 uint valuetype { get; set; }
public void Init(double version)
{
attrs = bits & 0xffff;
type = (Il2CppTypeEnum)((bits >> 16) & 0xff);
if (version >= 27.2)
{
num_mods = (bits >> 24) & 0x1f;
byref = (bits >> 29) & 1;
pinned = (bits >> 30) & 1;
valuetype = bits >> 31;
}
else
{
num_mods = (bits >> 24) & 0x3f;
byref = (bits >> 30) & 1;
pinned = bits >> 31;
}
data = new Union { dummy = datapoint };
}
public class Union
{
public ulong dummy;
/// <summary>
/// for VALUETYPE and CLASS
/// </summary>
public long klassIndex => (long)dummy;
/// <summary>
/// for VALUETYPE and CLASS at runtime
/// </summary>
public ulong typeHandle => dummy;
/// <summary>
/// for PTR and SZARRAY
/// </summary>
public ulong type => dummy;
/// <summary>
/// for ARRAY
/// </summary>
public ulong array => dummy;
/// <summary>
/// for VAR and MVAR
/// </summary>
public long genericParameterIndex => (long)dummy;
/// <summary>
/// for VAR and MVAR at runtime
/// </summary>
public ulong genericParameterHandle => dummy;
/// <summary>
/// for GENERICINST
/// </summary>
public ulong generic_class => dummy;
}
}
public class Il2CppGenericClass
{
[Version(Max = 24.5)]
public long typeDefinitionIndex; /* the generic type definition */
[Version(Min = 27)]
public ulong type; /* the generic type definition */
public Il2CppGenericContext context; /* a context that contains the type instantiation doesn't contain any method instantiation */
public ulong cached_class; /* if present, the Il2CppClass corresponding to the instantiation. */
}
public class Il2CppGenericContext
{
/* The instantiation corresponding to the class generic parameters */
public ulong class_inst;
/* The instantiation corresponding to the method generic parameters */
public ulong method_inst;
}
public class Il2CppGenericInst
{
public long type_argc;
public ulong type_argv;
}
public class Il2CppArrayType
{
public ulong etype;
public byte rank;
public byte numsizes;
public byte numlobounds;
public ulong sizes;
public ulong lobounds;
}
public class Il2CppGenericMethodFunctionsDefinitions
{
public int genericMethodIndex;
public Il2CppGenericMethodIndices indices;
}
public class Il2CppGenericMethodIndices
{
public int methodIndex;
public int invokerIndex;
[Version(Min = 24.5, Max = 24.5)]
[Version(Min = 27.1)]
public int adjustorThunk;
};
public class Il2CppMethodSpec
{
public int methodDefinitionIndex;
public int classIndexIndex;
public int methodIndexIndex;
};
public class Il2CppCodeGenModule
{
public ulong moduleName;
public long methodPointerCount;
public ulong methodPointers;
[Version(Min = 24.5, Max = 24.5)]
[Version(Min = 27.1)]
public long adjustorThunkCount;
[Version(Min = 24.5, Max = 24.5)]
[Version(Min = 27.1)]
public ulong adjustorThunks;
public ulong invokerIndices;
public ulong reversePInvokeWrapperCount;
public ulong reversePInvokeWrapperIndices;
public long rgctxRangesCount;
public ulong rgctxRanges;
public long rgctxsCount;
public ulong rgctxs;
public ulong debuggerMetadata;
[Version(Min = 27, Max = 27.2)]
public ulong customAttributeCacheGenerator;
[Version(Min = 27)]
public ulong moduleInitializer;
[Version(Min = 27)]
public ulong staticConstructorTypeIndices;
[Version(Min = 27)]
public ulong metadataRegistration; // Per-assembly mode only
[Version(Min = 27)]
public ulong codeRegistaration; // Per-assembly mode only
}
public class Il2CppRange
{
public int start;
public int length;
}
public class Il2CppTokenRangePair
{
public uint token;
public Il2CppRange range;
}
}
================================================
FILE: Il2CppDumper/Il2Cpp/Metadata.cs
================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
namespace Il2CppDumper
{
public sealed class Metadata : BinaryStream
{
public Il2CppGlobalMetadataHeader header;
public Il2CppImageDefinition[] imageDefs;
public Il2CppAssemblyDefinition[] assemblyDefs;
public Il2CppTypeDefinition[] typeDefs;
public Il2CppMethodDefinition[] methodDefs;
public Il2CppParameterDefinition[] parameterDefs;
public Il2CppFieldDefinition[] fieldDefs;
private readonly Dictionary<int, Il2CppFieldDefaultValue> fieldDefaultValuesDic;
private readonly Dictionary<int, Il2CppParameterDefaultValue> parameterDefaultValuesDic;
public Il2CppPropertyDefinition[] propertyDefs;
public Il2CppCustomAttributeTypeRange[] attributeTypeRanges;
public Il2CppCustomAttributeDataRange[] attributeDataRanges;
private readonly Dictionary<Il2CppImageDefinition, Dictionary<uint, int>> attributeTypeRangesDic;
public Il2CppStringLiteral[] stringLiterals;
private readonly Il2CppMetadataUsageList[] metadataUsageLists;
private readonly Il2CppMetadataUsagePair[] metadataUsagePairs;
public int[] attributeTypes;
public int[] interfaceIndices;
public Dictionary<Il2CppMetadataUsage, SortedDictionary<uint, uint>> metadataUsageDic;
public long metadataUsagesCount;
public int[] nestedTypeIndices;
public Il2CppEventDefinition[] eventDefs;
public Il2CppGenericContainer[] genericContainers;
public Il2CppFieldRef[] fieldRefs;
public Il2CppGenericParameter[] genericParameters;
public int[] constraintIndices;
public uint[] vtableMethods;
public Il2CppRGCTXDefinition[] rgctxEntries;
private readonly Dictionary<uint, string> stringCache = new();
public Metadata(Stream stream) : base(stream)
{
var sanity = ReadUInt32();
if (sanity != 0xFAB11BAF)
{
throw new InvalidDataException("ERROR: Metadata file supplied is not valid metadata file.");
}
var version = ReadInt32();
if (version < 0 || version > 1000)
{
throw new InvalidDataException("ERROR: Metadata file supplied is not valid metadata file.");
}
if (version < 16 || version > 31)
{
throw new NotSupportedException($"ERROR: Metadata file supplied is not a supported version[{version}].");
}
Version = version;
header = ReadClass<Il2CppGlobalMetadataHeader>(0);
if (version == 24)
{
if (header.stringLiteralOffset == 264)
{
Version = 24.2;
header = ReadClass<Il2CppGlobalMetadataHeader>(0);
}
else
{
imageDefs = ReadMetadataClassArray<Il2CppImageDefinition>(header.imagesOffset, header.imagesSize);
if (imageDefs.Any(x => x.token != 1))
{
Version = 24.1;
}
}
}
imageDefs = ReadMetadataClassArray<Il2CppImageDefinition>(header.imagesOffset, header.imagesSize);
if (Version == 24.2 && header.assembliesSize / 68 < imageDefs.Length)
{
Version = 24.4;
}
var v241Plus = false;
if (Version == 24.1 && header.assembliesSize / 64 == imageDefs.Length)
{
v241Plus = true;
}
if (v241Plus)
{
Version = 24.4;
}
assemblyDefs = ReadMetadataClassArray<Il2CppAssemblyDefinition>(header.assembliesOffset, header.assembliesSize);
if (v241Plus)
{
Version = 24.1;
}
typeDefs = ReadMetadataClassArray<Il2CppTypeDefinition>(header.typeDefinitionsOffset, header.typeDefinitionsSize);
methodDefs = ReadMetadataClassArray<Il2CppMethodDefinition>(header.methodsOffset, header.methodsSize);
parameterDefs = ReadMetadataClassArray<Il2CppParameterDefinition>(header.parametersOffset, header.parametersSize);
fieldDefs = ReadMetadataClassArray<Il2CppFieldDefinition>(header.fieldsOffset, header.fieldsSize);
var fieldDefaultValues = ReadMetadataClassArray<Il2CppFieldDefaultValue>(header.fieldDefaultValuesOffset, header.fieldDefaultValuesSize);
var parameterDefaultValues = ReadMetadataClassArray<Il2CppParameterDefaultValue>(header.parameterDefaultValuesOffset, header.parameterDefaultValuesSize);
fieldDefaultValuesDic = fieldDefaultValues.ToDictionary(x => x.fieldIndex);
parameterDefaultValuesDic = parameterDefaultValues.ToDictionary(x => x.parameterIndex);
propertyDefs = ReadMetadataClassArray<Il2CppPropertyDefinition>(header.propertiesOffset, header.propertiesSize);
interfaceIndices = ReadClassArray<int>(header.interfacesOffset, header.interfacesSize / 4);
nestedTypeIndices = ReadClassArray<int>(header.nestedTypesOffset, header.nestedTypesSize / 4);
eventDefs = ReadMetadataClassArray<Il2CppEventDefinition>(header.eventsOffset, header.eventsSize);
genericContainers = ReadMetadataClassArray<Il2CppGenericContainer>(header.genericContainersOffset, header.genericContainersSize);
genericParameters = ReadMetadataClassArray<Il2CppGenericParameter>(header.genericParametersOffset, header.genericParametersSize);
constraintIndices = ReadClassArray<int>(header.genericParameterConstraintsOffset, header.genericParameterConstraintsSize / 4);
vtableMethods = ReadClassArray<uint>(header.vtableMethodsOffset, header.vtableMethodsSize / 4);
stringLiterals = ReadMetadataClassArray<Il2CppStringLiteral>(header.stringLiteralOffset, header.stringLiteralSize);
if (Version > 16)
{
fieldRefs = ReadMetadataClassArray<Il2CppFieldRef>(header.fieldRefsOffset, header.fieldRefsSize);
if (Version < 27)
{
metadataUsageLists = ReadMetadataClassArray<Il2CppMetadataUsageList>(header.metadataUsageListsOffset, header.metadataUsageListsCount);
metadataUsagePairs = ReadMetadataClassArray<Il2CppMetadataUsagePair>(header.metadataUsagePairsOffset, header.metadataUsagePairsCount);
ProcessingMetadataUsage();
}
}
if (Version > 20 && Version < 29)
{
attributeTypeRanges = ReadMetadataClassArray<Il2CppCustomAttributeTypeRange>(header.attributesInfoOffset, header.attributesInfoCount);
attributeTypes = ReadClassArray<int>(header.attributeTypesOffset, header.attributeTypesCount / 4);
}
if (Version >= 29)
{
attributeDataRanges = ReadMetadataClassArray<Il2CppCustomAttributeDataRange>(header.attributeDataRangeOffset, header.attributeDataRangeSize);
}
if (Version > 24)
{
attributeTypeRangesDic = new Dictionary<Il2CppImageDefinition, Dictionary<uint, int>>();
foreach (var imageDef in imageDefs)
{
var dic = new Dictionary<uint, int>();
attributeTypeRangesDic[imageDef] = dic;
var end = imageDef.customAttributeStart + imageDef.customAttributeCount;
for (int i = imageDef.customAttributeStart; i < end; i++)
{
if (Version >= 29)
{
dic.Add(attributeDataRanges[i].token, i);
}
else
{
dic.Add(attributeTypeRanges[i].token, i);
}
}
}
}
if (Version <= 24.1)
{
rgctxEntries = ReadMetadataClassArray<Il2CppRGCTXDefinition>(header.rgctxEntriesOffset, header.rgctxEntriesCount);
}
}
private T[] ReadMetadataClassArray<T>(uint addr, int count) where T : new()
{
return ReadClassArray<T>(addr, count / SizeOf(typeof(T)));
}
public bool GetFieldDefaultValueFromIndex(int index, out Il2CppFieldDefaultValue value)
{
return fieldDefaultValuesDic.TryGetValue(index, out value);
}
public bool GetParameterDefaultValueFromIndex(int index, out Il2CppParameterDefaultValue value)
{
return parameterDefaultValuesDic.TryGetValue(index, out value);
}
public uint GetDefaultValueFromIndex(int index)
{
return (uint)(header.fieldAndParameterDefaultValueDataOffset + index);
}
public string GetStringFromIndex(uint index)
{
if (!stringCache.TryGetValue(index, out var result))
{
result = ReadStringToNull(header.stringOffset + index);
stringCache.Add(index, result);
}
return result;
}
public int GetCustomAttributeIndex(Il2CppImageDefinition imageDef, int customAttributeIndex, uint token)
{
if (Version > 24)
{
if (attributeTypeRangesDic[imageDef].TryGetValue(token, out var index))
{
return index;
}
else
{
return -1;
}
}
else
{
return customAttributeIndex;
}
}
public string GetStringLiteralFromIndex(uint index)
{
var stringLiteral = stringLiterals[index];
Position = (uint)(header.stringLiteralDataOffset + stringLiteral.dataIndex);
return Encoding.UTF8.GetString(ReadBytes((int)stringLiteral.length));
}
private void ProcessingMetadataUsage()
{
metadataUsageDic = new Dictionary<Il2CppMetadataUsage, SortedDictionary<uint, uint>>();
for (uint i = 1; i <= 6; i++)
{
metadataUsageDic[(Il2CppMetadataUsage)i] = new SortedDictionary<uint, uint>();
}
foreach (var metadataUsageList in metadataUsageLists)
{
for (int i = 0; i < metadataUsageList.count; i++)
{
var offset = metadataUsageList.start + i;
if (offset >= metadataUsagePairs.Length)
{
continue;
}
var metadataUsagePair = metadataUsagePairs[offset];
var usage = GetEncodedIndexType(metadataUsagePair.encodedSourceIndex);
var decodedIndex = GetDecodedMethodIndex(metadataUsagePair.encodedSourceIndex);
metadataUsageDic[(Il2CppMetadataUsage)usage][metadataUsagePair.destinationIndex] = decodedIndex;
}
}
//metadataUsagesCount = metadataUsagePairs.Max(x => x.destinationIndex) + 1;
metadataUsagesCount = metadataUsageDic.Max(x => x.Value.Select(y => y.Key).DefaultIfEmpty().Max()) + 1;
}
public static uint GetEncodedIndexType(uint index)
{
return (index & 0xE0000000) >> 29;
}
public uint GetDecodedMethodIndex(uint index)
{
if (Version >= 27)
{
return (index & 0x1FFFFFFEU) >> 1;
}
return index & 0x1FFFFFFFU;
}
public int SizeOf(Type type)
{
var size = 0;
foreach (var i in type.GetFields())
{
var attr = (VersionAttribute)Attribute.GetCustomAttribute(i, typeof(VersionAttribute));
if (attr != null)
{
if (Version < attr.Min || Version > attr.Max)
continue;
}
var fieldType = i.FieldType;
if (fieldType.IsPrimitive)
{
size += GetPrimitiveTypeSize(fieldType.Name);
}
else if (fieldType.IsEnum)
{
var e = fieldType.GetField("value__").FieldType;
size += GetPrimitiveTypeSize(e.Name);
}
else if (fieldType.IsArray)
{
var arrayLengthAttribute = i.GetCustomAttribute<ArrayLengthAttribute>();
size += arrayLengthAttribute.Length;
}
else
{
size += SizeOf(fieldType);
}
}
return size;
static int GetPrimitiveTypeSize(string name)
{
return name switch
{
"Int32" or "UInt32" => 4,
"Int16" or "UInt16" => 2,
_ => 0,
};
}
}
}
}
================================================
FILE: Il2CppDumper/Il2Cpp/MetadataClass.cs
================================================
using System;
namespace Il2CppDumper
{
public class Il2CppGlobalMetadataHeader
{
public uint sanity;
public int version;
public uint stringLiteralOffset; // string data for managed code
public int stringLiteralSize;
public uint stringLiteralDataOffset;
public int stringLiteralDataSize;
public uint stringOffset; // string data for metadata
public int stringSize;
public uint eventsOffset; // Il2CppEventDefinition
public int eventsSize;
public uint propertiesOffset; // Il2CppPropertyDefinition
public int propertiesSize;
public uint methodsOffset; // Il2CppMethodDefinition
public int methodsSize;
public uint parameterDefaultValuesOffset; // Il2CppParameterDefaultValue
public int parameterDefaultValuesSize;
public uint fieldDefaultValuesOffset; // Il2CppFieldDefaultValue
public int fieldDefaultValuesSize;
public uint fieldAndParameterDefaultValueDataOffset; // uint8_t
public int fieldAndParameterDefaultValueDataSize;
public int fieldMarshaledSizesOffset; // Il2CppFieldMarshaledSize
public int fieldMarshaledSizesSize;
public uint parametersOffset; // Il2CppParameterDefinition
public int parametersSize;
public uint fieldsOffset; // Il2CppFieldDefinition
public int fieldsSize;
public uint genericParametersOffset; // Il2CppGenericParameter
public int genericParametersSize;
public uint genericParameterConstraintsOffset; // TypeIndex
public int genericParameterConstraintsSize;
public uint genericContainersOffset; // Il2CppGenericContainer
public int genericContainersSize;
public uint nestedTypesOffset; // TypeDefinitionIndex
public int nestedTypesSize;
public uint interfacesOffset; // TypeIndex
public int interfacesSize;
public uint vtableMethodsOffset; // EncodedMethodIndex
public int vtableMethodsSize;
public int interfaceOffsetsOffset; // Il2CppInterfaceOffsetPair
public int interfaceOffsetsSize;
public uint typeDefinitionsOffset; // Il2CppTypeDefinition
public int typeDefinitionsSize;
[Version(Max = 24.1)]
public uint rgctxEntriesOffset; // Il2CppRGCTXDefinition
[Version(Max = 24.1)]
public int rgctxEntriesCount;
public uint imagesOffset; // Il2CppImageDefinition
public int imagesSize;
public uint assembliesOffset; // Il2CppAssemblyDefinition
public int assembliesSize;
[Version(Min = 19, Max = 24.5)]
public uint metadataUsageListsOffset; // Il2CppMetadataUsageList
[Version(Min = 19, Max = 24.5)]
public int metadataUsageListsCount;
[Version(Min = 19, Max = 24.5)]
public uint metadataUsagePairsOffset; // Il2CppMetadataUsagePair
[Version(Min = 19, Max = 24.5)]
public int metadataUsagePairsCount;
[Version(Min = 19)]
public uint fieldRefsOffset; // Il2CppFieldRef
[Version(Min = 19)]
public int fieldRefsSize;
[Version(Min = 20)]
public int referencedAssembliesOffset; // int32_t
[Version(Min = 20)]
public int referencedAssembliesSize;
[Version(Min = 21, Max = 27.2)]
public uint attributesInfoOffset; // Il2CppCustomAttributeTypeRange
[Version(Min = 21, Max = 27.2)]
public int attributesInfoCount;
[Version(Min = 21, Max = 27.2)]
public uint attributeTypesOffset; // TypeIndex
[Version(Min = 21, Max = 27.2)]
public int attributeTypesCount;
[Version(Min = 29)]
public uint attributeDataOffset;
[Version(Min = 29)]
public int attributeDataSize;
[Version(Min = 29)]
public uint attributeDataRangeOffset;
[Version(Min = 29)]
public int attributeDataRangeSize;
[Version(Min = 22)]
public int unresolvedVirtualCallParameterTypesOffset; // TypeIndex
[Version(Min = 22)]
public int unresolvedVirtualCallParameterTypesSize;
[Version(Min = 22)]
public int unresolvedVirtualCallParameterRangesOffset; // Il2CppRange
[Version(Min = 22)]
public int unresolvedVirtualCallParameterRangesSize;
[Version(Min = 23)]
public int windowsRuntimeTypeNamesOffset; // Il2CppWindowsRuntimeTypeNamePair
[Version(Min = 23)]
public int windowsRuntimeTypeNamesSize;
[Version(Min = 27)]
public int windowsRuntimeStringsOffset; // const char*
[Version(Min = 27)]
public int windowsRuntimeStringsSize;
[Version(Min = 24)]
public int exportedTypeDefinitionsOffset; // TypeDefinitionIndex
[Version(Min = 24)]
public int exportedTypeDefinitionsSize;
}
public class Il2CppAssemblyDefinition
{
public int imageIndex;
[Version(Min = 24.1)]
public uint token;
[Version(Max = 24)]
public int customAttributeIndex;
[Version(Min = 20)]
public int referencedAssemblyStart;
[Version(Min = 20)]
public int referencedAssemblyCount;
public Il2CppAssemblyNameDefinition aname;
}
public class Il2CppAssemblyNameDefinition
{
public uint nameIndex;
public uint cultureIndex;
[Version(Max = 24.3)]
public int hashValueIndex;
public uint publicKeyIndex;
public uint hash_alg;
public int hash_len;
public uint flags;
public int major;
public int minor;
public int build;
public int revision;
[ArrayLength(Length = 8)]
public byte[] public_key_token;
}
public class Il2CppImageDefinition
{
public uint nameIndex;
public int assemblyIndex;
public int typeStart;
public uint typeCount;
[Version(Min = 24)]
public int exportedTypeStart;
[Version(Min = 24)]
public uint exportedTypeCount;
public int entryPointIndex;
[Version(Min = 19)]
public uint token;
[Version(Min = 24.1)]
public int customAttributeStart;
[Version(Min = 24.1)]
public uint customAttributeCount;
}
public class Il2CppTypeDefinition
{
public uint nameIndex;
public uint namespaceIndex;
[Version(Max = 24)]
public int customAttributeIndex;
public int byvalTypeIndex;
[Version(Max = 24.5)]
public int byrefTypeIndex;
public int declaringTypeIndex;
public int parentIndex;
public int elementTypeIndex; // we can probably remove this one. Only used for enums
[Version(Max = 24.1)]
public int rgctxStartIndex;
[Version(Max = 24.1)]
public int rgctxCount;
public int genericContainerIndex;
[Version(Max = 22)]
public int delegateWrapperFromManagedToNativeIndex;
[Version(Max = 22)]
public int marshalingFunctionsIndex;
[Version(Min = 21, Max = 22)]
public int ccwFunctionIndex;
[Version(Min = 21, Max = 22)]
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_or_windows_runtime;
// 07-10 - One of nine possible PackingSize values (0, 1, 2, 4, 8, 16, 32, 64, or 128)
// 11 - PackingSize is default
// 12 - ClassSize is default
// 13-16 - One of nine possible PackingSize values (0, 1, 2, 4, 8, 16, 32, 64, or 128) - the specified packing size (even for explicit layouts)
public uint bitfield;
[Version(Min = 19)]
public uint token;
public bool IsValueType => (bitfield & 0x1) == 1;
public bool IsEnum => ((bitfield >> 1) & 0x1) == 1;
}
public class Il2CppMethodDefinition
{
public uint nameIndex;
public int declaringType;
public int returnType;
[Version(Min = 31)]
public int returnParameterToken;
public int parameterStart;
[Version(Max = 24)]
public int customAttributeIndex;
public int genericContainerIndex;
[Version(Max = 24.1)]
public int methodIndex;
[Version(Max = 24.1)]
public int invokerIndex;
[Version(Max = 24.1)]
public int delegateWrapperIndex;
[Version(Max = 24.1)]
public int rgctxStartIndex;
[Version(Max = 24.1)]
public int rgctxCount;
public uint token;
public ushort flags;
public ushort iflags;
public ushort slot;
public ushort parameterCount;
}
public class Il2CppParameterDefinition
{
public uint nameIndex;
public uint token;
[Version(Max = 24)]
public int customAttributeIndex;
public int typeIndex;
}
public class Il2CppFieldDefinition
{
public uint nameIndex;
public int typeIndex;
[Version(Max = 24)]
public int customAttributeIndex;
[Version(Min = 19)]
public uint token;
}
public class Il2CppFieldDefaultValue
{
public int fieldIndex;
public int typeIndex;
public int dataIndex;
}
public class Il2CppPropertyDefinition
{
public uint nameIndex;
public int get;
public int set;
public uint attrs;
[Version(Max = 24)]
public int customAttributeIndex;
[Version(Min = 19)]
public uint token;
}
public class Il2CppCustomAttributeTypeRange
{
[Version(Min = 24.1)]
public uint token;
public int start;
public int count;
}
public class Il2CppMetadataUsageList
{
public uint start;
public uint count;
}
public class Il2CppMetadataUsagePair
{
public uint destinationIndex;
public uint encodedSourceIndex;
}
public class Il2CppStringLiteral
{
public uint length;
public int dataIndex;
}
public class Il2CppParameterDefaultValue
{
public int parameterIndex;
public int typeIndex;
public int dataIndex;
}
public class Il2CppEventDefinition
{
public uint nameIndex;
public int typeIndex;
public int add;
public int remove;
public int raise;
[Version(Max = 24)]
public int customAttributeIndex;
[Version(Min = 19)]
public uint token;
}
public class Il2CppGenericContainer
{
/* index of the generic type definition or the generic method definition corresponding to this container */
public int ownerIndex; // either index into Il2CppClass metadata array or Il2CppMethodDefinition array
public int type_argc;
/* If true, we're a generic method, otherwise a generic type definition. */
public int is_method;
/* Our type parameters. */
public int genericParameterStart;
}
public class Il2CppFieldRef
{
public int typeIndex;
public int fieldIndex; // local offset into type fields
}
public class Il2CppGenericParameter
{
public int ownerIndex; /* Type or method this parameter was defined in. */
public uint nameIndex;
public short constraintsStart;
public short constraintsCount;
public ushort num;
public ushort flags;
}
public enum Il2CppRGCTXDataType
{
IL2CPP_RGCTX_DATA_INVALID,
IL2CPP_RGCTX_DATA_TYPE,
IL2CPP_RGCTX_DATA_CLASS,
IL2CPP_RGCTX_DATA_METHOD,
IL2CPP_RGCTX_DATA_ARRAY,
IL2CPP_RGCTX_DATA_CONSTRAINED,
}
public class Il2CppRGCTXDefinitionData
{
public int rgctxDataDummy;
public int methodIndex => rgctxDataDummy;
public int typeIndex => rgctxDataDummy;
}
public class Il2CppRGCTXDefinition
{
public Il2CppRGCTXDataType type => type_post29 == 0 ? (Il2CppRGCTXDataType)type_pre29 : (Il2CppRGCTXDataType)type_post29;
[Version(Max = 27.1)]
public int type_pre29;
[Version(Min = 29)]
public ulong type_post29;
[Version(Max = 27.1)]
public Il2CppRGCTXDefinitionData data;
[Version(Min = 27.2)]
public ulong _data;
}
public enum Il2CppMetadataUsage
{
kIl2CppMetadataUsageInvalid,
kIl2CppMetadataUsageTypeInfo,
kIl2CppMetadataUsageIl2CppType,
kIl2CppMetadataUsageMethodDef,
kIl2CppMetadataUsageFieldInfo,
kIl2CppMetadataUsageStringLiteral,
kIl2CppMetadataUsageMethodRef,
};
public class Il2CppCustomAttributeDataRange
{
public uint token;
public uint startOffset;
}
}
================================================
FILE: Il2CppDumper/Il2CppBinaryNinja/__init__.py
================================================
from binaryninja import *
from os.path import exists
def get_addr(bv: BinaryView, addr: int):
imageBase = bv.start
return imageBase + addr
class Il2CppProcessTask(BackgroundTaskThread):
def __init__(self, bv: BinaryView, script_path: str,
header_path: str):
BackgroundTaskThread.__init__(self, "Il2Cpp start", True)
self.bv = bv
self.script_path = script_path
self.header_path = header_path
self.has_types = False
def process_header(self):
self.progress = "Il2Cpp types (1/3)"
with open(self.header_path) as f:
result = self.bv.parse_types_from_string(f.read())
length = len(result.types)
i = 0
for name in result.types:
i += 1
if i % 100 == 0:
percent = i / length * 100
self.progress = f"Il2Cpp types: {percent:.2f}%"
if self.bv.get_type_by_name(name):
continue
self.bv.define_user_type(name, result.types[name])
def process_methods(self, data: dict):
self.progress = f"Il2Cpp methods (2/3)"
scriptMethods = data["ScriptMethod"]
length = len(scriptMethods)
i = 0
for scriptMethod in scriptMethods:
if self.cancelled:
self.progress = "Il2Cpp cancelled, aborting"
return
i += 1
if i % 100 == 0:
percent = i / length * 100
self.progress = f"Il2Cpp methods: {percent:.2f}%"
addr = get_addr(self.bv, scriptMethod["Address"])
name = scriptMethod["Name"].replace("$", "_").replace(".", "_")
signature = scriptMethod["Signature"]
func = self.bv.get_function_at(addr)
if func != None:
if func.name == name:
continue
if self.has_types:
func.function_type = signature
else:
func.name = scriptMethod["Name"]
def process_strings(self, data: dict):
self.progress = "Il2Cpp strings (3/3)"
scriptStrings = data["ScriptString"]
i = 0
for scriptString in scriptStrings:
i += 1
if self.cancelled:
self.progress = "Il2Cpp cancelled, aborting"
return
addr = get_addr(self.bv, scriptString["Address"])
value = scriptString["Value"]
var = self.bv.get_data_var_at(addr)
if var != None:
var.name = f"StringLiteral_{i}"
self.bv.set_comment_at(addr, value)
def run(self):
if exists(self.header_path):
self.process_header()
else:
log_warn("Header file not found")
if self.bv.get_type_by_name("Il2CppClass"):
self.has_types = True
data = json.loads(open(self.script_path, 'rb').read().decode('utf-8'))
if "ScriptMethod" in data:
self.process_methods(data)
if "ScriptString" in data:
self.process_strings(data)
def process(bv: BinaryView):
scriptDialog = OpenFileNameField("Select script.json", "script.json", "script.json")
headerDialog = OpenFileNameField("Select il2cpp_binja.h", "il2cpp_binja.h", "il2cpp_binja.h")
if not get_form_input([scriptDialog, headerDialog], "script.json from Il2CppDumper"):
return log_error("File not selected, try again!")
if not exists(scriptDialog.result):
return log_error("File not found, try again!")
task = Il2CppProcessTask(bv, scriptDialog.result, headerDialog.result)
task.start()
PluginCommand.register("Il2CppDumper", "Process file", process)
================================================
FILE: Il2CppDumper/Il2CppBinaryNinja/plugin.json
================================================
{
"pluginmetadataversion": 2,
"name": "Il2CppDumper",
"type": [
"core",
"ui",
"binaryview"
],
"api": [
"python3"
],
"description": "Add Il2Cpp structs and method signatures",
"longdescription": "",
"license": {
"name": "MIT",
"text": "Copyright (c) 2022 Il2CppDumper contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
},
"platforms": [
"Darwin",
"Linux",
"Windows"
],
"installinstructions": {
"Darwin": "Install Il2CppDumper",
"Linux": "Install Il2CppDumper",
"Windows": "Install Il2CppDumper"
},
"dependencies": {
},
"version": "1.0.0",
"author": "Il2CppDumper contributors",
"minimumbinaryninjaversion": 3164
}
================================================
FILE: Il2CppDumper/Il2CppDumper.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
<Version>1.0.0.0</Version>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>
<Copyright>Copyright © Perfare 2016-2024</Copyright>
<DebugType>embedded</DebugType>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Mono.Cecil" Version="0.11.4" />
</ItemGroup>
<ItemGroup>
<Compile Update="Resource1.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resource1.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Resource1.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resource1.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Update="config.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="ghidra.py">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="ghidra_wasm.py">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="ghidra_with_struct.py">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="ida.py">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="ida_py3.py">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="ida_with_struct.py">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="ida_with_struct_py3.py">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="il2cpp_header_to_ghidra.py">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
================================================
FILE: Il2CppDumper/Outputs/DummyAssemblyExporter.cs
================================================
using System.IO;
namespace Il2CppDumper
{
public static class DummyAssemblyExporter
{
public static void Export(Il2CppExecutor il2CppExecutor, string outputDir, bool addToken)
{
Directory.SetCurrentDirectory(outputDir);
if (Directory.Exists("DummyDll"))
Directory.Delete("DummyDll", true);
Directory.CreateDirectory("DummyDll");
Directory.SetCurrentDirectory("DummyDll");
var dummy = new DummyAssemblyGenerator(il2CppExecutor, addToken);
foreach (var assembly in dummy.Assemblies)
{
using var stream = new MemoryStream();
assembly.Write(stream);
File.WriteAllBytes(assembly.MainModule.Name, stream.ToArray());
}
}
}
}
================================================
FILE: Il2CppDumper/Outputs/HeaderConstants.cs
================================================
namespace Il2CppDumper
{
public static class HeaderConstants
{
public readonly static string GenericHeader =
@"typedef void(*Il2CppMethodPointer)();
struct MethodInfo;
struct VirtualInvokeData
{
Il2CppMethodPointer methodPtr;
const MethodInfo* method;
};
struct Il2CppType
{
void* data;
unsigned int bits;
};
struct Il2CppClass;
struct Il2CppObject
{
Il2CppClass *klass;
void *monitor;
};
union Il2CppRGCTXData
{
void* rgctxDataDummy;
const MethodInfo* method;
const Il2CppType* type;
Il2CppClass* klass;
};
struct Il2CppRuntimeInterfaceOffsetPair
{
Il2CppClass* interfaceType;
int32_t offset;
};
";
public readonly static string HeaderV29 =
@"struct Il2CppClass_1
{
void* image;
void* gc_desc;
const char* name;
const char* namespaze;
Il2CppType byval_arg;
Il2CppType this_arg;
Il2CppClass* element_class;
Il2CppClass* castClass;
Il2CppClass* declaringType;
Il2CppClass* parent;
void *generic_class;
void* typeMetadataHandle;
void* interopData;
Il2CppClass* klass;
void* fields;
void* events;
void* properties;
void* methods;
Il2CppClass** nestedTypes;
Il2CppClass** implementedInterfaces;
Il2CppRuntimeInterfaceOffsetPair* interfaceOffsets;
};
struct Il2CppClass_2
{
Il2CppClass** typeHierarchy;
void *unity_user_data;
uint32_t initializationExceptionGCHandle;
uint32_t cctor_started;
uint32_t cctor_finished;
size_t cctor_thread;
void* genericContainerHandle;
uint32_t instance_size;
uint32_t actualSize;
uint32_t element_size;
int32_t native_size;
uint32_t static_fields_size;
uint32_t thread_static_fields_size;
int32_t thread_static_fields_offset;
uint32_t flags;
uint32_t token;
uint16_t method_count;
uint16_t property_count;
uint16_t field_count;
uint16_t event_count;
uint16_t nested_type_count;
uint16_t vtable_count;
uint16_t interfaces_count;
uint16_t interface_offsets_count;
uint8_t typeHierarchyDepth;
uint8_t genericRecursionDepth;
uint8_t rank;
uint8_t minimumAlignment;
uint8_t naturalAligment;
uint8_t packingSize;
uint8_t bitflags1;
uint8_t bitflags2;
};
struct Il2CppClass
{
Il2CppClass_1 _1;
void* static_fields;
Il2CppRGCTXData* rgctx_data;
Il2CppClass_2 _2;
VirtualInvokeData vtable[255];
};
typedef uintptr_t il2cpp_array_size_t;
typedef int32_t il2cpp_array_lower_bound_t;
struct Il2CppArrayBounds
{
il2cpp_array_size_t length;
il2cpp_array_lower_bound_t lower_bound;
};
typedef void (*InvokerMethod)(Il2CppMethodPointer, const MethodInfo*, void*, void**, void*);
struct MethodInfo
{
Il2CppMethodPointer methodPointer;
Il2CppMethodPointer virtualMethodPointer;
InvokerMethod invoker_method;
const char* name;
Il2CppClass *klass;
const Il2CppType *return_type;
const Il2CppType** parameters;
union
{
const Il2CppRGCTXData* rgctx_data;
const void* methodMetadataHandle;
};
union
{
const void* genericMethod;
const void* genericContainerHandle;
};
uint32_t token;
uint16_t flags;
uint16_t iflags;
uint16_t slot;
uint8_t parameters_count;
uint8_t bitflags;
};
";
public readonly static string HeaderV27 =
@"struct Il2CppClass_1
{
void* image;
void* gc_desc;
const char* name;
const char* namespaze;
Il2CppType byval_arg;
Il2CppType this_arg;
Il2CppClass* element_class;
Il2CppClass* castClass;
Il2CppClass* declaringType;
Il2CppClass* parent;
void *generic_class;
void* typeMetadataHandle;
void* interopData;
Il2CppClass* klass;
void* fields;
void* events;
void* properties;
void* methods;
Il2CppClass** nestedTypes;
Il2CppClass** implementedInterfaces;
Il2CppRuntimeInterfaceOffsetPair* interfaceOffsets;
};
struct Il2CppClass_2
{
Il2CppClass** typeHierarchy;
void *unity_user_data;
uint32_t initializationExceptionGCHandle;
uint32_t cctor_started;
uint32_t cctor_finished;
size_t cctor_thread;
void* genericContainerHandle;
uint32_t instance_size;
uint32_t actualSize;
uint32_t element_size;
int32_t native_size;
uint32_t static_fields_size;
uint32_t thread_static_fields_size;
int32_t thread_static_fields_offset;
uint32_t flags;
uint32_t token;
uint16_t method_count;
uint16_t property_count;
uint16_t field_count;
uint16_t event_count;
uint16_t nested_type_count;
uint16_t vtable_count;
uint16_t interfaces_count;
uint16_t interface_offsets_count;
uint8_t typeHierarchyDepth;
uint8_t genericRecursionDepth;
uint8_t rank;
uint8_t minimumAlignment;
uint8_t naturalAligment;
uint8_t packingSize;
uint8_t bitflags1;
uint8_t bitflags2;
};
struct Il2CppClass
{
Il2CppClass_1 _1;
void* static_fields;
Il2CppRGCTXData* rgctx_data;
Il2CppClass_2 _2;
VirtualInvokeData vtable[255];
};
typedef uintptr_t il2cpp_array_size_t;
typedef int32_t il2cpp_array_lower_bound_t;
struct Il2CppArrayBounds
{
il2cpp_array_size_t length;
il2cpp_array_lower_bound_t lower_bound;
};
struct MethodInfo
{
Il2CppMethodPointer methodPointer;
void* invoker_method;
const char* name;
Il2CppClass *klass;
const Il2CppType *return_type;
const void* parameters;
union
{
const Il2CppRGCTXData* rgctx_data;
const void* methodMetadataHandle;
};
union
{
const void* genericMethod;
const void* genericContainerHandle;
};
uint32_t token;
uint16_t flags;
uint16_t iflags;
uint16_t slot;
uint8_t parameters_count;
uint8_t bitflags;
};
";
public readonly static string HeaderV242 =
@"struct Il2CppClass_1
{
void* image;
void* gc_desc;
const char* name;
const char* namespaze;
Il2CppType byval_arg;
Il2CppType this_arg;
Il2CppClass* element_class;
Il2CppClass* castClass;
Il2CppClass* declaringType;
Il2CppClass* parent;
void *generic_class;
void* typeDefinition;
void* interopData;
Il2CppClass* klass;
void* fields;
void* events;
void* properties;
void* methods;
Il2CppClass** nestedTypes;
Il2CppClass** implementedInterfaces;
Il2CppRuntimeInterfaceOffsetPair* interfaceOffsets;
};
struct Il2CppClass_2
{
Il2CppClass** typeHierarchy;
void *unity_user_data;
uint32_t initializationExceptionGCHandle;
uint32_t cctor_started;
uint32_t cctor_finished;
size_t cctor_thread;
int32_t genericContainerIndex;
uint32_t instance_size;
uint32_t ac
gitextract_h0jok5q9/ ├── .gitattributes ├── .github/ │ └── ISSUE_TEMPLATE/ │ ├── config.yml │ ├── problem_report.md │ └── problem_report_cn.md ├── .gitignore ├── Il2CppDumper/ │ ├── Attributes/ │ │ ├── ArrayLengthAttribute.cs │ │ └── VersionAttribute.cs │ ├── Config.cs │ ├── ExecutableFormats/ │ │ ├── Elf.cs │ │ ├── Elf64.cs │ │ ├── ElfBase.cs │ │ ├── ElfClass.cs │ │ ├── Macho.cs │ │ ├── Macho64.cs │ │ ├── MachoClass.cs │ │ ├── MachoFat.cs │ │ ├── NSO.cs │ │ ├── NSOClass.cs │ │ ├── PE.cs │ │ ├── PEClass.cs │ │ ├── WebAssembly.cs │ │ ├── WebAssemblyClass.cs │ │ └── WebAssemblyMemory.cs │ ├── Extensions/ │ │ ├── BinaryReaderExtensions.cs │ │ ├── BoyerMooreHorspool.cs │ │ ├── HexExtensions.cs │ │ └── StringExtensions.cs │ ├── IO/ │ │ ├── BinaryStream.cs │ │ └── Lz4DecoderStream.cs │ ├── Il2Cpp/ │ │ ├── Il2Cpp.cs │ │ ├── Il2CppClass.cs │ │ ├── Metadata.cs │ │ └── MetadataClass.cs │ ├── Il2CppBinaryNinja/ │ │ ├── __init__.py │ │ └── plugin.json │ ├── Il2CppDumper.csproj │ ├── Outputs/ │ │ ├── DummyAssemblyExporter.cs │ │ ├── HeaderConstants.cs │ │ ├── Il2CppConstants.cs │ │ ├── Il2CppDecompiler.cs │ │ ├── ScriptJson.cs │ │ ├── StructGenerator.cs │ │ └── StructInfo.cs │ ├── Program.cs │ ├── Resource1.Designer.cs │ ├── Resource1.resx │ ├── Utils/ │ │ ├── ArmUtils.cs │ │ ├── AttributeArgument.cs │ │ ├── BlobValue.cs │ │ ├── CustomAttributeDataReader.cs │ │ ├── CustomAttributeReaderVisitor.cs │ │ ├── DummyAssemblyGenerator.cs │ │ ├── FileDialogNative.cs │ │ ├── Il2CppExecutor.cs │ │ ├── MyAssemblyResolver.cs │ │ ├── OpenFileDialog.cs │ │ ├── PELoader.cs │ │ ├── SearchSection.cs │ │ └── SectionHelper.cs │ ├── config.json │ ├── ghidra.py │ ├── ghidra_wasm.py │ ├── ghidra_with_struct.py │ ├── hopper-py3.py │ ├── ida.py │ ├── ida_py3.py │ ├── ida_with_struct.py │ ├── ida_with_struct_py3.py │ ├── il2cpp_header_to_binja.py │ └── il2cpp_header_to_ghidra.py ├── Il2CppDumper.sln ├── LICENSE ├── README.md └── README.zh-CN.md
SYMBOL INDEX (477 symbols across 60 files)
FILE: Il2CppDumper/Attributes/ArrayLengthAttribute.cs
class ArrayLengthAttribute (line 5) | [AttributeUsage(AttributeTargets.Field)]
FILE: Il2CppDumper/Attributes/VersionAttribute.cs
class VersionAttribute (line 5) | [AttributeUsage(AttributeTargets.Field, AllowMultiple = true)]
FILE: Il2CppDumper/Config.cs
class Config (line 3) | public class Config
FILE: Il2CppDumper/ExecutableFormats/Elf.cs
class Elf (line 9) | public sealed class Elf : ElfBase
method Elf (line 26) | public Elf(Stream stream) : base(stream)
method Load (line 32) | protected override void Load()
method CheckSection (line 57) | protected override bool CheckSection()
method MapVATR (line 80) | public override ulong MapVATR(ulong addr)
method MapRTVA (line 86) | public override ulong MapRTVA(ulong addr)
method Search (line 96) | public override bool Search()
method PlusSearch (line 152) | public override bool PlusSearch(int methodCount, int typeDefinitionsCo...
method SymbolSearch (line 160) | public override bool SymbolSearch()
method ReadSymbol (line 190) | private void ReadSymbol()
method RelocationProcessing (line 243) | private void RelocationProcessing()
method CheckProtection (line 275) | private bool CheckProtection()
method GetRVA (line 310) | public override ulong GetRVA(ulong pointer)
method FixedProgramSegment (line 319) | private void FixedProgramSegment()
method FixedDynamicSection (line 335) | private void FixedDynamicSection()
method GetSectionHelper (line 361) | public override SectionHelper GetSectionHelper(int methodCount, int ty...
FILE: Il2CppDumper/ExecutableFormats/Elf64.cs
class Elf64 (line 9) | public sealed class Elf64 : ElfBase
method Elf64 (line 18) | public Elf64(Stream stream) : base(stream)
method Load (line 23) | protected override void Load()
method CheckSection (line 48) | protected override bool CheckSection()
method MapVATR (line 71) | public override ulong MapVATR(ulong addr)
method MapRTVA (line 77) | public override ulong MapRTVA(ulong addr)
method Search (line 87) | public override bool Search()
method PlusSearch (line 92) | public override bool PlusSearch(int methodCount, int typeDefinitionsCo...
method SymbolSearch (line 100) | public override bool SymbolSearch()
method ReadSymbol (line 130) | private void ReadSymbol()
method RelocationProcessing (line 183) | private void RelocationProcessing()
method CheckProtection (line 218) | private bool CheckProtection()
method GetRVA (line 253) | public override ulong GetRVA(ulong pointer)
method FixedProgramSegment (line 262) | private void FixedProgramSegment()
method FixedDynamicSection (line 278) | private void FixedDynamicSection()
method GetSectionHelper (line 304) | public override SectionHelper GetSectionHelper(int methodCount, int ty...
FILE: Il2CppDumper/ExecutableFormats/ElfBase.cs
class ElfBase (line 5) | public abstract class ElfBase : Il2Cpp
method ElfBase (line 7) | protected ElfBase(Stream stream) : base(stream) { }
method Load (line 8) | protected abstract void Load();
method CheckSection (line 9) | protected abstract bool CheckSection();
method CheckDump (line 11) | public override bool CheckDump() => !CheckSection();
method Reload (line 13) | public void Reload() => Load();
FILE: Il2CppDumper/ExecutableFormats/ElfClass.cs
class Elf32_Ehdr (line 3) | public class Elf32_Ehdr
class Elf32_Phdr (line 28) | public class Elf32_Phdr
class Elf32_Shdr (line 40) | public class Elf32_Shdr
class Elf32_Sym (line 54) | public class Elf32_Sym
class Elf32_Dyn (line 64) | public class Elf32_Dyn
class Elf32_Rel (line 70) | public class Elf32_Rel
class Elf64_Ehdr (line 76) | public class Elf64_Ehdr
class Elf64_Phdr (line 101) | public class Elf64_Phdr
class Elf64_Shdr (line 113) | public class Elf64_Shdr
class Elf64_Sym (line 127) | public class Elf64_Sym
class Elf64_Dyn (line 137) | public class Elf64_Dyn
class Elf64_Rela (line 143) | public class Elf64_Rela
class ElfConstants (line 150) | public static class ElfConstants
FILE: Il2CppDumper/ExecutableFormats/Macho.cs
class Macho (line 10) | public sealed class Macho : Il2Cpp
method Macho (line 17) | public Macho(Stream stream) : base(stream)
method Init (line 70) | public override void Init(ulong codeRegistration, ulong metadataRegist...
method MapVATR (line 77) | public override ulong MapVATR(ulong addr)
method MapRTVA (line 83) | public override ulong MapRTVA(ulong addr)
method Search (line 93) | public override bool Search()
method PlusSearch (line 177) | public override bool PlusSearch(int methodCount, int typeDefinitionsCo...
method SymbolSearch (line 185) | public override bool SymbolSearch()
method GetRVA (line 190) | public override ulong GetRVA(ulong pointer)
method GetSectionHelper (line 195) | public override SectionHelper GetSectionHelper(int methodCount, int ty...
method CheckDump (line 207) | public override bool CheckDump() => false;
FILE: Il2CppDumper/ExecutableFormats/Macho64.cs
class Macho64 (line 10) | public sealed class Macho64 : Il2Cpp
method Macho64 (line 17) | public Macho64(Stream stream) : base(stream)
method MapVATR (line 69) | public override ulong MapVATR(ulong addr)
method MapRTVA (line 79) | public override ulong MapRTVA(ulong addr)
method Search (line 93) | public override bool Search()
method PlusSearch (line 239) | public override bool PlusSearch(int methodCount, int typeDefinitionsCo...
method SymbolSearch (line 247) | public override bool SymbolSearch()
method GetRVA (line 252) | public override ulong GetRVA(ulong pointer)
method GetSectionHelper (line 257) | public override SectionHelper GetSectionHelper(int methodCount, int ty...
method CheckDump (line 269) | public override bool CheckDump() => false;
method ReadUIntPtr (line 271) | public override ulong ReadUIntPtr()
FILE: Il2CppDumper/ExecutableFormats/MachoClass.cs
class MachoSection (line 3) | public class MachoSection
class MachoSection64Bit (line 12) | public class MachoSection64Bit
class Fat (line 21) | public class Fat
FILE: Il2CppDumper/ExecutableFormats/MachoFat.cs
class MachoFat (line 6) | public sealed class MachoFat : BinaryStream
method MachoFat (line 10) | public MachoFat(Stream stream) : base(stream)
method GetMacho (line 32) | public byte[] GetMacho(int index)
FILE: Il2CppDumper/ExecutableFormats/NSO.cs
class NSO (line 9) | public sealed class NSO : Il2Cpp
method NSO (line 21) | public NSO(Stream stream) : base(stream)
method ReadSymbol (line 114) | private void ReadSymbol()
method RelocationProcessing (line 167) | private void RelocationProcessing()
method MapVATR (line 203) | public override ulong MapVATR(ulong addr)
method MapRTVA (line 209) | public override ulong MapRTVA(ulong addr)
method Search (line 219) | public override bool Search()
method PlusSearch (line 224) | public override bool PlusSearch(int methodCount, int typeDefinitionsCo...
method SymbolSearch (line 232) | public override bool SymbolSearch()
method UnCompress (line 237) | public NSO UnCompress()
method GetSectionHelper (line 325) | public override SectionHelper GetSectionHelper(int methodCount, int ty...
method CheckDump (line 334) | public override bool CheckDump() => false;
FILE: Il2CppDumper/ExecutableFormats/NSOClass.cs
class NSOHeader (line 3) | public class NSOHeader
class NSOSegmentHeader (line 30) | public class NSOSegmentHeader
class NSORelativeExtent (line 37) | public class NSORelativeExtent
FILE: Il2CppDumper/ExecutableFormats/PE.cs
class PE (line 8) | public sealed class PE : Il2Cpp
method PE (line 12) | public PE(Stream stream) : base(stream)
method LoadFromMemory (line 47) | public void LoadFromMemory(ulong addr)
method MapVATR (line 57) | public override ulong MapVATR(ulong absAddr)
method MapRTVA (line 68) | public override ulong MapRTVA(ulong addr)
method Search (line 78) | public override bool Search()
method PlusSearch (line 83) | public override bool PlusSearch(int methodCount, int typeDefinitionsCo...
method SymbolSearch (line 91) | public override bool SymbolSearch()
method GetRVA (line 96) | public override ulong GetRVA(ulong pointer)
method GetSectionHelper (line 101) | public override SectionHelper GetSectionHelper(int methodCount, int ty...
method CheckDump (line 127) | public override bool CheckDump()
FILE: Il2CppDumper/ExecutableFormats/PEClass.cs
class DosHeader (line 5) | public class DosHeader
class FileHeader (line 30) | public class FileHeader
class OptionalHeader (line 41) | public class OptionalHeader
class OptionalHeader64 (line 76) | public class OptionalHeader64
class SectionHeader (line 116) | public class SectionHeader
type SectionCharacteristics (line 131) | [Flags]
FILE: Il2CppDumper/ExecutableFormats/WebAssembly.cs
class WebAssembly (line 6) | public sealed class WebAssembly : BinaryStream
method WebAssembly (line 10) | public WebAssembly(Stream stream) : base(stream)
method CreateMemory (line 47) | public WebAssemblyMemory CreateMemory()
FILE: Il2CppDumper/ExecutableFormats/WebAssemblyClass.cs
class DataSection (line 3) | public class DataSection
FILE: Il2CppDumper/ExecutableFormats/WebAssemblyMemory.cs
class WebAssemblyMemory (line 5) | public sealed class WebAssemblyMemory : Il2Cpp
method WebAssemblyMemory (line 9) | public WebAssemblyMemory(Stream stream, uint bssStart) : base(stream)
method MapVATR (line 15) | public override ulong MapVATR(ulong addr)
method MapRTVA (line 20) | public override ulong MapRTVA(ulong addr)
method PlusSearch (line 25) | public override bool PlusSearch(int methodCount, int typeDefinitionsCo...
method Search (line 33) | public override bool Search()
method SymbolSearch (line 38) | public override bool SymbolSearch()
method GetSectionHelper (line 43) | public override SectionHelper GetSectionHelper(int methodCount, int ty...
method CheckDump (line 73) | public override bool CheckDump() => false;
FILE: Il2CppDumper/Extensions/BinaryReaderExtensions.cs
class BinaryReaderExtensions (line 7) | public static class BinaryReaderExtensions
method ReadString (line 9) | public static string ReadString(this BinaryReader reader, int numChars)
method ReadULeb128 (line 20) | public static uint ReadULeb128(this BinaryReader reader)
method ReadCompressedUInt32 (line 39) | public static uint ReadCompressedUInt32(this BinaryReader reader)
method ReadCompressedInt32 (line 86) | public static int ReadCompressedInt32(this BinaryReader reader)
FILE: Il2CppDumper/Extensions/BoyerMooreHorspool.cs
class BoyerMooreHorspool (line 6) | static class BoyerMooreHorspool
method Search (line 8) | public static IEnumerable<int> Search(this byte[] source, byte[] pattern)
method Search (line 59) | public static IEnumerable<int> Search(this byte[] source, string strin...
method CheckEqual (line 116) | private static bool CheckEqual(byte[] source, string[] pattern, int in...
FILE: Il2CppDumper/Extensions/HexExtensions.cs
class HexExtensions (line 6) | static class HexExtensions
method HexToBin (line 8) | public static string HexToBin(this byte b)
method HexToBin (line 13) | public static string HexToBin(this byte[] bytes)
FILE: Il2CppDumper/Extensions/StringExtensions.cs
class StringExtensions (line 5) | public static class StringExtensions
method ToEscapedString (line 7) | public static string ToEscapedString(this string s)
FILE: Il2CppDumper/IO/BinaryStream.cs
class BinaryStream (line 10) | public class BinaryStream : IDisposable
method BinaryStream (line 23) | public BinaryStream(Stream input)
method ReadBoolean (line 34) | public bool ReadBoolean() => reader.ReadBoolean();
method ReadByte (line 36) | public byte ReadByte() => reader.ReadByte();
method ReadBytes (line 38) | public byte[] ReadBytes(int count) => reader.ReadBytes(count);
method ReadSByte (line 40) | public sbyte ReadSByte() => reader.ReadSByte();
method ReadInt16 (line 42) | public short ReadInt16() => reader.ReadInt16();
method ReadUInt16 (line 44) | public ushort ReadUInt16() => reader.ReadUInt16();
method ReadInt32 (line 46) | public int ReadInt32() => reader.ReadInt32();
method ReadUInt32 (line 48) | public uint ReadUInt32() => reader.ReadUInt32();
method ReadInt64 (line 50) | public long ReadInt64() => reader.ReadInt64();
method ReadUInt64 (line 52) | public ulong ReadUInt64() => reader.ReadUInt64();
method ReadSingle (line 54) | public float ReadSingle() => reader.ReadSingle();
method ReadDouble (line 56) | public double ReadDouble() => reader.ReadDouble();
method ReadCompressedUInt32 (line 58) | public uint ReadCompressedUInt32() => reader.ReadCompressedUInt32();
method ReadCompressedInt32 (line 60) | public int ReadCompressedInt32() => reader.ReadCompressedInt32();
method ReadULeb128 (line 62) | public uint ReadULeb128() => reader.ReadULeb128();
method Write (line 64) | public void Write(bool value) => writer.Write(value);
method Write (line 66) | public void Write(byte value) => writer.Write(value);
method Write (line 68) | public void Write(sbyte value) => writer.Write(value);
method Write (line 70) | public void Write(short value) => writer.Write(value);
method Write (line 72) | public void Write(ushort value) => writer.Write(value);
method Write (line 74) | public void Write(int value) => writer.Write(value);
method Write (line 76) | public void Write(uint value) => writer.Write(value);
method Write (line 78) | public void Write(long value) => writer.Write(value);
method Write (line 80) | public void Write(ulong value) => writer.Write(value);
method Write (line 82) | public void Write(float value) => writer.Write(value);
method Write (line 84) | public void Write(double value) => writer.Write(value);
method ReadPrimitive (line 94) | private object ReadPrimitive(Type type)
method ReadClass (line 109) | public T ReadClass<T>(ulong addr) where T : new()
method ReadClass (line 115) | public T ReadClass<T>() where T : new()
method ReadClassArray (line 185) | public T[] ReadClassArray<T>(long count) where T : new()
method ReadClassArray (line 195) | public T[] ReadClassArray<T>(ulong addr, ulong count) where T : new()
method ReadClassArray (line 200) | public T[] ReadClassArray<T>(ulong addr, long count) where T : new()
method ReadStringToNull (line 206) | public string ReadStringToNull(ulong addr)
method ReadIntPtr (line 216) | public long ReadIntPtr()
method ReadUIntPtr (line 221) | public virtual ulong ReadUIntPtr()
method Dispose (line 235) | protected virtual void Dispose(bool disposing)
method Dispose (line 245) | public void Dispose()
FILE: Il2CppDumper/IO/Lz4DecoderStream.cs
class Lz4DecoderStream (line 10) | public class Lz4DecoderStream : Stream
method Lz4DecoderStream (line 12) | public Lz4DecoderStream(Stream input, long inputLength = long.MaxValue)
method Reset (line 17) | private void Reset(Stream input, long inputLength = long.MaxValue)
method Dispose (line 34) | protected override void Dispose(bool disposing)
type DecodePhase (line 72) | private enum DecodePhase
method Read (line 87) | public override int Read(byte[] buffer, int offset, int count)
method ReadByteCore (line 377) | private int ReadByteCore()
method ReadOffsetCore (line 400) | private int ReadOffsetCore()
method ReadCore (line 449) | private int ReadCore(byte[] buffer, int offset, int count)
method Flush (line 511) | public override void Flush()
method Seek (line 523) | public override long Seek(long offset, SeekOrigin origin)
method SetLength (line 528) | public override void SetLength(long value)
method Write (line 533) | public override void Write(byte[] buffer, int offset, int count)
FILE: Il2CppDumper/Il2Cpp/Il2Cpp.cs
class Il2Cpp (line 8) | public abstract class Il2Cpp : BinaryStream
method MapVATR (line 35) | public abstract ulong MapVATR(ulong addr);
method MapRTVA (line 36) | public abstract ulong MapRTVA(ulong addr);
method Search (line 37) | public abstract bool Search();
method PlusSearch (line 38) | public abstract bool PlusSearch(int methodCount, int typeDefinitionsCo...
method SymbolSearch (line 39) | public abstract bool SymbolSearch();
method GetSectionHelper (line 40) | public abstract SectionHelper GetSectionHelper(int methodCount, int ty...
method CheckDump (line 41) | public abstract bool CheckDump();
method Il2Cpp (line 43) | protected Il2Cpp(Stream stream) : base(stream) { }
method SetProperties (line 45) | public void SetProperties(double version, long metadataUsagesCount)
method AutoPlusInit (line 51) | protected bool AutoPlusInit(ulong codeRegistration, ulong metadataRegi...
method Init (line 120) | public virtual void Init(ulong codeRegistration, ulong metadataRegistr...
method MapVATR (line 259) | public T MapVATR<T>(ulong addr) where T : new()
method MapVATR (line 264) | public T[] MapVATR<T>(ulong addr, ulong count) where T : new()
method MapVATR (line 269) | public T[] MapVATR<T>(ulong addr, long count) where T : new()
method GetFieldOffsetFromIndex (line 274) | public int GetFieldOffsetFromIndex(int typeIndex, int fieldIndexInType...
method GetIl2CppType (line 314) | public Il2CppType GetIl2CppType(ulong pointer)
method GetMethodPointer (line 323) | public ulong GetMethodPointer(string imageName, Il2CppMethodDefinition...
method GetRVA (line 343) | public virtual ulong GetRVA(ulong pointer)
FILE: Il2CppDumper/Il2Cpp/Il2CppClass.cs
class Il2CppCodeRegistration (line 5) | public class Il2CppCodeRegistration
class Il2CppMetadataRegistration (line 68) | public class Il2CppMetadataRegistration
type Il2CppTypeEnum (line 96) | public enum Il2CppTypeEnum
class Il2CppType (line 139) | public class Il2CppType
method Init (line 151) | public void Init(double version)
class Union (line 171) | public class Union
class Il2CppGenericClass (line 205) | public class Il2CppGenericClass
class Il2CppGenericContext (line 215) | public class Il2CppGenericContext
class Il2CppGenericInst (line 223) | public class Il2CppGenericInst
class Il2CppArrayType (line 229) | public class Il2CppArrayType
class Il2CppGenericMethodFunctionsDefinitions (line 239) | public class Il2CppGenericMethodFunctionsDefinitions
class Il2CppGenericMethodIndices (line 245) | public class Il2CppGenericMethodIndices
class Il2CppMethodSpec (line 254) | public class Il2CppMethodSpec
class Il2CppCodeGenModule (line 261) | public class Il2CppCodeGenModule
class Il2CppRange (line 292) | public class Il2CppRange
class Il2CppTokenRangePair (line 298) | public class Il2CppTokenRangePair
FILE: Il2CppDumper/Il2Cpp/Metadata.cs
class Metadata (line 10) | public sealed class Metadata : BinaryStream
method Metadata (line 43) | public Metadata(Stream stream) : base(stream)
method ReadMetadataClassArray (line 160) | private T[] ReadMetadataClassArray<T>(uint addr, int count) where T : ...
method GetFieldDefaultValueFromIndex (line 165) | public bool GetFieldDefaultValueFromIndex(int index, out Il2CppFieldDe...
method GetParameterDefaultValueFromIndex (line 170) | public bool GetParameterDefaultValueFromIndex(int index, out Il2CppPar...
method GetDefaultValueFromIndex (line 175) | public uint GetDefaultValueFromIndex(int index)
method GetStringFromIndex (line 180) | public string GetStringFromIndex(uint index)
method GetCustomAttributeIndex (line 190) | public int GetCustomAttributeIndex(Il2CppImageDefinition imageDef, int...
method GetStringLiteralFromIndex (line 209) | public string GetStringLiteralFromIndex(uint index)
method ProcessingMetadataUsage (line 216) | private void ProcessingMetadataUsage()
method GetEncodedIndexType (line 242) | public static uint GetEncodedIndexType(uint index)
method GetDecodedMethodIndex (line 247) | public uint GetDecodedMethodIndex(uint index)
method SizeOf (line 256) | public int SizeOf(Type type)
FILE: Il2CppDumper/Il2Cpp/MetadataClass.cs
class Il2CppGlobalMetadataHeader (line 5) | public class Il2CppGlobalMetadataHeader
class Il2CppAssemblyDefinition (line 111) | public class Il2CppAssemblyDefinition
class Il2CppAssemblyNameDefinition (line 125) | public class Il2CppAssemblyNameDefinition
class Il2CppImageDefinition (line 143) | public class Il2CppImageDefinition
class Il2CppTypeDefinition (line 166) | public class Il2CppTypeDefinition
class Il2CppMethodDefinition (line 235) | public class Il2CppMethodDefinition
class Il2CppParameterDefinition (line 263) | public class Il2CppParameterDefinition
class Il2CppFieldDefinition (line 272) | public class Il2CppFieldDefinition
class Il2CppFieldDefaultValue (line 282) | public class Il2CppFieldDefaultValue
class Il2CppPropertyDefinition (line 289) | public class Il2CppPropertyDefinition
class Il2CppCustomAttributeTypeRange (line 301) | public class Il2CppCustomAttributeTypeRange
class Il2CppMetadataUsageList (line 309) | public class Il2CppMetadataUsageList
class Il2CppMetadataUsagePair (line 315) | public class Il2CppMetadataUsagePair
class Il2CppStringLiteral (line 321) | public class Il2CppStringLiteral
class Il2CppParameterDefaultValue (line 327) | public class Il2CppParameterDefaultValue
class Il2CppEventDefinition (line 334) | public class Il2CppEventDefinition
class Il2CppGenericContainer (line 347) | public class Il2CppGenericContainer
class Il2CppFieldRef (line 358) | public class Il2CppFieldRef
class Il2CppGenericParameter (line 364) | public class Il2CppGenericParameter
type Il2CppRGCTXDataType (line 374) | public enum Il2CppRGCTXDataType
class Il2CppRGCTXDefinitionData (line 384) | public class Il2CppRGCTXDefinitionData
class Il2CppRGCTXDefinition (line 391) | public class Il2CppRGCTXDefinition
type Il2CppMetadataUsage (line 404) | public enum Il2CppMetadataUsage
class Il2CppCustomAttributeDataRange (line 415) | public class Il2CppCustomAttributeDataRange
FILE: Il2CppDumper/Il2CppBinaryNinja/__init__.py
function get_addr (line 4) | def get_addr(bv: BinaryView, addr: int):
class Il2CppProcessTask (line 8) | class Il2CppProcessTask(BackgroundTaskThread):
method __init__ (line 9) | def __init__(self, bv: BinaryView, script_path: str,
method process_header (line 17) | def process_header(self):
method process_methods (line 32) | def process_methods(self, data: dict):
method process_strings (line 57) | def process_strings(self, data: dict):
method run (line 73) | def run(self):
function process (line 86) | def process(bv: BinaryView):
FILE: Il2CppDumper/Outputs/DummyAssemblyExporter.cs
class DummyAssemblyExporter (line 5) | public static class DummyAssemblyExporter
method Export (line 7) | public static void Export(Il2CppExecutor il2CppExecutor, string output...
FILE: Il2CppDumper/Outputs/HeaderConstants.cs
class HeaderConstants (line 3) | public static class HeaderConstants
FILE: Il2CppDumper/Outputs/Il2CppConstants.cs
class Il2CppConstants (line 3) | class Il2CppConstants
FILE: Il2CppDumper/Outputs/Il2CppDecompiler.cs
class Il2CppDecompiler (line 10) | public class Il2CppDecompiler
method Il2CppDecompiler (line 17) | public Il2CppDecompiler(Il2CppExecutor il2CppExecutor)
method Decompile (line 25) | public void Decompile(Config config, string outputDir)
method GetCustomAttribute (line 399) | public string GetCustomAttribute(Il2CppImageDefinition imageDef, int c...
method GetModifiers (line 451) | public string GetModifiers(Il2CppMethodDefinition methodDef)
FILE: Il2CppDumper/Outputs/ScriptJson.cs
class ScriptJson (line 5) | public class ScriptJson
class ScriptMethod (line 14) | public class ScriptMethod
class ScriptString (line 22) | public class ScriptString
class ScriptMetadata (line 28) | public class ScriptMetadata
class ScriptMetadataMethod (line 35) | public class ScriptMetadataMethod
FILE: Il2CppDumper/Outputs/StructGenerator.cs
class StructGenerator (line 12) | public class StructGenerator
method StructGenerator (line 35) | public StructGenerator(Il2CppExecutor il2CppExecutor)
method WriteScript (line 42) | public void WriteScript(string outputDir)
method AddMetadataUsageTypeInfo (line 434) | private void AddMetadataUsageTypeInfo(ScriptJson json, uint index, ulo...
method AddMetadataUsageIl2CppType (line 453) | private void AddMetadataUsageIl2CppType(ScriptJson json, uint index, u...
method AddMetadataUsageMethodDef (line 464) | private void AddMetadataUsageMethodDef(ScriptJson json, uint index, ul...
method AddMetadataUsageFieldInfo (line 482) | private void AddMetadataUsageFieldInfo(ScriptJson json, uint index, ul...
method AddMetadataUsageStringLiteral (line 495) | private void AddMetadataUsageStringLiteral(ScriptJson json, uint index...
method AddMetadataUsageMethodRef (line 503) | private void AddMetadataUsageMethodRef(ScriptJson json, uint index, ul...
method FixName (line 521) | private static string FixName(string str)
method ParseType (line 542) | private string ParseType(Il2CppType il2CppType, Il2CppGenericContext c...
method GetMethodTypeSignature (line 678) | public static string GetMethodTypeSignature(List<Il2CppTypeEnum> types)
method AddStruct (line 697) | private void AddStruct(Il2CppTypeDefinition typeDef)
method AddGenericClassStruct (line 709) | private void AddGenericClassStruct(ulong pointer)
method AddParents (line 722) | private void AddParents(Il2CppTypeDefinition typeDef, StructInfo struc...
method AddFields (line 737) | private void AddFields(Il2CppTypeDefinition typeDef, StructInfo struct...
method AddVTableMethod (line 775) | private void AddVTableMethod(StructInfo structInfo, Il2CppTypeDefiniti...
method AddRGCTX (line 812) | private void AddRGCTX(StructInfo structInfo, Il2CppTypeDefinition type...
method GenerateRGCTX (line 858) | private List<StructRGCTXInfo> GenerateRGCTX(string imageName, Il2CppMe...
method ParseArrayClassStruct (line 905) | private void ParseArrayClassStruct(Il2CppType il2CppType, Il2CppGeneri...
method GetTypeDefinition (line 916) | private Il2CppTypeDefinition GetTypeDefinition(Il2CppType il2CppType)
method CreateStructNameDic (line 949) | private void CreateStructNameDic(Il2CppTypeDefinition typeDef)
method GetUniqueName (line 957) | private string GetUniqueName(string name)
method RecursionStructInfo (line 968) | private string RecursionStructInfo(StructInfo info)
method GetIl2CppStructName (line 1128) | private string GetIl2CppStructName(Il2CppType il2CppType, Il2CppGeneri...
method IsValueType (line 1224) | private bool IsValueType(Il2CppType il2CppType, Il2CppGenericContext c...
method IsCustomType (line 1270) | private bool IsCustomType(Il2CppType il2CppType, Il2CppGenericContext ...
method GenerateMethodInfo (line 1336) | private void GenerateMethodInfo(string methodInfoName, string structTy...
FILE: Il2CppDumper/Outputs/StructInfo.cs
class StructInfo (line 6) | public class StructInfo
class StructFieldInfo (line 17) | public class StructFieldInfo
class StructVTableMethodInfo (line 25) | public class StructVTableMethodInfo
class StructRGCTXInfo (line 30) | public class StructRGCTXInfo
FILE: Il2CppDumper/Program.cs
class Program (line 9) | class Program
method Main (line 13) | [STAThread]
method ShowHelp (line 114) | static void ShowHelp()
method Init (line 119) | private static bool Init(string il2cppPath, string metadataPath, out M...
method Dump (line 254) | private static void Dump(Metadata metadata, Il2Cpp il2Cpp, string outp...
FILE: Il2CppDumper/Resource1.Designer.cs
class Resource1 (line 22) | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resource...
method Resource1 (line 31) | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Mic...
FILE: Il2CppDumper/Utils/ArmUtils.cs
class ArmUtils (line 5) | static class ArmUtils
method DecodeMov (line 7) | public static uint DecodeMov(byte[] asm)
method DecodeAdr (line 14) | public static ulong DecodeAdr(ulong pc, byte[] inst)
method DecodeAdrp (line 22) | public static ulong DecodeAdrp(ulong pc, byte[] inst)
method DecodeAdd (line 31) | public static ulong DecodeAdd(byte[] inst)
method IsAdr (line 40) | public static bool IsAdr(byte[] inst)
FILE: Il2CppDumper/Utils/AttributeArgument.cs
class AttributeArgument (line 3) | public class AttributeArgument
FILE: Il2CppDumper/Utils/BlobValue.cs
class BlobValue (line 3) | public class BlobValue
FILE: Il2CppDumper/Utils/CustomAttributeDataReader.cs
class CustomAttributeDataReader (line 6) | public class CustomAttributeDataReader : BinaryReader
method CustomAttributeDataReader (line 15) | public CustomAttributeDataReader(Il2CppExecutor executor, byte[] buff)...
method GetStringCustomAttributeData (line 24) | public string GetStringCustomAttributeData()
method AttributeDataToString (line 71) | private string AttributeDataToString(BlobValue blobValue)
method VisitCustomAttributeData (line 98) | public CustomAttributeReaderVisitor VisitCustomAttributeData()
method ReadAttributeDataValue (line 142) | private BlobValue ReadAttributeDataValue()
method ReadCustomAttributeNamedArgumentClassAndIndex (line 153) | private (Il2CppTypeDefinition, int) ReadCustomAttributeNamedArgumentCl...
FILE: Il2CppDumper/Utils/CustomAttributeReaderVisitor.cs
class CustomAttributeReaderVisitor (line 3) | public class CustomAttributeReaderVisitor
FILE: Il2CppDumper/Utils/DummyAssemblyGenerator.cs
class DummyAssemblyGenerator (line 11) | public class DummyAssemblyGenerator
method DummyAssemblyGenerator (line 27) | public DummyAssemblyGenerator(Il2CppExecutor il2CppExecutor, bool addT...
method GetTypeReferenceWithByRef (line 451) | private TypeReference GetTypeReferenceWithByRef(MemberReference member...
method GetTypeReference (line 464) | private TypeReference GetTypeReference(MemberReference memberReference...
method CreateCustomAttribute (line 562) | private void CreateCustomAttribute(Il2CppImageDefinition imageDef, int...
method TryRestoreCustomAttribute (line 639) | private static bool TryRestoreCustomAttribute(TypeDefinition attribute...
method CreateGenericParameter (line 654) | private GenericParameter CreateGenericParameter(Il2CppGenericParameter...
method CreateCustomAttributeArgument (line 673) | private CustomAttributeArgument CreateCustomAttributeArgument(TypeRefe...
method GetBlobValueTypeReference (line 709) | private TypeReference GetBlobValueTypeReference(BlobValue blobValue, M...
FILE: Il2CppDumper/Utils/FileDialogNative.cs
class FileDialogNative (line 6) | static class FileDialogNative
class FileOpenDialogRCW (line 8) | [ComImport]
class IIDGuid (line 15) | internal class IIDGuid
method IIDGuid (line 17) | private IIDGuid() { }
class CLSIDGuid (line 28) | internal class CLSIDGuid
method CLSIDGuid (line 30) | private CLSIDGuid() { }
type IFileDialog (line 35) | [ComImport()]
method Show (line 40) | [PreserveSig]
method SetFileTypes (line 43) | void SetFileTypes([In] uint cFileTypes, [In][MarshalAs(UnmanagedType...
method SetFileTypeIndex (line 45) | void SetFileTypeIndex([In] uint iFileType);
method GetFileTypeIndex (line 47) | void GetFileTypeIndex(out uint piFileType);
method Advise (line 49) | void Advise([In, MarshalAs(UnmanagedType.Interface)] IFileDialogEven...
method Unadvise (line 51) | void Unadvise([In] uint dwCookie);
method SetOptions (line 53) | void SetOptions([In] FOS fos);
method GetOptions (line 55) | void GetOptions(out FOS pfos);
method SetDefaultFolder (line 57) | void SetDefaultFolder([In, MarshalAs(UnmanagedType.Interface)] IShel...
method SetFolder (line 59) | void SetFolder([In, MarshalAs(UnmanagedType.Interface)] IShellItem p...
method GetFolder (line 61) | void GetFolder([MarshalAs(UnmanagedType.Interface)] out IShellItem p...
method GetCurrentSelection (line 63) | void GetCurrentSelection([MarshalAs(UnmanagedType.Interface)] out IS...
method SetFileName (line 65) | void SetFileName([In, MarshalAs(UnmanagedType.LPWStr)] string pszName);
method GetFileName (line 67) | void GetFileName([MarshalAs(UnmanagedType.LPWStr)] out string pszName);
method SetTitle (line 69) | void SetTitle([In, MarshalAs(UnmanagedType.LPWStr)] string pszTitle);
method SetOkButtonLabel (line 71) | void SetOkButtonLabel([In, MarshalAs(UnmanagedType.LPWStr)] string p...
method SetFileNameLabel (line 73) | void SetFileNameLabel([In, MarshalAs(UnmanagedType.LPWStr)] string p...
method GetResult (line 75) | void GetResult([MarshalAs(UnmanagedType.Interface)] out IShellItem p...
method AddPlace (line 77) | void AddPlace([In, MarshalAs(UnmanagedType.Interface)] IShellItem ps...
method SetDefaultExtension (line 79) | void SetDefaultExtension([In, MarshalAs(UnmanagedType.LPWStr)] strin...
method Close (line 81) | void Close([MarshalAs(UnmanagedType.Error)] int hr);
method SetClientGuid (line 83) | void SetClientGuid([In] ref Guid guid);
method ClearClientData (line 85) | void ClearClientData();
method SetFilter (line 87) | void SetFilter([MarshalAs(UnmanagedType.Interface)] IntPtr pFilter);
type IFileDialogEvents (line 90) | [ComImport,
method OnFileOk (line 99) | [PreserveSig]
method OnFolderChanging (line 102) | [PreserveSig]
method OnFolderChange (line 105) | void OnFolderChange([In, MarshalAs(UnmanagedType.Interface)] IFileDi...
method OnSelectionChange (line 107) | void OnSelectionChange([In, MarshalAs(UnmanagedType.Interface)] IFil...
method OnShareViolation (line 109) | void OnShareViolation([In, MarshalAs(UnmanagedType.Interface)] IFile...
method OnTypeChange (line 111) | void OnTypeChange([In, MarshalAs(UnmanagedType.Interface)] IFileDial...
method OnOverwrite (line 113) | void OnOverwrite([In, MarshalAs(UnmanagedType.Interface)] IFileDialo...
type IShellItem (line 116) | [ComImport,
method BindToHandler (line 121) | void BindToHandler([In, MarshalAs(UnmanagedType.Interface)] IntPtr p...
method GetParent (line 123) | void GetParent([MarshalAs(UnmanagedType.Interface)] out IShellItem p...
method GetDisplayName (line 125) | void GetDisplayName([In] SIGDN sigdnName, [MarshalAs(UnmanagedType.L...
method GetAttributes (line 127) | void GetAttributes([In] uint sfgaoMask, out uint psfgaoAttribs);
method Compare (line 129) | void Compare([In, MarshalAs(UnmanagedType.Interface)] IShellItem psi...
type SIGDN (line 132) | internal enum SIGDN : uint
type COMDLG_FILTERSPEC (line 145) | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)]
type FOS (line 154) | [Flags]
type FDE_SHAREVIOLATION_RESPONSE (line 179) | internal enum FDE_SHAREVIOLATION_RESPONSE
type FDE_OVERWRITE_RESPONSE (line 186) | internal enum FDE_OVERWRITE_RESPONSE
FILE: Il2CppDumper/Utils/Il2CppExecutor.cs
class Il2CppExecutor (line 9) | public class Il2CppExecutor
method Il2CppExecutor (line 36) | public Il2CppExecutor(Metadata metadata, Il2Cpp il2Cpp)
method GetTypeName (line 61) | public string GetTypeName(Il2CppType il2CppType, bool addNamespace, bo...
method GetTypeDefName (line 149) | public string GetTypeDefName(Il2CppTypeDefinition typeDef, bool addNam...
method GetGenericInstParams (line 181) | public string GetGenericInstParams(Il2CppGenericInst genericInst)
method GetGenericContainerParams (line 193) | public string GetGenericContainerParams(Il2CppGenericContainer generic...
method GetMethodSpecName (line 205) | public (string, string) GetMethodSpecName(Il2CppMethodSpec methodSpec,...
method GetMethodSpecGenericContext (line 224) | public Il2CppGenericContext GetMethodSpecGenericContext(Il2CppMethodSp...
method GetRGCTXDefinition (line 239) | public Il2CppRGCTXDefinition[] GetRGCTXDefinition(string imageName, Il...
method GetRGCTXDefinition (line 257) | public Il2CppRGCTXDefinition[] GetRGCTXDefinition(string imageName, Il...
method GetGenericClassTypeDefinition (line 275) | public Il2CppTypeDefinition GetGenericClassTypeDefinition(Il2CppGeneri...
method GetTypeDefinitionFromIl2CppType (line 293) | public Il2CppTypeDefinition GetTypeDefinitionFromIl2CppType(Il2CppType...
method GetGenericParameteFromIl2CppType (line 307) | public Il2CppGenericParameter GetGenericParameteFromIl2CppType(Il2CppT...
method GetSectionHelper (line 321) | public SectionHelper GetSectionHelper()
method TryGetDefaultValue (line 326) | public bool TryGetDefaultValue(int typeIndex, int dataIndex, out objec...
method GetConstantValueFromBlob (line 343) | public bool GetConstantValueFromBlob(Il2CppTypeEnum type, BinaryReader...
method ReadEncodedTypeEnum (line 464) | public Il2CppTypeEnum ReadEncodedTypeEnum(BinaryReader reader, out Il2...
FILE: Il2CppDumper/Utils/MyAssemblyResolver.cs
class MyAssemblyResolver (line 5) | public class MyAssemblyResolver : DefaultAssemblyResolver
method Register (line 7) | public void Register(AssemblyDefinition assembly)
FILE: Il2CppDumper/Utils/OpenFileDialog.cs
class OpenFileDialog (line 6) | public class OpenFileDialog
method ShowDialog (line 12) | public bool ShowDialog()
FILE: Il2CppDumper/Utils/PELoader.cs
class PELoader (line 9) | public class PELoader
method LoadLibrary (line 11) | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unic...
method Load (line 14) | public static PE Load(string fileName)
FILE: Il2CppDumper/Utils/SearchSection.cs
type SearchSectionType (line 3) | public enum SearchSectionType
class SearchSection (line 10) | public class SearchSection
FILE: Il2CppDumper/Utils/SectionHelper.cs
class SectionHelper (line 7) | public class SectionHelper
method SectionHelper (line 23) | public SectionHelper(Il2Cpp il2Cpp, int methodCount, int typeDefinitio...
method SetSection (line 32) | public void SetSection(SearchSectionType type, Elf32_Phdr[] sections)
method SetSection (line 51) | public void SetSection(SearchSectionType type, Elf64_Phdr[] sections)
method SetSection (line 70) | public void SetSection(SearchSectionType type, MachoSection[] sections)
method SetSection (line 89) | public void SetSection(SearchSectionType type, MachoSection64Bit[] sec...
method SetSection (line 108) | public void SetSection(SearchSectionType type, ulong imageBase, Sectio...
method SetSection (line 127) | public void SetSection(SearchSectionType type, params NSOSegmentHeader...
method SetSection (line 146) | public void SetSection(SearchSectionType type, params SearchSection[] ...
method SetSection (line 151) | private void SetSection(SearchSectionType type, List<SearchSection> secs)
method FindCodeRegistration (line 167) | public ulong FindCodeRegistration()
method FindMetadataRegistration (line 198) | public ulong FindMetadataRegistration()
method FindCodeRegistrationOld (line 211) | private ulong FindCodeRegistrationOld()
method FindMetadataRegistrationOld (line 245) | private ulong FindMetadataRegistrationOld()
method FindMetadataRegistrationV21 (line 281) | private ulong FindMetadataRegistrationV21()
method CheckPointerRangeDataRa (line 329) | private bool CheckPointerRangeDataRa(ulong pointer)
method CheckPointerRangeExecVa (line 334) | private bool CheckPointerRangeExecVa(ulong[] pointers)
method CheckPointerRangeDataVa (line 339) | private bool CheckPointerRangeDataVa(ulong[] pointers)
method CheckPointerRangeBssVa (line 344) | private bool CheckPointerRangeBssVa(ulong[] pointers)
method FindCodeRegistrationData (line 351) | private ulong FindCodeRegistrationData()
method FindCodeRegistrationExec (line 356) | private ulong FindCodeRegistrationExec()
method FindCodeRegistration2019 (line 361) | private ulong FindCodeRegistration2019(List<SearchSection> secs)
method FindReference (line 409) | private IEnumerable<ulong> FindReference(ulong addr)
FILE: Il2CppDumper/ghidra.py
function get_addr (line 16) | def get_addr(addr):
function set_name (line 19) | def set_name(addr, name):
function make_function (line 23) | def make_function(start):
FILE: Il2CppDumper/ghidra_wasm.py
function get_addr (line 25) | def get_addr(addr):
function set_name (line 28) | def set_name(addr, name):
function make_function (line 32) | def make_function(start):
FILE: Il2CppDumper/ghidra_with_struct.py
function get_addr (line 19) | def get_addr(addr):
function set_name (line 22) | def set_name(addr, name):
function set_type (line 29) | def set_type(addr, type):
function make_function (line 56) | def make_function(start):
function set_sig (line 64) | def set_sig(addr, name, sig):
FILE: Il2CppDumper/hopper-py3.py
function deserializeJSON (line 4) | def deserializeJSON(script_file):
function changeAddressNames (line 14) | def changeAddressNames(script):
function main (line 26) | def main():
FILE: Il2CppDumper/ida.py
function get_addr (line 14) | def get_addr(addr):
function set_name (line 17) | def set_name(addr, name):
function make_function (line 23) | def make_function(start, end):
FILE: Il2CppDumper/ida_py3.py
function get_addr (line 14) | def get_addr(addr):
function set_name (line 17) | def set_name(addr, name):
function make_function (line 23) | def make_function(start, end):
FILE: Il2CppDumper/ida_with_struct.py
function get_addr (line 14) | def get_addr(addr):
function set_name (line 17) | def set_name(addr, name):
function make_function (line 23) | def make_function(start, end):
FILE: Il2CppDumper/ida_with_struct_py3.py
function get_addr (line 14) | def get_addr(addr):
function set_name (line 17) | def set_name(addr, name):
function make_function (line 23) | def make_function(start, end):
FILE: Il2CppDumper/il2cpp_header_to_ghidra.py
function main (line 17) | def main():
Condensed preview — 74 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (482K chars).
[
{
"path": ".gitattributes",
"chars": 2518,
"preview": "###############################################################################\n# Set default behavior to automatically "
},
{
"path": ".github/ISSUE_TEMPLATE/config.yml",
"chars": 28,
"preview": "blank_issues_enabled: false\n"
},
{
"path": ".github/ISSUE_TEMPLATE/problem_report.md",
"chars": 324,
"preview": "---\nname: Problem report\nabout: Problem report\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\nNote: if you do not provide all "
},
{
"path": ".github/ISSUE_TEMPLATE/problem_report_cn.md",
"chars": 182,
"preview": "---\nname: 问题报告\nabout: 中文问题报告\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n请注意:如果你没有提供以下所有信息我将会直接无视并关闭这个issue\n\n- Il2CppDumper"
},
{
"path": ".gitignore",
"chars": 6223,
"preview": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n##\n## G"
},
{
"path": "Il2CppDumper/Attributes/ArrayLengthAttribute.cs",
"chars": 183,
"preview": "using System;\n\nnamespace Il2CppDumper\n{\n [AttributeUsage(AttributeTargets.Field)]\n class ArrayLengthAttribute : A"
},
{
"path": "Il2CppDumper/Attributes/VersionAttribute.cs",
"chars": 252,
"preview": "using System;\n\nnamespace Il2CppDumper\n{\n [AttributeUsage(AttributeTargets.Field, AllowMultiple = true)]\n class Ve"
},
{
"path": "Il2CppDumper/Config.cs",
"chars": 924,
"preview": "namespace Il2CppDumper\n{\n public class Config\n {\n public bool DumpMethod { get; set; } = true;\n pub"
},
{
"path": "Il2CppDumper/ExecutableFormats/Elf.cs",
"chars": 14589,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing static Il2CppDumper.ElfConsta"
},
{
"path": "Il2CppDumper/ExecutableFormats/Elf64.cs",
"chars": 12141,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing static Il2CppDumper.ElfConsta"
},
{
"path": "Il2CppDumper/ExecutableFormats/ElfBase.cs",
"chars": 352,
"preview": "using System.IO;\n\nnamespace Il2CppDumper\n{\n public abstract class ElfBase : Il2Cpp\n {\n protected ElfBase(S"
},
{
"path": "Il2CppDumper/ExecutableFormats/ElfClass.cs",
"chars": 4941,
"preview": "namespace Il2CppDumper\n{\n public class Elf32_Ehdr\n {\n public uint ei_mag;\n public byte ei_class;\n "
},
{
"path": "Il2CppDumper/ExecutableFormats/Macho.cs",
"chars": 9362,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing static Il2"
},
{
"path": "Il2CppDumper/ExecutableFormats/Macho64.cs",
"chars": 12207,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing static Il2"
},
{
"path": "Il2CppDumper/ExecutableFormats/MachoClass.cs",
"chars": 514,
"preview": "namespace Il2CppDumper\n{\n public class MachoSection\n {\n public string sectname;\n public uint addr;\n"
},
{
"path": "Il2CppDumper/ExecutableFormats/MachoFat.cs",
"chars": 1054,
"preview": "using System.Buffers.Binary;\nusing System.IO;\n\nnamespace Il2CppDumper\n{\n public sealed class MachoFat : BinaryStream"
},
{
"path": "Il2CppDumper/ExecutableFormats/NSO.cs",
"chars": 13877,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing static Il2CppDumper.ElfConsta"
},
{
"path": "Il2CppDumper/ExecutableFormats/NSOClass.cs",
"chars": 1144,
"preview": "namespace Il2CppDumper\n{\n public class NSOHeader\n {\n public uint Magic;\n public uint Version;\n "
},
{
"path": "Il2CppDumper/ExecutableFormats/PE.cs",
"chars": 4736,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\n\nnamespace Il2CppDumper\n{\n publi"
},
{
"path": "Il2CppDumper/ExecutableFormats/PEClass.cs",
"chars": 4234,
"preview": "using System;\n\nnamespace Il2CppDumper\n{\n public class DosHeader\n {\n public ushort Magic;\n public us"
},
{
"path": "Il2CppDumper/ExecutableFormats/WebAssembly.cs",
"chars": 2088,
"preview": "using System;\nusing System.IO;\n\nnamespace Il2CppDumper\n{\n public sealed class WebAssembly : BinaryStream\n {\n "
},
{
"path": "Il2CppDumper/ExecutableFormats/WebAssemblyClass.cs",
"chars": 152,
"preview": "namespace Il2CppDumper\n{\n public class DataSection\n {\n public uint Index;\n public uint Offset;\n "
},
{
"path": "Il2CppDumper/ExecutableFormats/WebAssemblyMemory.cs",
"chars": 2356,
"preview": "using System.IO;\n\nnamespace Il2CppDumper\n{\n public sealed class WebAssemblyMemory : Il2Cpp\n {\n private rea"
},
{
"path": "Il2CppDumper/Extensions/BinaryReaderExtensions.cs",
"chars": 3196,
"preview": "using System;\nusing System.IO;\nusing System.Text;\n\nnamespace Il2CppDumper\n{\n public static class BinaryReaderExtensi"
},
{
"path": "Il2CppDumper/Extensions/BoyerMooreHorspool.cs",
"chars": 3503,
"preview": "using System;\nusing System.Collections.Generic;\n\nnamespace Il2CppDumper\n{\n static class BoyerMooreHorspool\n {\n "
},
{
"path": "Il2CppDumper/Extensions/HexExtensions.cs",
"chars": 526,
"preview": "using System;\nusing System.Text;\n\nnamespace Il2CppDumper\n{\n static class HexExtensions\n {\n public static s"
},
{
"path": "Il2CppDumper/Extensions/StringExtensions.cs",
"chars": 1967,
"preview": "using System.Text;\n\nnamespace Il2CppDumper\n{\n public static class StringExtensions\n {\n public static strin"
},
{
"path": "Il2CppDumper/IO/BinaryStream.cs",
"chars": 8207,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing Syst"
},
{
"path": "Il2CppDumper/IO/Lz4DecoderStream.cs",
"chars": 14039,
"preview": "#define CHECK_ARGS\n#define CHECK_EOF\n//#define LOCAL_SHADOW\n\nusing System;\nusing System.IO;\n\nnamespace Il2CppDumper\n{\n "
},
{
"path": "Il2CppDumper/Il2Cpp/Il2Cpp.cs",
"chars": 15986,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\n\nnamespace Il2CppDumper\n{\n publi"
},
{
"path": "Il2CppDumper/Il2Cpp/Il2CppClass.cs",
"chars": 10643,
"preview": "using System;\n\nnamespace Il2CppDumper\n{\n public class Il2CppCodeRegistration\n {\n [Version(Max = 24.1)]\n "
},
{
"path": "Il2CppDumper/Il2Cpp/Metadata.cs",
"chars": 13381,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing Syst"
},
{
"path": "Il2CppDumper/Il2Cpp/MetadataClass.cs",
"chars": 13634,
"preview": "using System;\n\nnamespace Il2CppDumper\n{\n public class Il2CppGlobalMetadataHeader\n {\n public uint sanity;\n "
},
{
"path": "Il2CppDumper/Il2CppBinaryNinja/__init__.py",
"chars": 3739,
"preview": "from binaryninja import *\nfrom os.path import exists\n\ndef get_addr(bv: BinaryView, addr: int):\n imageBase = bv.start\n"
},
{
"path": "Il2CppDumper/Il2CppBinaryNinja/plugin.json",
"chars": 1696,
"preview": "{\n \"pluginmetadataversion\": 2,\n \"name\": \"Il2CppDumper\",\n \"type\": [\n \"core\",\n \"ui\",\n \"binaryview\"\n ],\n \"api"
},
{
"path": "Il2CppDumper/Il2CppDumper.csproj",
"chars": 2030,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n <PropertyGroup>\n <OutputType>Exe</OutputType>\n <TargetFrameworks>net6.0;net8"
},
{
"path": "Il2CppDumper/Outputs/DummyAssemblyExporter.cs",
"chars": 816,
"preview": "using System.IO;\n\nnamespace Il2CppDumper\n{\n public static class DummyAssemblyExporter\n {\n public static vo"
},
{
"path": "Il2CppDumper/Outputs/HeaderConstants.cs",
"chars": 15607,
"preview": "namespace Il2CppDumper\n{\n public static class HeaderConstants\n {\n public readonly static string GenericHea"
},
{
"path": "Il2CppDumper/Outputs/Il2CppConstants.cs",
"chars": 3052,
"preview": "namespace Il2CppDumper\n{\n class Il2CppConstants\n {\n /*\n * Field Attributes (21.1.5).\n */\n "
},
{
"path": "Il2CppDumper/Outputs/Il2CppDecompiler.cs",
"chars": 27954,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing static Il2"
},
{
"path": "Il2CppDumper/Outputs/ScriptJson.cs",
"chars": 935,
"preview": "using System.Collections.Generic;\n\nnamespace Il2CppDumper\n{\n public class ScriptJson\n {\n public List<Scrip"
},
{
"path": "Il2CppDumper/Outputs/StructGenerator.cs",
"chars": 70605,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing System.Tex"
},
{
"path": "Il2CppDumper/Outputs/StructInfo.cs",
"chars": 927,
"preview": "using System;\nusing System.Collections.Generic;\n\nnamespace Il2CppDumper\n{\n public class StructInfo\n {\n pub"
},
{
"path": "Il2CppDumper/Program.cs",
"chars": 10727,
"preview": "using System;\nusing System.IO;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Text.Json;\n\nnamesp"
},
{
"path": "Il2CppDumper/Resource1.Designer.cs",
"chars": 2751,
"preview": "//------------------------------------------------------------------------------\n// <auto-generated>\n// 此代码由工具生成。\n/"
},
{
"path": "Il2CppDumper/Resource1.resx",
"chars": 6073,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n <!-- \n Microsoft ResX Schema \n \n Version 2.0\n \n The prim"
},
{
"path": "Il2CppDumper/Utils/ArmUtils.cs",
"chars": 1539,
"preview": "using System;\n\nnamespace Il2CppDumper\n{\n static class ArmUtils\n {\n public static uint DecodeMov(byte[] asm"
},
{
"path": "Il2CppDumper/Utils/AttributeArgument.cs",
"chars": 133,
"preview": "namespace Il2CppDumper\n{\n public class AttributeArgument\n {\n public BlobValue Value;\n public int In"
},
{
"path": "Il2CppDumper/Utils/BlobValue.cs",
"chars": 178,
"preview": "namespace Il2CppDumper\n{\n public class BlobValue\n {\n public object Value;\n public Il2CppTypeEnum il"
},
{
"path": "Il2CppDumper/Utils/CustomAttributeDataReader.cs",
"chars": 6730,
"preview": "using System.Collections.Generic;\nusing System.IO;\n\nnamespace Il2CppDumper\n{\n public class CustomAttributeDataReader"
},
{
"path": "Il2CppDumper/Utils/CustomAttributeReaderVisitor.cs",
"chars": 252,
"preview": "namespace Il2CppDumper\n{\n public class CustomAttributeReaderVisitor\n {\n public int CtorIndex;\n publ"
},
{
"path": "Il2CppDumper/Utils/DummyAssemblyGenerator.cs",
"chars": 42865,
"preview": "using Mono.Cecil;\nusing Mono.Cecil.Cil;\nusing Mono.Collections.Generic;\nusing System;\nusing System.Collections.Generic;"
},
{
"path": "Il2CppDumper/Utils/FileDialogNative.cs",
"chars": 8318,
"preview": "using System;\nusing System.Runtime.InteropServices;\n\nnamespace Il2CppDumper\n{\n static class FileDialogNative\n {\n "
},
{
"path": "Il2CppDumper/Utils/Il2CppExecutor.cs",
"chars": 19770,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\n\nnamespace Il2Cp"
},
{
"path": "Il2CppDumper/Utils/MyAssemblyResolver.cs",
"chars": 239,
"preview": "using Mono.Cecil;\n\nnamespace Il2CppDumper\n{\n public class MyAssemblyResolver : DefaultAssemblyResolver\n {\n "
},
{
"path": "Il2CppDumper/Utils/OpenFileDialog.cs",
"chars": 1575,
"preview": "using System;\nusing static Il2CppDumper.FileDialogNative;\n\nnamespace Il2CppDumper\n{\n public class OpenFileDialog\n "
},
{
"path": "Il2CppDumper/Utils/PELoader.cs",
"chars": 3032,
"preview": "using System;\nusing System.ComponentModel;\nusing System.IO;\nusing System.Runtime.InteropServices;\nusing System.Text;\n\nn"
},
{
"path": "Il2CppDumper/Utils/SearchSection.cs",
"chars": 282,
"preview": "namespace Il2CppDumper\n{\n public enum SearchSectionType\n {\n Exec,\n Data,\n Bss\n }\n\n pub"
},
{
"path": "Il2CppDumper/Utils/SectionHelper.cs",
"chars": 15891,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Il2CppDumper\n{\n public class SectionHe"
},
{
"path": "Il2CppDumper/config.json",
"chars": 391,
"preview": "{\n \"DumpMethod\": true,\n \"DumpField\": true,\n \"DumpProperty\": true,\n \"DumpAttribute\": true,\n \"DumpFieldOffset\": true,"
},
{
"path": "Il2CppDumper/ghidra.py",
"chars": 2756,
"preview": "# -*- coding: utf-8 -*-\nimport json\n\nprocessFields = [\n\t\"ScriptMethod\",\n\t\"ScriptString\",\n\t\"ScriptMetadata\",\n\t\"ScriptMeta"
},
{
"path": "Il2CppDumper/ghidra_wasm.py",
"chars": 3235,
"preview": "# -*- coding: utf-8 -*-\nimport json\n\nfrom wasm import WasmLoader\nfrom wasm.analysis import WasmAnalysis\nfrom ghidra.util"
},
{
"path": "Il2CppDumper/ghidra_with_struct.py",
"chars": 5156,
"preview": "# -*- coding: utf-8 -*-\nimport json\n\nfrom ghidra.app.util.cparser.C import CParserUtils\nfrom ghidra.app.cmd.function imp"
},
{
"path": "Il2CppDumper/hopper-py3.py",
"chars": 711,
"preview": "import codecs\nimport json\n\ndef deserializeJSON(script_file):\n if script_file is not None:\n f = codecs.open(scr"
},
{
"path": "Il2CppDumper/ida.py",
"chars": 2405,
"preview": "# -*- coding: utf-8 -*-\nimport json\n\nprocessFields = [\n\t\"ScriptMethod\",\n\t\"ScriptString\",\n\t\"ScriptMetadata\",\n\t\"ScriptMeta"
},
{
"path": "Il2CppDumper/ida_py3.py",
"chars": 2342,
"preview": "# -*- coding: utf-8 -*-\nimport json\n\nprocessFields = [\n\t\"ScriptMethod\",\n\t\"ScriptString\",\n\t\"ScriptMetadata\",\n\t\"ScriptMeta"
},
{
"path": "Il2CppDumper/ida_with_struct.py",
"chars": 2903,
"preview": "# -*- coding: utf-8 -*-\nimport json\n\nprocessFields = [\n\t\"ScriptMethod\",\n\t\"ScriptString\",\n\t\"ScriptMetadata\",\n\t\"ScriptMeta"
},
{
"path": "Il2CppDumper/ida_with_struct_py3.py",
"chars": 2809,
"preview": "# -*- coding: utf-8 -*-\nimport json\n\nprocessFields = [\n\t\"ScriptMethod\",\n\t\"ScriptString\",\n\t\"ScriptMetadata\",\n\t\"ScriptMeta"
},
{
"path": "Il2CppDumper/il2cpp_header_to_binja.py",
"chars": 1498,
"preview": "import re\n\ndata = open(\"./il2cpp.h\").read()\n\nbuiltin = [\"void\", \"intptr_t\", \"uint32_t\", \"uint16_t\", \"int32_t\", \"uint8_t\""
},
{
"path": "Il2CppDumper/il2cpp_header_to_ghidra.py",
"chars": 1207,
"preview": "import re\n\nheader = \"typedef unsigned __int8 uint8_t;\\n\" \\\n \"typedef unsigned __int16 uint16_t;\\n\" \\\n \""
},
{
"path": "Il2CppDumper.sln",
"chars": 1115,
"preview": "\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 17\nVisualStudioVersion = 17.1.3222"
},
{
"path": "LICENSE",
"chars": 1064,
"preview": "MIT License\n\nCopyright (c) 2016 Perfare\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof"
},
{
"path": "README.md",
"chars": 4257,
"preview": "# Il2CppDumper\n\n[](https://ci.appv"
},
{
"path": "README.zh-CN.md",
"chars": 2691,
"preview": "# Il2CppDumper\n\n[](https://ci.appv"
}
]
About this extraction
This page contains the full source code of the Perfare/Il2CppDumper GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 74 files (450.9 KB), approximately 96.0k tokens, and a symbol index with 477 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.