Merge branch 'master' into confuser

This commit is contained in:
de4dot 2013-09-22 14:07:05 +02:00
commit ab4daa56cb
19 changed files with 127 additions and 127 deletions

View File

@ -238,7 +238,7 @@ namespace de4dot.blocks {
return;
for (int i = 0; i < 10; i++) {
bool changed = false;
bool modified = false;
foreach (var block in allBlocks) {
Block nopBlockTarget;
@ -246,7 +246,7 @@ namespace de4dot.blocks {
nopBlockTarget = GetNopBlockTarget(nopBlocks, block, block.FallThrough);
if (nopBlockTarget != null) {
block.SetNewFallThrough(nopBlockTarget);
changed = true;
modified = true;
}
if (block.Targets != null) {
@ -255,12 +255,12 @@ namespace de4dot.blocks {
if (nopBlockTarget == null)
continue;
block.SetNewTarget(targetIndex, nopBlockTarget);
changed = true;
modified = true;
}
}
}
if (!changed)
if (!modified)
break;
}

View File

@ -25,7 +25,7 @@ namespace de4dot.blocks.cflow {
protected List<Block> allBlocks;
protected Blocks blocks;
public bool ExecuteOnNoChange { get; set; }
public bool ExecuteIfNotModified { get; set; }
public virtual void DeobfuscateBegin(Blocks blocks) {
this.blocks = blocks;
@ -34,16 +34,16 @@ namespace de4dot.blocks.cflow {
public bool Deobfuscate(List<Block> allBlocks) {
Initialize(allBlocks);
bool changed = false;
bool modified = false;
foreach (var block in allBlocks) {
try {
changed |= Deobfuscate(block);
modified |= Deobfuscate(block);
}
catch (NullReferenceException) {
// Here if eg. invalid metadata token in a call instruction (operand is null)
}
}
return changed;
return modified;
}
protected virtual void Initialize(List<Block> allBlocks) {

View File

@ -37,13 +37,13 @@ namespace de4dot.blocks.cflow {
}
void Initialize() {
ourBlocksDeobfuscators.Add(new BlockCflowDeobfuscator { ExecuteOnNoChange = false });
ourBlocksDeobfuscators.Add(new SwitchCflowDeobfuscator { ExecuteOnNoChange = false });
ourBlocksDeobfuscators.Add(new DeadStoreRemover { ExecuteOnNoChange = false });
ourBlocksDeobfuscators.Add(new DeadCodeRemover { ExecuteOnNoChange = false });
ourBlocksDeobfuscators.Add(new ConstantsFolder { ExecuteOnNoChange = true });
ourBlocksDeobfuscators.Add(new StLdlocFixer { ExecuteOnNoChange = true });
ourBlocksDeobfuscators.Add(new DupBlockCflowDeobfuscator { ExecuteOnNoChange = true });
ourBlocksDeobfuscators.Add(new BlockCflowDeobfuscator { ExecuteIfNotModified = false });
ourBlocksDeobfuscators.Add(new SwitchCflowDeobfuscator { ExecuteIfNotModified = false });
ourBlocksDeobfuscators.Add(new DeadStoreRemover { ExecuteIfNotModified = false });
ourBlocksDeobfuscators.Add(new DeadCodeRemover { ExecuteIfNotModified = false });
ourBlocksDeobfuscators.Add(new ConstantsFolder { ExecuteIfNotModified = true });
ourBlocksDeobfuscators.Add(new StLdlocFixer { ExecuteIfNotModified = true });
ourBlocksDeobfuscators.Add(new DupBlockCflowDeobfuscator { ExecuteIfNotModified = true });
}
public void Add(IEnumerable<IBlocksDeobfuscator> blocksDeobfuscators) {
@ -61,7 +61,7 @@ namespace de4dot.blocks.cflow {
}
public void Deobfuscate() {
bool changed;
bool modified;
int iterations = -1;
DeobfuscateBegin(userBlocksDeobfuscators);
@ -69,20 +69,20 @@ namespace de4dot.blocks.cflow {
do {
iterations++;
changed = false;
modified = false;
RemoveDeadBlocks();
MergeBlocks();
blocks.MethodBlocks.GetAllBlocks(allBlocks);
if (iterations == 0)
changed |= FixDotfuscatorLoop();
modified |= FixDotfuscatorLoop();
changed |= Deobfuscate(userBlocksDeobfuscators, allBlocks);
changed |= Deobfuscate(ourBlocksDeobfuscators, allBlocks);
changed |= DeobfuscateNoChange(changed, userBlocksDeobfuscators, allBlocks);
changed |= DeobfuscateNoChange(changed, ourBlocksDeobfuscators, allBlocks);
} while (changed);
modified |= Deobfuscate(userBlocksDeobfuscators, allBlocks);
modified |= Deobfuscate(ourBlocksDeobfuscators, allBlocks);
modified |= DeobfuscateIfNotModified(modified, userBlocksDeobfuscators, allBlocks);
modified |= DeobfuscateIfNotModified(modified, ourBlocksDeobfuscators, allBlocks);
} while (modified);
}
void DeobfuscateBegin(IEnumerable<IBlocksDeobfuscator> bds) {
@ -91,24 +91,24 @@ namespace de4dot.blocks.cflow {
}
bool Deobfuscate(IEnumerable<IBlocksDeobfuscator> bds, List<Block> allBlocks) {
bool changed = false;
bool modified = false;
foreach (var bd in bds) {
if (bd.ExecuteOnNoChange)
if (bd.ExecuteIfNotModified)
continue;
changed |= bd.Deobfuscate(allBlocks);
modified |= bd.Deobfuscate(allBlocks);
}
return changed;
return modified;
}
bool DeobfuscateNoChange(bool changed, IEnumerable<IBlocksDeobfuscator> bds, List<Block> allBlocks) {
bool DeobfuscateIfNotModified(bool modified, IEnumerable<IBlocksDeobfuscator> bds, List<Block> allBlocks) {
foreach (var bd in bds) {
if (changed)
if (modified)
break;
if (!bd.ExecuteOnNoChange)
if (!bd.ExecuteIfNotModified)
continue;
changed |= bd.Deobfuscate(allBlocks);
modified |= bd.Deobfuscate(allBlocks);
}
return changed;
return modified;
}
// Hack for old Dotfuscator
@ -127,7 +127,7 @@ namespace de4dot.blocks.cflow {
pop
...
*/
bool changed = false;
bool modified = false;
foreach (var block in allBlocks) {
if (block.Instructions.Count != 5)
continue;
@ -154,9 +154,9 @@ namespace de4dot.blocks.cflow {
if (next.FirstInstr.OpCode.Code != Code.Pop)
continue;
block.ReplaceLastInstrsWithBranch(5, next);
changed = true;
modified = true;
}
return changed;
return modified;
}
bool RemoveDeadBlocks() {
@ -164,10 +164,10 @@ namespace de4dot.blocks.cflow {
}
bool MergeBlocks() {
bool changed = false;
bool modified = false;
foreach (var scopeBlock in GetAllScopeBlocks(blocks.MethodBlocks))
changed |= scopeBlock.MergeBlocks() > 0;
return changed;
modified |= scopeBlock.MergeBlocks() > 0;
return modified;
}
IEnumerable<ScopeBlock> GetAllScopeBlocks(ScopeBlock scopeBlock) {

View File

@ -35,7 +35,7 @@ namespace de4dot.blocks.cflow {
}
protected override bool Deobfuscate(Block block) {
bool changed = false;
bool modified = false;
instructionEmulator.Initialize(blocks);
var instrs = block.Instructions;
@ -49,7 +49,7 @@ namespace de4dot.blocks.cflow {
case Code.Ldarg_2:
case Code.Ldarg_3:
case Code.Ldarg_S:
changed |= FixLoadInstruction(block, i, instructionEmulator.GetArg(instr.Instruction.GetParameter(args)));
modified |= FixLoadInstruction(block, i, instructionEmulator.GetArg(instr.Instruction.GetParameter(args)));
break;
case Code.Ldloc:
@ -58,7 +58,7 @@ namespace de4dot.blocks.cflow {
case Code.Ldloc_2:
case Code.Ldloc_3:
case Code.Ldloc_S:
changed |= FixLoadInstruction(block, i, instructionEmulator.GetLocal(instr.Instruction.GetLocal(blocks.Locals)));
modified |= FixLoadInstruction(block, i, instructionEmulator.GetLocal(instr.Instruction.GetLocal(blocks.Locals)));
break;
case Code.Ldarga:
@ -81,7 +81,7 @@ namespace de4dot.blocks.cflow {
}
}
return changed;
return modified;
}
bool FixLoadInstruction(Block block, int index, Value value) {

View File

@ -30,7 +30,7 @@ namespace de4dot.blocks.cflow {
protected override bool Deobfuscate(Block block) {
allDeadInstructions.Clear();
bool changed = false;
bool modified = false;
var instructions = block.Instructions;
for (int i = 0; i < instructions.Count; i++) {
var instr = instructions[i];
@ -71,10 +71,10 @@ namespace de4dot.blocks.cflow {
if (allDeadInstructions.Count > 0) {
block.Remove(allDeadInstructions);
changed = true;
modified = true;
}
return changed;
return modified;
}
bool OkInstructions(Block block, IEnumerable<int> indexes) {

View File

@ -39,7 +39,7 @@ namespace de4dot.blocks.cflow {
Write = 2,
}
public bool ExecuteOnNoChange { get; set; }
public bool ExecuteIfNotModified { get; set; }
public void DeobfuscateBegin(Blocks blocks) {
this.blocks = blocks;
@ -123,7 +123,7 @@ namespace de4dot.blocks.cflow {
}
bool RemoveDeadStores() {
bool changed = false;
bool modified = false;
foreach (var block in allBlocks) {
var instructions = block.Instructions;
for (int i = 0; i < instructions.Count; i++) {
@ -148,11 +148,11 @@ namespace de4dot.blocks.cflow {
if (!deadLocals[local.Index])
continue;
instructions[i] = new Instr(OpCodes.Pop.ToInstruction());
changed = true;
modified = true;
}
}
return changed;
return modified;
}
}
}

View File

@ -21,7 +21,7 @@ using System.Collections.Generic;
namespace de4dot.blocks.cflow {
public interface IBlocksDeobfuscator {
bool ExecuteOnNoChange { get; }
bool ExecuteIfNotModified { get; }
void DeobfuscateBegin(Blocks blocks);

View File

@ -30,14 +30,14 @@ namespace de4dot.blocks.cflow {
}
protected override bool DeobfuscateInternal() {
bool changed = false;
bool modified = false;
var instructions = block.Instructions;
for (int i = 0; i < instructions.Count; i++) {
var instr = instructions[i].Instruction;
if (instr.OpCode.Code == Code.Call)
changed |= InlineMethod(instr, i);
modified |= InlineMethod(instr, i);
}
return changed;
return modified;
}
protected virtual bool CanInline(MethodDef method) {

View File

@ -31,7 +31,7 @@ namespace de4dot.blocks.cflow {
int iteration;
AccessChecker accessChecker;
public bool ExecuteOnNoChange { get; set; }
public bool ExecuteIfNotModified { get; set; }
public void DeobfuscateBegin(Blocks blocks) {
this.blocks = blocks;
@ -42,12 +42,12 @@ namespace de4dot.blocks.cflow {
if (iteration++ >= MAX_ITERATIONS)
return false;
bool changed = false;
bool modified = false;
foreach (var block in allBlocks) {
this.block = block;
changed |= DeobfuscateInternal();
modified |= DeobfuscateInternal();
}
return changed;
return modified;
}
protected abstract bool DeobfuscateInternal();

View File

@ -32,7 +32,7 @@ namespace de4dot.blocks.cflow {
}
protected override bool Deobfuscate(Block block) {
bool changed = false;
bool modified = false;
var instructions = block.Instructions;
for (int i = 0; i < instructions.Count; i++) {
var instr = instructions[i];
@ -56,7 +56,7 @@ namespace de4dot.blocks.cflow {
break;
instructions[i] = new Instr(OpCodes.Dup.ToInstruction());
instructions[i + 1] = instr;
changed = true;
modified = true;
break;
default:
@ -64,7 +64,7 @@ namespace de4dot.blocks.cflow {
}
}
return changed;
return modified;
}
}
}

View File

@ -103,46 +103,46 @@ namespace de4dot.blocks.cflow {
}
bool DeobfuscateTOS(Block switchBlock) {
bool changed = false;
bool modified = false;
if (switchBlock.Targets == null)
return changed;
return modified;
var targets = new List<Block>(switchBlock.Targets);
changed |= DeobfuscateTOS(targets, switchBlock.FallThrough, switchBlock);
modified |= DeobfuscateTOS(targets, switchBlock.FallThrough, switchBlock);
return changed;
return modified;
}
bool DeobfuscateLdloc(Block switchBlock) {
bool changed = false;
bool modified = false;
var switchVariable = Instr.GetLocalVar(blocks.Locals, switchBlock.Instructions[0]);
if (switchVariable == null)
return changed;
return modified;
if (switchBlock.Targets == null)
return changed;
return modified;
var targets = new List<Block>(switchBlock.Targets);
changed |= DeobfuscateLdloc(targets, switchBlock.FallThrough, switchBlock, switchVariable);
modified |= DeobfuscateLdloc(targets, switchBlock.FallThrough, switchBlock, switchVariable);
return changed;
return modified;
}
bool DeobfuscateStLdloc(Block switchBlock) {
bool changed = false;
bool modified = false;
var switchVariable = Instr.GetLocalVar(blocks.Locals, switchBlock.Instructions[0]);
if (switchVariable == null)
return changed;
return modified;
if (switchBlock.Targets == null)
return changed;
return modified;
var targets = new List<Block>(switchBlock.Targets);
changed |= DeobfuscateStLdloc(targets, switchBlock.FallThrough, switchBlock);
modified |= DeobfuscateStLdloc(targets, switchBlock.FallThrough, switchBlock);
return changed;
return modified;
}
// Switch deobfuscation when block uses stloc N, ldloc N to load switch constant
@ -154,7 +154,7 @@ namespace de4dot.blocks.cflow {
// ldloc N
// switch (......)
bool DeobfuscateStLdloc(IList<Block> switchTargets, Block switchFallThrough, Block block) {
bool changed = false;
bool modified = false;
foreach (var source in new List<Block>(block.Sources)) {
if (!isBranchBlock(source))
continue;
@ -166,9 +166,9 @@ namespace de4dot.blocks.cflow {
continue;
source.ReplaceLastNonBranchWithBranch(0, target);
source.Add(new Instr(OpCodes.Pop.ToInstruction()));
changed = true;
modified = true;
}
return changed;
return modified;
}
// Switch deobfuscation when block uses ldloc N to load switch constant
@ -180,7 +180,7 @@ namespace de4dot.blocks.cflow {
// ldloc N
// switch (......)
bool DeobfuscateLdloc(IList<Block> switchTargets, Block switchFallThrough, Block block, Local switchVariable) {
bool changed = false;
bool modified = false;
foreach (var source in new List<Block>(block.Sources)) {
if (isBranchBlock(source)) {
instructionEmulator.Initialize(blocks);
@ -190,7 +190,7 @@ namespace de4dot.blocks.cflow {
if (target == null)
continue;
source.ReplaceLastNonBranchWithBranch(0, target);
changed = true;
modified = true;
}
else if (IsBccBlock(source)) {
instructionEmulator.Initialize(blocks);
@ -201,15 +201,15 @@ namespace de4dot.blocks.cflow {
continue;
if (source.Targets[0] == block) {
source.SetNewTarget(0, target);
changed = true;
modified = true;
}
if (source.FallThrough == block) {
source.SetNewFallThrough(target);
changed = true;
modified = true;
}
}
}
return changed;
return modified;
}
// Switch deobfuscation when block has switch contant on TOS:
@ -219,7 +219,7 @@ namespace de4dot.blocks.cflow {
// swblk:
// switch (......)
bool DeobfuscateTOS(IList<Block> switchTargets, Block switchFallThrough, Block block) {
bool changed = false;
bool modified = false;
foreach (var source in new List<Block>(block.Sources)) {
if (!isBranchBlock(source))
continue;
@ -228,15 +228,15 @@ namespace de4dot.blocks.cflow {
var target = GetSwitchTarget(switchTargets, switchFallThrough, instructionEmulator.Pop());
if (target == null) {
changed |= DeobfuscateTos_Ldloc(switchTargets, switchFallThrough, source);
modified |= DeobfuscateTos_Ldloc(switchTargets, switchFallThrough, source);
}
else {
source.ReplaceLastNonBranchWithBranch(0, target);
source.Add(new Instr(OpCodes.Pop.ToInstruction()));
changed = true;
modified = true;
}
}
return changed;
return modified;
}
// ldloc N
@ -314,7 +314,7 @@ namespace de4dot.blocks.cflow {
if (!EmulateGetTarget(switchBlock, out target) || target != null)
return false;
bool changed = false;
bool modified = false;
foreach (var source in new List<Block>(switchBlock.Sources)) {
if (!source.CanAppend(switchBlock))
@ -323,14 +323,14 @@ namespace de4dot.blocks.cflow {
continue;
source.Append(switchBlock);
changed = true;
modified = true;
}
return changed;
return modified;
}
bool DeobfuscateType2(Block switchBlock) {
bool changed = false;
bool modified = false;
var bccSources = new List<Block>();
foreach (var source in new List<Block>(switchBlock.Sources)) {
@ -344,7 +344,7 @@ namespace de4dot.blocks.cflow {
continue;
source.Append(switchBlock);
changed = true;
modified = true;
}
foreach (var bccSource in bccSources) {
@ -361,10 +361,10 @@ namespace de4dot.blocks.cflow {
bccSource.SetNewTarget(0, newTarget);
newFallThrough.SetNewFallThrough(oldFallThrough);
newTarget.SetNewFallThrough(oldTarget);
changed = true;
modified = true;
}
return changed;
return modified;
}
static Block CreateBlock(Dictionary<Local, int> consts, Block fallThrough) {
@ -462,7 +462,7 @@ namespace de4dot.blocks.cflow {
// switch
// Inline common into blk1 and blk2.
bool changed = false;
bool modified = false;
foreach (var commonSource in new List<Block>(switchBlock.Sources)) {
if (commonSource.Instructions.Count != 1)
@ -472,12 +472,12 @@ namespace de4dot.blocks.cflow {
foreach (var blk in new List<Block>(commonSource.Sources)) {
if (blk.CanAppend(commonSource)) {
blk.Append(commonSource);
changed = true;
modified = true;
}
}
}
return changed;
return modified;
}
}
}

View File

@ -69,7 +69,7 @@ namespace de4dot.code {
var dm = GetDumpedMethod(rid);
if (dm == null)
return null;
return MethodBodyReader.Create(module, dm.code, dm.extraSections, parameters, dm.mhFlags, dm.mhMaxStack, dm.mhCodeSize, dm.mhLocalVarSigTok);
return MethodBodyReader.CreateCilBody(module, dm.code, dm.extraSections, parameters, dm.mhFlags, dm.mhMaxStack, dm.mhCodeSize, dm.mhLocalVarSigTok);
}
}
}

View File

@ -72,15 +72,15 @@ namespace de4dot.code.deobfuscators.Babel_NET {
}
protected override bool DeobfuscateInternal() {
bool changed = false;
bool modified = false;
var instructions = block.Instructions;
for (int i = 0; i < instructions.Count; i++) {
var instr = instructions[i].Instruction;
if (instr.OpCode.Code == Code.Call)
changed |= InlineMethod(instr, i);
modified |= InlineMethod(instr, i);
}
instructions = null;
return changed;
return modified;
}
static bool CanInline(MethodDef method) {

View File

@ -185,7 +185,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
bitwiseNotEncryptedFlag = 4;
}
static bool checkFlipBits(MethodDef method) {
static bool CheckFlipBits(MethodDef method) {
var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 1; i++) {
var ldloc = instrs[i];
@ -231,7 +231,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
constants.Add(flagValue);
}
flipFlagsBits = checkFlipBits(method);
flipFlagsBits = CheckFlipBits(method);
skipBytes = GetHeaderSkipBytes(method);
switch (frameworkType) {

View File

@ -64,31 +64,31 @@ namespace de4dot.code.deobfuscators.DeepSea {
}
protected override bool Deobfuscate(Block block) {
bool changed = false;
bool modified = false;
constantsReader = null;
var instrs = block.Instructions;
for (int i = 0; i < instrs.Count; i++) {
bool ch = Deobfuscate1(block, i);
if (ch) {
changed = true;
modified = true;
continue;
}
ch = Deobfuscate2(block, i);
if (ch) {
changed = true;
modified = true;
continue;
}
ch = Deobfuscate3(block, i);
if (ch) {
changed = true;
modified = true;
continue;
}
}
return changed;
return modified;
}
static bool IsLdelem(ArrayBlockState.FieldInfo info, Code code) {

View File

@ -71,7 +71,7 @@ namespace de4dot.code.deobfuscators.DeepSea {
}
}
public bool ExecuteOnNoChange {
public bool ExecuteIfNotModified {
get { return true; }
}
@ -83,7 +83,7 @@ namespace de4dot.code.deobfuscators.DeepSea {
if (!Initialize(allBlocks))
return false;
bool changed = false;
bool modified = false;
var indexesToRemove = new List<int>();
foreach (var block in allBlocks) {
@ -113,7 +113,7 @@ namespace de4dot.code.deobfuscators.DeepSea {
}
if (indexesToRemove.Count > 0) {
block.Remove(indexesToRemove);
changed = true;
modified = true;
}
}
@ -123,7 +123,7 @@ namespace de4dot.code.deobfuscators.DeepSea {
info.local.Type = info.CastType.ToTypeSig();
}
if (changed) {
if (modified) {
foreach (var block in allBlocks) {
var instrs = block.Instructions;
for (int i = 0; i < instrs.Count - 1; i++) {
@ -154,7 +154,7 @@ namespace de4dot.code.deobfuscators.DeepSea {
}
}
return changed;
return modified;
}
bool AddCast(Block block, int castIndex, int index, TypeSig type) {

View File

@ -37,16 +37,16 @@ namespace de4dot.code.deobfuscators.DeepSea {
}
protected override bool DeobfuscateInternal() {
bool changed = false;
bool modified = false;
var instructions = block.Instructions;
for (int i = 0; i < instructions.Count; i++) {
var instr = instructions[i].Instruction;
if (instr.OpCode.Code == Code.Call)
changed |= InlineMethod(instr, i);
modified |= InlineMethod(instr, i);
}
return changed;
return modified;
}
bool InlineMethod(Instruction callInstr, int instrIndex) {

View File

@ -171,10 +171,10 @@ namespace de4dot.code.deobfuscators {
void DeobfuscateLoop() {
for (int i = 0; i < 10; i++) {
bool changed = false;
changed |= DeobfuscateFields();
changed |= DeobfuscateMethods();
if (!changed)
bool modified = false;
modified |= DeobfuscateFields();
modified |= DeobfuscateMethods();
if (!modified)
break;
}
}
@ -223,7 +223,7 @@ namespace de4dot.code.deobfuscators {
}
bool DeobfuscateMethods() {
bool changed = false;
bool modified = false;
foreach (var method in allMethods) {
methodReturnInfo = new TypeInfo<Parameter>(method.Parameters.ReturnParameter);
DeobfuscateMethod(method);
@ -231,18 +231,18 @@ namespace de4dot.code.deobfuscators {
if (methodReturnInfo.UpdateNewType(module)) {
GetUpdatedMethod(method).newReturnType = methodReturnInfo.newType;
method.MethodSig.RetType = methodReturnInfo.newType;
changed = true;
modified = true;
}
foreach (var info in argInfos.Values) {
if (info.UpdateNewType(module)) {
GetUpdatedMethod(method).newArgTypes[info.arg.Index] = info.newType;
info.arg.Type = info.newType;
changed = true;
modified = true;
}
}
}
return changed;
return modified;
}
static int SortTypeInfos(TypeInfo<Parameter> a, TypeInfo<Parameter> b) {
@ -537,19 +537,19 @@ namespace de4dot.code.deobfuscators {
}
}
bool changed = false;
bool modified = false;
var removeThese = new List<FieldDef>();
foreach (var info in fieldWrites.Values) {
if (info.UpdateNewType(module)) {
removeThese.Add(info.arg);
GetUpdatedField(info.arg).newFieldType = info.newType;
info.arg.FieldSig.Type = info.newType;
changed = true;
modified = true;
}
}
foreach (var field in removeThese)
fieldWrites.Remove(field);
return changed;
return modified;
}
TypeSig GetLoadedType(IGenericParameterProvider gpp, MethodDef method, IList<Instruction> instructions, int instrIndex, out bool wasNewobj) {

2
dnlib

@ -1 +1 @@
Subproject commit 4dd65aaa8de082ce08c63d19055214bebfa56b53
Subproject commit fda808afae435fe1259074dd129e0ba97b0091c1