Anonymous、 发表于 2018-9-30 16:50

钉钉CTF+AliCTF2015第三题+Android逆向小助手使用详解

本帖最后由 Anonymous、 于 2018-10-12 20:39 编辑

一、说明
钉钉CTF是一个网友昨晚给我的,比较简单,但是思路和AliCTF非常像,所以就放在一起了,一些坛友问工具怎么使用
其实很简单,在这也稍微加下使用说明,自己技术比较菜,全程靠猜~~~~~有什么不对的地方,还请各位师傅指点.

二、钉钉CTF
这一题比较简单,先打开app看下

随便输入

错了,但是有个welcome to flag blank!根据题目意思,尝试什么都不输入

什么??????居然就对了!!!!!
好了,开始看Ali的吧...............

算啦算啦,还是看看内部怎么实现的这么牛逼的功能的吧
    protected void onCreate(Bundle arg3) {
      super.onCreate(arg3);
      this.setContentView(2130968603);
      this.text = this.findViewById(2131427416);
      this.textView1 = this.findViewById(2131427418);
      this.button = this.findViewById(2131427415);
      this.button.setOnClickListener(new View$OnClickListener() {
            public void onClick(View arg4) {
                MainActivity.this.c = new CheckClass();
                MainActivity.this.c.a(MainActivity.this.text.getText().toString());//先获取输入的字符串
                if(MainActivity.this.c.check()) {//关键点
                  MainActivity.this.textView1.setText("flag is XMAN{" + MainActivity.this.text.getText().toString() + "}");   
                }
                else {
                  MainActivity.this.textView1.setText("WORING!");
                }
            }
      });
    }
onCreate方法中,先看MainActivity.this.c.a
public void a(String arg5) {
      int v1 = 30;
      this.A = new byte;
      this.B = arg5.getBytes();
      int v0;
      for(v0 = 0; v0 < arg5.length(); ++v0) {
            this.A = this.B;
      }

      this.B = new byte;
    }
获取输入的字符串,再看MainActivity.this.c.check()
public boolean check() {
      boolean v9 = false;
      int[] v0 = new int[]{40, 42, 65, 67, 68, 2, 64, 70, 96, 98, 181, 7, 10, 64, 23, 17, 37, 20, 45, 91, 74, 72, 135, 33, 57, 43, 87, 99, 147, 53};
      byte[] v5 = new byte[]{52, 111, 102, 113, 52, 52, 98};
      int v2 = 0;
      int v4 = 0;
      int v7 = 0;
      int v1;
      for(v1 = 0; v1 < v0.length; ++v1) {
            int v8 = this.b(v0);
            new String();
            Log.d("now array:", String.valueOf(v8));
            switch(v8) {
                case 0: {
                  this.A = ((byte)(this.A ^ v7));
                  break;
                }
                case 1: {
                  if(this.A != 0) {
                        ++v4;
                  }
                  else {
                  }

                  break;
                }
                case 2: {
                  v5 = ((byte)(v5 ^ v4));
                  ++v4;
                  break;
                }
                case 3: {
                  if(v5 == this.A) {
                        ++v7;
                  }
                  else {
                  }

                  break;
                }
                case 4: {
                  if(v7 == v4) {
                        v9 = true;
                  }

                  return v9;
                }
                case 5: {
                  if(v4 != v5.length) {
                        v1 = v0.length - 3;
                  }
                  else {
                        v4 = 0;
                  }

                  break;
                }
                default: {
                  ++v2;
                  break;
                }
            }
      }

      return v9;
    }

public int b(int arg4) {
      int v0 = 181 & arg4;
      return (v0 & 1) + ((v0 & 4) >> 2) + ((v0 & 16) >> 4) + ((v0 & 32) >> 5) + ((v0 & 128) >> 7);
}

此函数为关键点,看着挺复杂的,只要返回为true即可
case 4: {
                  if(v7 == v4) {
                        v9 = true;
                  }
                  return v9;
                }
