kxctf第五题

2018kxctf第五题

Posted by gxkyrftx on December 30, 2018

1 前期准备

本题为安卓逆向,需要反编译工具可以使用jeb这种集成环境,或dex2jar 和 jd-gui配合使用 。 这里使用dex2jar 和 jd-gui

下载文件,解压,将apk再次解压,得到如图所示的几个文件

1

随后将classes.dex文件拖入d2j-dex2jar.bat,多出来一个classes-dex2jar.jar文件,然后用jd-gui-1.4.0.jar打开

2 函数分析

crackme类的结构如下

2

流程还是很清楚的,直接从上往下走就行

2.1 初始部分

前面定义了a,b,c,d四个数组,参数如下

int[] a = { 16, 6, 7, 10, 9, 16, 10, 8, 8, 9, 6, 6 };
int[] b = { 5, 10, 8, 15, 16, 15, 8, 16, 8, 16, 9, 17, 8, 17, 10, 8, 9, 18, 5, 15, 10, 9, 8, 9, 15, 18, 7, 8, 16, 6 };
int[] c = { 6, 7, 18, 9, 5, 16, 9, 15, 18, 8, 9, 5 };
int[] d = { 7, 7, 9, 12, 8, 7, 13, 5, 14, 5, 9, 17, 5, 7, 12, 8, 8, 6, 19, 6, 8, 16, 10, 6, 12, 9, 6, 7, 12, 5, 9, 8, 7, 8, 15, 9, 16, 8, 8, 19, 12, 6, 8, 7, 5, 15, 6, 16, 15, 7, 9, 12, 10, 7, 15, 6, 5, 14, 14, 9 };

中间一堆没有赋值的变量+空数组l 有一个字符串数组

String[] m = { "23to01", "01to03", "03to05", "05to07", "07to09", "09to11", "11to13", "13to15", "15to17", "17to19", "19to21", "21to23" };

textView是用来显示字符串的组件,在手机上就是显示一块文本的区域。

2.2 a()

private void a()
  {
    try
    {
      c();
      if ((this.j != 0) && (this.i != 0) && (this.h != 0))
      {
        d();
        a(e() + f() + g() + h());
        return;
      }
      this.n.setText(getString(2131427370));
      return;
    }
    catch (Exception localException)
    {
      for (;;) {}
    }
    this.n.setText(getString(2131427370));
  }

2.3 c()

具体代码解释参考注释

private void c()
  {
    try
    {
      str = ((EditText)findViewById(2131165227)).getText().toString();//获取输入
      this.j = 0;
      this.i = 0;
      this.h = 0;
      if (str.length() <= 4) {  //字符串长度大于4,取出前四位
        break label223;
      }
      localObject = str.substring(0, 4);
    }
    catch (Exception localException)
    {
      for (;;)
      {
        String str;
        continue;
        label223:
        Object localObject = localException;
        continue;
        localObject = localException;
      }
    }
    this.j = Integer.parseInt((String)localObject); //在这里对前四位的输入做了限制在1984-2006之间,像是生日,hhhh
    if ((this.j > 0) && (this.j < 189)) {
      this.j = 0;
    }
    if ((this.j <= 1983) || (this.j >= 2007)) {
      this.j = 0;
    }
    if (str.length() > 6)   //同样的输入长度大于6,取5,6位
    {
      localObject = str.substring(4, 6);
      this.i = Integer.parseInt((String)localObject);
      if ((this.i < 1) || (this.i > 12)) {  //判断是不是在1-12之间,生日无疑
        this.i = 0;
      }
      localObject = str;
      if (str.length() > 8) {   //输入长度大于8,取出7,8位
        localObject = str.substring(6, 8);
      }
      this.h = Integer.parseInt((String)localObject);
      if ((this.h < 1) || (this.h > 31))    //判断是不是在1-31之间
      {
        this.h = 0;
        return;
        this.n.setText(getString(2131427370));
      }
      return;
    }
  }

总体功能,检查输入的前8位(生日)是不是满足要求

2.4 d()

