开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 1500|回复: 0
收起左侧

[图文资料] AliCTF2015第三题+Android逆向小助手使用详解

[复制链接]
结帖率:100% (3/3)
发表于 2018-10-9 16:20:36 | 显示全部楼层 |阅读模式   浙江省杭州市
本帖最后由 Breathless 于 2018-10-9 16:25 编辑

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

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

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

  13.         if(((String)v1).equalsIgnoreCase("x86")) {
  14.             System.loadLibrary("mobisecx");
  15.         }
  16.         else {
  17.             System.loadLibrary("mobisec");
  18.         }
  19.     }

  20.     public StubApplication() {
  21.         super();
  22.     }

  23.     protected native void attachBaseContext(Context arg1) {
  24.     }

  25.     public native void onCreate() {
  26.     }
  27. }
复制代码

加了壳子~~~~关键代码看不到,那就先用ida脱壳吧
先打开DDMS
1.png
获取入口点
2.png
一键挂起
3.png
用ida附加
4.png
在ibdvm的dvmDefineClass下了个断点,通过DvmDex的指针,把odex dump下来,下好断点,点jdb启动
5.png
查看r0地址
6.png
跟随上面的地址
7.png
用脚步dump下来
  1. static main(void)
  2. {
  3. auto fp, dex_addr, end_addr;
  4. fp = fopen("C:\\dump.dex", "wb");
  5. end_addr = 0x75512000 + 0x00010000;
  6. for ( dex_addr = 0x75512000; dex_addr < end_addr; dex_addr ++ )
  7. fputc(Byte(dex_addr), fp);
  8. }
复制代码

然后修复,最后用版主的Apktool工具,反编译dex,再回编译,就可以用jeb打开了
8.png

9.png
下面就是分析java代码了
主要是根据这个表对我们输入的字符串,进行置换
  1. static {
  2.         e.a = new HashMap();
  3.         e.a("a", ". _");
  4.         e.a("b", "_ . . .");
  5.         e.a("c", "_ . _ .");
  6.         e.a("d", "_ . .");
  7.         e.a("e", ".");
  8.         e.a("f", ". . _ .");
  9.         e.a("g", "_ _ .");
  10.         e.a("h", ". . . .");
  11.         e.a("i", ". .");
  12.         e.a("j", ". _ _ _");
  13.         e.a("k", "_ . _");
  14.         e.a("l", ". _ . .");
  15.         e.a("m", "_ _");
  16.         e.a("n", "_ .");
  17.         e.a("o", "_ _ _");
  18.         e.a("p", ". _ _ .");
  19.         e.a("q", "_ _ . _");
  20.         e.a("r", ". _ .");
  21.         e.a("s", ". . .");
  22.         e.a("t", "_");
  23.         e.a("u", ". . _");
  24.         e.a("v", ". . . _");
  25.         e.a("w", ". _ _");
  26.         e.a("x", "_ . . _");
  27.         e.a("y", "_ . _ _");
  28.         e.a("z", "_ _ . .");
  29.         e.a("2", ". _ _ _ _");
  30.         e.a("1", ". . _ _ _");
  31.         e.a("3", ". . . _ _");
  32.         e.a("4", ". . . . _");
  33.         e.a("0", ". . . . .");
  34.         e.a("6", "_ . . . .");
  35.         e.a("9", "_ _ . . .");
  36.         e.a("8", "_ _ _ . .");
  37.         e.a("7", "_ _ _ _ .");
  38.         e.a("5", "_ _ _ _ _");
  39.     }

  40.     public e() {
  41.         super();
  42.     }

  43.     public String a(String arg8) {
  44.         String v0;
  45.         dn.b(dn.a());
  46.         if(arg8.equals("...___...")) {
  47.             v0 = "sos";
  48.         }
  49.         else {
  50.             StringBuilder v2 = new StringBuilder();
  51.             String[] v3 = arg8.split("\\s+");  //根据空格进行分割
  52.             int v4 = v3.length;
  53.             int v1 = 0;
  54.             while(true) {
  55.                 if(v1 < v4) {
  56.                     Object v0_1 = e.a.get(v3[v1]); //替换
  57.                     if(v0_1 != null) {
  58.                         v2.append(((String)v0_1));//连接
  59.                         ++v1;
  60.                         continue;
  61.                     }
  62.                     else {
  63.                         break;
  64.                     }
  65.                 }
  66.                 else {
  67.                     goto label_26;
  68.                 }

  69.                 return v0;
  70.             }

  71.             throw new IllegalArgumentException();
  72.         label_26:
  73.             v0 = v2.toString();
  74.         }
  75.         return v0;
  76.     }