case 4里的判断执行,下面再接着分析v8 int v8 = this.b(v0);
由于v0是固定的,所以v8也是固定的,那么switch语句就好分析了
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class DCtf {
         private static byte[] A;
         private static byte[] B;
      public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException {
                a("4");
                check();
          }      
      
      public static void a(String arg5) {
      int v1 = 30;
      A = new byte;
      B = arg5.getBytes();
      int v0;
      for(v0 = 0; v0 < arg5.length(); ++v0) {
            A = B;
      }

      B = new byte;
    }

    public static int b(int arg4) {
      int v0 = 181 & arg4;
      return (v0 & 1) + ((v0 & 4) >> 2) + ((v0 & 16) >> 4) + ((v0 & 32) >> 5) + ((v0 & 128) >> 7);
    }

    public static boolean check() {
      boolean v9 = false;
      int[] v0 = new int[]{40, 42, 65, 67, 68, 2, 64, 70, 96, 98, 181, 7, 10, 64, 23, 17, 37, 20, 45, 91, 74, 72, 135, 33, 57, 43, 87, 99, 147, 53};
      byte[] v5 = new byte[]{52, 111, 102, 113, 52, 52, 98};
      int v2 = 0;
      int v4 = 0;
      int v7 = 0;
      int v1;
      for(v1 = 0; v1 < v0.length; ++v1) {
            int v8 = b(v0);
            new String();
            System.out.println("now array:" + String.valueOf(v8));
            switch(v8) {
                case 0: {
                  A = ((byte)(A ^ v7));
                  break;
                }
                case 1: {
                  if(A != 0) {
                        ++v4;
                  }
                  else {
                  }
                  break;
                }
                case 2: {
                  v5 = ((byte)(v5 ^ v4));
                  ++v4;
                  break;
                }
                case 3: {
                  if(v5 == A) {
                            System.out.println("v5 "+v5+"------A "+A+" "+v7);
                        ++v7;
                  }
                  else {
                  }
                  break;
                }
                case 4: {
                  if(v7 == v4) {
                        v9 = true;
                  }
                  System.out.println("v7 "+v7+"------v4 "+v4);

                  return v9;
                }
                case 5: {
                  if(v4 != v5.length) {
                        v1 = v0.length - 3;
                  }
                  else {
                        v4 = 0;
                  }

                  break;
                }
                default: {
                  ++v2;
                  break;
                }
               
            }
      }

      return v9;
    }
}
运行上面的代码,可以得到v8的值分别是
now array:1
now array:1
now array:1
now array:1
now array:1
now array:0
now array:0
now array:1
now array:1
now array:1
now array:5
now array:3
now array:4
最后执行的就是case 4,符合我们前面的分析,但是v7 == v4,能影响v7的只有case 3这个分支,看上面v8的值,知道下面的代码只执行了一次
case 3: {
                  if(v5 == this.A) {
                        ++v7;
                  }
                  else {
                  }
                  break;
                }
所以要想v7 == v4,v7和v4只能为1或者0,0就是什么都不输入,++v7执行之后为1,执行之前v7为就为0,所以A=52,查找ascall码表结果为4

分析到这,你就认为完了?然后并没有结束、、、、
case 5: {
                              if (v4 != v5.length) {
                                        v1 = v0.length - 3;
                              } else {
                                        v4 = 0;
                              }

                              break;
                        }
上面的分析的是v4 != v5.length结果,如果v4 = v5.length呢,继续往下分析吧,也就是输入的字符串为7位
now array:1
now array:1
now array:1
now array:1
now array:1
now array:0
now array:0
now array:1
now array:1
now array:1
now array:5
now array:2
now array:0
now array:0
now array:3
v5 52------A 52 v7 0
now array:2
now array:3
now array:2
now array:3
now array:2
now array:0
now array:0
now array:3
now array:2
now array:3
now array:2
now array:3
now array:2
now array:3
now array:4
v7 1------v4 7

