Analysis
Code
submitFlag
public final void submitFlag(View view) {
EditText editText = (EditText) findViewById(R.id.editText3);
d.b(editText, "editText3");
if (d.a(editText.getText().toString(), k.a("k3FElEG9lnoWbOateGhj5pX6QsXRNJKh///8Jxi8KXW7iDpk2xRxhQ=="))) {
Intent intent = new Intent(this, FlagOneSuccess.class);
FlagsOverview.D = true;
new j().b(this, "flagSixButtonColor", true);
startActivity(intent);
}
}
public class k {
private static final byte[] f1917a = h.b();
public static String a(String str) {
if (c(str)) {
try {
SecretKey generateSecret = SecretKeyFactory.getInstance("DES").generateSecret(new DESKeySpec(f1917a));
byte[] decode = Base64.decode(str, 0);
Cipher instance = Cipher.getInstance("DES");
instance.init(2, generateSecret);
return new String(instance.doFinal(decode));
} catch (InvalidKeyException | NoSuchAlgorithmException | InvalidKeySpecException | BadPaddingException | IllegalBlockSizeException | NoSuchPaddingException e) {
e.printStackTrace();
}
} else {
System.out.println("Not a string!");
return str;
}
}
...
}
submitFlag함수는 다음과 같은 순서로 진행한다.
- editText3 값을 이용하여 사용자가 입력한 값을 가져온다.
- 값 비교를 위해 d 클래스 a 함수에 입력받은 값을 문자열로 변환한 값과 암호화된 값("k3FElEG9lnoWbOateGhj5pX6QsXRNJKh///8Jxi8KXW7iDpk2xRxhQ==")을 복화된 값을 인자로 넘겨준다
- 두 값이 같으면 FlagOneSuccess 액티비티를 활성화 시킨다.
여기서 문제점은 암호화된 문자열과 반환 값으로 복호화 값을 보내주는 함수가 모두 코드 안에 존재한다는 점이다.
Exploit
문제를 해결하기 위해 암호화 루틴(k클래스의 a함수)을 후킹한 후 암호화된 값을 넘겨주어 해결한다.
이를 위한 코드는 다음과 같다.
Java.perform(function x() {
var my_class = Java.use("b3nac.injuredandroid.k");
var string_class = Java.use("java.lang.String");
my_class.a.overload("java.lang.String").implementation = function (args) {
var my_string = string_class.$new("k3FElEG9lnoWbOateGhj5pX6QsXRNJKh///8Jxi8KXW7iDpk2xRxhQ==");
console.log("original: " + args);
var ret = this.a(my_string);
console.log("return: " + ret);
return ret;
}
})
- Java.use(ClassName) : 앱에서 사용하는 클래스와 연동되는 클래스를 선언한다.
- java.lang.String : java.lang 패키지에 포함되어 있으며 Java에서 문자열을 사용하기 위한 String 클래스이다.
- .overload(Type).implementation(args) : 오버로드를 할때 사용한다. 인자를 받는 함수인 경우 타입과 그에 맞는 인자를 써줘야 한다.
코드를 설명하자면 다음과 같다.
- 복호화 루틴이 존재하는 "b3nac.injuredandroid.k"와 String 클래스가 포함된 "Java.lang.String"을 선언한다.
- 복호화 루틴 함수를 오버로딩 하기 위해 그에 맞는 타입(String)과 인자를 받도록 선언한다.
- 암호화 문자열을 이전에 가져온 string 클래스를 사용하여 my_string에 저장한다.
- 복호화 함수에 암호화된 문자열을 넘겨 복호화된 문자열을 받는다.
스크립트를 실행하면 다음과 같이 화면을 확인할 수 있는데
이후 FlagSIX에 들어가서 아무 값을 입력한 후 등록을 해주면
다음과 같이 복호화된 문자열이 출력되는 것을 확인할 수 있다.
마지막으로 복호화된 문자열을 입력해주면 문제를 해결할 수 있다.
Reference
- Frida - JavaScript
https://frida.re/docs/javascript-api/#frida - frida - overload
https://aboutsc.tistory.com/164
'Android > InjuredAndroid' 카테고리의 다른 글
FLAG SEVEN - SQLITE (0) | 2021.09.21 |
---|---|
FLAG FOUR - Login 2 (0) | 2021.09.21 |
FLAG THREE - RESOURCES (0) | 2021.09.21 |
FLAG TWO - EXPORTED ACTIVITY (0) | 2021.09.21 |
FLAG ONE - Login (0) | 2021.09.21 |