무기는 끈기

[모바일 앱 해킹 / 안드로이드] Google 2020 CTF reverse.apk 해킹 CTF write up 본문

Hacking/Mobile Hacking

[모바일 앱 해킹 / 안드로이드] Google 2020 CTF reverse.apk 해킹 CTF write up

김유비야 2024. 6. 18. 17:05

*개인적인 풀이 소감
모바일 앱을 공부한지 얼마 안된 사람으로서 너무너무 어려웠다,,,
일단 수학 알고리즘도 등장하고, 의도적인 난독화로 인해 애초에 풀이법 자체를 감 잡기가 힘들었다.
다른 분들의 write up과 ChatGPT의 도움이 없었다면 풀어내지도 못했을거고, 이해도 어려웠을 것 같은 난이도였다.

그래도 모바일 앱 해킹에 있어서 다양한 케이스와 풀이법, 다양한 툴과 툴 버전의 응용 등을 접할 수 있는 문제여서 굉장히 의미 있었다.

 

Step 1. reverse.apk 안드로이드 어플리케이션을 설치한다.

안드로이드 애뮬레이터인 Noxreverse.apk 파일을 설치한다.

 

Step 2. 모바일 앱 내부 UI를 살펴본다.

앱을 실행시키면 이러한 화면이 나온다.

-       이미지는 추측으로는 깨져서 제대로 보이지 않는 상태 같다. 그래도 위에 튀어나온 부분으로 추측할 수 있을 것 같아 이대로 진행하려고 한다.

중간에 Key 암호를 입력할 수 있는 입력창과 [CHECK] 버튼이 존재한다.

-       ECK 버튼을 누르면 위에 튀어나온 부분이 사라지고 하늘색 상자만 남는다.

-       올바른 Key 암호를 입력할 경우에 다른 눈에 보이는 변화가 있을 것으로 예상된다.

해당 기능을 제외하고는 다른 기능은 없다. 이제 내부 로직 코드를 살펴보자.

 

Step 3. JADX를 이용해 내부 로직을 분석한다.

JADX를 이용해서 AndroidManifest.xml 파일을 먼저 열어 먼저 봐야 할 package를 확인한다.

해당 클래스로 이동해서 내부 onCreate onClick 메소드를 확인하면 난독화가 제대로 해제되지 않은 상태로 보여진다. 난독화를 해제하지 않은 상태로는 분석이 어렵기에 Ghidra를 활용해서 디컴파일 해보도록 하자.

 

 

Step 4. Ghidra를 이용해서 다시 디컴파일 한다.

JADX로는 내부 로직을 제대로 분석할 수 없어 다른 디컴파일 툴인 Ghidra를 이용해서 분석해보자.

툴마다 설정값 등이 다르기에 확인할 수 있는 정도가 달라 다양하게 디컴파일 해보고 원하는 부분을 비교해서 필요한 부분을 추출해내는 능력도 중요하다는 것을 알게 되었다.

 

눈여겨봐야 하는 부분인 onCreate onClick 메소드는 이상한 특수문자 속에 들어있다.

일단 코드를 확인해보자.

아스키 코드가 나열되어 있는 것을 확인할 수 있다. 문자로 바꾸면 이렇게 나온다.

Apprarently this is not flag. What's going on?

Fake Flag로 보인다. 입력창에 넣어봐도 실패로 뜬다.

진짜 Flag를 찾으려면 다른 방법으로 디컴파일 해야 할 것 같다.

 

Step 5. 진짜 Flag를 얻기 위해 다시 디컴파일 한다.

이 과정에서도 다양하게 헤맸다.

특수문자를 전부 변경해서 디컴파일 하는 방법도 시도해봤지만 잘 되지 않아 포기했고, 아이다를 사용해서 디컴파일 해보려고 해봤는데 실패했고,

결국 JADX 최신이 아닌 예전 버전을 사용해서 디컴파일 했고, 성공적으로 진짜 코드를 볼 수 있었다.

 

 

Step 6. 난독화 완전히 해제된 진짜 코드를 분석한다.

대략 3개의 조건을 확인할 수 있다.

조건 1: 암호가 48자리가 아니면 실패를 반환한다는 것을 알 수 있다.

바로 밑 코드에선

조건 2: 48자리의 암호를 총 4번을 나누어 ‘f2’ 배열에 저장하고, ‘R.m0’ 함수와 비교한다.

조건  3: ‘R.m0’ 함수의 결과를 ‘f0class’ 배열의 값과 일치해야 한다.

 

m0 함수는 이렇게 구성되어 있다.

확장된 유클리드 알고리즘 (= 확장된 유클리드 호제법) 으로 불리는 공식이라고 한다.

모르는 내용이라 구글링 했지만 완벽이 이해하진 못했다.

이 함수를 거의 그대로 파이썬 코드에 가져와서 Flag를 구할 수 있을 것 같아 그대로 가져와서 조금만 수정을 거쳐서 사용했다.

 

Step 7. 진짜 Flag를 찾기 위한 Python 코드를 짜고, 돌린다.

코드를 부분별로 뜯어보자.

‘num_maker’ 함수는 Java 코드에서 ‘flagString’의 각 4자리 문자들을 비트 연산으로 하나의 32비트 정수로 만드는 부분과 동일한 역할을 한다.

이 부분은 위에서 설명한 확장된 유클리드 알고리즘을 사용해서 계산하는 부분으로 Java 코드에서 거의 그대로 가져왔다.

여기는 Java 코드에서 미리 정의된 f0class 값을 가져온 부분이다.

Java 코드에서는 사전 연산으로 ‘dict_ans’와 같은 값을 저장하지 않지만, 여기선 미리 계산해서 사전 형태로 저장한다. (성능향상을 위한 부분)

Flag 문자열을 찾기 위한 초기화 부분으로, 4개로 나누어 검증하는 부분과 동일하게 재구성한다.

 

 

Python 파일을 실행해서 진짜 Flag를 찾고, 앱의 입력란에 입력해준다.

미세하지만 Flag 이미지가 보인다. 성공!