控制v7的的case只有一个
case 3: {
                              if (v5 == A) {
                                        System.out.println("v5 " + v5 + "------A " + A + " v7 " + v7);
                                        ++v7;
                              } else {
                              }
                              break;
                        }
根据上面的代码循环,可以慢慢倒推出来结果为4ndr01d,真是一波三折呀。。。

放下分析的代码
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class ctf1 {
      private static byte[] A;
      private static byte[] B;

      public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException {
                a("4ndr01d");
                check();
      }

      public static void a(String arg5) {
                int v1 = 30;
                A = new byte;
                B = arg5.getBytes();
                int v0;
                for (v0 = 0; v0 < arg5.length(); ++v0) {
                        A = B;
                }

                B = new byte;
      }

      public static int b(int arg4) {
                int v0 = 181 & arg4;
                return (v0 & 1) + ((v0 & 4) >> 2) + ((v0 & 16) >> 4) + ((v0 & 32) >> 5) + ((v0 & 128) >> 7);
      }

      public static boolean check() {
                boolean v9 = false;
                int[] v0 = new int[] { 40, 42, 65, 67, 68, 2, 64, 70, 96, 98, 181, 7, 10, 64, 23, 17, 37, 20, 45, 91, 74, 72,
                              135, 33, 57, 43, 87, 99, 147, 53 };
                byte[] v5 = new byte[] { 52, 111, 102, 113, 52, 52, 98 };
                int v2 = 0;
                int v4 = 0;
                int v7 = 0;
                int v1;
                for (v1 = 0; v1 < v0.length; ++v1) {
                        int v8 = b(v0);
                        new String();
                        System.out.println("now array:" + String.valueOf(v8));
                        switch (v8) {
                        case 0: {
                              A = ((byte) (A ^ v7));
                              break;
                        }
                        case 1: {
                              if (A != 0) {
                                        ++v4;
                              } else {
                              }
                              break;
                        }
                        case 2: {
                              v5 = ((byte) (v5 ^ v4));
                              ++v4;
                              break;
                        }
                        case 3: {
                              if (v5 == A) {
                                        System.out.println("v5 " + v5 + "------A " + A + " v7 " + v7);
                                        ++v7;
                              } else {
                              }
                              break;
                        }
                        case 4: {
                              if (v7 == v4) {
                                        v9 = true;
                              }
                              System.out.println("v7 " + v7 + "------v4 " + v4);
                              return v9;
                        }
                        case 5: {
                              if (v4 != v5.length) {
                                        v1 = v0.length - 3;
                              } else {
                                        v4 = 0;
                              }

                              break;
                        }
                        default: {
                              ++v2;
                              break;
                        }

                        }
                }

                return v9;
      }
}


三、Alictf
好啦,终于可以上主菜了~~~~~~

先用jeb反编译
package com.ali.mobisecenhance;

import android.app.Application;
import android.content.Context;

public class StubApplication extends Application {
    static {
      try {
            Class v2 = Class.forName("android.os.SystemProperties");
            Object v1 = v2.getDeclaredMethod("get", String.class).invoke(v2, "ro.product.cpu.abi");
      }
      catch(Exception v3) {
            v3.printStackTrace();
      }

      if(((String)v1).equalsIgnoreCase("x86")) {
            System.loadLibrary("mobisecx");
      }
      else {
            System.loadLibrary("mobisec");
      }
    }

    public StubApplication() {
      super();
    }

    protected native void attachBaseContext(Context arg1) {
    }

    public native void onCreate() {
    }
}
加了壳子~~~~关键代码看不到,那就先用ida脱壳吧
先打开DDMS

获取入口点

一键挂起

用ida附加

在ibdvm的dvmDefineClass下了个断点,通过DvmDex的指针,把odex dump下来,下好断点,点jdb启动

查看r0地址

跟随上面的地址

