Defcon qualifier 2015 pr0dk3y(reverse2) WriteUp

Reading time ~1 minute

作为逆向题,题目自然木有神马描述,但看一眼就知道,这题是要算个序列号,但是比较蛋疼的是,这题的大多数对单个参数的限制条件都是不等于什么,而做等于判断的各个条件又都是些涉及到好几个参数的检验,所以很是麻烦。

程序首先读入一个序列号的字符串,然后会转换为5个dword,一个word来进行一些check,然后check的大致流程如下:

__int64 __fastcall check_key(char *a1)
{
  __int64 result; // rax@3
  __int16 v2; // [sp+1Ah] [bp-16h]@1
  unsigned int v3; // [sp+1Ch] [bp-14h]@1
  unsigned int v4; // [sp+20h] [bp-10h]@1
  unsigned int v5; // [sp+24h] [bp-Ch]@1
  int v6; // [sp+28h] [bp-8h]@1
  unsigned int v7; // [sp+2Ch] [bp-4h]@1

  v3 = *(_DWORD *)a1;
  v4 = *((_DWORD *)a1 + 1);
  v5 = *((_DWORD *)a1 + 2);
  v6 = *((_DWORD *)a1 + 3);
  v7 = *((_DWORD *)a1 + 4);
  v2 = *((_WORD *)a1 + 10);
  if ( (unsigned int)sub_E10(v2) || (unsigned int)sub_DA2(v2) )
  {
    result = 0LL;
  }
  else if ( (sub_F0F(a1, 20) & 0x7FFF) == v2 )
  {
    if ( (unsigned int)sub_E40(v3, v4, v5) == v6 )
    {
      if ( (unsigned int)sub_1566(v7) )
      {
        if ( (unsigned int)no_equal_adj_4(v3) )
        {
          result = 0LL;
        }
        else if ( (unsigned int)no_equal_adj_8(v3) )
        {
          result = 0LL;
        }
        else if ( (unsigned int)is_prime_larger(v3) )
        {
          if ( (unsigned int)some_bits_mod7_0(v4) )
          {
            if ( (unsigned int)some_bits_saf(v5) )
            {
              if ( (unsigned int)odd_v4_v5_mul_v3(v4, v5, v3) )
                result = (unsigned __int16)calc_jiaoyan(v4, v5) == v2;
              else
                result = 0LL;
            }
            else
            {
              result = 0LL;
            }
          }
          else
          {
            result = 0LL;
          }
        }
        else
        {
          result = 0LL;
        }
      }
      else
      {
        result = 0LL;
      }
    }
    else
    {
      result = 0LL;
    }
  }
  else
  {
    result = 0LL;
  }
  return result;
}

这里的check很多,为了我们能够高效的找到key,这里我们需要选择一个合适的搜索顺序,尽可能的将强的条件放在外面判断。

  1. 首先先是some_bits_mod7_0和some_bits_saf分别是对v4、v5的偶数位的判断,我们暴力穷举会发现两者分别有9363和5042种可能;

  2. 然后在odd_v4_v5_mul_v3这里面,对v4、v5的奇数位做了很弱的限制,但是有个v4_odd * v5_odd = v3 + 1的限制,也就是说,这里我们通过枚举v4、v5的奇数位,我们可以计算出v3,然后就可以将v3带到前面的各个对v3单独限制的地方,很好的做一个筛选;

  3. 接下来,看calc_jiaoyan,由于v4、v5我们已经枚举过了,根据v4、v5我们可以计算出对应的v2,然后带入前面对v2的单独校验中检查;

  4. 然后sub_1566是对v7单独的校验,这个校验可以确定v7总共有171955可能;

  5. 此时,我们仅仅剩下了一个判断(sub_F0F(a1, 20) & 0x7FFF) == v2,这句判断实际是用v3-v7计算出一个校验和,与v2进行比较,当我们进行到这一步之前,我们可以秒出很多的结果,但是,当我们加上了这个判断之后,我跑了很久也没能跑出结果,很是无奈,不过想想也是,本来其实v4、v5枚举完后量还好,但是和v7的这近20W一乘起来,也确实恐怖;

  6. 最后,仔细再观察一下最后那个校验和的判断,我们会发现,v2其实隐式的被限制必须要小于0x7FFF,于是我们完全可以在v4、v5算出v2后,先进行这个判断,然后再来和v7联合起来校验,这样其实我们搜到一个解的工作量直接就相当于是减少了10W倍这个级别的,尤其是当v2大于0x7FFF的量比较大的时候。因为在这里,其实可行解的量是巨大的,最后一个校验也没有很严,我们现在一次判断就可以排除10W多组不可能的情况。

总之,程序写好之后,很快便可以跑出刷屏的解,随便选个就好,然后再按照规则,用算出来的6个数,反向去计算序列号即可,这一步是队友做的,我这里就没有了……

pr0dk3y.zip

挂载网络文件夹后网络故障时文件操作命令卡死

挂载 NFS 或者 Samba 的时候,经常会由于网络故障导致挂载好的链接断掉。此时如果尝试进行 ls、cd、df 等各种命令,只要与此目录沾上边,就会卡住。如果使用了类似 oh-my-zsh 这种配置的,只要在网络目录中,弹出命令提示符前就会直接卡住。这个时候第一反应就是...… Continue reading

路由折腾记 第四弹

Published on September 02, 2017