Re: Obfuscator and Decompiler

From: Jonathan Pierce (jpierce_at_nyc.rr.com)
Date: 07/20/04

  • Next message: Jonathan Pierce: "Re: Obfuscator and Decompiler"
    Date: 20 Jul 2004 06:00:15 -0700
    
    

    "Eugene" <eugeneh@nospam.hotmail.com> wrote in message news:<OLqiWGgbEHA.1248@TK2MSFTNGP11.phx.gbl>...
    > Funny enough Reflector 4.0.15.0 outputs the right code:
    >
    > public int ReadInt32()
    > {
    > return ((int) (((this.buffer[this.position++] |
    > (this.buffer[this.position++] << 8)) | (this.buffer[this.position++] << 16))
    > | (this.buffer[this.position++] << 24)));
    > }
    >
    >

    Eugene,

    That is funny. Don't get me wrong, I'm not trying to imply that
    Reflector is not a good tool, only that Decompiler.NET does a much
    better job of generating correct code if that is important to you. I
    have a lot of respect for Lutz's talent since I understand first hand
    how difficult it is to develop a good decompiler. I also appreciate
    that he develops these tools on his own time and donates them to the
    community. As I've said earlier, I try to send bug reports to Lutz
    and other competitors when I see them so that they can improve their
    products and the quality of all of the available products in the
    marketplace. I am glad to see that Lutz is addressing the bugs on his
    list or the ones mentioned in these discussions. I am only interested
    in competing fairly with all of the available products in this market,
    so I try to give my competitors a chance to fix problems in their
    products that they may not be aware of. I want developers reading this
    to choose the best product based on it's merits and I would appreciate
    if bugs were reported and isolated for me in my product, even if they
    came from my competitors since it save me the time of finding them,
    and I am interested in fixing the bugs and improving the product,
    rather than hiding their existence from the developer community. I fix
    any bugs as soon as I identify them and would expect my competitors to
    find the time to do the same.

    I am aware of many outstanding Reflector bugs that still cause it to
    generate code that doesn't compile.

    It's very possible that Lutz hasn't been tracking all of the bugs that
    I've sent him, and there are probably many more that I may have
    forgotten to report. I'll see what I can do to list them out again and
    send them to him since there are still many examples of cide generated
    by Reflector that doesn't compile or run correctly where
    Decompiler.NET succeeds.

    I'll try to focus on the runtime bugs here since they are harder to
    identify.

    Here's two that I've already reported but are still broken in
    Reflector 4.0.15 that he can get started on.

    Bug 1:
    Missing casts on method arguments with constant byte values cause the
    wrong method to be called.

    Original Code:

    class Class1
            {
                    const byte kSearchByteValue = 93;
                    private static void Write (byte theByte)
                    {
                            if (theByte == kSearchByteValue)
                            {
                                    Console.Write ("Found SearchByteValue...");
                            }
                            Console.WriteLine ("The value is: " + theByte.ToString ("X4"));
                    }
                    private static void Write (int theInt)
                    {
                            Console.WriteLine ("The value is: " + theInt.ToString ("X4"));
                    } [STAThread]
                    static void Main(string[] args)
                    {
                            Write (kSearchByteValue);
                    }
            }

    Reflector generated code:

    Notice the missing casts on the 93 const value in the following two
    statements that both cause incorrect runtime behavior since the
    literal const value is treated as an int.

     Class1.Write(93);
    if (theByte == 93) { ... }

    internal class Class1
        {
            // Methods
            public Class1()
            {
            }

            [STAThread]
            private static void Main(string[] args)
            {
                Class1.Write(93);
            }

            private static void Write(byte theByte)
            {
                if (theByte == 93)
                {
                    Console.Write("Found SearchByteValue...");
                }
                Console.WriteLine("The value is: " +
    theByte.ToString("X4"));
            }

            private static void Write(int theInt)
            {
                Console.WriteLine("The value is: " +
    theInt.ToString("X4"));
            }

            // Fields
            private const byte kSearchByteValue = 93;
        }

    Bug 2:

    I've reported this several times before and Lutz has partially fixed
    it by supporting the fixed statement, but Reflector does not properly
    account for pointer element sizes when handling unsafe code:

    Original Code:
    unsafe static bool unsafePointer(string s) {
                            char[] c = new char[10];
                            s.CopyTo(0,c,0,10);
                            fixed(char *p=c){
                                    *(p+5) = 'x';
                                    for (int i = 0; i < 10; i++)
                                    if (*(p+i) == 'p')
                                            return true;
                                    }
                            return false;
                    }
    Reflector 4.1.15 generated code:

    private static bool unsafePointer(string s)
    {
          int num1;
          char[] chArray1 = new char[10];
          s.CopyTo(0, chArray1, 0, 10);
          fixed (char* local1 = chArray1)
          {
                ((IntPtr) local1)[((IntPtr) 10)] = 120;
                for (num1 = 0; (num1 < 10); ++num1)
                {
                      if ((((IntPtr) local1) + (((IntPtr) num1) * 2)) ==
    112)
                      {
                            return true;
                      }
                }
          }
          return false;
    }

    Notice that this code doesn't convert the numeric literal values to
    chars, and doesn't account for the char element size, so the
    comparison is incorrect and the method returns the wrong value.

    Decompiler.NET generates correct code here:
    static unsafe bool unsafePointer (string s)
                            
                            {
                                    char[] c;
                                    c = new char[10];
                                    s.CopyTo (0, c, 0, 10);
                                    fixed (char* p = c)
                                    {
                                            p[5] = 'x';
                                            for (int i = 0; (i < 10); i++)
                                            {
                                                    if (p[i] == 'p')
                                                    {
                                                            return true;
                                                    }
                                            }
                                    }
                                    return false;
                            }

    Jonathan Pierce
    President
    Jungle Creatures, Inc.
    http://www.junglecreatures.com/


  • Next message: Jonathan Pierce: "Re: Obfuscator and Decompiler"

    Relevant Pages

    • Re: Obfuscator and Decompiler
      ... Reflector is not open source. ... > justify spending more time supporting it and correcting problems with ... > wastes more time tracking down dependant bugs that don't really exist. ... > of their employers resources than the cost of purchasing a supported ...
      (microsoft.public.dotnet.security)
    • Re: Obfuscator and Decompiler
      ... Reflector is not using ILReader anymore. ... >> justify spending more time supporting it and correcting problems with ... >> wastes more time tracking down dependant bugs that don't really exist. ... >> of their employers resources than the cost of purchasing a supported ...
      (microsoft.public.dotnet.security)
    • Re: Obfuscator and Decompiler
      ... > Remember that you asked Lutz to charge for Reflector because it makes ... The reason I asked Lutz to charge for his tool is so that he could ... justify spending more time supporting it and correcting problems with ... wastes more time tracking down dependant bugs that don't really exist. ...
      (microsoft.public.dotnet.security)
    • Re: Ngen.exe
      ... implementations for all of your development needs. ... I even go the extra step of reporting bugs and incorrect ... correct the code generated by Reflector 4.0.5 for the ILReader library ... I would not expect Reflector 4.0 to be able to ...
      (microsoft.public.dotnet.security)
    • Re: Decompiler.NET reverse engineers your CLS compliant code
      ... There are 2 fundamental issues reported for your tool and 3 bug reports. ... > identified two tiny bugs which we have already fixed. ... > We do not actively search our competitors web sites looking for their test ... Our customers agree that our product is the only one ...
      (microsoft.public.dotnet.languages.vb)