用脚步dump下来
static main(void)
{
auto fp, dex_addr, end_addr;
fp = fopen("C:\\dump.dex", "wb");
end_addr = 0x75512000 + 0x00010000;
for ( dex_addr = 0x75512000; dex_addr < end_addr; dex_addr ++ )
fputc(Byte(dex_addr), fp);
}
然后修复,最后用版主的Apktool工具,反编译dex,再回编译,就可以用jeb打开了



下面就是分析java代码了
主要是根据这个表对我们输入的字符串,进行置换
static {
      e.a = new HashMap();
      e.a("a", ". _");
      e.a("b", "_ . . .");
      e.a("c", "_ . _ .");
      e.a("d", "_ . .");
      e.a("e", ".");
      e.a("f", ". . _ .");
      e.a("g", "_ _ .");
      e.a("h", ". . . .");
      e.a("i", ". .");
      e.a("j", ". _ _ _");
      e.a("k", "_ . _");
      e.a("l", ". _ . .");
      e.a("m", "_ _");
      e.a("n", "_ .");
      e.a("o", "_ _ _");
      e.a("p", ". _ _ .");
      e.a("q", "_ _ . _");
      e.a("r", ". _ .");
      e.a("s", ". . .");
      e.a("t", "_");
      e.a("u", ". . _");
      e.a("v", ". . . _");
      e.a("w", ". _ _");
      e.a("x", "_ . . _");
      e.a("y", "_ . _ _");
      e.a("z", "_ _ . .");
      e.a("2", ". _ _ _ _");
      e.a("1", ". . _ _ _");
      e.a("3", ". . . _ _");
      e.a("4", ". . . . _");
      e.a("0", ". . . . .");
      e.a("6", "_ . . . .");
      e.a("9", "_ _ . . .");
      e.a("8", "_ _ _ . .");
      e.a("7", "_ _ _ _ .");
      e.a("5", "_ _ _ _ _");
    }

    public e() {
      super();
    }

    public String a(String arg8) {
      String v0;
      dn.b(dn.a());
      if(arg8.equals("...___...")) {
            v0 = "sos";
      }
      else {
            StringBuilder v2 = new StringBuilder();
            String[] v3 = arg8.split("\\s+");//根据空格进行分割
            int v4 = v3.length;
            int v1 = 0;
            while(true) {
                if(v1 < v4) {
                  Object v0_1 = e.a.get(v3); //替换
                  if(v0_1 != null) {
                        v2.append(((String)v0_1));//连接
                        ++v1;
                        continue;
                  }
                  else {
                        break;
                  }
                }
                else {
                  goto label_26;
                }

                return v0;
            }

            throw new IllegalArgumentException();
      label_26:
            v0 = v2.toString();
      }
      return v0;
    }
下面这部分代码,根据压缩包里的strings.xml和public.xml可以分析run()返回值为0时,提示成功的字符
public void handleMessage(Message arg5) {
      dn.b(dn.a());
      int v2 = -65536;
      this.a.b.setEnabled(true);
      switch(arg5.what) {
            case 0: {
                goto label_10;
            }
            case 1: {
                goto label_27;
            }
            case 2: {
                goto label_51;
            }
            case 3: {
                goto label_66;
            }
      }
      return;
    label_66:
      this.a.a.setTextColor(v2);
      TextView v1 = this.a.a;
      int v0 = Main.a(this.a).nextBoolean() ? 2130968582 : 2130968581;
      v1.setText(v0);
      return;
      try {
      label_51:
            this.a.a.setTextColor(-65536);
      }
      catch(Exception v0_1) {
            this.a.a.setTextColor(-7829368);
      }

      this.a.a.setText(2130968580);
      return;
    label_10:
      this.a.a.setTextColor(-16776961);
      try {
            this.a.a.setText(103 / arg5.what);
      }
      catch(Exception v0_1) {
            this.a.a.setText(2130968586);
      }
      return;
    label_27:
      this.a.a.setTextColor(v2);
      switch(Main.a(this.a).nextInt(3)) {
            case 0: {
                goto label_36;
            }
            case 1: {
                goto label_41;
            }
            case 2: {
                goto label_46;
            }
      }
      return;
    label_36:
      this.a.a.setText(2130968583);
      return;
    label_41:
      this.a.a.setText(2130968585);
      return;
    label_46:
      this.a.a.setText(2130968584);
    }
