Bug SimplifyMacros, OptimizeMacros

142 views
Skip to first unread message

ayke

unread,
Nov 19, 2010, 7:04:46 AM11/19/10
to mono-...@googlegroups.com

using Mono.Cecil.Rocks;

body.SimplifyMacros( );
body.OptimizeMacros( );

////////////////////////////////////////
if (sVar == true)
path = "ccc";

else
path = "bbb";

make wrong offsets.
////////////////////////////////////////


////////////////////////////////////////
if (sVar == true)
{
path = "ccc";
}

else
{
path = "bbb";
}

works
////////////////////////////////////////
switch (sVar)
{
case 1:
path = "aaa";
break;
case 2:
path = "aaa";
break;
case 4:
path = "aaa";
break;
default:
throw new NotSupportedException("Version not supported:
" + version);
break;
}
with default statement wrong offsets (use {, })
////////////////////////////////////////
true ? GetSimpleString ("_CorDllMain")
: GetSimpleString ("_CorExeMain");

wrong offsets
//////////////////////////////////////


--
View this message in context: http://mono.1490590.n4.nabble.com/Bug-SimplifyMacros-OptimizeMacros-tp3050250p3050250.html
Sent from the Mono - Cecil mailing list archive at Nabble.com.

Jb Evain

unread,
Nov 19, 2010, 8:40:10 AM11/19/10
to mono-...@googlegroups.com
Hi,

Look, I'd really like to be able to help you, unfortunately, I have no
idea what is it you think is going wrong. As I already said, please
provide a simple, compilable, reproducible test case, that shows:

1) The output of the test case
2) What you think the test case should output

Thanks!

> --
> --
> mono-cecil

ayke

unread,
Nov 19, 2010, 10:46:30 AM11/19/10
to mono-cecil
Hallo Evain,

thanks for writing Cecil its a really great project.
Here is my method to to replace all ldstr with my encryption method

private void InjectCode(MethodBody body, CryptingMethodType
eCryptingMethod, MethodReference refDecryptionMethod)
{
InstructionCollection instructions =
(InstructionCollection)body.Instructions;
ILProcessor ilProcessor = body.GetILProcessor( );
List<int> listOffsets = new List<int>( );
int instructionSize = 0;

//Search for all ldstr Instructions
List<Instruction> listInstructionsToChange = new
List<Instruction>( );
foreach (Instruction instruction in instructions)
{
if (instruction.OpCode.Name == "ldstr")
{
if (instruction.Operand is string)
listInstructionsToChange.Add(instruction);
}
}

// Insert my Encryption Methode
if (instructions.Count > 0)
body.SimplifyMacros( );
foreach (Instruction instruction in
listInstructionsToChange)
{
listOffsets.Add(instruction.Offset);

string sOriginalValue =
instruction.Operand.ToString( );
KeyValuePair<string, object> pairStringAndKey =
GetEncryptedStringAndKey(sOriginalValue, eCryptingMethod);

string value = pairStringAndKey.Key;
object key = pairStringAndKey.Value;
Instruction loadKey = null;
if (key is int)
loadKey = ilProcessor.Create(OpCodes.Ldc_I4,
(int)key);
if (key is string)
loadKey = ilProcessor.Create(OpCodes.Ldstr,
(string)key);

Instruction loadString =
ilProcessor.Create(OpCodes.Ldstr, value);
ilProcessor.Replace(instruction, loadString);
ilProcessor.InsertAfter(loadString, loadKey);
Instruction callMethod =
ilProcessor.Create(OpCodes.Call, refDecryptionMethod);
ilProcessor.InsertAfter(loadKey, callMethod);

instructionSize = loadKey.GetSize( ) +
loadString.GetSize( );
}
if (instructions.Count > 0)
body.OptimizeMacros( );
}

Now i use it on a simple Programm.
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
I dont use the { } symbols in the "else" and "default:" statements.
Without them the programm will crash.

