简单逆向12

诺莫12

开始

放入IDA:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  signed int v3; // eax
  char v4; // al
  signed int v5; // ecx
  char v6; // al
  signed int v7; // ecx
  char v8; // al
  signed int v9; // ecx
  char v10; // al
  signed int v11; // ecx
  char v12; // al
  signed int v13; // ecx
  __int64 v15; // [rsp+0h] [rbp-1A0h]
  signed int v16; // [rsp+4Ch] [rbp-154h]
  char dest; // [rsp+50h] [rbp-150h]
  int v18; // [rsp+E8h] [rbp-B8h]
  int v19; // [rsp+ECh] [rbp-B4h]
  char v20[64]; // [rsp+F0h] [rbp-B0h]
  char s[108]; // [rsp+130h] [rbp-70h]
  int v22; // [rsp+19Ch] [rbp-4h]

  v22 = 0;
  printf("please input string:\n", argv, envp);
  gets(s);
  v18 = strlen(s);
  v19 = 5;
  v16 = -1046111848;
  while ( 1 )
  {
    while ( 1 )
    {
      while ( 1 )
      {
        while ( v16 == -2012804730 )
        {
          memcpy(&dest, &dword_401480, 0x90uLL);// J2261C63-3I2I-EGE4-IBCC-IE41A5I5F4HB
          v4 = fun_check1(s);                   // 判断长度0-50
          v5 = -1855144052;
          if ( v4 & 1 )
            v5 = 1890735184;                    // 满足check1
          v16 = v5;
        }
        if ( v16 != -1855144052 )
          break;
        v16 = -1153978545;
        LODWORD(v15) = printf("what a shame !!!\n", v15);
      }
      if ( v16 != -1612797716 )
        break;
      v10 = fun_check4(s);                      // 判断-
      v11 = -1855144052;
      if ( v10 & 1 )
        v11 = -842747696;
      v16 = v11;
    }
    if ( v16 == -1153978545 )
      break;
    switch ( v16 )
    {
      case -1046111848:
        v3 = -2012804730;
        if ( v19 < v18 - 1 )
          v3 = -370117910;
        v16 = v3;
        break;
      case -842747696:
        v12 = fun_check5(v20, (int *)&dest);    // ‘0’~‘9’,v13[v5] = v15[v5]+17,v5++
                                                // ’a’~‘z’,v13[v5] = v15[v5] - 0x30,v5++
                                                // ’A’~‘Z’,v5++
                                                // ‘-’,    v13[v5] = v15[v5],v5++
        v13 = -1855144052;
        if ( v12 & 1 )
          v13 = -194644933;
        v16 = v13;
        break;
      case -370117910:
        v20[v19 - 5] = s[v19];
        v16 = 805361575;
        break;
      case -194644933:
        v16 = -1153978545;
        HIDWORD(v15) = printf("you got it !\n", v15);
        break;
      case 805361575:
        ++v19;
        v16 = -1046111848;
        break;
      case 1222385267:
        v8 = fun_check3(s);                     // 判断最后是否为}
        v9 = -1855144052;
        if ( v8 & 1 )
          v9 = -1612797716;
        v16 = v9;
        break;
      case 1890735184:
        v6 = fun_check2(s);                     // 判断前几个字符是否为flag{
        v7 = -1855144052;
        if ( v6 & 1 )
          v7 = 1222385267;
        v16 = v7;
        break;
    }
  }
  return 0;
}

数据:

简单逆向12

分析

这是一个控制流平坦化程序,就是由控制中心把目标分发到要执行的块。

1.fun_check1:判断字符范围在 0-50
2.fun_check2:判断前面是否为 flag{
3.fun_check3:判断最后是否为 }
4.fun_check4:
‘0’~‘9’,v13[v5] = v15[v5]+17,v5++
’a’~‘z’,v13[v5] = v15[v5] - 0x30,v5++
’A’~‘Z’,v5++
‘-’, v13[v5] = v15[v5],v5++
再将处理后的字符与dest区域进行strcmp

逆向

我们将check4的代码逆向就行,对ascii码分析,如果在dest是字母(全大写),他是由源数字+17过去的,如果在dest是数字,他是由源小写字母-0x30得到的

写出你想脚本:

dest = "J2261C63-3I2I-EGE4-IBCC-IE41A5I5F4HB"
flag = ""
for i in dest:
    if ord(i) >= 65 and ord(i) <= 90:
        flag += chr(ord(i) - 17)
    elif ord(i) >= 48 and ord(i) <= 57:
        flag += chr(ord(i) + 0x30)
    elif i == "-":
        flag += "-"

print(flag)


简单逆向12

因为check4省去了前面5个和最后一个字符,则需要自己套上flag{}

flag{9bbfa2fc-c8b8-464d-8122-84da0e8e5d71}

注:分析比较杂,建议以块来读

【附】
控制流平坦化
https://security.tencent.com/index.php/blog/msg/112

上一篇:博图V13、V14、V15、V15.1、V16版本安装包链接下载


下一篇:java 常见面试题