[CTF]Mobile_AOS_SUMMER_FAN Writeup

Jongmin Park·2022년 12월 1일
0
post-custom-banner

Dreamhack "BOB 정보보안 CTF(BISC)" 대회 문제

리버싱 분야이고 문제파일을 받아보면 안드로이드 앱(apk) 파일 하나가 주어진다

앱을 설치하고 실행하면 0으로 멈춰있는 시간과 선풍기 하나가 보인다. 터치를 해바도 아무런 반응이 엄다. 시간과 관련잇는건가?.... Jadx로 앱 파일을 분석해보자

앱 실행 시 처음 시작되는 "MainActivity"의 함수들을 살펴보면, 친절하게 flag 를 생성하는 함수라는 것을 알려주는 "generateFlag()"함수가 보인다. 이 함수 바로위에 "checkTime()"함수에서 특정 시간 달성 시 "generateFlag()"함수를 호출하고 잇어 해당 함수가 flag를 호출하는 함수라는 것이 유력해진다.

해당 함수에서 실제 flag를 생성하는지 확인하는 방법은 두가지가 있다.

  1. generateFlag() frida로 후킹하여 리턴값 확인.
  2. flag 를 생성하는 내부 로직을 분석, 코드로 구현하여 확인

첫 번째 frida후킹 방법으로 확인해보자
frida 후킹 방법 중 "implementation"으로 "generateFlag()"후킹하는 코드를 작성하여 리턴값을 확인해보고자 하였다.

Java.perform(function()
{
    var Hook_Class_name = Java.use("com.example.summer.MainActivity");
    
    Hook_Class_name.generateFlag.implementation = function()
    {
        var retval = this.generateFlag();
        console.log("ORG retval: "+retval);
        //retVal.replace(true);
        //console.warn("change --> retVal: "+retVal);
        return retval;
    }
});

실행 결과는, 후킹이 걸리지 않았다. implementation 으로 후킹을 할 경우에는 해당 함수가 호출이 되야 후킹이 걸리는데, "generateFlag()" 함수는 호출되는 곳이 "checkTime()"함수 하나이고, 특정시간을 만족해야 호출된다.

frida 후킹 방법 중에 "Java.choose"로 이를 해결 할 수 있다.

Java.perform(function () {
        var retval;
        Java.choose('com.example.summer.MainActivity', {
            onMatch: function (instance) {               
              
                    retval=instance.generateFlag();         
                    console.warn(retval);
            },
            onComplete: function (retval) {
               
               
            }
        })         
    })

실행 결과 "generateFlag()" 리턴 값이 확인 가능하며, flag 값이라는 것을 알 수 있다.

2번째 방법, generateFlag() 함수의 로직을 분석, 코드로 구현하여 확인해보자.


MainActivityKt.getFLAG(), MainActivityKt.getKEY()값을 알 수 있고, gen() 함수도 단순하기 때문에 코드를 구현하는데 큰 어려움은 없을 것이다.

import math

flag=[220, 211, 180, 230, 192, 22, 341, 220, 227, 341, 139, 163, 355, 293, 333, 196, 142, 216, 376, 133, 248, 26, 342, 378, 231, 149, 145, 173, 185, 1, 10, 198]
key=["h", "o", "t", "_", "h", "o", "t", "_", "s", "u", "m", "m", "m", "e", "r", "r"]

"""
///원본 코드
  private final int gen(int i) {
        int size = MainActivityKt.getKEY().size();
        return (((int) Math.pow(i, 3.0d)) % 256) ^ StringsKt.first(MainActivityKt.getKEY().get(size - ((i % size) + 1)));
    }
"""
def gen(i):
	size = len(key)
	ret=int((math.pow(i,3.0)%256))
	ret01=(key[size-((i%size)+1)])
	return ret ^ ord(ret01)

"""
///원본 코드
 private final String generateFlag() {
        ArrayList arrayList = new ArrayList();
        int size = MainActivityKt.getFLAG().size();
        for (int i = 0; i < size; i++) {
            arrayList.add(Character.valueOf((char) ((MainActivityKt.getFLAG().get(i).intValue() ^ StringsKt.first(MainActivityKt.getKEY().get(i % MainActivityKt.getKEY().size()))) - gen(i))));
        }
        return CollectionsKt.joinToString$default(arrayList, "", null, null, 0, null, null, 62, null);
    }
"""
size=len(flag)
result_flag=''

for i in range(size):
	result_flag+= chr((flag[i] ^ ord(key[i%len(key)]))-gen(i))

print(result_flag)

-끝-

profile
i love hacking
post-custom-banner

0개의 댓글