static void Main(string[] args)
{
if (someString == "Text")
Console.WriteLine("Some string is Text");
else //I dont use the symbols { }
Console.WriteLine("Some string is somehing else");
//Crash becouse of wrong offsets

switch (someString)
{
case "Text":
Console.WriteLine("Some string is Text");
break;
case "None":
Console.WriteLine("Some string is None");
break;
default: //I dont use the symbols { }
Console.WriteLine("Some string is something
else");
break;
//Crash becouse the wrong offsets
}
}

IL CODE //Look at brtrue.s L_0024
.method private hidebysig static void Main(string[] args) cil managed
{
.maxstack 3
.locals init (
[0] bool flag,
[1] string str)
L_0000: nop
L_0001: ldsfld string
Log4Me.Logic.Cloaking.Cloaking_StringsEncryption::someString
L_0006: ldstr "\ubcf1\ubcc0\ubcdd\ubcd1"
L_000b: ldc.i4 0x7098bca5
L_0010: call string <Module>::StringDecryption(string, int32)
L_0015: call bool [mscorlib]System.String::op_Equality(string,
string)
L_001a: ldc.i4.0
L_001b: ceq
L_001d: stloc.0
L_001e: ldloc.0
L_001f: brtrue.s L_0024 <<<<<<<<<<<shows on
nothing ?????????????????????????
L_0021: ldstr "\u123b\u1207\u1205\u120d\u1248\u121b\u121c\u121a
\u1201\u1206\u120f\u1248\u1201\u121b\u1248\u123c\u120d\u1210\u121c"
L_0026: ldc.i4 0x58561268
L_002b: call string <Module>::StringDecryption(string, int32)
L_0030: call void [mscorlib]System.Console::WriteLine(string)
L_0035: nop
L_0036: br.s L_004d
L_0038: ldstr "\u162e\u1612\u1610\u1618\u165d\u160e\u1609\u160f
\u1614\u1613\u161a\u165d\u1614\u160e\u165d\u160e
\u1612\u1610\u1618\u1615\u1614\u1613\u161a\u165d\u1618\u1611\u160e
\u1618"
L_003d: ldc.i4 0x4292167d
L_0042: call string <Module>::StringDecryption(string, int32)
L_0047: call void [mscorlib]System.Console::WriteLine(string)
L_004c: nop
L_004d: ldsfld string MyProgramm.Form::someString
L_0052: stloc.1
L_0053: ldloc.1
L_0054: brfalse.s L_006e
L_0056: ldloc.1
L_0057: ldstr "\u3d46\u3d77\u3d6a\u3d66"
L_005c: ldc.i4 0x28083d12
L_0061: call string <Module>::StringDecryption(string, int32)
L_0066: call bool [mscorlib]System.String::op_Equality(string,
string)
L_006b: brtrue.s L_0054
L_006d: ldloc.1
L_006e: ldstr "\u6f68\u6f49\u6f48\u6f43"
L_0073: ldc.i4 0x2ab66f26
L_0078: call string <Module>::StringDecryption(string, int32)
L_007d: call bool [mscorlib]System.String::op_Equality(string,
string)
L_0082: brtrue.s L_0061
L_0084: br.s L_006e
L_0086: ldstr "\u010a\u0136\u0134\u013c\u0179\u012a\u012d\u012b
\u0130\u0137\u013e\u0179\u0130\u012a\u0179\u010d\u013c\u0121\u012d"
L_008b: ldc.i4 0x6cef0159
L_0090: call string <Module>::StringDecryption(string, int32)
L_0095: call void [mscorlib]System.Console::WriteLine(string)
L_009a: nop
L_009b: br.s L_00cb
L_009d: ldstr "\u51d3\u51ef\u51ed
\u51e5\u51a0\u51f3\u51f4\u51f2\u51e9\u51ee
\u51e7\u51a0\u51e9\u51f3\u51a0\u51ce\u51ef\u51ee\u51e5"
L_00a2: ldc.i4 0x6d315180
L_00a7: call string <Module>::StringDecryption(string, int32)
L_00ac: call void [mscorlib]System.Console::WriteLine(string)
L_00b1: nop
L_00b2: br.s L_00cb
L_00b4: ldstr "\u6d9b\u6da7\u6da5\u6dad\u6de8\u6dbb\u6dbc\u6dba
\u6da1\u6da6\u6daf\u6de8\u6da1\u6dbb\u6de8\u6dbb\u6da7\u6da5\u6dad
\u6dbc\u6da0\u6da1\u6da6\u6daf\u6de8\u6dad\u6da4\u6dbb\u6dad"
L_00b9: ldc.i4 0x8b6dc8
L_00be: call string <Module>::StringDecryption(string, int32)
L_00c3: call void [mscorlib]System.Console::WriteLine(string)
L_00c8: nop
L_00c9: br.s L_00cb
L_00cb: ret
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
I used the { } symbols in the "else" and "default:" statements.
The programm works well.

static void Main(string[] args)
{
if (someString == "Text")
Console.WriteLine("Some string is Text");
else //I use the symbols { }
{
Console.WriteLine("Some string is somehing else");
//works fine
}

switch (someString)
{
case "Text":
Console.WriteLine("Some string is Text");
break;
case "None":
Console.WriteLine("Some string is None");
break;
default: //I use the symbols { }
{
Console.WriteLine("Some string is something
else");
break;
//works fine
}
}
}

IL CODE

.method private hidebysig static void Main(string[] args) cil managed
{
.maxstack 3
.locals init (
[0] bool flag,
[1] string str)
L_0000: nop
L_0001: ldsfld string MyProgram.Form1::someString
L_0006: ldstr "\u9220\u9211\u920c\u9200"
L_000b: ldc.i4 0x74099274
L_0010: call string <Module>::StringDecryption(string, int32)
L_0015: call bool [mscorlib]System.String::op_Equality(string,
string)
L_001a: ldc.i4.0
L_001b: ceq
L_001d: stloc.0
L_001e: ldloc.0
L_001f: brtrue.s L_0038
L_0021: ldstr "\ufb35\ufb09\ufb0b
\ufb03\ufb46\ufb15\ufb12\ufb14\ufb0f\ufb08\ufb01\ufb46\ufb0f
\ufb15\ufb46\ufb32\ufb03\ufb1e\ufb12"
L_0026: ldc.i4 0x1452fb66
L_002b: call string <Module>::StringDecryption(string, int32)
L_0030: call void [mscorlib]System.Console::WriteLine(string)
L_0035: nop
L_0036: br.s L_004f
L_0038: nop
L_0039: ldstr "\u0bd5\u0be9\u0beb
\u0be3\u0ba6\u0bf5\u0bf2\u0bf4\u0bef\u0be8\u0be1\u0ba6\u0bef
\u0bf5\u0ba6\u0bf5\u0be9\u0beb\u0be3\u0bee\u0bef
\u0be8\u0be1\u0ba6\u0be3\u0bea\u0bf5\u0be3"
L_003e: ldc.i4 0x5aa0b86
L_0043: call string <Module>::StringDecryption(string, int32)
L_0048: call void [mscorlib]System.Console::WriteLine(string)
L_004d: nop
L_004e: nop
L_004f: ldsfld string
Log4Me.Logic.Cloaking.Cloaking_StringsEncryption::someString
L_0054: stloc.1
L_0055: ldloc.1
L_0056: brfalse.s L_00b6
L_0058: ldloc.1
L_0059: ldstr "\u81d9\u81e8\u81f5\u81f9"
L_005e: ldc.i4 0x7f9a818d
L_0063: call string <Module>::StringDecryption(string, int32)
L_0068: call bool [mscorlib]System.String::op_Equality(string,
string)
L_006d: brtrue.s L_0056
L_006f: ldloc.1
L_0070: ldstr "\u98ca\u98eb\u98ea\u98e1"
L_0075: ldc.i4 0x496d9884
L_007a: call string <Module>::StringDecryption(string, int32)
L_007f: call bool [mscorlib]System.String::op_Equality(string,
string)
L_0084: brtrue.s L_0063
L_0086: br.s L_00b6
L_0088: ldstr "\u9d46\u9d7a
\u9d78\u9d70\u9d35\u9d66\u9d61\u9d67\u9d7c\u9d7b\u9d72\u9d35\u9d7c
\u9d66\u9d35\u9d41\u9d70\u9d6d\u9d61"
L_008d: ldc.i4 0x2b349d15
L_0092: call string <Module>::StringDecryption(string, int32)
L_0097: call void [mscorlib]System.Console::WriteLine(string)
L_009c: nop
L_009d: br.s L_00ce
L_009f: ldstr "\u0373\u034f\u034d
\u0345\u0300\u0353\u0354\u0352\u0349\u034e
\u0347\u0300\u0349\u0353\u0300\u036e\u034f\u034e\u0345"
L_00a4: ldc.i4 0x6ae50320
L_00a9: call string <Module>::StringDecryption(string, int32)
L_00ae: call void [mscorlib]System.Console::WriteLine(string)
L_00b3: nop
L_00b4: br.s L_00ce
L_00b6: nop
L_00b7: ldstr "\ubd1b\ubd27\ubd25\ubd2d\ubd68\ubd3b\ubd3c\ubd3a
\ubd21\ubd26\ubd2f\ubd68\ubd21\ubd3b\ubd68\ubd3b\ubd27\ubd25\ubd2d
\ubd3c\ubd20\ubd21\ubd26\ubd2f\ubd68\ubd2d\ubd24\ubd3b\ubd2d"
L_00bc: ldc.i4 0x4d4dbd48
L_00c1: call string <Module>::StringDecryption(string, int32)
L_00c6: call void [mscorlib]System.Console::WriteLine(string)
L_00cb: nop
L_00cc: br.s L_00ce
L_00ce: ret
}

Jb Evain

unread,
Nov 19, 2010, 10:56:44 AM11/19/10
to mono-...@googlegroups.com
It looks to me that you're removing instructions that are branch
targets. This has nothing to do with SimplifyMacros and
OptimizeMacros. You have to make sure that you properly adjust the
operands of the branch targets to instructions by those you've
replaced.

> --
> --
> mono-cecil

ayke

unread,
Nov 19, 2010, 11:29:39 AM11/19/10
to mono-cecil
Ok i understand but why its working if i use {} ??

Jb Evain

unread,
Nov 19, 2010, 11:42:37 AM11/19/10
to mono-...@googlegroups.com
On Fri, Nov 19, 2010 at 5:29 PM, ayke <ba...@live.de> wrote:
> Ok i understand but why its working if i use {} ??

Because the compiler will insert nop instructions where they place
sequence points for you to debug your code. And as the branch possibly
targets those instructions, and as you don't remove them, the branches
remain valid.

ayke

unread,
Nov 19, 2010, 12:14:48 PM11/19/10
to mono-cecil
big thanks to you evain

Jeff Nevins

unread,
Nov 22, 2010, 3:23:26 PM11/22/10
to mono-cecil
Thanks for the explanation evain. I have a somewhat related
question.... If I insertbefore/after instructions in such a method,
but do not remove any, will calling SimplyMacros/OptimizeMacros before/
after adjusting the method be sufficient to update the Br_S
instructions? Or do I still need to recalculate by hand? If I need to
adjust them by hand, how can I do so? It looks like the Operand
property on such instructions is set to the target instruction
itself...so what might I set it to instead?

Thanks a lot! Please let me know if I'm not being clear.

On Nov 19, 12:14 pm, ayke <ba...@live.de> wrote:
> big thanks to you evain

Jb Evain

unread,
Nov 22, 2010, 3:43:43 PM11/22/10
to mono-...@googlegroups.com
Hi,

On Mon, Nov 22, 2010 at 9:23 PM, Jeff Nevins <jeffn...@gmail.com> wrote:
> Thanks for the explanation evain. I have a somewhat related
> question.... If I insertbefore/after instructions in such a method,
> but do not remove any, will calling SimplyMacros/OptimizeMacros before/
> after adjusting the method be sufficient to update the Br_S
> instructions?

Yup.

Jb

Jeff Nevins

unread,
Nov 22, 2010, 4:30:29 PM11/22/10
to mono-cecil
That's what I thought...very strange...

I'm getting

Branch out of the method.

after inserting some instructions

without calling SimplifyMacros/OptimizeMacros. But after doing so, I
get

Unexpected type on the stack

I guess I must be doing something else to screw up the flow.

I will try to put together a sample, as I assume that's not enough to
go on.

On Nov 22, 3:43 pm, Jb Evain <jbev...@gmail.com> wrote:
> Hi,
>

Joe Robe

unread,
Nov 22, 2010, 4:56:04 PM11/22/10
to mono-...@googlegroups.com
if you run peverfiy, it will tell you what it expected on the stack
and what it got in case of errors. This is a pretty good hint !

I also realized that the awesome reflexil extension for reflector
usually stills shows the IL even if it is crap (reflector frequently
crashes in such scenarios).

So once you have the peverify error, it gives you whats is wrong and
WHERE (offset). So you just open reflexil and take a look what your
stack is there.

Joe

> --
> --
> mono-cecil

--
Kindest regards

Joe Robe
President
RobeSoft Inc.
Phone:+1 954 234 2662
Fax:+1 813 425-9759
EMail:Joe...@RobeSoft.com
Skype:joer00
Yahoo Messenger ONLY(do not send email):joer...@yahoo.com
MSN:Messenger ONLY(do not send email):joer...@hotmail.com
www.RobeSoft.com

Jb Evain

unread,
Nov 22, 2010, 5:34:06 PM11/22/10
to mono-...@googlegroups.com
On Mon, Nov 22, 2010 at 10:56 PM, Joe Robe <joe...@gmail.com> wrote:
> I also realized that the awesome reflexil extension for reflector
> usually stills shows the IL even if it is crap (reflector frequently
> crashes in such scenarios).

Extension which uses Cecil :)

Jb

Reply all
Reply to author
Forward
0 new messages