H1ghker 发表于 2019-5-21 22:20

萌新的第一个CM

本帖最后由 H1ghker 于 2019-5-21 22:57 编辑

如题,萌新的第一个CM,希望大佬们在破解的同时附上图文,让菜鸡楼主再学习一波,感谢了~
输入正确key后会弹出如下字符串

更新一下字符表,纯爆破没啥营养
zyxwvutsrqponmlkjihgfedcba
ABCDEFGHIJKLMNOPQRSTUVWXYZ

lizhirui 发表于 2019-5-21 23:28


这题有相当多的解,应当至少是65^23组解
算法如下:
首先是楼主的main函数:

int main_0()
{
char v1; // @1
int curchar; // @3
char encryptedstr; // @57
int i; // @1
char inputstr; // @1

memset(&v1, 0xCCu, 0x110u);
i = 0;
printf("start your crack!\n");
scanf("%s", inputstr);
while ( inputstr )
{
    curchar = inputstr;
    curchar -= 65;
    switch ( curchar )
    {
      case 0:
      inputstr = 122;
      break;
      case 1:
      inputstr = 121;
      break;
      case 2:
      inputstr = 120;
      break;
      case 3:
      inputstr = 119;
      break;
      case 4:
      inputstr = 118;
      break;
      case 5:
      inputstr = 117;
      break;
      case 6:
      inputstr = 116;
      break;
      case 7:
      inputstr = 115;
      break;
      case 8:
      inputstr = 114;
      break;
      case 9:
      inputstr = 113;
      break;
      case 10:
      inputstr = 112;
      break;
      case 11:
      inputstr = 111;
      break;
      case 12:
      inputstr = 110;
      break;
      case 13:
      inputstr = 109;
      break;
      case 14:
      inputstr = 108;
      break;
      case 15:
      inputstr = 107;
      break;
      case 16:
      inputstr = 106;
      break;
      case 17:
      inputstr = 105;
      break;
      case 18:
      inputstr = 104;
      break;
      case 19:
      inputstr = 103;
      break;
      case 20:
      inputstr = 102;
      break;
      case 21:
      inputstr = 101;
      break;
      case 22:
      inputstr = 100;
      break;
      case 23:
      inputstr = 99;
      break;
      case 24:
      inputstr = 98;
      break;
      case 25:
      inputstr = 97;
      break;
      case 57:
      inputstr = 65;
      break;
      case 56:
      inputstr = 66;
      break;
      case 55:
      inputstr = 67;
      break;
      case 54:
      inputstr = 68;
      break;
      case 53:
      inputstr = 69;
      break;
      case 52:
      inputstr = 70;
      break;
      case 51:
      inputstr = 71;
      break;
      case 50:
      inputstr = 72;
      break;
      case 49:
      inputstr = 73;
      break;
      case 48:
      inputstr = 74;
      break;
      case 47:
      inputstr = 75;
      break;
      case 46:
      inputstr = 76;
      break;
      case 45:
      inputstr = 77;
      break;
      case 44:
      inputstr = 78;
      break;
      case 43:
      inputstr = 79;
      break;
      case 42:
      inputstr = 80;
      break;
      case 41:
      inputstr = 81;
      break;
      case 40:
      inputstr = 82;
      break;
      case 39:
      inputstr = 83;
      break;
      case 38:
      inputstr = 84;
      break;
      case 37:
      inputstr = 85;
      break;
      case 36:
      inputstr = 86;
      break;
      case 35:
      inputstr = 87;
      break;
      case 34:
      inputstr = 88;
      break;
      case 33:
      inputstr = 89;
      break;
      case 32:
      inputstr = 90;
      break;
      default:
      break;
    }
    ++i;
}
j_TextEncrypt((int)inputstr, (int)&encryptedstr);
printf("%s\n", &encryptedstr);
if ( !strcmp(&encryptedstr, "Th1s_crAcKme_1s_S0_juNk") )
    printf("you_got_it!\n");
else
    printf("nonono\n");
system("pause");
return 0;
}

可见一开始做了个字符替换
然后是楼主的TextEncrypt函数:

int __cdecl TextEncrypt(int inputstr, int resultstr)
{
char strbuf; // @1
int ch1; // @1
int ch2; // @1
int ch3; // @1
int ch4; // @1
int j; // @1
int i; // @1

memset(&strbuf, 0xCCu, 0x58u);
i = 0;
j = 0;
ch1 = 0;
ch2 = 0;
ch3 = 0;
ch4 = 0;
while ( *(_BYTE *)(i + inputstr) )
{
    ch1 = GetCharOffset(CharList, *(_BYTE *)(i + inputstr));
    ch2 = GetCharOffset(CharList, *(_BYTE *)(i + inputstr + 1));
    *(_BYTE *)(j++ + resultstr) = (ch2 >> 4) & 3 | 4 * ch1 & 0xFC;
    if ( *(_BYTE *)(i + inputstr + 2) != 61 )   // 61是等号
    {
      ch3 = GetCharOffset(CharList, *(_BYTE *)(i + inputstr + 2));
      *(_BYTE *)(j++ + resultstr) = (ch3 >> 2) & 0xF | 16 * ch2 & 0xF0;
      if ( *(_BYTE *)(i + inputstr + 3) != 61 )
      {
      ch4 = GetCharOffset(CharList, *(_BYTE *)(i + inputstr + 3));
      *(_BYTE *)(j++ + resultstr) = ch4 & 0x3F | ((_BYTE)ch3 << 6) & 0xC0;
      }
    }
    i += 4;
}
*(_BYTE *)(j + resultstr) = 0;
return 0;
}

