쥐뇨닝 ( geeneoning )
친절한 쥐뇽씨
쥐뇨닝 ( geeneoning )
전체 방문자
오늘
어제

공지사항

  • 분류 전체보기 (13)
    • Pentesting (2)
      • Hack The Box (0)
      • Try Hack Me (2)
    • War Game (5)
      • Web (0)
      • Rev (1)
      • Pwn (1)
      • Crypt (0)
      • Forensic (0)
      • Mobile (3)
      • Misc (0)
    • 환경 구축 (2)
      • Tool (1)
    • Dev (1)
      • etc (1)
    • 스터디 (0)
      • React 스터디 (0)
      • 수학 (0)
      • 시스템 해킹 (0)
    • 잡담 (1)
쥐뇨닝 ( geeneoning )

친절한 쥐뇽씨

[ OWASP MAS Crackmes] UnCrackable-Level1 풀이와 해설!
War Game/Mobile

[ OWASP MAS Crackmes] UnCrackable-Level1 풀이와 해설!

2023. 4. 6. 16:54

fridalab 에 이어 이번에는 OWASP의 UnCrackable 시리즈 입니다!

https://mas.owasp.org/crackmes/

 

MAS Crackmes - OWASP Mobile Application Security

MAS Crackmes Welcome to the MAS Crackmes aka. UnCrackable Apps, a collection of mobile reverse engineering challenges. These challenges are used as examples throughout the OWASP MASTG. Of course, you can also solve them for fun.

mas.owasp.org

 

Android 문제 5문제와 iOS 문제 2문제가 있습니다!

이것까지 다 학습하고나면 사실상 이제 실전세계로 들어가면 되는 부분 ㅋㅎ

 

먼저 첫번째 문제인 Android UnCrackable L1 을 풀이해봅시다!

 

앱을 설치하고 실행하면 기본적으로 루팅탐지를 하여

메세지 박스가 나타나고 OK 를 누르면 앱이 강제로 종료되게 됩니다.

 

그럼 루팅탐지를 우회하기 위해 소스코드를 확인해봅시다!

 

먼저 루팅탐지는 앱이 실행되자마자 가장 먼저 탐지하게 되는데요.

앱 실행의 가장 첫 부분을 찾는 꿀팁은

리소스 -> AndroidManifest.xml 를 찾아갑니다!

그 파일에서 가장 첫번째 activity 의 패키지명을 찾아 들어가면

Android 생명주기의 가장 첫 부분인 onCreate 함수가 있습니다!

그 부분이 앱 실행의 가장 첫 부분입니다 ㅎㅎ

 

첫번째 activity 의 패키지명을 그대로 따라오니 onCreate 부분에 루팅탐지 로직이 존재하는것이 보이시죠?

그럼 여기서 소스코드를 더 깊이 분석해봅시다!

 

c 클래스를 타고 들어가보면 루팅을 탐지하는 a, b, c 메서드가 있습니다.

1년전만 해도 이런코드들을 보면 해석하기도 너무어렵고 누가 알려줄 사람도 없어서

상당한 고통을 받았었지만,

우리는 지금 chatGPT의 시대에 살고있습니다!!!

바로 헬프요청을 해봅시다!

 

정말 깔끔하게 설명해주죠? ㅋㅋ

독학할때 chatGPT를 잘 활용하시길 강추드립니다!

다시 MainActivity를 살펴보면, onCreate에서 루팅탐지를 하고

AlertDialog , 즉 알림창을 만들어 setMessage로 문자열을 띄우고,

OK 버튼을 누를시 onClick 이벤트가 발생해 System.exit(0) 을 호출하여

앱을 강제로 종료시키고 있습니다.

 

여기서 해킹이 어렵고도 재밌는 사실은

대부분의 해킹, 특히 모바일에서는 더욱!!

정해진 정답이 없다는 것입니다.

 

같은 목표를 위해서 정말 다양한 방법으로 문제를 해결할 수 있기때문에

공부할때도 이런저런 다양한 방법들을 많이 시도해 보시길 추천드립니다!

 

일단 제가 풀었던 방법 위주로 해설해보겠습니다! ㅎㅎ

 

저는 우선 여러가지 방법 중, onClick 함수를 후킹하여 System.exit(0) 을 무력화 시켜보도록 하겠습니다!

 

onClick 함수를 재정의하면 System.exit(0) 이 날라가버리기 때문에

재정의 후 아무것도 리턴해주지 않아도 간단히 우회가 가능하지만