private void d()
  {
    try
    {
      if ((this.j == 1989) || (this.j == 2004)) {   //1989.xx.31 or 2004.xx.31
        this.h = 31;
      }
      if ((this.i == 1) || (this.i == 4) || (this.i == 5) || (this.i == 7) || (this.i == 10) || (this.i == 11) || (this.i == 12)) {
        this.j = 1999;
      } //1999.1.xx or 1999.4.xx or 1999.5.xx or 1999.7.xx or 1999.10.xx or 1999.11.xx or 1999.12.xx
      if ((this.j <= 1994) && ((this.i == 2) || (this.i == 6) || (this.i == 8))) {
        this.i = 3;
      } // 1984-1994.2.3 or 1984-1994.6.3 or 1984-1994.8.3
      if ((this.j >= 1996) && ((this.i == 2) || (this.i == 6) || (this.i == 8))) {
        this.i = 9;
      } //1996-2006.2.9 or 1996-2006.6.9 or 1996-2006.8.9 
      if ((this.j == 1995) && ((this.h > this.i + 2) || (this.i == this.h))) {
        this.i = 6;
      } //1995 年,日大于(月+2)或者日月相等,月份等于6
      this.g = this.j; 
      this.f = this.i;
      this.e = this.h;
      return;   //把jih,赋值给gfe
    }
    catch (Exception localException)
    {
      for (;;) {}
    }
    this.n.setText(getString(2131427370));
  }

这个函数,对c中输入的年月日,做出了检查

2.5 e()

private int e()
  {
    try
    {
      int i1 = this.g;  
      i1 = this.d[((i1 - 1900) % 60)];  //年份-1900,对60取余
      return i1;
    }
    catch (Exception localException)
    {
      for (;;) {}
    }
    this.n.setText(getString(2131427370));
    return 0;
  }

年份-1900,对60取余,返回余数

2.6 f()

 private int f()
  {
    try
    {
      int i1 = this.f;
      i1 = this.c[(i1 - 1)]; //月份-1,然后与c数组中的值对应
      return i1;
    }
    catch (Exception localException)
    {
      for (;;) {}
    }
    this.n.setText(getString(2131427370));
    return 0;
  }

把月份当成了一个c数组的索引

2.7 g()

private int g()
  {
    try
    {
      int i1 = this.e;
      i1 = this.b[(i1 - 1)];    //日期-1当作b数组的索引
      return i1;
    }
    catch (Exception localException)
    {
      for (;;) {}
    }
    this.n.setText(getString(2131427370));
    return 0;
  }

日期-1当作b数组的索引

2.8 h()

private int h()
  {
    try
    {
      str = ((EditText)findViewById(2131165227)).getText().toString();
      str = str.substring(8, str.length()); //第8位后面的
      i2 = this.f;  //月份
      i1 = 0;
    }
    catch (Exception localException)
    {
      for (;;)
      {
        String str;
        int i2;
        continue;
        i1 += 1;
        continue;
        int i1 = 0;
      }
    }
    if (i1 < this.m.length) {   
      if (str.equals(this.m[i1]))   //如果第八位后面的和m数组中的第i1位相等
      {
        if ((i2 == 2) && (str.equals(this.m[6]))) { //如果月份=2,后面的字符串="11to13"
          return 63;
        }
        this.k = this.a[i1];    //k是a中第i1个元素
        i1 = 1;
        if (i1 == 0) {
          this.n.setText(getString(2131427370));
        }
        i1 = this.k;
        return i1;
        this.n.setText(getString(2131427370));
        return 0;
      }
    }
  }

第一编是0,抛异常,i1++,遍历数组,寻找两字符串相等的索引值,然后在a中对应。

2.9 a(int)

回来看a(int)的原因

    d();
    a(e() + f() + g() + h());   //四个值相加

函数逻辑

 private void a(int paramInt)
  {
    if ((paramInt <= 34) && (paramInt >= 34)) {}    //传入的参数必须等于34,不然就要抛异常出来
    try
    {
      this.n.setText(String.format("%s%s", new Object[] { getString(2131427369), this.l[paramInt] }));
      ((Button)findViewById(2131165273)).setEnabled(false);
      return;
    }
    catch (Exception localException)
    {
      for (;;) {}
    }
    this.n.setText(getString(2131427370));
    return;
    this.n.setText(getString(2131427370));
  }

函数逻辑分析完了,接下来直接解吧,穷举就可以,总的逻辑很清楚,输入,然后乱七八糟的变换,还好都不算复杂。