复制代码

下面这部分代码,根据压缩包里的strings.xml和public.xml可以分析run()返回值为0时,提示成功的字符
  1. public void handleMessage(Message arg5) {
  2.         dn.b(dn.a());
  3.         int v2 = -65536;
  4.         this.a.b.setEnabled(true);
  5.         switch(arg5.what) {
  6.             case 0: {
  7.                 goto label_10;
  8.             }
  9.             case 1: {
  10.                 goto label_27;
  11.             }
  12.             case 2: {
  13.                 goto label_51;
  14.             }
  15.             case 3: {
  16.                 goto label_66;
  17.             }
  18.         }
  19.         return;
  20.     label_66:
  21.         this.a.a.setTextColor(v2);
  22.         TextView v1 = this.a.a;
  23.         int v0 = Main.a(this.a).nextBoolean() ? 2130968582 : 2130968581;
  24.         v1.setText(v0);
  25.         return;
  26.         try {
  27.         label_51:
  28.             this.a.a.setTextColor(-65536);
  29.         }
  30.         catch(Exception v0_1) {
  31.             this.a.a.setTextColor(-7829368);
  32.         }

  33.         this.a.a.setText(2130968580);
  34.         return;
  35.     label_10:
  36.         this.a.a.setTextColor(-16776961);
  37.         try {
  38.             this.a.a.setText(103 / arg5.what);
  39.         }
  40.         catch(Exception v0_1) {
  41.             this.a.a.setText(2130968586);
  42.         }
  43.         return;
  44.     label_27:
  45.         this.a.a.setTextColor(v2);
  46.         switch(Main.a(this.a).nextInt(3)) {
  47.             case 0: {
  48.                 goto label_36;
  49.             }
  50.             case 1: {
  51.                 goto label_41;
  52.             }
  53.             case 2: {
  54.                 goto label_46;
  55.             }
  56.         }
  57.         return;
  58.     label_36:
  59.         this.a.a.setText(2130968583);
  60.         return;
  61.     label_41:
  62.         this.a.a.setText(2130968585);
  63.         return;
  64.     label_46:
  65.         this.a.a.setText(2130968584);
  66.     }