그래도 어떤값들이 넘어오는지 보여주기위해 받아온 인자들을 출력하는 형태로

작성해보았습니다!

먼저 OK 버튼을 눌렀음에도 System.exit(0) 가 날아가버렸기 때문에

종료되지 않는 모습!

 

그리고 console.log(arg1) 의 결과는 [object Object] 로 출력된 것을 볼 수 있습니다.

이것은 사실 javascript의 고유의 문제인 다중 중첩된 object를 출력할 수 없는점으로 인해

발생하는 문제입니다!

 

javascript안에 내장되어있는 api인 JSON.stringify() 함수를 사용하면

이 다중 중첩된 object를 풀어서 확인할 수 있습니다.

 

[object Object] 로 출력되던 arg1 이 쫙 풀리는거 보이시죠?

이런식으로 frida를 사용하다보면 Java지식과 Javascript지식이 골고루 필요하게 되니

틈틈히 공부해두시는게 좋습니다 !

 

아무튼 저부분은 출력과 상관없이 재정의 된것만으로 해결이 완료되었습니다!

다른방법으로는 탐지하는 로직으로 들어가서 하나하나 후킹하거나,

아니면 실제 탐지하고있는 파일명을 바꿔버린다거나 하는식으로도

여러 방법으로 해결이 가능하겠죠!?

 

그리고 Java.use("sg.vantagepoint.uncrackable1.MainActivity$1") 부분에서

$1은 뭐냐 하고 의문을 품으시는 분들도 있으실 것 같습니다!

 

여기서는 또 Java지식이 필요합니다.

"$1" , "$2" 등 이런 문자는 Java에서의 중첩 클래스를 의미합니다.

 

아래의 코드를 보면 new DialogInterface.OnClickListener() 를 통해

새로운 익명클래스가 생성되었기때문에

MainActivity 내부에 또다른 익명클래스가 생겨 그 부분을 $1으로 지정하는 것입니다!

create.setButton(-3, "OK", new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialogInterface, int i) {
        System.exit(0);
    }
});

결론적으로 후킹할 onClick 함수는 MainActivity 내부에서 익명클래스로 생성되었기때문에

$1으로 지정해주어야 후킹이 가능한 것입니다!

 

그래서 쓸모없는 부분을 제외하고 간단한 루팅탐지 우회 코드를 작성하면

아래와 같이 해결이 가능합니다! ( console.log 부분도 제외해도 괜찮습니다! )

Java.perform(function () {
  const rooting = Java.use("sg.vantagepoint.uncrackable1.MainActivity$1");
  rooting.onClick.implementation = function (arg1, arg2) {
    console.log("[+] rooting bypass success");
  };
});

 

 

이번엔 루팅우회 다음 목표인 Secret String을 찾아봅시다!

 

먼저 아무것도 입력하지 않거나 틀린 String을 입력하면 Nope... 하는 메세지가 출력되네요.

물론 리얼월드에서는 훨씬 어려운 로직이겠지만,

유료제품의 인증키를 찾아낸다거나 할때 충분히 활용 가능성이 있을 것 같네요 :)

 

그럼 소스코드를 확인해보겠습니다!

 

간단히 요약해보자면, 

a.a(obj) 가 true를 만족한다면 Success! 가 출력되고

만족하지 못한다면 Nope... 가 출력되는 코드입니다!

 

그럼 a.a(obj) 에서 입력되어야할 secret 메세지가 있을테니 분석해봐야겠죠?!

a class로 타고 들어가봅시다!

 

코드를 보고 와우.. 어지럽다.. 라고 느낄 수 있지만

차근차근 분석해봅시다! ㅋㅋㅋㅋ

 

먼저 저만의 꿀팁을 알려드리자면 저는 return 위주로 빠르게 분석을 들어가는 편입니다!

fridalab를 열심히 공부하셨다면

딱 봐도 str.equals 에서 정답을 비교하겠구나~? 하는 짬에서 나오는 바이브가 생기실 겁니다!!

대충 풀이만 보고 공부하신분들은 아무것도 안보고 혼자 백지에다가 코드를 다 작성해서

풀 수 있을정도로 연습하고 오십시오!!

그럼 안에서 또 쪼개서 생각해보면

sg.vantagepoint.a.a.a() 함수는 인자로

b("8d127684cbc37c17616d806cf50473cc") 과 Base64.decode("5UJiFctbmgbDoLXmpL12mkno8HT4Lv8dlat8FxR2GOc=", 0) 이 두가지를 인자로 받고 있습니다.

