下面是一个经流程混淆后的IL代码,用于解密字符串儿。常见于xenocode混淆后的代码中。这是最近的一个软件中摘出来的。对于破解,求它的反函数多此一举,此处仅作学习探讨。
希望高手能够给出它的反函数,也即加密函数。(本函数的作者是如何生成那些加密串儿的)

解密函数用例:
  string tmpStr=x9919("ckoe",280841806);
   则:tmpStr=="T"

那么:
现有一字串儿“The license is not valid for this product.”  intkey=280841806
如何加密成字串儿
"ckoedlffnkmffgdgokkgikbhpjihojphekgigknifjejneljdjckkjjkeealpihlniolpifmidmmlidndhknlhbofhiongpogcgpjgnppgeapglakbcblgjbmfackfhcbgoclafdifmdhfdebfkedebfbfifmdpfkeggbang"

求下面函数的反函数!

IL解密函数:

代码:
.method public hidebysig static string 
          x9919(string x12346_1,
                int32 x12347_2) cil managed
  {
    // 代码大小       158 (0x9e)
      .maxstack  5
      .locals init (unsigned int16 V_0,
               char[] V_1,
               int32 V_2,
               unsigned int16 V_3)
      IL_0000:  ldarg.1           //参数 1 入栈,int32 x12347_2
      IL_0001:  conv.u2           //将位于计算堆栈顶部的值转换为 unsigned int16,然后将其扩展为 int32 
      IL_0002:  br.s       IL_0060 //跳转到标签处

      IL_0004:  add         
      IL_0005:  ldarg.0
      IL_0006:  br.s       IL_0024

      IL_0008:  conv.u2
      IL_0009:  stloc.3
      IL_000a:  ldloc.1
      IL_000b:  ldloc.2
      IL_000c:  ldloc.3
      IL_000d:  stelem.i2
      IL_000e:  br.s       IL_0016

      IL_0010:  stloc.0
      IL_0011:  ldloc.2
      IL_0012:  ldc.i4.1
      IL_0013:  add
      IL_0014:  br.s       IL_0020

      IL_0016:  ldloc.0
      IL_0017:  ldc.i4     0x6fd
      IL_001c:  add
      IL_001d:  conv.u2
      IL_001e:  br.s       IL_0010

      IL_0020:  stloc.2
      IL_0021:  ldloc.2   //V_2入栈,int32 V_2,第一次到此处时为0
      IL_0022:  br.s       IL_003c  ////跳到标签处

      IL_0024:  ldc.i4.4
      IL_0025:  ldloc.2
      IL_0026:  mul
      IL_0027:  ldc.i4.3
      IL_0028:  add
      IL_0029:  callvirt   instance char [mscorlib]System.String::get_Chars(int32)
      IL_002e:  ldc.i4.s   97
      IL_0030:  sub
      IL_0031:  ldc.i4.s   12
      IL_0033:  shl
      IL_0034:  add
      IL_0035:  conv.u2
      IL_0036:  stloc.3
      IL_0037:  ldloc.3
      IL_0038:  ldloc.0
      IL_0039:  sub
      IL_003a:  br.s       IL_0008

      IL_003c:  ldarg.0   //参数0入栈,那个string
      IL_003d:  callvirt   instance int32 [mscorlib]System.String::get_Length() //又调用求串儿长度
      IL_0042:  ldc.i4.4  ////将整数值 4 作为 int32 推送到计算堆栈上 //这段儿和标签IL_0061及其后的作用一样,好象,往下跑着看
      IL_0043:  div        //除,上面的串儿长度除以4?
      IL_0044:  blt.s      IL_006c //小于跳转

      IL_0046:  ldloc.1
      IL_0047:  br.s       IL_0098

      IL_0049:  sub   //减97
      IL_004a:  ldarg.0 //参数0入栈,那个string
      IL_004b:  ldc.i4.4 //将整数值 4 作为 int32 推送到计算堆栈上
      IL_004c:  ldloc.2 ///V_2入栈,int32 V_2
      IL_004d:  mul     //乘  4*V_2入栈
      IL_004e:  ldc.i4.1  //将整数值 1 作为 int32 推送到计算堆栈上
      IL_004f:  add       //加 4*V_2+1
      IL_0050:  callvirt   instance char [mscorlib]System.String::get_Chars(int32) //据一个int32值取它对应的字符
      IL_0055:  ldc.i4.s   97 //将 num 作为 int32 推送到堆栈上(短格式)。
      IL_0057:  sub          //减
      IL_0058:  ldc.i4.4     //将整数值 4 作为 int32 推送到计算堆栈上
      IL_0059:  shl          //左移,移上面指出的4位,后面补0
      IL_005a:  add          //加
      IL_005b:  ldarg.0        ////参数0入栈,那个string
      IL_005c:  ldc.i4.4      //将整数值 4 作为 int32 推送到计算堆栈上
      IL_005d:  ldloc.2       //V_2入栈,int32 V_2
      IL_005e:  br.s       IL_0086

      IL_0060:  stloc.0     //出栈到V_0 int16型
      IL_0061:  ldarg.0     //参数 0 入栈,那个入参string x12346_1
      IL_0062:  callvirt   instance int32 [mscorlib]System.String::get_Length() //调用求字符串儿长度函数
      IL_0067:  ldc.i4.4    //将整数值 4 作为 int32 推送到计算堆栈上
      IL_0068:  br.s       IL_0072 //跳到标签处

      IL_006a:  br.s       IL_0021 //跳到标签处

      IL_006c:  ldarg.0   ////参数0入栈,那个string
      IL_006d:  ldc.i4.4  //将整数值 4 作为 int32 推送到计算堆栈上
      IL_006e:  ldloc.2   //V_2入栈,int32 V_2
      IL_006f:  mul       //乘  4*V_2入栈
      IL_0070:  br.s       IL_007d //跳转

      IL_0072:  div        //除,上面的串儿长度除以4?
      IL_0073:  newarr     [mscorlib]System.Char //Create a zero-base, on-dimensional array
      IL_0078:  stloc.1    //出栈到V_1,那个char[]数组
      IL_0079:  ldc.i4.0   //将整数值 0 作为 int32 推送到计算堆栈上
      IL_007a:  stloc.2    //出栈到V_2,那个int32 V_2的临时变量
      IL_007b:  br.s       IL_006a //跳到标签处

      IL_007d:  callvirt   instance char [mscorlib]System.String::get_Chars(int32) //据一个int32值取它对应的字符
      IL_0082:  ldc.i4.s   97   //将 num 作为 int32 推送到堆栈上(短格式)。
      IL_0084:  br.s       IL_0049 //跳到标签处

      IL_0086:  mul       //从栈取两值乘,结果入栈
      IL_0087:  ldc.i4.2  //将整数值2 作为 int32 推送到计算堆栈上
      IL_0088:  add       //从栈取两值加,结果入栈
      IL_0089:  callvirt   instance char [mscorlib]System.String::get_Chars(int32) //据一个int32值取它对应的字符
      IL_008e:  ldc.i4.s   97  //将 num 作为 int32 推送到堆栈上(短格式)。
      IL_0090:  sub        //减
      IL_0091:  ldc.i4.8   //将整数值8作为 int32 推送到计算堆栈上
      IL_0092:  shl         //左移8位
      IL_0093:  br         IL_0004 //跳到标签处

      IL_0098:  newobj     instance void [mscorlib]System.String::.ctor(char[])
      IL_009d:  ret
  } // end of method Form1::x9919

  • 标 题:答复
  • 作 者:tease
  • 时 间:2009-06-04 22:45