3.暴力破解

java代码如下(来自大佬)

public class CTF {
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
 
        new CTF().run();
    }
 
      int[] a = { 16, 6, 7, 10, 9, 16, 10, 8, 8, 9, 6, 6 };
      int[] b = { 5, 10, 8, 15, 16, 15, 8, 16, 8, 16, 9, 17, 8, 17, 10, 8, 9, 18, 5, 15, 10, 9, 8, 9, 15, 18, 7, 8, 16, 6 };
      int[] c = { 6, 7, 18, 9, 5, 16, 9, 15, 18, 8, 9, 5 };
      int[] d = { 7, 7, 9, 12, 8, 7, 13, 5, 14, 5, 9, 17, 5, 7, 12, 8, 8, 6, 19, 6, 8, 16, 10, 6, 12, 9, 6, 7, 12, 5, 9, 8, 7, 8, 15, 9, 16, 8, 8, 19, 12, 6, 8, 7, 5, 15, 6, 16, 15, 7, 9, 12, 10, 7, 15, 6, 5, 14, 14, 9 };
      int e;
      int f;
      int g;
      int h;
      int i;
      int j;
      int k;
      String[] l = new String[73];
      String[] m = { "23to01", "01to03", "03to05", "05to07", "07to09", "09to11", "11to13", "13to15", "15to17", "17to19", "19to21", "21to23" };
     
    private void run() {
         
        int result_len = 0;
        for(int a1 = 1983;a1<2007;a1+=1){
 
            for(int a2 = 1;a2<=12;a2+=1)
            {
 
                for(int a3 = 1;a3<=31;a3+=1){
                for(String item :m)
                {
                
                    this.j = a1;
                    this.i = a2;
                    this.h = a3;
                    str = item;
                    d();
                    int re_e = e();
                    int re_f = f();
                    int re_g = g();
                    int re_h = h();
                   
                    if(re_e+re_f+re_g+re_h==34)
                    {
                        
                        if(re_g==0)
                        {
                            
                        }
                        System.out.println(re_e+" "+" "+re_f+" "+re_g+" "+re_h);
                        System.out.println(a1+" "+" "+a2+" "+a3+" "+item);
                        result_len +=1;
                    }
                         
                    }
                }
            }
             
             
             
        }
         
        System.out.println("数量:"+result_len);
         
    }
     
  
 
      private void d()
      {
        try
        {
          if ((this.j == 1989) || (this.j == 2004)) {
            this.h = 31;
          }
          if ((this.i == 1) || (this.i == 4) || (this.i == 5) || (this.i == 7) || (this.i == 10) || (this.i == 11) || (this.i == 12)) {
            this.j = 1999;
          }
          if ((this.j <= 1994) && ((this.i == 2) || (this.i == 6) || (this.i == 8))) {
            this.i = 3;
          }
          if ((this.j >= 1996) && ((this.i == 2) || (this.i == 6) || (this.i == 8))) {
            this.i = 9;
          }
          if ((this.j == 1995) && ((this.h > this.i + 2) || (this.i == this.h))) {
            this.i = 6;
          }
          this.g = this.j;
          this.f = this.i;
          this.e = this.h;
          return;
        }
        catch (Exception localException)
        {
          for (;;) {}
        }
      }
 
       
       
       
       
 
      private int e()
      {
        try
        {
          int i1 = this.g;
          i1 = this.d[((i1 - 1900) % 60)];
          return i1;
        }
        catch (Exception localException)
        {
            localException.printStackTrace();
         // for (;;) {}
        }
        //this.n.setText(getString(2131427370));
        return 0;
      }
       
      private int f()
      {
        try
        {
          int i1 = this.f;
          i1 = this.c[(i1 - 1)];
          return i1;
        }
        catch (Exception localException)
        {
     //     for (;;) {}
        }
    //    this.n.setText(getString(2131427370));
        return 0;
      }
       
      private int g()
      {
        try
        {
          int i1 = this.e;
          i1 = this.b[(i1 - 1)];
          return i1;
        }
        catch (Exception localException)
        {
       //   for (;;) {}
        }
     //   this.n.setText(getString(2131427370));
        return 0;
      }
       
     
      String str;
      
      private int h()
      {
//      try
//      {
//        str = ((EditText)findViewById(2131165227)).getText().toString();
//        str = str.substring(8, str.length());
          int i2 = this.f;
//        i1 = 0;
//      }
//      catch (Exception localException)
//      {
//        for (;;)
//        {
//          String str;
//          int i2;
//          continue;
//          i1 += 1;
//          continue;
//          int i1 = 0;
//        }
//      }
        //if (i1 < this.m.length)
        //这里是个循环
          for(int i1=0;i1<this.m.length;i1+=1)
          {
          if (str.equals(this.m[i1]))
          {
            if ((i2 == 2) && (str.equals(this.m[6]))) {
              return 63;
            }
            this.k = this.a[i1];
            i1 = 1;
            if (i1 == 0) {
            //  this.n.setText(getString(2131427370));
            }
            i1 = this.k;
            return i1;
            //this.n.setText(getString(2131427370));
           // return 0;
          }
        }
        return i2;
      }
       
}