下面的run()函数为关键点,只要返回0即可,分析逻辑和上面那个CTF很类似
b(a arg1, Handler arg2, String arg3) {
      this.d = arg1;
      this.b = arg2;
      this.input = arg3;
      super();
    }

    public void run() {
      int v0_6;
      String v0_5;
      String v1_5;
      byte[] v2_3;
      Cipher v1_1;
      MessageDigest v0_3;
      String str;
      dn.b(dn.a());
      MessageDigest v1 = null;
      if(Build$VERSION.SDK_INT >= 10 && (Debug.isDebuggerConnected())) {
            this.b.sendEmptyMessage(1);
            return;
      }

      try {
            str = new e().a(this.input);//a函数的主要目的,在莫尔斯码表中置换
      }
      catch(Exception v0) {
            this.b.sendEmptyMessage(3);
            return;
      }

      try {
            if(str.equals("sos")) {
                this.b.sendEmptyMessage(2);
                return;
            }

            CRC32 v0_1 = new CRC32();//crc加密
            v0_1.update(str.getBytes());
            v0_1.getValue();
            str.hashCode();
            try {
                v0_3 = MessageDigest.getInstance("sha1"); //sha1加密
            }
            catch(NoSuchAlgorithmException v0_2) {
                v0_2.printStackTrace();
                v0_3 = v1;
            }

            try {
                v1_1 = Cipher.getInstance("AES");   
            }
            catch(NoSuchPaddingException v0_4) {
                v0_4.printStackTrace();
                return;
            }
            catch(NoSuchAlgorithmException v2) {
                v2.printStackTrace();
            }

            if(!b.a && v1_1 == null) {
                throw new AssertionError();
            }
      }
      catch(Exception v0) {
            goto label_26;
      }

      int v2_1 = 2;
      try {
            v1_1.init(v2_1, new SecretKeySpec(Base64.decode("GXiQHT1CZ2elMzwpvvAoPA==".getBytes(), 0), "AES")); //AES设置key
            goto label_69;
      }
      catch(Exception v0) {
      }
      catch(InvalidKeyException v2_2) {
      label_69:
            try {
                new byte;
                try {
                  v2_3 = v1_1.doFinal(Base64.decode("hjdsUjIT5je69WXIZP7Kzw==".getBytes("UTf-8"), 0));//AES解密,值固定
                  goto label_78;
                }
                catch(UnsupportedEncodingException v1_2) {
                  try {
                        v1_2.printStackTrace();
                  label_78:
                        String v6 = new String(v2_3);   //上面AES解密的
                        v0_3.update(new byte[]{127});
                        v0_3.update(str.getBytes());   
                        v0_3.update(new byte[]{1});
                  }
                  catch(Exception v0) {
                        goto label_26;
                  }
                }
                catch(BadPaddingException v1_3) {
                  goto label_78;
                }
                catch(IllegalBlockSizeException v1_4) {
                  goto label_78;
                }
            }
            catch(Exception v0) {
                goto label_26;
            }

            try {
                v1_5 = new String(Base64.encode(v0_3.digest(), 0));//
                goto label_99;
            }
            catch(Exception v0) {
                try {
                  v0.printStackTrace();
                  return;
                label_99:
                  if(!str.equals(v6)) {
                        goto label_190;
                  }
                  else if(Arrays.equals(v1_5.getBytes(), "2398lj2n".getBytes())) {
                        this.b.sendEmptyMessage(0);
                        return;
                  }
                  else {
                        v0_5 = "234";
                  }

                  goto label_117;
                }
                catch(Exception v0) {
                  goto label_26;
                }
            }

      label_190:
            v0_5 = v1_5;
            try {
            label_117:
                if(v0_5.equals("lsdf==")) {
                  this.b.sendEmptyMessage(0);
                  return;
                }

                char[] v1_6 = str.toCharArray();
                v0_6 = str.substring(0, 2).hashCode();
                if(v0_6 > 3904) {
                  this.b.sendEmptyMessage(4);
                  return;
                }

                if(v0_6 == 3618) {
                  if(v1_6 + v1_6 != 168) {
                        goto label_178;
                  }

                  do {
                  label_144:
                        byte[] v5_1 = e.class.getAnnotation(f.class).a() + a.class.getAnnotation(f.class).a().getBytes();
                        if(v1_6.length - 2 == v5_1.length) {
                            v0_6 = 0;
                            while(true) {
                              if(v0_6 >= v5_1.length) {
                                    goto label_188;
                              }
                              else if(v1_6 != v5_1) {
                                    v0_6 = 0;
                              }
                              else {
                                    ++v0_6;
                                    continue;
                              }

                              goto label_170;
                            }
                        }

                        goto label_177;
                  }
                  while(true);
                }

                goto label_178;
            }
            catch(Exception v0) {
                goto label_26;
            }

      label_188:
            v0_6 = 1;
            try {
            label_170:
                if(v0_6 != 0) {
                  this.b.sendEmptyMessage(0);
                  return;
                }

            label_177:
                if(v2_3 == null) {
                  goto label_144;
                }

            label_178:
                this.b.sendEmptyMessage(1);
            }
            catch(Exception v0) {
            label_26:
                this.b.sendEmptyMessage(1);
            }
      }
    }