做了一些神秘的二进制运算

然后是楼主的GetCharOffset函数

int __cdecl sub_401220(char *a1, char a2)
{
int result; // eax@2
char v3; // @1
char *v4; // @1

memset(&v3, 0xCCu, 0x44u);
v4 = strchr(a1, a2);
if ( v4 )
    result = v4 - a1;
else
    result = -1;
return result;
}


就是在一个给定的串中获取字符的索引
串为:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

上面的算法很明显了,直接暴力求解即可:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _20190521
{
    class Program
    {
      static string strlist = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
      static int GetCharOffset(string str,char ch)
      {
            return str.IndexOf(ch);   
      }

      static string TextEncrypt(string str)
      {
            char ch1,ch2,ch3,ch4;
            string r = "";

            ch1 = (char)GetCharOffset(strlist,str);
            ch2 = (char)GetCharOffset(strlist,str);
            ch3 = (char)GetCharOffset(strlist,str);
            ch4 = (char)GetCharOffset(strlist,str);
            r += (char)((ch2 >> 4) & 3 | 4 * ch1 & 0xFC);

            if(str != '=')
            {
                r += (char)((ch3 >> 2) & 0xF | 16 * ch2 & 0xF0);   
               
                if(str != '=')
                {
                  r += (char)(ch4 & 0x3F | (ch3 << 6) & 0xC0);   
                }
            }
            
            return r;
      }


      static void Main(string[] args)
      {
            string target = "Th1s_crAcKme_1s_S0_juNk";
            string result = "";
            int i,j,k,l;
            int index;
            string str1 = "zyxwvutsrqponmlkjihgfedcbaABCDEFGHIJKLMNOPQRSTUVWXYZ";
            string str2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZzyxwvutsrqponmlkjihgfedcba";
            var map = new Dictionary<char,char>();

            for(i = 0;i < str1.Length;i++)
            {
                map] = str2;
            }

            for(index = 0;index < target.Length;)
            {
                bool flag = false;

                for(i = 0;i < strlist.Length;i++)
                {
                  for(j = 0;j < strlist.Length;j++)
                  {
                        //for(k = 0;k < strlist.Length;k++)
                        {
                            //for(l = 0;l < strlist.Length;l++)
                            {
                              string str = TextEncrypt("" + strlist + strlist + "==");//后面两个字符直接取等于号即可,使用前面两个字符就能凑出全部的字符

                              if(((target.Length - index) >= str.Length) && (str == target.Substring(index,str.Length)))
                              {
                                    result += "" + strlist + strlist + "==";
                                    index += str.Length;
                                    flag = true;
                                    goto next;   
                              }
                            }
                        }
                  }
                }

                next:
                  if(flag == false)
                  {
                        throw new Exception();
                  }
                  else
                  {
                        Console.WriteLine(result);
                  }
            }

            Console.WriteLine(result);

            var result2 = "";

            for(i = 0;i < result.Length;i++)
            {
                if(map.ContainsKey(result))
                {
                  result2 += map];
                }
                else
                {
                  result2 += result;
                }
            }

            Console.WriteLine(result2);
            while(true);
      }
    }
}

repobor 发表于 2019-5-21 22:31

这样吗?

H1ghker 发表于 2019-5-21 22:33

repobor 发表于 2019-5-21 22:31
这样吗?

不对不对哦

cdevil 发表于 2019-5-22 12:34

lizhirui 发表于 2019-5-21 23:28
这题有相当多的解,应当至少是65^23组解
算法如下:
首先是楼主的main函数:


变形的base64编码

lizhirui 发表于 2019-5-22 14:46

cdevil 发表于 2019-5-22 12:34
变形的base64编码

原来如此

lizhirui 发表于 2019-5-22 14:47

cdevil 发表于 2019-5-22 12:34
变形的base64编码

ch1 = GetCharOffset(CharList, *(_BYTE *)(i + inputstr));
    ch2 = GetCharOffset(CharList, *(_BYTE *)(i + inputstr + 1));
    *(_BYTE *)(j++ + resultstr) = (ch2 >> 4) & 3 | 4 * ch1 & 0xFC;
    if ( *(_BYTE *)(i + inputstr + 2) != 61 )   // 61是等号
    {
      ch3 = GetCharOffset(CharList, *(_BYTE *)(i + inputstr + 2));
      *(_BYTE *)(j++ + resultstr) = (ch3 >> 2) & 0xF | 16 * ch2 & 0xF0;
      if ( *(_BYTE *)(i + inputstr + 3) != 61 )
      {
      ch4 = GetCharOffset(CharList, *(_BYTE *)(i + inputstr + 3));
      *(_BYTE *)(j++ + resultstr) = ch4 & 0x3F | ((_BYTE)ch3 << 6) & 0xC0;
      }
    }

没研究出来这块怎么直接逆向
所以就直接暴力枚举了

52lxw 发表于 2019-5-27 00:11

变形base64的话,那还是挺简单的
页: [1]
查看完整版本: 萌新的第一个CM