본문 바로가기

Android

[OWASP-MSTG] UnCrackable-Level2.apk

반응형

두 번째 분석 시간입니다
UnCrackable-Level2 앱을 열어보면 이전과 마찬가지로 루팅 탐지, 디버깅 가능 여부 탐지가 작동하는 것을 볼 수 있습니다

 

이전과 같은 방식으로 우회해줍니다

Java.perform(function () {
  passRootDetection();
});

function passRootDetection() {
  const b = Java.use("sg.vantagepoint.a.b");
  b["a"].implementation = function () {
    return false;
  };
  b["b"].implementation = function () {
    return false;
  };
  b["c"].implementation = function () {
    return false;
  };
}

추가된 비동기 탐지 로직이 보입니다
android.os.Debug.isDebuggerConnected()를 활용하여 100ms마다 디버거 부착 여부를 탐지하는 로직입니다
안타깝게도 frida가 탐지되지 않는 모양입니다 별다른 코드를 작성하지 않았지만 디버거가 탐지되지 않습니다

이제 키 값을 알아낼 시간입니다

이전과 비슷하게 코드를 따라가보면 native 함수를 사용하는 것을 알 수 있습니다

jadx에서는 네이티브 라이브러리를 분석할 수 없는 것으로 알고 있어
ghidra로 마저 진행하도록 하겠습니다
apk 파일은 일종의 압축 파일로, 압축을 해제하면 lib/ 폴더 아래에 앱이 지원하는 아키텍처 별로 네이티브 라이브러리가 제공되는 것을 확인할 수 있습니다

가장 익숙한 x86 아키텍처의 네이티브 라이브러리를 분석합니다
ghidra 프로젝트에서 파일을 import 하고 Symbol Tree > Functions를 확인합니다
패키지, 클래스, 메소드 이름이 다 붙어서 나오긴 하지만 CodeCheck의 bar 함수를 충분히 식별할 수 있습니다

해당 심볼을 선택하면 디컴파일 된 코드를 확인할 수 있습니다

bar 함수는 __s1local_30 주소에 담긴 값을 0x17만큼 읽어 비교하는 것으로 보입니다
strncmp는 두 값이 같을 때 0을 반환하고, 이때 해당 함수는 1을 반환하네요
local_30에 담긴 값을 읽어봅시다 local_30 > local_2c > local_28 > ... > local_1a 순으로 선언되었으니 순서대로 읽으면 되겠네요
hex to ascii 변환 사이트를 이용하며, 사용하는 아키텍처에 맞는 Endian을 적용하여 적절히 변환합시다
x86의 경우 일반적으로 little endian을 사용합니다

이렇게 나온 값은 Thanks for all the fish입니다
이를 입력하면 키 값 비교에 성공할 수 있습니다

아무런 장치가 없다면 네이티브 라이브러리 분석도 너무 간단한 것 같네요..

반응형