Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question on comparing array sigs #35

Closed
greenozon opened this issue Jun 13, 2015 · 1 comment
Closed

Question on comparing array sigs #35

greenozon opened this issue Jun 13, 2015 · 1 comment

Comments

@greenozon
Copy link

I'm not sure if thats an issue, but anyway I'd like to raise it here.

I've such a method in some class (as seen in SAE for example):
myMeth1(Double[0...,0...], Double[]&&): Boolean

Now, there is a code in some assembly that calls this method
and the 1st parameter is declared as follows:

http://prntscr.com/7gj2sd

now, taking into account how dnlib compares the arraysig, the lookup fails....

module: SigComparer.cs
code:

namespace dnlib.DotNet {
......

public bool Equals(TypeSig a, TypeSig b) {
{
...........
                case ElementType.Array:
                    ArraySig ara = a as ArraySig, arb = b as ArraySig;
                    result = ara.Rank == arb.Rank &&
                            Equals(ara.Sizes, arb.Sizes) &&
Equals(ara.LowerBounds, arb.LowerBounds) &&
                        Equals(a.Next, b.Next);
                    break;

}

here is an example of the comparing code:
bool flag6 = !default(SigComparer).Equals(methodSig.Params[i], babelMethodRef.Parameters[i].Type);

I've looked around, there is interesting arcticle about this case:

Array lower bounds can be only '0'
https://msdn.microsoft.com/en-us/library/ttw7c10x%28v=vs.90%29.aspx

So the question is: does it make sense to relax the LowerBounds comparing way?
maybe it'll make sense to check if one side has 0 lower bounds and another no, then the result still may be "equal"?

Thanks

@0xd4d
Copy link
Collaborator

0xd4d commented Jun 14, 2015

I wrote some code that tests this and peverify complains if caller's method signature doesn't include the 0 lower bounds that matches the called method's 0 lower bounds.

The reason that the code you're investigating might work is that it seems from your info above that it's a Babel.NET obfuscated assembly. The obfuscator resolves the correct method and then creates the correct code.

C:\arytest>peverify theexe.exe

Microsoft (R) .NET Framework PE Verifier.  Version  4.0.30319.0
Copyright (c) Microsoft Corporation.  All rights reserved.

[IL]: Error: [C:\arytest\theexe.exe : main.Start::Method][offset 0x00000001] Unable to resolve token.
1 Error(s) Verifying theexe.exe

C:\arytest>theexe.exe

Unhandled Exception: System.MissingMethodException: Method not found: 'Int32 ns.Class1.Method(Double[,])'.
   at main.Start.Method()

Fixing the signature results in everything working again:

C:\arytest>theexe.exe

C:\arytest>peverify theexe.exe

Microsoft (R) .NET Framework PE Verifier.  Version  4.0.30319.0
Copyright (c) Microsoft Corporation.  All rights reserved.

All Classes and Methods in theexe.exe Verified.

Here's the code I used:

using dnlib.DotNet;
using dnlib.DotNet.Emit;

....

            {
                var mod = new ModuleDefUser("themod", Guid.NewGuid());
                var asm = new AssemblyDefUser("themod", new Version(0, 0, 0, 0));
                asm.Modules.Add(mod);
                mod.Kind = ModuleKind.Dll;

                var cl = new TypeDefUser("ns", "Class1", mod.CorLibTypes.Object.TypeDefOrRef);
                mod.Types.Add(cl);
                cl.Visibility = TypeAttributes.Public;

                var arg1 = new ArraySig(mod.CorLibTypes.Double, 2);
                arg1.LowerBounds.Add(0);
                arg1.LowerBounds.Add(0);
                var meth = new MethodDefUser("Method", MethodSig.CreateStatic(mod.CorLibTypes.Int32, arg1),
                    MethodImplAttributes.IL | MethodImplAttributes.Managed,
                    MethodAttributes.Public | MethodAttributes.Static);
                cl.Methods.Add(meth);
                var body = new CilBody();
                meth.Body = body;
                body.Instructions.Add(OpCodes.Ldc_I4_3.ToInstruction());
                body.Instructions.Add(OpCodes.Ret.ToInstruction());

                mod.Write(@"C:\arytest\themod.dll");
            }
            {
                var mod = new ModuleDefUser("theexe", Guid.NewGuid());
                var asm = new AssemblyDefUser("theexe", new Version(0, 0, 0, 0));
                asm.Modules.Add(mod);
                mod.Kind = ModuleKind.Console;

                var cl = new TypeDefUser("main", "Start", mod.CorLibTypes.Object.TypeDefOrRef);
                mod.Types.Add(cl);

                var asmRef = new AssemblyRefUser("themod", new Version(0, 0, 0, 0));
                var tr = new TypeRefUser(mod, "ns", "Class1", asmRef);
                var arg1 = new ArraySig(mod.CorLibTypes.Double, 2);
// Comment these and the program will fail because the correct method can't be found
                arg1.LowerBounds.Add(0);
                arg1.LowerBounds.Add(0);
                var mr = new MemberRefUser(mod, "Method", MethodSig.CreateStatic(mod.CorLibTypes.Int32, arg1), tr);

                var meth = new MethodDefUser("Method", MethodSig.CreateStatic(mod.CorLibTypes.Void),
                    MethodImplAttributes.IL | MethodImplAttributes.Managed,
                    MethodAttributes.Public | MethodAttributes.Static);
                cl.Methods.Add(meth);
                mod.EntryPoint = meth;
                var body = new CilBody();
                meth.Body = body;
                body.Instructions.Add(OpCodes.Ldnull.ToInstruction());
                body.Instructions.Add(OpCodes.Call.ToInstruction(mr));
                body.Instructions.Add(OpCodes.Pop.ToInstruction());
                body.Instructions.Add(OpCodes.Ret.ToInstruction());

                mod.Write(@"C:\arytest\theexe.exe");
            }

@0xd4d 0xd4d closed this as completed Jun 18, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant