LINK:https://www.root-me.org/en/Challenges/Cracking/APK-Anti-debug
Mobsf下载地址:https://github.com/MobSF/Mobile-Security-Framework-MobSF
使用Mobsf等apk反编译工具将目标程序反编译,得到如下java代码:关键代码已经标注。也可以使用d2j-dex2jar ch16.apk转换成jar文件再使用jd-gui打开。
还可以使用unzip -l ch16.apk解压后。
Validate.java
/*
* Decompiled with CFR 0_132.
*
* Could not load the following classes:
* android.content.Context
* android.util.Log
*/
package com.fortiguard.challenge.hashdays2012.challengeapp;
import android.content.Context;
import android.util.Log;
import java.lang.reflect.Array;
import java.security.MessageDigest;
import java.util.Arrays;
public class Validate {
private static final String[] answers;
private static byte[][] bh;
private static boolean computed;
private static final String[] hashes;
public static String[] hexArray;
private Context context;
static {
//需要破解的Hash值
hashes = new String[]{"622a751d6d12b46ad74049cf50f2578b871ca9e9447a98b06c21a44604cab0b4", "301c4cd0097640bdbfe766b55924c0d5c5cc28b9f2bdab510e4eb7c442ca0c66", "d09e1fe7c97238c68e4be7b3cd64230c638dde1d08c656a1c9eaae30e49c4caf", "4813494d137e1631bba301d5acab6e7bb7aa74ce1185d456565ef51d737677b2"};
answers = new String[]{"Congrats from the FortiGuard team :)", "Nice try, but that would be too easy", "Ha! Ha! FortiGuard grin ;)", "Are you implying we are n00bs?", "Come on, this is a DEFCON conference!"};
hexArray = new String[]{"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D", "7E", "7F", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF", "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF", "C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF", "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF", "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF", "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF"};
bh = (byte[][])Array.newInstance(Byte.TYPE, 4, 32);
computed = false;
}
public Validate(Context context) {
this.context = context;
}
/*
* Enabled aggressive block sorting
* Enabled unnecessary exception pruning
* Enabled aggressive exception aggregation
*/
public static String checkSecret(String object) {
byte[] arrby;
block5 : {
try {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.reset();
arrby = messageDigest.digest(object.getBytes());
if (!computed) {
Validate.convert2bytes();
}
break block5;
}
catch (Exception exception) {
Log.w((String)"Hashdays", (String)("checkSecret: " + exception.toString()));
}
return answers[4];
}
int n = 0;
while (n < hashes.length) {
if (Arrays.equals(arrby, bh[n])) {
return answers[n];
}
++n;
}
return answers[4];
}
//转换函数
public static void convert2bytes() {
for (int i = 0; i < hashes.length; ++i) {
Validate.bh[i] = Validate.hexStringToByteArray(hashes[i]);
}
computed = true;
}
//Hex转Byte函数
public static byte[] hexStringToByteArray(String string2) {
int n = string2.length() - 1;
byte[] arrby = new byte[n / 2 + 1];
for (int i = 0; i < n; i += 2) {
arrby[i / 2] = (byte)((Character.digit(string2.charAt(i), 16) << 4) + Character.digit(string2.charAt(i + 1), 16));
}
return arrby;
}
public static boolean isEmulator() {
return true;
}
}
Character.digit(string2.charAt(i), 16)表示取字符串string2第i-1位字符的16进制的值
参考java官方文档得到如下信息:
-
digit
public static int digit(int codePoint, int radix)
Returns the numeric value of the specified character (Unicode code point) in the specified radix.If the radix is not in the range
MIN_RADIX
≤radix
≤MAX_RADIX
or if the character is not a valid digit in the specified radix,-1
is returned. A character is a valid digit if at least one of the following is true:- The method
isDigit(codePoint)
istrue
of the character and the Unicode decimal digit value of the character (or its single-character decomposition) is less than the specified radix. In this case the decimal digit value is returned. - The character is one of the uppercase Latin letters
'A'
through'Z'
and its code is less thanradix + 'A' - 10
. In this case,codePoint - 'A' + 10
is returned. - The character is one of the lowercase Latin letters
'a'
through'z'
and its code is less thanradix + 'a' - 10
. In this case,codePoint - 'a' + 10
is returned. - The character is one of the fullwidth uppercase Latin letters A (
'\uFF21'
) through Z ('\uFF3A'
) and its code is less thanradix + '\uFF21' - 10
. In this case,codePoint - '\uFF21' + 10
is returned. - The character is one of the fullwidth lowercase Latin letters a (
'\uFF41'
) through z ('\uFF5A'
) and its code is less thanradix + '\uFF41'- 10
. In this case,codePoint - '\uFF41' + 10
is returned.
-
Parameters:
-
codePoint
- the character (Unicode code point) to be converted. -
radix
- the radix.
Returns:
- the numeric value represented by the character in the specified radix. Since:
- 1.5 See Also:
-
forDigit(int, int)
,isDigit(int)
- The method
答案及参考:
The AES key is AnakinSkywalker.
To get the message ”Nice try, but that would be too easy”, use AnakinSkywalker as password.
To get the message ”Ha! Ha! FortiGuard grin ;)”, use Fortiguard as password.
To get the message ”Are you implying we are n00bs?”, use root as password.
References
[010] 010 Editor. http://www.sweetscape.com/010editor/.
[apk] APKTool. code.google.com/p/android-apktool.
[Des] Anthony Desnos. Androguard. http://code.google.com/p/androguard.
[DEXa] .dex Dalvik Executable Format. http://source.android.com/tech/dalvik/dex-format.html.
[Dexb] Dex2jar. http://code.google.com/p/dex2jar/.
[has12] Hashdays 2012, November 2012. https://www.hashdays.ch/.
[Lar] Jon Larimer. DEX Template. https://github.com/jlarimer/android-stuff/blob/master/
DEXTemplate.bt.