只有为这个的时候this.b.sendEmptyMessage(0);才会提示成功, label_188: ---label_117:---label_190:,跳转这三个点才能成功,
label_190:
            v0_5 = v1_5;
            try {
            label_117:
                if(v0_5.equals("lsdf==")) {
                  this.b.sendEmptyMessage(0);
                  return;
                }
v0_3.update(new byte[]{127});v0_3.update(str.getBytes());
v0_3.update(new byte[]{1});
v1_5 = new String(Base64.encode(v0_3.digest(), 0));
v0_5 = v1_5;
由于前面对v0_3的处理,导致不能相等,所以只剩下label_170:这个独苗,然后看可以谁跳转到label_170:
char[] v1_6 = str.toCharArray();
                v0_6 = str.substring(0, 2).hashCode();
                if(v0_6 > 3904) {
                  this.b.sendEmptyMessage(4);
                  return;
                }

                if(v0_6 == 3618) {
                  if(v1_6 + v1_6 != 168) {
                        goto label_178;
                  }

                  do {
                  label_144:
                        byte[] v5_1 = e.class.getAnnotation(f.class).a() + a.class.getAnnotation(f.class).a().getBytes();
                        if(v1_6.length - 2 == v5_1.length) {
                            v0_6 = 0;
                            while(true) {
                              if(v0_6 >= v5_1.length) {
                                    goto label_188;
                              }
                              else if(v1_6 != v5_1) {
                                    v0_6 = 0;
                              }
                              else {
                                    ++v0_6;
                                    continue;
                              }

                              goto label_170;
                            }
                        }

                        goto label_177;
                  }
                  while(true);
                }

                goto label_178;
            }
分析可知,v0_6 == 3618 和 v1_6 + v1_6 = 168必须同时成立,v0_6 = str.substring(0, 2).hashCode();,由于前面置换表只有小写字母和数字,所以可以直接遍历
#include <stdio.h>
#include <stdlib.h>


int main()
{
      int arry[] = { 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122 };
      int n = sizeof(arry) / sizeof(arry);
      for (int i = 0; i < n; i++)
      {
                for (int j = 0; j < n; j++)
                {
                        if ((arry * 31 + arry) == 3618)
                        {
                              printf("%d----%d\n", arry,arry);
                        }
                }
      }
      system("pause");
      return 0;
}