그럼 저 sg.vantagepoint.a 라는 클래스를 타고 들어가봅시다!

 

a 클래스의 a 함수는 배열 bArr 과 배열 bArr2 를 인자로 받아

AES 암호화 알고리즘의 복호화 과정을 거쳐 cipher.doFinal(bArr2) 로

복호화된 문자열을 리턴하는 함수입니다!

 

어쨌거나 난독화든, 암호화는 풀어야 앱에서 실행가능하기 때문에

푸는 로직이 들어있겠죠?

이러한 부분때문에 사실 모바일해킹은 시간만 있으면 다 뚫을 수 있다 라는 이야기가 나오는것이고,

개인의 실력에 따라 모든 솔루션을 우회해버리기도 합니다 ㅎㅎ

 

그럼 이 a함수로 전달되는 인자들을 함수 재정의를 통해 console.log로 출력시켜봅시다.

 

아래와 같이 받아온 인자들을 출력하는 형태로 함수를 재정의 하고 VERIFY 버튼을 누르면

a함수를 통해 전달되는 인자들을 출력합니다.

하지만 올바른 형태가 아니기때문에 app이 크래쉬가 나서 강제로 종료되어버리네요 ㅎㅎ

상관없습니다! 이미 값을 획득해버렸으니까요 ㅋㅎ

 

그럼 가져온 값을 이용해 코드를 수정하여 a함수에 올바른 값을 넘겨주는 코드를 작성해보겠습니다!

Java.perform(function () {
  const rooting = Java.use("sg.vantagepoint.uncrackable1.MainActivity$1");
  rooting.onClick.implementation = function (arg1, arg2) {
    console.log("[+] rooting bypass success");
  };

  const check = Java.use("sg.vantagepoint.a.a");
  const arg1 = [
    -115, 18, 118, -124, -53, -61, 124, 23, 97, 109, -128, 108, -11, 4, 115,
    -52,
  ];
  const arg2 = [
    -27, 66, 98, 21, -53, 91, -102, 6, -61, -96, -75, -26, -92, -67, 118, -102,
    73, -24, -16, 116, -8, 46, -1, 29, -107, -85, 124, 23, 20, 118, 24, -25,
  ];
  console.log(check.a(arg1, arg2));
});

 

쨘! 딱봐도 ascii값 처럼 생긴 일련의 숫자 모음의 나오네요!!

 

그럼 이 ascii코드들을 string 형태로 바꿔주는 자바스크립트 코드를 통해

secret string을 알아내봅시다!

 

자바스크립트에서는 String.fromCharCode() 를 사용하면 ascii코드를 문자열로 변경시킬 수 있습니다!

그래서 반복문을 통해 ascii 코드들을 문자열로 하나씩 바꾸어주어 flag 변수에 저장해주면

secret 키를 획득할 수 있습니다!!

Java.perform(function () {
  const rooting = Java.use("sg.vantagepoint.uncrackable1.MainActivity$1");
  rooting.onClick.implementation = function (arg1, arg2) {
    console.log("[+] rooting bypass success");
  };

  const check = Java.use("sg.vantagepoint.a.a");
  const arg1 = [
    -115, 18, 118, -124, -53, -61, 124, 23, 97, 109, -128, 108, -11, 4, 115,
    -52,
  ];
  const arg2 = [
    -27, 66, 98, 21, -53, 91, -102, 6, -61, -96, -75, -26, -92, -67, 118, -102,
    73, -24, -16, 116, -8, 46, -1, 29, -107, -85, 124, 23, 20, 118, 24, -25,
  ];
  let flag = "";
  const result = check.a(arg1, arg2);
  for (let i = 0; i < result.length; i++) {
    flag += String.fromCharCode(result[i]);
  }
  console.log(flag);
});

I want to believe 라는 문자열을 획득했습니다!

Success! 획득!

'War Game > Mobile' 카테고리의 다른 글

Fridalab challenge_01 ~ 05 풀이와 해설 + 꿀팁 !  (1) 2023.04.05
Frida를 사용하기 전 알아야 할 기본 지식!  (0) 2023.04.02
    'War Game/Mobile' 카테고리의 다른 글
    • Fridalab challenge_01 ~ 05 풀이와 해설 + 꿀팁 !
    • Frida를 사용하기 전 알아야 할 기본 지식!
    쥐뇨닝 ( geeneoning )
    쥐뇨닝 ( geeneoning )

    티스토리툴바