复制代码
下面的run()函数为关键点,只要返回0即可,分析逻辑和上面那个CTF很类似
  1. b(a arg1, Handler arg2, String arg3) {
  2.         this.d = arg1;
  3.         this.b = arg2;
  4.         this.input = arg3;
  5.         super();
  6.     }

  7.     public void run() {
  8.         int v0_6;
  9.         String v0_5;
  10.         String v1_5;
  11.         byte[] v2_3;
  12.         Cipher v1_1;
  13.         MessageDigest v0_3;
  14.         String str;
  15.         dn.b(dn.a());
  16.         MessageDigest v1 = null;
  17.         if(Build$VERSION.SDK_INT >= 10 && (Debug.isDebuggerConnected())) {
  18.             this.b.sendEmptyMessage(1);
  19.             return;
  20.         }

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

  28.         try {
  29.             if(str.equals("sos")) {
  30.                 this.b.sendEmptyMessage(2);
  31.                 return;
  32.             }

  33.             CRC32 v0_1 = new CRC32();  //crc加密
  34.             v0_1.update(str.getBytes());
  35.             v0_1.getValue();
  36.             str.hashCode();
  37.             try {
  38.                 v0_3 = MessageDigest.getInstance("sha1"); //sha1加密
  39.             }
  40.             catch(NoSuchAlgorithmException v0_2) {
  41.                 v0_2.printStackTrace();
  42.                 v0_3 = v1;
  43.             }

  44.             try {
  45.                 v1_1 = Cipher.getInstance("AES");   
  46.             }
  47.             catch(NoSuchPaddingException v0_4) {
  48.                 v0_4.printStackTrace();
  49.                 return;
  50.             }
  51.             catch(NoSuchAlgorithmException v2) {
  52.                 v2.printStackTrace();
  53.             }

  54.             if(!b.a && v1_1 == null) {
  55.                 throw new AssertionError();
  56.             }
  57.         }
  58.         catch(Exception v0) {
  59.             goto label_26;
  60.         }

  61.         int v2_1 = 2;
  62.         try {
  63.             v1_1.init(v2_1, new SecretKeySpec(Base64.decode("GXiQHT1CZ2elMzwpvvAoPA==".getBytes(), 0), "AES")); //AES设置key
  64.             goto label_69;
  65.         }
  66.         catch(Exception v0) {
  67.         }
  68.         catch(InvalidKeyException v2_2) {
  69.         label_69:
  70.             try {
  71.                 new byte[0];
  72.                 try {
  73.                     v2_3 = v1_1.doFinal(Base64.decode("hjdsUjIT5je69WXIZP7Kzw==".getBytes("UTf-8"), 0));  //AES解密,值固定
  74.                     goto label_78;
  75.                 }
  76.                 catch(UnsupportedEncodingException v1_2) {
  77.                     try {
  78.                         v1_2.printStackTrace();
  79.                     label_78:
  80.                         String v6 = new String(v2_3);   //上面AES解密的
  81.                         v0_3.update(new byte[]{127});
  82.                         v0_3.update(str.getBytes());   
  83.                         v0_3.update(new byte[]{1});
  84.                     }
  85.                     catch(Exception v0) {
  86.                         goto label_26;
  87.                     }
  88.                 }
  89.                 catch(BadPaddingException v1_3) {
  90.                     goto label_78;
  91.                 }
  92.                 catch(IllegalBlockSizeException v1_4) {
  93.                     goto label_78;
  94.                 }
  95.             }
  96.             catch(Exception v0) {
  97.                 goto label_26;
  98.             }

  99.             try {
  100.                 v1_5 = new String(Base64.encode(v0_3.digest(), 0));  //
  101.                 goto label_99;
  102.             }
  103.             catch(Exception v0) {
  104.                 try {
  105.                     v0.printStackTrace();
  106.                     return;
  107.                 label_99:
  108.                     if(!str.equals(v6)) {
  109.                         goto label_190;
  110.                     }
  111.                     else if(Arrays.equals(v1_5.getBytes(), "2398lj2n".getBytes())) {
  112.                         this.b.sendEmptyMessage(0);
  113.                         return;
  114.                     }
  115.                     else {
  116.                         v0_5 = "234";
  117.                     }

  118.                     goto label_117;
  119.                 }
  120.                 catch(Exception v0) {
  121.                     goto label_26;
  122.                 }
  123.             }

  124.         label_190:
  125.             v0_5 = v1_5;
  126.             try {
  127.             label_117:
  128.                 if(v0_5.equals("lsdf==")) {
  129.                     this.b.sendEmptyMessage(0);
  130.                     return;
  131.                 }

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

  138.                 if(v0_6 == 3618) {
  139.                     if(v1_6[0] + v1_6[1] != 168) {
  140.                         goto label_178;
  141.                     }

  142.                     do {
  143.                     label_144:
  144.                         byte[] v5_1 = e.class.getAnnotation(f.class).a() + a.class.getAnnotation(f.class).a().getBytes();
  145.                         if(v1_6.length - 2 == v5_1.length) {
  146.                             v0_6 = 0;
  147.                             while(true) {
  148.                                 if(v0_6 >= v5_1.length) {
  149.                                     goto label_188;
  150.                                 }
  151.                                 else if(v1_6[v0_6 + 2] != v5_1[v0_6]) {
  152.                                     v0_6 = 0;
  153.                                 }
  154.                                 else {
  155.                                     ++v0_6;
  156.                                     continue;
  157.                                 }

  158.                                 goto label_170;
  159.                             }
  160.                         }

  161.                         goto label_177;
  162.                     }
  163.                     while(true);
  164.                 }

  165.                 goto label_178;
  166.             }
  167.             catch(Exception v0) {
  168.                 goto label_26;
  169.             }

  170.         label_188:
  171.             v0_6 = 1;
  172.             try {
  173.             label_170:
  174.                 if(v0_6 != 0) {
  175.                     this.b.sendEmptyMessage(0);
  176.                     return;
  177.                 }

  178.             label_177:
  179.                 if(v2_3 == null) {
  180.                     goto label_144;
  181.                 }

  182.             label_178:
  183.                 this.b.sendEmptyMessage(1);
  184.             }
  185.             catch(Exception v0) {
  186.             label_26:
  187.                 this.b.sendEmptyMessage(1);
  188.             }
  189.         }
  190.     }
复制代码

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

  7.                 if(v0_6 == 3618) {
  8.                     if(v1_6[0] + v1_6[1] != 168) {
  9.                         goto label_178;
  10.                     }

  11.                     do {
  12.                     label_144:
  13.                         byte[] v5_1 = e.class.getAnnotation(f.class).a() + a.class.getAnnotation(f.class).a().getBytes();
  14.                         if(v1_6.length - 2 == v5_1.length) {
  15.                             v0_6 = 0;
  16.                             while(true) {
  17.                                 if(v0_6 >= v5_1.length) {
  18.                                     goto label_188;
  19.                                 }
  20.                                 else if(v1_6[v0_6 + 2] != v5_1[v0_6]) {
  21.                                     v0_6 = 0;
  22.                                 }
  23.                                 else {
  24.                                     ++v0_6;
  25.                                     continue;
  26.                                 }

  27.                                 goto label_170;
  28.                             }
  29.                         }

  30.                         goto label_177;
  31.                     }
  32.                     while(true);
  33.                 }

  34.                 goto label_178;
  35.             }
复制代码

分析可知,v0_6 == 3618 和 v1_6[0] + v1_6[1] = 168必须同时成立,v0_6 = str.substring(0, 2).hashCode();,由于前面置换表只有小写字母和数字,所以可以直接遍历
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main()
  4. {
  5.         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 };
  6.         int n = sizeof(arry) / sizeof(arry[0]);
  7.         for (int i = 0; i < n; i++)
  8.         {
  9.                 for (int j = 0; j < n; j++)
  10.                 {
  11.                         if ((arry[i] * 31 + arry[j]) == 3618)
  12.                         {
  13.                                 printf("%d----%d\n", arry[i],arry[j]);
  14.                         }
  15.                 }
  16.         }
  17.         system("pause");
  18.         return 0;
  19. }
复制代码

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

  15.                                 goto label_170;
  16.                             }
  17.                         }
复制代码

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

  8. import javax.crypto.BadPaddingException;
  9. import javax.crypto.Cipher;
  10. import javax.crypto.IllegalBlockSizeException;
  11. import javax.crypto.NoSuchPaddingException;
  12. import javax.crypto.spec.SecretKeySpec;

  13. public class aestest {
  14.         
  15.         public static void main(String[] args) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException  {
  16.                 byte[] v2_3;
  17.                 Cipher v1_1;
  18.                 String v5 = "s57e1p";
  19.                 String v1_5;
  20.                 int v0_6;
  21.                 MessageDigest v0_3;
  22.                 char[] v1_6 = v5.toCharArray();
  23.                 v0_3 = MessageDigest.getInstance("sha1");
  24.                 v1_1 = Cipher.getInstance("AES");
  25.                 Decoder decoder = Base64.getDecoder();
  26.                 Encoder encode = Base64.getEncoder();
  27.                 v1_1.init(2, new SecretKeySpec(decoder.decode("GXiQHT1CZ2elMzwpvvAoPA==".getBytes()), "AES"));
  28.                 v2_3 = v1_1.doFinal(decoder.decode("hjdsUjIT5je69WXIZP7Kzw==".getBytes("UTf-8")));
  29.                 System.out.println(v2_3);
  30.                 v0_3.update(new byte[]{127});
  31.                 v0_3.update(v5.getBytes());
  32.                 v0_3.update(new byte[]{1});
  33.                 String v6 = new String(v2_3);
  34.                 v1_5 = new String(encode.encode(v0_3.digest()));
  35.                 System.out.println(v1_5);
  36.                 v0_6 = v5.substring(0, 2).hashCode();
  37.                 System.out.println(v0_6);
  38.           }        
  39. }
复制代码




您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 793400750,邮箱:wp@125.la
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表