Initial import of IC.Rebuild
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
param(
|
||||
[Parameter(Mandatory)][string]$AssemblyPath,
|
||||
[Parameter(Mandatory)][string]$OutputPath,
|
||||
[string]$CecilPath = (Join-Path $env:APPDATA 'XIVLauncher\addon\Hooks\dev\Mono.Cecil.dll')
|
||||
)
|
||||
$ErrorActionPreference = 'Stop'
|
||||
# Read the target as data with Cecil. Never load or execute the target assembly.
|
||||
Add-Type -Path $CecilPath
|
||||
$icInput = (Resolve-Path -LiteralPath $AssemblyPath).Path
|
||||
$icAssembly = [Mono.Cecil.AssemblyDefinition]::ReadAssembly($icInput)
|
||||
try {
|
||||
$icSelected = $icAssembly.MainModule.Types | Where-Object {
|
||||
$_.FullName -match '^StatusEffectList(Entry)?$|^SamplePlugin\.Hook\.(ActorRadiusHook|NoActionMoveHook|YMove|StatusCheck)$'
|
||||
}
|
||||
$icTypes = foreach ($icType in $icSelected) {
|
||||
$icMethods = foreach ($icMethod in $icType.Methods) {
|
||||
$icState = 'NoBody'
|
||||
$icError = $null
|
||||
$icCodeSize = $null
|
||||
$icInstructions = $null
|
||||
if ($icMethod.HasBody) {
|
||||
try {
|
||||
$icBody = $icMethod.get_Body()
|
||||
$icCodeSize = $icBody.CodeSize
|
||||
$icInstructions = @($icBody.Instructions | ForEach-Object { $_.ToString() })
|
||||
# Parsing success alone is not validation of a protected method body.
|
||||
$icState = 'ParsedUnvalidated'
|
||||
$icMissingOperands = @($icBody.Instructions | Where-Object {
|
||||
$_.OpCode.OperandType.ToString() -ne 'InlineNone' -and $null -eq $_.Operand
|
||||
})
|
||||
if ($icCodeSize -gt 1048576 -or $icInstructions.Count -eq 0 -or
|
||||
$icBody.Instructions[0].OpCode.Name -eq 'ldelem.i1' -or $icMissingOperands.Count -gt 0) {
|
||||
$icState = 'SuspiciousBody'
|
||||
$icInstructions = $null
|
||||
}
|
||||
} catch {
|
||||
$icState = 'ReadError'
|
||||
$icError = $_.Exception.GetBaseException().Message
|
||||
}
|
||||
}
|
||||
[ordered]@{
|
||||
Signature = $icMethod.FullName
|
||||
Token = $icMethod.MetadataToken.ToUInt32()
|
||||
RVA = ('0x{0:X}' -f $icMethod.RVA)
|
||||
BodyState = $icState
|
||||
DeclaredCodeSize = $icCodeSize
|
||||
Error = $icError
|
||||
UnvalidatedIL = $icInstructions
|
||||
}
|
||||
}
|
||||
[ordered]@{
|
||||
Name = $icType.FullName
|
||||
Attributes = $icType.Attributes.ToString()
|
||||
DeclaredSize = $icType.ClassSize
|
||||
PackingSize = $icType.PackingSize
|
||||
Fields = @($icType.Fields | ForEach-Object {
|
||||
[ordered]@{Name=$_.Name; Type=$_.FieldType.FullName; Offset=$_.Offset}
|
||||
})
|
||||
NestedTypes = @($icType.NestedTypes | ForEach-Object {
|
||||
[ordered]@{
|
||||
Name=$_.FullName
|
||||
DeclaredSize=$_.ClassSize
|
||||
DelegateInvoke=@($_.Methods | Where-Object Name -eq 'Invoke' | ForEach-Object { $_.FullName })
|
||||
}
|
||||
})
|
||||
Methods = @($icMethods)
|
||||
}
|
||||
}
|
||||
$icReport = [ordered]@{
|
||||
Source = $icInput
|
||||
SHA256 = (Get-FileHash -LiteralPath $icInput -Algorithm SHA256).Hash
|
||||
Assembly = $icAssembly.Name.FullName
|
||||
Runtime = $icAssembly.MainModule.RuntimeVersion
|
||||
References = @($icAssembly.MainModule.AssemblyReferences | ForEach-Object {
|
||||
[ordered]@{Name=$_.Name; Version=$_.Version.ToString()}
|
||||
})
|
||||
Types = @($icTypes)
|
||||
Limitation = 'Metadata only. Method-body parsing is not proof of executable logic. Target assembly was not executed.'
|
||||
}
|
||||
$icReport | ConvertTo-Json -Depth 12 | Set-Content -LiteralPath $OutputPath -Encoding utf8
|
||||
"Saved metadata audit: $OutputPath"
|
||||
} finally { $icAssembly.Dispose() }
|
||||
@@ -0,0 +1,73 @@
|
||||
param(
|
||||
[Parameter(Mandatory)][string]$FirstPath,
|
||||
[Parameter(Mandatory)][string]$SecondPath,
|
||||
[Parameter(Mandatory)][string]$OutputPath,
|
||||
[string]$CecilPath = (Join-Path $env:APPDATA 'XIVLauncher\addon\Hooks\dev\Mono.Cecil.dll')
|
||||
)
|
||||
$ErrorActionPreference = 'Stop'
|
||||
Add-Type -Path $CecilPath
|
||||
function Get-IcTypes($Types) {
|
||||
foreach ($icType in $Types) {
|
||||
$icType
|
||||
Get-IcTypes $icType.NestedTypes
|
||||
}
|
||||
}
|
||||
function Get-IcMetadata([string]$Path) {
|
||||
$icFile = Get-Item -LiteralPath $Path
|
||||
$icAsm = [Mono.Cecil.AssemblyDefinition]::ReadAssembly($icFile.FullName)
|
||||
try {
|
||||
$icAllTypes = @(Get-IcTypes $icAsm.MainModule.Types)
|
||||
$icNamedTypes = @($icAllTypes | Where-Object { $_.FullName -match '^[\x20-\x7E]+$' })
|
||||
$icShapes = [ordered]@{}
|
||||
foreach ($icType in $icNamedTypes) {
|
||||
$icShapes[$icType.FullName] = @(
|
||||
"TYPE $($icType.Attributes) SIZE $($icType.ClassSize) PACK $($icType.PackingSize) BASE $($icType.BaseType.FullName)"
|
||||
$icType.Interfaces | ForEach-Object { "INTERFACE $($_.InterfaceType.FullName)" }
|
||||
$icType.Fields | ForEach-Object { "FIELD $($_.FullName) OFFSET $($_.Offset) FLAGS $($_.Attributes)" }
|
||||
$icType.Methods | ForEach-Object { "METHOD $($_.FullName) FLAGS $($_.Attributes) IMPL $($_.ImplAttributes)" }
|
||||
) | Sort-Object
|
||||
}
|
||||
[ordered]@{
|
||||
File=$icFile.Name
|
||||
Size=$icFile.Length
|
||||
SHA256=(Get-FileHash -LiteralPath $icFile.FullName).Hash
|
||||
Assembly=$icAsm.Name.FullName
|
||||
MVID=$icAsm.MainModule.Mvid.ToString()
|
||||
Architecture=$icAsm.MainModule.Architecture.ToString()
|
||||
Attributes=@($icAsm.CustomAttributes | Where-Object {
|
||||
$_.AttributeType.Name -match '^TargetFrameworkAttribute$|^Assembly(File|Informational)VersionAttribute$'
|
||||
} | ForEach-Object {
|
||||
[ordered]@{Type=$_.AttributeType.FullName; Values=@($_.ConstructorArguments | ForEach-Object { [string]$_.Value })}
|
||||
})
|
||||
References=@($icAsm.MainModule.AssemblyReferences | ForEach-Object { "$($_.Name) $($_.Version)" })
|
||||
Resources=@($icAsm.MainModule.Resources | ForEach-Object { "$($_.ResourceType) $($_.Name)" })
|
||||
TopLevelTypeCount=$icAsm.MainModule.Types.Count
|
||||
TotalTypeCount=$icAllTypes.Count
|
||||
AsciiNamedTypeCount=$icNamedTypes.Count
|
||||
TypeShapes=$icShapes
|
||||
}
|
||||
} finally { $icAsm.Dispose() }
|
||||
}
|
||||
$icFirst = Get-IcMetadata $FirstPath
|
||||
$icSecond = Get-IcMetadata $SecondPath
|
||||
$icOnlyFirst = @($icFirst.TypeShapes.Keys | Where-Object { !$icSecond.TypeShapes.Contains($_) })
|
||||
$icOnlySecond = @($icSecond.TypeShapes.Keys | Where-Object { !$icFirst.TypeShapes.Contains($_) })
|
||||
$icChanges = foreach ($icName in $icFirst.TypeShapes.Keys) {
|
||||
if (!$icSecond.TypeShapes.Contains($icName)) { continue }
|
||||
$icDiff = @(Compare-Object $icFirst.TypeShapes[$icName] $icSecond.TypeShapes[$icName])
|
||||
if ($icDiff.Count -gt 0) {
|
||||
[ordered]@{Type=$icName; Differences=@($icDiff | ForEach-Object {
|
||||
[ordered]@{OnlyIn=if ($_.SideIndicator -eq '=>') {'Second'} else {'First'}; Declaration=$_.InputObject}
|
||||
})}
|
||||
}
|
||||
}
|
||||
$icOutput = [ordered]@{
|
||||
First=$icFirst
|
||||
Second=$icSecond
|
||||
AsciiTypesOnlyInFirst=$icOnlyFirst
|
||||
AsciiTypesOnlyInSecond=$icOnlySecond
|
||||
CommonTypeMetadataChanges=@($icChanges)
|
||||
Limitation='Static declarations only; equal metadata does not establish equal method bodies or behavior. No target assembly was executed.'
|
||||
}
|
||||
$icOutput | ConvertTo-Json -Depth 12 | Set-Content -LiteralPath $OutputPath -Encoding utf8
|
||||
"Saved comparison: $OutputPath"
|
||||
Reference in New Issue
Block a user