Skip to content
This repository has been archived by the owner on Jan 27, 2019. It is now read-only.

Commit

Permalink
Merge pull request #299 from jbeshir/fix-for-null-propagation-il
Browse files Browse the repository at this point in the history
C# 6 null propagation generates IL which causes invalid IL after SwitchMangler.
  • Loading branch information
yck1509 committed Oct 7, 2015
2 parents 3beb64f + 5627ce7 commit 1487f41
Showing 1 changed file with 138 additions and 78 deletions.
216 changes: 138 additions & 78 deletions Confuser.Protections/ControlFlow/SwitchMangler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ LinkedList<Instruction[]> SpiltStatements(InstrBlock block, Trace trace, CFConte
shouldSpilt = true;
break;
}
if ((instr.OpCode.OpCodeType != OpCodeType.Prefix && trace.AfterStack[instr.Offset] == 0) &&
if ((instr.OpCode.OpCodeType != OpCodeType.Prefix && (trace.AfterStack[instr.Offset] == 0 || instr.IsBr())) &&
(shouldSpilt || ctx.Intensity > ctx.Random.NextDouble())) {
statements.AddLast(currentStatement.ToArray());
currentStatement.Clear();
Expand Down Expand Up @@ -272,8 +272,15 @@ public override void Mangle(CilBody body, ScopeBlock root, CFContext ctx) {
switchHdr.Add(Instruction.Create(OpCodes.Rem_Un));
switchHdr.Add(switchInstr);

ctx.AddJump(switchHdr, statements.Last.Value[0]);
ctx.AddJunk(switchHdr);
if (trace.BeforeStack[statements.Last.Value[0].Offset] == 0)
{
ctx.AddJump(switchHdr, statements.Last.Value[0]);
}
else
{
ctx.AddJump(switchHdr, switchHdr[0]);
}
ctx.AddJunk(switchHdr);

var operands = new Instruction[statements.Count];
current = statements.First;
Expand All @@ -292,27 +299,37 @@ public override void Mangle(CilBody body, ScopeBlock root, CFContext ctx) {
int brKey;
if (!trace.IsBranchTarget(newStatement.Last().Offset) &&
statementKeys.TryGetValue(target, out brKey)) {
var targetKey = predicate != null ? predicate.GetSwitchKey(brKey) : brKey;
var unkSrc = hasUnknownSource(newStatement);

newStatement.RemoveAt(newStatement.Count - 1);

if (unkSrc) {
newStatement.Add(Instruction.Create(OpCodes.Ldc_I4, targetKey));
}
else {
var thisKey = key[i];
var r = ctx.Random.NextInt32();
newStatement.Add(Instruction.Create(OpCodes.Ldloc, local));
newStatement.Add(Instruction.CreateLdcI4(r));
newStatement.Add(Instruction.Create(OpCodes.Mul));
newStatement.Add(Instruction.Create(OpCodes.Ldc_I4, (thisKey * r) ^ targetKey));
newStatement.Add(Instruction.Create(OpCodes.Xor));
if (trace.BeforeStack[target.Offset] == 0)
{
var targetKey = predicate != null ? predicate.GetSwitchKey(brKey) : brKey;
var unkSrc = hasUnknownSource(newStatement);

var initialBeforeStack = trace.BeforeStack[newStatement[0].Offset];
newStatement.RemoveAt(newStatement.Count - 1);

if (unkSrc || initialBeforeStack != 0) {
newStatement.Add(Instruction.Create(OpCodes.Ldc_I4, targetKey));
}
else {
var thisKey = key[i];
var r = ctx.Random.NextInt32();
newStatement.Add(Instruction.Create(OpCodes.Ldloc, local));
newStatement.Add(Instruction.CreateLdcI4(r));
newStatement.Add(Instruction.Create(OpCodes.Mul));
newStatement.Add(Instruction.Create(OpCodes.Ldc_I4, (thisKey * r) ^ targetKey));
newStatement.Add(Instruction.Create(OpCodes.Xor));
}

ctx.AddJump(newStatement, switchHdr[1]);
ctx.AddJunk(newStatement);
}

ctx.AddJump(newStatement, switchHdr[1]);
ctx.AddJunk(newStatement);
operands[keyId[i]] = newStatement[0];
if (trace.BeforeStack[newStatement[0].Offset] == 0)
{
operands[keyId[i]] = newStatement[0];
}

converted = true;
}
}
Expand All @@ -323,71 +340,97 @@ public override void Mangle(CilBody body, ScopeBlock root, CFContext ctx) {
int brKey;
if (!trace.IsBranchTarget(newStatement.Last().Offset) &&
statementKeys.TryGetValue(target, out brKey)) {
bool unkSrc = hasUnknownSource(newStatement);
int nextKey = key[i + 1];
OpCode condBr = newStatement.Last().OpCode;
newStatement.RemoveAt(newStatement.Count - 1);

if (ctx.Random.NextBoolean()) {
condBr = InverseBranch(condBr);
int tmp = brKey;
brKey = nextKey;
nextKey = tmp;
}

var thisKey = key[i];
int r = 0, xorKey = 0;
if (!unkSrc) {
r = ctx.Random.NextInt32();
xorKey = thisKey * r;
}
if (trace.BeforeStack[target.Offset] == 0)
{
bool unkSrc = hasUnknownSource(newStatement);
int nextKey = key[i + 1];
OpCode condBr = newStatement.Last().OpCode;
newStatement.RemoveAt(newStatement.Count - 1);

Instruction brKeyInstr = Instruction.CreateLdcI4(xorKey ^ (predicate != null ? predicate.GetSwitchKey(brKey) : brKey));
Instruction nextKeyInstr = Instruction.CreateLdcI4(xorKey ^ (predicate != null ? predicate.GetSwitchKey(nextKey) : nextKey));
Instruction pop = Instruction.Create(OpCodes.Pop);

newStatement.Add(Instruction.Create(condBr, brKeyInstr));
newStatement.Add(nextKeyInstr);
newStatement.Add(Instruction.Create(OpCodes.Dup));
newStatement.Add(Instruction.Create(OpCodes.Br, pop));
newStatement.Add(brKeyInstr);
newStatement.Add(Instruction.Create(OpCodes.Dup));
newStatement.Add(pop);

if (!unkSrc) {
newStatement.Add(Instruction.Create(OpCodes.Ldloc, local));
newStatement.Add(Instruction.CreateLdcI4(r));
newStatement.Add(Instruction.Create(OpCodes.Mul));
newStatement.Add(Instruction.Create(OpCodes.Xor));
}
if (ctx.Random.NextBoolean()) {
condBr = InverseBranch(condBr);
int tmp = brKey;
brKey = nextKey;
nextKey = tmp;
}

ctx.AddJump(newStatement, switchHdr[1]);
ctx.AddJunk(newStatement);
operands[keyId[i]] = newStatement[0];
converted = true;
var thisKey = key[i];
int r = 0, xorKey = 0;
if (!unkSrc) {
r = ctx.Random.NextInt32();
xorKey = thisKey * r;
}

Instruction brKeyInstr = Instruction.CreateLdcI4(xorKey ^ (predicate != null ? predicate.GetSwitchKey(brKey) : brKey));
Instruction nextKeyInstr = Instruction.CreateLdcI4(xorKey ^ (predicate != null ? predicate.GetSwitchKey(nextKey) : nextKey));
Instruction pop = Instruction.Create(OpCodes.Pop);

newStatement.Add(Instruction.Create(condBr, brKeyInstr));
newStatement.Add(nextKeyInstr);
newStatement.Add(Instruction.Create(OpCodes.Dup));
newStatement.Add(Instruction.Create(OpCodes.Br, pop));
newStatement.Add(brKeyInstr);
newStatement.Add(Instruction.Create(OpCodes.Dup));
newStatement.Add(pop);

if (!unkSrc) {
newStatement.Add(Instruction.Create(OpCodes.Ldloc, local));
newStatement.Add(Instruction.CreateLdcI4(r));
newStatement.Add(Instruction.Create(OpCodes.Mul));
newStatement.Add(Instruction.Create(OpCodes.Xor));
}

ctx.AddJump(newStatement, switchHdr[1]);
ctx.AddJunk(newStatement);

converted = true;
}

if (trace.BeforeStack[newStatement[0].Offset] == 0)
{
operands[keyId[i]] = newStatement[0];
}
}
}

if (!converted) {
// Normal

var targetKey = predicate != null ? predicate.GetSwitchKey(key[i + 1]) : key[i + 1];
if (!hasUnknownSource(newStatement)) {
var thisKey = key[i];
var r = ctx.Random.NextInt32();
newStatement.Add(Instruction.Create(OpCodes.Ldloc, local));
newStatement.Add(Instruction.CreateLdcI4(r));
newStatement.Add(Instruction.Create(OpCodes.Mul));
newStatement.Add(Instruction.Create(OpCodes.Ldc_I4, (thisKey * r) ^ targetKey));
newStatement.Add(Instruction.Create(OpCodes.Xor));
}
else {
newStatement.Add(Instruction.Create(OpCodes.Ldc_I4, targetKey));
if (newStatement[newStatement.Count - 1].OpCode != OpCodes.Ret)
{
var nextStatement = current.Next;
if (trace.BeforeStack[nextStatement.Value[0].Offset] == 0)
{
var targetKey = predicate != null ? predicate.GetSwitchKey(key[i + 1]) : key[i + 1];
if (!hasUnknownSource(newStatement) && trace.BeforeStack[newStatement[0].Offset] == 0)
{
var thisKey = key[i];
var r = ctx.Random.NextInt32();
newStatement.Add(Instruction.Create(OpCodes.Ldloc, local));
newStatement.Add(Instruction.CreateLdcI4(r));
newStatement.Add(Instruction.Create(OpCodes.Mul));
newStatement.Add(Instruction.Create(OpCodes.Ldc_I4, (thisKey*r) ^ targetKey));
newStatement.Add(Instruction.Create(OpCodes.Xor));
}
else
{
newStatement.Add(Instruction.Create(OpCodes.Ldc_I4, targetKey));
}

ctx.AddJump(newStatement, switchHdr[1]);
ctx.AddJunk(newStatement);
}
else
{
newStatement.Add(Instruction.Create(OpCodes.Br, nextStatement.Value[0]));
}
}

ctx.AddJump(newStatement, switchHdr[1]);
ctx.AddJunk(newStatement);
operands[keyId[i]] = newStatement[0];
if (trace.BeforeStack[newStatement[0].Offset] == 0)
{
operands[keyId[i]] = newStatement[0];
}
}
}
else
Expand All @@ -397,22 +440,39 @@ public override void Mangle(CilBody body, ScopeBlock root, CFContext ctx) {
current = current.Next;
i++;
}
operands[keyId[i]] = current.Value[0];

if (trace.BeforeStack[current.Value[0].Offset] == 0)
{
operands[keyId[i]] = current.Value[0];
}

for (i = 0; i < operands.Length; i++)
{
if (operands[i] == null)
{
operands[i] = switchHdr[0];
}
}

switchInstr.Operand = operands;

Instruction[] first = statements.First.Value;
statements.RemoveFirst();
Instruction[] last = statements.Last.Value;
statements.RemoveLast();

List<Instruction[]> newStatements = statements.ToList();
List<Instruction[]> newStatements = statements.Where(s => trace.BeforeStack[s[0].Offset] == 0).ToList();
ctx.Random.Shuffle(newStatements);

List<Instruction[]> newOrderedStatements = statements.Where(s => trace.BeforeStack[s[0].Offset] != 0).ToList();

block.Instructions.Clear();
block.Instructions.AddRange(first);
block.Instructions.AddRange(switchHdr);
foreach (var statement in newStatements)
block.Instructions.AddRange(statement);
block.Instructions.AddRange(statement);
foreach (var statement in newOrderedStatements)
block.Instructions.AddRange(statement);
block.Instructions.AddRange(last);
}
}
Expand Down

0 comments on commit 1487f41

Please sign in to comment.