运行结果

3

python代码(菜鸡)

b_ary_day = [5, 10, 8, 15, 16, 15, 8, 16, 8, 16, 9, 17, 8, 17, 10, 8, 9, 18, 5, 15, 10, 9, 8, 9, 15, 18, 7, 8, 16, 6];
c_ary_month = [6, 7, 18, 9, 5, 16, 9, 15, 18, 8, 9, 5]
d_ary_year = [7, 7, 9, 12, 8, 7, 13, 5, 14, 5, 9, 17, 5, 7, 12, 8, 8, 6, 19, 6, 8, 16, 10, 6, 12, 9, 6, 7, 12, 5, 9, 8, 7, 8, 15, 9, 16, 8, 8, 19, 12, 6, 8, 7, 5, 15, 6, 16, 15, 7, 9, 12, 10, 7, 15, 6, 5, 14, 14, 9]
 
m_strList=["23to01", "01to03", "03to05", "05to07", "07to09", "09to11", "11to13", "13to15", "15to17", "17to19", "19to21", "21to23"]
a_ary = [16, 6, 7, 10, 9, 16, 10, 8, 8, 9, 6, 6]
 
 
#c 函数
def checkData(year,month,day):
    if year<0 and year<189:
        return False
    if year<=1983 or year>2007:
        return False
    if month<1 or month>12:
        return False
    if day>=1 and day<=31:
        return True
    return False
 
#d 函数
def d_dayCheck(year,month,day):
    ret_year=0
    ret_month=0
    ret_day=0
    if year==1989 or year==2004:
        day=31
    if month==1 or month==4 or month==5 or month==7 or month==10 or month==11 or month==12:
        year=1999
    if year<=1994 and (month==2 or month==6 or month==8):
        month=3
    if year>=1996 and (month==2 or month==6 or month==8):
        month=9
    if year==1995 and (day>(2+month) or month==day):
        month=6
    ret_year=year
    ret_month=month
    ret_day=day
    #print "xx"
    return ret_year,ret_month,ret_day
 
#h函数
def check4(month,strxx):
    #print month,strxx
    v4=0
    v0=0
    k=0
    for i,x in enumerate(m_strList):
        if strxx==x:
            if month==2 and strxx==m_strList[6]:
                k=63
            else:
                k=a_ary[i]
    return k                
 
             
            
for y in xrange(1984,2008):
    for m in xrange(1,13):
        for d in xrange(1,32):
            for x in m_strList:
                #print y,m,d,checkData(y,m,d)
                if checkData(y,m,d):
                    n_y,n_m,n_d=d_dayCheck(y,m,d)
                    num1=d_ary_year[(n_y-1900)%60]
                    num2=c_ary_month[n_m-1]
                    if n_d>=30:
                        continue
                    num3=b_ary_day[n_d-1]
                    num4=check4(m,x)                    
                    if num1+num2+num3+num4==34:
                        if y==n_y and n_m==m and n_d==d:
                            print n_y,n_m,n_d,num1,num2,num3,num4
                            print y,m,d,x
                            print "key:%04d%02d%02d%s"%(y,m,d,x)

运行结果 4

大佬脚本跑出来1400组解,哎。。差距,抽空改一下自己的

最后结果

5


本文访问量: