『reverse』2016年全国大学生信息安全大赛——珍贵资料解题报告

  将题目文件下载、解压,得到两个文件,unknown和unknown2:


文件系统显示unknown2为压缩文件,unknown为二进制文件,而unknown2则为zip压缩文件,,归档管理器查看unknown2,发现以下文件结构:

『reverse』2016年全国大学生信息安全大赛——珍贵资料解题报告_第1张图片

显然是apk包,将文件改名为unkown2.apk,使用apktool反编译,得到以下文件目录

『reverse』2016年全国大学生信息安全大赛——珍贵资料解题报告_第2张图片

用dex2jar + jdgui反编译,得到java文件

『reverse』2016年全国大学生信息安全大赛——珍贵资料解题报告_第3张图片

搜索所有文件,发现未出现flag关键字,故flag应该与文件代码相关。通过阅读分析代码,发现WelcomeAvtivity.java中以下代码

protected void onCreate(Bundle paramBundle)  {
   super.onCreate(paramBundle);
    setContentView(2130903042);
    paramBundle = (TextView)findViewById(2131165192);
    String str = getIntent().getStringExtra("i");
    try
    {
      paramBundle.setText;
      return;
    }
    catch (Exception paramBundle)
    {
      paramBundle.printStackTrace();
    }
}
 
  
其中str为可疑点,在LogoActivity.java中发现对应代码
protected void onCreate(Bundle paramBundle)
  {
    super.onCreate(paramBundle);
    requestWindowFeature(1);
    setContentView(2130903041);
    this.progressBar = ((ProgressBar)findViewById(2131165189));
    this.backButton = ((Button)findViewById(2131165191));
    paramBundle = new Intent(this, WelcomeAvtivity.class);
    paramBundle.putExtra("i", "mgjl+bx+{jxx|dyo");
    startActivity(paramBundle);  
}
str确认为 mgjl+bx+{jxx|dyo ,将函数encode2 
public static final int LEN = "abcdefghijklmnopqrstuvwxyz".length();
public static final String SOURCE = "abcdefghijklmnopqrstuvwxyz";
  private static String encode2(String paramString)
  {
    paramString = paramString.toCharArray();
    int i = 0;
    for (;;)
    {
      if (i >= paramString.length) {
        return new String(paramString);
      }
      paramString[i] = ((char)(paramString[i] ^ 0xB));
      i += 1;
    }
  }
 
  
单独取出来,对str调用,打印得到提示信息:flag is password,然后跟踪password,在 LoginActivity.java 中,发现以下代码:

public void onClick(View paramAnonymousView) {
LoginActivity.this.userNameValue = LoginActivity.this.userName.getText().toString();
	LoginActivity.this.passwordValue = LoginActivity.this.LoginActivity.this.password.getText().toString();
        if ((LoginActivity.this.userNameValue.equals(LoginActivity.this.sp.getString("USER_NAME", ""))) && (LoginActivity.this.
	passwordValue.equals(LoginActivity.this.sp.getString("PASSWORD", ""))))
        {
          Toast.makeText(LoginActivity.this, "登录成功", 0).show();
          paramAnonymousView = new Intent(LoginActivity.this, LogoActivity.class);
          LoginActivity.this.startActivity(paramAnonymousView);
          return;
        }
        Toast.makeText(LoginActivity.this, "登陆失败", 1).show();
      }
}
 
    
 
   
大致意思是对用户输入密码执行encode函数后,与数据库中PASSWORD对应的值进行比对,如果二者相等则判定输入密码正确,那么我们要找到password,就需要找到存储在数据库中的PASSWORD对应的值,进行encode的逆操作,得到真正的password。然而经过一番查找无果。  想到解压后还有另一个unknown文件没有用到,想必与PASSWORD有关,使用gedit打开,发现乱码,但是前面关键字

ANDROID BACKUP
1
1
none

 
   
显示正常,显然这是一个backup文件,格式为.ab,通过以下代码(代码源自 http://android.stackexchange.com/questions/28481/how-do-you-extract-an-apps-data-from-a-full-backup-made-through-adb-backup)进行还原

import java.io.*;
import java.util.zip.*;
/** Run: javac unab.java && java unab backupfile.ab */
public class unab {
    private static final int BACKUP_HEADER_LENGTH = 24;
    public static void main(String[] args) throws IOException {
        InputStream in = new FileInputStream(args[0]);
        try {
            OutputStream out = new FileOutputStream(args[0] + ".tar");
            try {
            if (in.skip(BACKUP_HEADER_LENGTH) != BACKUP_HEADER_LENGTH) {
                throw new IOException("Unexpected end of file while skipping backup header.");
            }
            byte[] buffer = new byte[100 * 1024];
            int count;
            InputStream zip = new InflaterInputStream(in);
            while ((count = zip.read(buffer)) > 0) {
                out.write(buffer, 0, count);
            }
            } finally {
                out.close();
            }
        } finally {
            in.close();
        }
    }
}
 
   
在得到的文件目录中发现userInfo.xml:
『reverse』2016年全国大学生信息安全大赛——珍贵资料解题报告_第4张图片
dudqlvqrero1
user
 
  
 
  

PASSWORD为 dudqlvqrerol,再来看encode函数:

  public static String Encryption(String paramString) {
    StringBuilder localStringBuilder = new StringBuilder();
    if ((paramString == null) || (paramString.length() < 1))
    {
      System.out.println("you Input nothing.");
      return null;
    }
    paramString = paramString.toLowerCase();
    int m = paramString.length();
    int k = 0;
    for (;;)
    {
      if (k >= m) {
        return localStringBuilder.toString();
      }
      int j = "ijklmstuvwxyz0123abcdenopqrfgh456789".indexOf(paramString.charAt(k));
      int i = j;
      if (j == LEN - 1) {
        i = -1;
      }
      j = i;
      if (i == LEN - 2) {
        j = -2;
      }
      i = j;
      if (j == LEN - 3) {
        i = -3;
      }
      localStringBuilder.append("ijklmstuvwxyz0123abcdenopqrfgh456789".charAt(i + 3));
      k += 1;
    }
  }
  
  private String encode(String paramString)
  {
    paramString = Encryption(paramString);
    if (paramString != null) {
      return paramString;
    }
    return "";
  }

分析发现就是一个简单的移位操作:对password在 ijklmstuvwxyz0123abcdenopqrfgh456789 中找到每一个字符,并替换为右边第三个字符(超出返回左边第一个继续右移),得到PASSWORD,那么只需要将PASSWORD左移三位即可,最后得到password为:amanisnobody。最终得到flag(格式为flag{结果})为: flag{amanisnobody}。


总结:
做此类题目的突破口大多在于可疑字符串,与登录相关的大多用户和密码脱不了关系,基本步骤为:反编译,字符串搜索,字符串跟踪,分析代码,逆向。此外从这道题中也可以看到
这个apk的漏洞在于采用了可逆加密方式,密码与摘要是一一对应关系,如果采用复杂的不可逆方式则即使对方破解了摘要与加密方式,也难以得到用户密码信息。

 

你可能感兴趣的:(ctf)