c语言很垃圾,只能写这个了.........结果有两个113----115和115----53,只有后面的符合要求,转换成acsll为s5,接着往下看
byte[] v5_1 = e.class.getAnnotation(f.class).a() + a.class.getAnnotation(f.class).a().getBytes(); //获取后面四个字符
                        if(v1_6.length - 2 == v5_1.length) {
                            v0_6 = 0;
                            while(true) {
                              if(v0_6 >= v5_1.length) {
                                    goto label_188;
                              }
                              else if(v1_6 != v5_1) {
                                    v0_6 = 0;
                              }
                              else {
                                    ++v0_6;
                                    continue;
                              }

                              goto label_170;
                            }
                        }
下面就可以看出来是比较了,要长度相等,字符相等,所以后面的为7e1p,加上前面的s5为s57e1p,然后再置换一下就行了,结果为... _____ ____. . ..___ .__.
贴下java的分析代码,很垃圾····························
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Base64.Decoder;
import java.util.Base64.Encoder;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

public class aestest {
      
      public static void main(String[] args) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException{
                byte[] v2_3;
                Cipher v1_1;
                String v5 = "s57e1p";
                String v1_5;
                int v0_6;
                MessageDigest v0_3;
                char[] v1_6 = v5.toCharArray();
                v0_3 = MessageDigest.getInstance("sha1");
                v1_1 = Cipher.getInstance("AES");
                Decoder decoder = Base64.getDecoder();
                Encoder encode = Base64.getEncoder();
                v1_1.init(2, new SecretKeySpec(decoder.decode("GXiQHT1CZ2elMzwpvvAoPA==".getBytes()), "AES"));
                v2_3 = v1_1.doFinal(decoder.decode("hjdsUjIT5je69WXIZP7Kzw==".getBytes("UTf-8")));
                System.out.println(v2_3);
                v0_3.update(new byte[]{127});
                v0_3.update(v5.getBytes());
                v0_3.update(new byte[]{1});
                String v6 = new String(v2_3);
                v1_5 = new String(encode.encode(v0_3.digest()));
                System.out.println(v1_5);
                v0_6 = v5.substring(0, 2).hashCode();
                System.out.println(v0_6);
          }      
}

C_Ryan 发表于 2018-10-4 03:07

钉钉CTF这一道,还有一种情况没有分析,就是当case5时候v4 = v5.length,会是一个另一个截然不同的分析方向,大致就是v4先加累加到7,然后case5后v7再累加到7,这就需要对输入的字符串有要求了,会进行些亦或比较操作,这个flag答案为4ndr01d。

Anonymous、 发表于 2018-10-4 09:07

C_Ryan 发表于 2018-10-4 03:07
钉钉CTF这一道,还有一种情况没有分析,就是当case5时候v4 = v5.length,会是一个另一个截然不同的分析方向 ...

666,这么多答案吗....当时分析出一个,就没再仔细看了:$qqq

sqln0324 发表于 2018-9-30 16:56

又一个看不懂系列

90182si 发表于 2018-9-30 17:17

看不懂系列,哈哈哈

hechenpi 发表于 2018-9-30 18:22

看不懂系列, 不知所云

多瑙河下 发表于 2018-9-30 19:18


看不懂系列, 不知所云

雨落丶千寒 发表于 2018-9-30 19:19

向大佬致敬

kanxue2018 发表于 2018-9-30 20:13



感谢楼主分享,支持一下!{:1_893:}

onmiuncai 发表于 2018-9-30 20:17

请问下LZ dump后的odex怎么修复,是直接用baksmali -x 转dex 还是需要手动修复什么?

linuxprobe 发表于 2018-9-30 21:09

你即便把它全部逆向了又能怎么样呢?

kk1212 发表于 2018-9-30 21:41

能把这几个学会也挺厉害的
页: [1] 2 3
查看完整版本: 钉钉CTF+AliCTF2015第三题+Android逆向小助手使用详解