-
-
Notifications
You must be signed in to change notification settings - Fork 210
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Arm64 improvements - throw helpers, literals, etc.
- Loading branch information
Sam Byass
committed
Sep 22, 2021
1 parent
87a8642
commit bb98da2
Showing
13 changed files
with
496 additions
and
197 deletions.
There are no files selected for viewing
87 changes: 87 additions & 0 deletions
87
Cpp2IL.Core/Analysis/Actions/ARM64/Arm64CallThrowHelperAction.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
using System; | ||
using System.Collections.Concurrent; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using Cpp2IL.Core.Analysis.Actions.Base; | ||
using Cpp2IL.Core.Analysis.ResultModels; | ||
using Gee.External.Capstone.Arm64; | ||
using LibCpp2IL; | ||
using Mono.Cecil; | ||
|
||
namespace Cpp2IL.Core.Analysis.Actions.ARM64 | ||
{ | ||
public class Arm64CallThrowHelperAction : AbstractExceptionThrowerAction<Arm64Instruction> | ||
{ | ||
private static readonly ConcurrentDictionary<long, TypeDefinition> _exceptionsThrownByAddress = new(); | ||
private static readonly List<long> _checkedAddresses = new(); | ||
|
||
public static bool IsThrowHelper(long pointer, int depth = 0) | ||
{ | ||
if (depth >= 5) | ||
return false; | ||
|
||
if (_exceptionsThrownByAddress.ContainsKey(pointer)) | ||
return true; | ||
|
||
if (_checkedAddresses.Contains(pointer)) | ||
return false; | ||
|
||
_checkedAddresses.Add(pointer); | ||
|
||
//This will only return up to the first branch, because it's an unmanaged function, but that's fine for these purposes | ||
var funcBody = Utils.GetArm64MethodBodyAtVirtualAddress((ulong)pointer, false); | ||
|
||
var registerPages = new Dictionary<string, long>(); | ||
foreach (var arm64Instruction in funcBody.Where(i => i.Mnemonic is "adrp")) | ||
{ | ||
registerPages[arm64Instruction.Details.Operands[0].Register.Name.ToLowerInvariant()] = arm64Instruction.Details.Operands[1].Immediate; | ||
} | ||
|
||
var registerAddresses = new Dictionary<string, long>(); | ||
foreach (var arm64Instruction in funcBody.Where(i => i.Mnemonic is "add" && i.Details.Operands.Length == 3)) | ||
{ | ||
var regName = arm64Instruction.Details.Operands[1].RegisterSafe()?.Name; | ||
if (regName != null && registerPages.TryGetValue(regName, out var page) && arm64Instruction.Details.Operands[2].IsImmediate()) | ||
{ | ||
var destName = arm64Instruction.Details.Operands[0].RegisterSafe()?.Name; | ||
registerAddresses[destName ?? "invalid"] = page + arm64Instruction.Details.Operands[2].Immediate; | ||
} | ||
} | ||
|
||
foreach (var potentialLiteralAddress in registerAddresses.Values) | ||
{ | ||
if (Utils.TryGetLiteralAt(LibCpp2IlMain.Binary!, (ulong)LibCpp2IlMain.Binary!.MapVirtualAddressToRaw((ulong)potentialLiteralAddress)) is not { } literal) | ||
continue; | ||
if (Utils.TryLookupTypeDefKnownNotGeneric($"System.{literal}") is not { } exceptionType) | ||
continue; | ||
|
||
Logger.VerboseNewline($"Identified direct exception thrower: 0x{pointer:X} throws {exceptionType.FullName}. Instructions were {string.Join(", ", funcBody.Select(i => $"0x{i.Address:X} {i.Mnemonic}"))}", "Analyze"); | ||
_exceptionsThrownByAddress.TryAdd(pointer, exceptionType); | ||
return true; | ||
} | ||
|
||
//Check for inherited exception throwers. | ||
foreach (var nextPtr in | ||
from i in funcBody | ||
where i.Mnemonic is "b" or "bl" && i.Details.Operands[0].IsImmediate() | ||
select i.Details.Operands[0].Immediate | ||
into nextPtr | ||
where IsThrowHelper(nextPtr, depth + 1) | ||
select nextPtr) | ||
{ | ||
_exceptionsThrownByAddress.TryAdd(pointer, _exceptionsThrownByAddress[nextPtr]); | ||
return true; | ||
} | ||
|
||
return false; | ||
} | ||
|
||
public static TypeDefinition? GetExceptionThrown(long ptr) => _exceptionsThrownByAddress.TryGetValue(ptr, out var ex) ? ex : null; | ||
|
||
public Arm64CallThrowHelperAction(MethodAnalysis<Arm64Instruction> context, Arm64Instruction instruction) : base(context, instruction) | ||
{ | ||
var functionAddress = instruction.Details.Operands[0].Immediate; | ||
_exceptionType = _exceptionsThrownByAddress[functionAddress]; | ||
} | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
Cpp2IL.Core/Analysis/Actions/ARM64/Arm64UnknownGlobalToConstantAction.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
using Cpp2IL.Core.Analysis.Actions.Base; | ||
using Cpp2IL.Core.Analysis.ResultModels; | ||
using Gee.External.Capstone.Arm64; | ||
using Mono.Cecil.Cil; | ||
|
||
namespace Cpp2IL.Core.Analysis.Actions.ARM64 | ||
{ | ||
public class Arm64UnknownGlobalToConstantAction : BaseAction<Arm64Instruction> | ||
{ | ||
private UnknownGlobalAddr? _globalAddr; | ||
private ConstantDefinition? _constantMade; | ||
|
||
public Arm64UnknownGlobalToConstantAction(MethodAnalysis<Arm64Instruction> context, Arm64Instruction instruction, ulong globalAddress) : base(context, instruction) | ||
{ | ||
var destReg = Utils.GetRegisterNameNew(instruction.Details.Operands[0].RegisterSafe()?.Id ?? Arm64RegisterId.Invalid); | ||
|
||
if(string.IsNullOrEmpty(destReg)) | ||
return; | ||
|
||
_globalAddr = new(globalAddress); | ||
_constantMade = context.MakeConstant(typeof(Il2CppString), _globalAddr, reg: destReg); | ||
} | ||
|
||
public override Instruction[] ToILInstructions(MethodAnalysis<Arm64Instruction> context, ILProcessor processor) | ||
{ | ||
throw new System.NotImplementedException(); | ||
} | ||
|
||
public override string? ToPsuedoCode() | ||
{ | ||
throw new System.NotImplementedException(); | ||
} | ||
|
||
public override string ToTextSummary() | ||
{ | ||
return $"Loads {_globalAddr} into new constant {_constantMade}"; | ||
} | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
Cpp2IL.Core/Analysis/Actions/ARM64/Arm64UnmanagedLiteralToConstantAction.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
using Cpp2IL.Core.Analysis.Actions.Base; | ||
using Cpp2IL.Core.Analysis.ResultModels; | ||
using Gee.External.Capstone.Arm64; | ||
using Mono.Cecil.Cil; | ||
|
||
namespace Cpp2IL.Core.Analysis.Actions.ARM64 | ||
{ | ||
public class Arm64UnmanagedLiteralToConstantAction : BaseAction<Arm64Instruction> | ||
{ | ||
private readonly ConstantDefinition? _constantMade; | ||
public readonly Il2CppString? Il2CppString; | ||
|
||
public Arm64UnmanagedLiteralToConstantAction(MethodAnalysis<Arm64Instruction> context, Arm64Instruction instruction, string literal, ulong address) : base(context, instruction) | ||
{ | ||
var destReg = Utils.GetRegisterNameNew(instruction.Details.Operands[0].RegisterSafe()?.Id ?? Arm64RegisterId.Invalid); | ||
|
||
if(string.IsNullOrEmpty(destReg)) | ||
return; | ||
|
||
Il2CppString = new(literal, address); | ||
_constantMade = context.MakeConstant(typeof(Il2CppString), Il2CppString, reg: destReg); | ||
} | ||
|
||
public override Instruction[] ToILInstructions(MethodAnalysis<Arm64Instruction> context, ILProcessor processor) | ||
{ | ||
throw new System.NotImplementedException(); | ||
} | ||
|
||
public override string? ToPsuedoCode() | ||
{ | ||
throw new System.NotImplementedException(); | ||
} | ||
|
||
public override string ToTextSummary() | ||
{ | ||
return $"Loads il2cpp string {Il2CppString} into new constant {_constantMade}"; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
58 changes: 58 additions & 0 deletions
58
Cpp2IL.Core/Analysis/Actions/Base/AbstractExceptionThrowerAction.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
using System.Linq; | ||
using Cpp2IL.Core.Analysis.ResultModels; | ||
using Mono.Cecil; | ||
using Mono.Cecil.Cil; | ||
using Mono.Cecil.Rocks; | ||
using Instruction = Iced.Intel.Instruction; | ||
|
||
namespace Cpp2IL.Core.Analysis.Actions.Base | ||
{ | ||
public abstract class AbstractExceptionThrowerAction<T> : BaseAction<T> | ||
{ | ||
protected TypeDefinition? _exceptionType; | ||
|
||
protected AbstractExceptionThrowerAction(MethodAnalysis<T> context, T instruction) : base(context, instruction) | ||
{ | ||
} | ||
|
||
public sealed override Mono.Cecil.Cil.Instruction[] ToILInstructions(MethodAnalysis<T> context, ILProcessor processor) | ||
{ | ||
if (_exceptionType == null) | ||
throw new TaintedInstructionException(); | ||
|
||
var ctor = _exceptionType.GetConstructors().FirstOrDefault(c => !c.HasParameters); | ||
|
||
if (ctor == null) | ||
{ | ||
var exceptionCtor = Utils.ExceptionReference.GetConstructors().First(c => c.HasParameters && c.Parameters.Count == 1 && c.Parameters[0].ParameterType.Name == "String"); | ||
return new[] | ||
{ | ||
processor.Create(OpCodes.Ldstr, $"Exception of type {_exceptionType.FullName}, but couldn't find a no-arg ctor"), | ||
processor.Create(OpCodes.Newobj, processor.ImportReference(exceptionCtor)), | ||
processor.Create(OpCodes.Throw) | ||
}; | ||
} | ||
|
||
return new[] | ||
{ | ||
processor.Create(OpCodes.Newobj, processor.ImportReference(ctor)), | ||
processor.Create(OpCodes.Throw) | ||
}; | ||
} | ||
|
||
public sealed override string? ToPsuedoCode() | ||
{ | ||
return $"throw new {_exceptionType}()"; | ||
} | ||
|
||
public sealed override string ToTextSummary() | ||
{ | ||
return $"[!] Constructs and throws an exception of kind {_exceptionType}\n"; | ||
} | ||
|
||
public sealed override bool IsImportant() | ||
{ | ||
return true; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.