虽然我最擅长的领域不是算法,但偶尔客串一下还是可以的。(上次做“有道难题”的在线答题,只得了一个及格分......不爽,所以希望我的回答能满足搂主的需求。)
我希望大家可以把DONET发扬光大,让看雪开一个DONET板块是最终目的!
希望大家能讨论更多的DONET问题。

代码:
        private string GetEncyptString(string inputString, int intKey)
        {
            ushort num = (ushort)intKey;
            char[] chArray = new char[4 * inputString.Length];
            for (int i = 0; i < inputString.Length; i++)
            {
                ushort num3 = (ushort)(inputString[i] + num);
                string str = new string(new char[] { this.GetNewChar((byte)(num3 & 15)), this.GetNewChar((byte)((num3 >> 4) & 15)), this.GetNewChar((byte)((num3 >> 8) & 15)), this.GetNewChar((byte)((num3 >> 12) & 15)) });
                chArray[4 * i] = str[0];
                chArray[(4 * i) + 1] = str[1];
                chArray[(4 * i) + 2] = str[2];
                chArray[(4 * i) + 3] = str[3];
                num = (ushort)(num + 0x6fd);
            }
            return new string(chArray);
        }

        private char GetNewChar(byte value)
        {
            return (char)(0x61 + value);
        }
上传的附件 DEMO.rar

  • 标 题:答复
  • 作 者:grassdrago
  • 时 间:2009-06-05 08:50

一看楼上的算法就知道不用验证了。牛人,正解!想不到会这么快,佩服!
在阅读看雪帖子的过程中,对楼上印象深刻,还望以后多多指教。

下面是手动反流程后的IL代码。只要象个精干的妇人收拾屋子般,把它们规整的有序而决不多余就成了。

代码:
.method public hidebysig static string 
          x9919(string x12346_1,
                int32 x12347_2) cil managed
  {
    // 代码大小       158 (0x9e)
      .maxstack  5
      .locals init (unsigned int16 V_0,
               char[] V_1,
               int32 V_2,
               unsigned int16 V_3)
        ldarg.1           //参数 1 入栈,int32 x12347_2
        conv.u2           //将位于计算堆栈顶部的值转换为 unsigned int16,然后将其扩展为 int32 
        stloc.0     //出栈到V_0 int16型
        ldarg.0     //参数 0 入栈,那个入参string x12346_1
        callvirt   instance int32 [mscorlib]System.String::get_Length() //调用求字符串儿长度函数
        ldc.i4.4    //将整数值 4 作为 int32 推送到计算堆栈上
         div        //除,上面的串儿长度除以4?
        newarr     [mscorlib]System.Char //Create a zero-base, on-dimensional array
        stloc.1    //出栈到V_1,那个char[]数组
        ldc.i4.0   //将整数值 0 作为 int32 推送到计算堆栈上
        stloc.2    //出栈到V_2,那个int32 V_2的临时变量
       IL_WHILE: ldloc.2   //V_2入栈,int32 V_2,第一次到此处时为0
     
        ldarg.0   //参数0入栈,那个string
        callvirt   instance int32 [mscorlib]System.String::get_Length() //又调用求串儿长度
        ldc.i4.4  ////将整数值 4 作为 int32 推送到计算堆栈上 //这段儿和标签IL_0061及其后的作用一样,好象,往下跑着看
        div        //除,上面的串儿长度除以4?
        blt.s      IL_IF //小于跳转

        ldloc.1
        br.s       IL_END
      
      IL_IF:  ldarg.0   ////参数0入栈,那个string
        ldc.i4.4  //将整数值 4 作为 int32 推送到计算堆栈上
        ldloc.2   //V_2入栈,int32 V_2
        mul       //乘  4*V_2入栈
         callvirt   instance char [mscorlib]System.String::get_Chars(int32) //据一个int32值取它对应的字符
        ldc.i4.s   97   //将 num 作为 int32 推送到堆栈上(短格式)。
         sub   //减97
       ldarg.0 //参数0入栈,那个string
        ldc.i4.4 //将整数值 4 作为 int32 推送到计算堆栈上
        ldloc.2 ///V_2入栈,int32 V_2
        mul     //乘  4*V_2入栈
        ldc.i4.1  //将整数值 1 作为 int32 推送到计算堆栈上
        add       //加 4*V_2+1
        callvirt   instance char [mscorlib]System.String::get_Chars(int32) //据一个int32值取它对应的字符
        ldc.i4.s   97 //将 num 作为 int32 推送到堆栈上(短格式)。
        sub          //减
        ldc.i4.4     //将整数值 4 作为 int32 推送到计算堆栈上
        shl          //左移,移上面指出的4位,后面补0
        add          //加
        ldarg.0        ////参数0入栈,那个string
        ldc.i4.4      //将整数值 4 作为 int32 推送到计算堆栈上
        ldloc.2       //V_2入栈,int32 V_2
        mul       //从栈取两值乘,结果入栈
       ldc.i4.2  //将整数值2 作为 int32 推送到计算堆栈上
        add       //从栈取两值加,结果入栈
        callvirt   instance char [mscorlib]System.String::get_Chars(int32) //据一个int32值取它对应的字符
        ldc.i4.s   97  //将 num 作为 int32 推送到堆栈上(短格式)。
        sub        //减
        ldc.i4.8   //将整数值8作为 int32 推送到计算堆栈上
        shl         //左移8位
        add         
        ldarg.0
        ldc.i4.4
        ldloc.2
        mul
        ldc.i4.3
        add
        callvirt   instance char [mscorlib]System.String::get_Chars(int32)
        ldc.i4.s   97
        sub
        ldc.i4.s   12
        shl
        add
        conv.u2
        stloc.3
       ldloc.3
       ldloc.0
       sub
        conv.u2
        stloc.3
        ldloc.1
        ldloc.2
        ldloc.3
        stelem.i2
       ldloc.0
       ldc.i4     0x6fd
        add
        conv.u2
        stloc.0
        ldloc.2
        ldc.i4.1
        add
        stloc.2
       // ldloc.2   //V_2入栈,int32 V_2,第一次到此处时为0
        br.s       IL_WHILE  ////跳到标签处
      
      IL_END:  newobj     instance void [mscorlib]System.String::.ctor(char[])
      ret
  } // end of method Form1::x9919

现在可以看到可读性强的代码了,比如C#:
代码:
private static string x9919(string x12346_1, int x12347_2)
{
    ushort num = (ushort) x12347_2;
    char[] chArray = new char[x12346_1.Length / 4];
    for (int i = 0; i < (x12346_1.Length / 4); i++)
    {
        ushort num3 = (ushort) ((((x12346_1[4 * i] - 'a') + ((x12346_1[(4 * i) + 1] - 0x61) << 4)) + ((x12346_1[(4 * i) + 2] - 0x61) << 8)) + ((x12346_1[(4 * i) + 3] - 0x61) << 12));
        num3 = (ushort) (num3 - num);
        chArray[i] = (char) num3;
        num = (ushort) (num + 0x6fd);
    }
    return new string(chArray);
}
那么对比一下楼上的反函数。。。感觉那个---美!