ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Frida를 이용한 App DB복호화Key 알아내기(with.TigerText)
    Mobile/Frida 2019. 7. 5. 10:16


    이번에는 Frida를 이용해서 TigerText App의 암호화된 DB를 복호화 해볼 것이다.

    TigerText App은 카카오톡과 같은 메신저App이며, 텔레그램처럼 보안메시지 기능을 지원하는 App이다.

    현재는 TigerConnect라는 이름으로 서비스하고 있다.


    1. Frida란?

    모바일 환경에서 대표적인 DBI(Dynamic Binary Instrumentation)Tool로 스크립트를 통해서 App을 분석할 수 있다.

    Frida를 사용하는 목적은 Java Method나 Native함수를 후킹해서 흐름을 조작하려는 것이 가장 크다.

    대표적인 예로는 SSL Pinning BypassDecrypt Key LeakMethod Trace 등이 있다.

    Frida는 Python이나 C언어등 다양한 언어환경에서 Frida모듈을 로드하여 사용가능하며, 후킹스크립트는 JavaScript로 작성한다.

    대부분은 가볍고 간단하다는 이유로 Python을 가장 많이 사용한다.

     

    Frida를 사용할 때는 루트권한으로 사용하는 것이 가장 좋다.

    만약 루트권한을 얻지 못하는 환경이라면, App Native에 Frida Gadget을 로드시켜서 사용하는 방법이 있다.

    단, App ByteCode를 수정 해야하기 때문에 리패키징 작업이 필요하다.

    Ref. https://lief.quarkslab.com/doc/latest/tutorials/09_frida_lief.html


    2. Frida 설치 방법

    - Frida 설치

    Frida는 Module / CLI 두 가지 방식으로 사용할 수 있다.

    • Frida Module설치

    pip install frida

     Frida CLI설치

    pip install frida-tools

    - Frida-Server 설치

    HostPC에 Frida설치가 완료 됐으면 대상기기에 Frida-Server를 올려줘야 한다.

    • Github for Frida-Server

    위 링크에서 대상기기 환경에 맞는 Frida-Server를 다운로드해준다.

    대상기기를 adb로 접속하여 getprop ro.product.cpu.abilist 명령어로 기기환경을 알아낼 수 있다.

     

    Frida-Server 다운로드가 완료되었으면 adb push [Frida-Server경로] /data/local/tmp 명령어로 옮겨준다.

    옮긴 뒤, chmod 777 /data/local/tmp/frida-server 명령어로 권한을 부여해준다.

    그리고 ./frida-server & 명령어로 Frida-Server를 백그라운드로 실행하면 된다.

    아래 그림처럼 ps명령어로 확인해 해봤을때 root권한으로 실행되고 있으면 정상적으로 실행된 것이다.

    이로써 Frida를 사용하기 위한 환경세팅은 완료되었다


    3. Frida-Trace

    Frida로 Java Method를 Trace할 때의 방법이다.

    • Hooking 스크립트 제작Tool

    Frida_Tracing_v1.0.exe

    출처: https://bl4k0ut.blogspot.com/2018/07/frida-tracing-tool-smali-frida.html

    우선 위 프로그램으로 Trace Script를 만들어준다.

    프로그램 사용법은 다음과 같다.


    1) Frida_Tracing_v1.0.exe [Smali코드가 있는 폴더경로] 

    - 경로에 한글이 포함되어 있으면 안된다.
    - 너무 많은 Method를 Trace하면 Frida가 제대로 동작하지 않는다.
    - 스크립트 제작이 완료되면 현재경로에 hooking.js 라는 스크립트 파일이 생성된다.

    2) frida -U -n [패키지 이름] -l hooking.js --no-pause

    - U : USB Device 연결
    - n : 패키지명으로 App Attach
    - l : Script Load
    - no-pause : App Main Thread 자동실행

    정상적으로 frida가 실행되면 아래와 같이 Java Method들을 Trace할 수 있다.


    4. Frida Method Hooking

    상황에 따라서 후킹을 하고자 하는 목적은 다양하다.

    해당 예제에서는 'TigerText DB복호화 키'를 알아내기 위한 Hooking 방법을 작성하도록 한다.

    내용 간략화를 위해 데이터 획득까지의 과정은 생략하도록 하며, TigerText Database 중 'ttandroid.db'가 암호화되어 있는 상황이다.

    - Method Trace

    위에서 설명한 방법대로 Trace Hooking Script로 Method들의 흐름을 먼저 살펴보도록 한다.

    • TigerText Trace 결과

    App을 처음 실행했을 때, 실행되는 Method들이다.

    해당 결과를 텍스트편집기로 옮겨와서 Database를 관리하는 Method가 실행되는지 찾아보도록 한다.

    • Database 관리 Method

    이렇게 Method들을 찾을 때는 관련성있는 단어들을 검색해보면서 찾을 수 있다. decrypt, encrypt, database, auth 등..

    만약 관련함수들이 전부 난독화 되어있다면, 해당 방법으로 찾는 것보다 소스코드를 보면서 찾는게 더 효율적일 수 있다.

    우선 database로 검색했을 때, com.tigertext.ttandroid.api.TT.getDatabaseHelper 라는 Method가 호출되는 것을 확인할 수 있다.

    JEB로 해당 Method를 찾아가 추가분석을 하도록 한다.

     

    • getDatabaseHelper( )

    GetDatabaseHelper( )는 this.k 를 반환하는 기능을 한다.

     

    • this.k

    k는 DatabaseHelper클래스의 객체이다.

    따라서, getDatabaseHelper( )는 DatabaseHelper의 객체를 반환해주는 Method라는 것을 알 수 있다.

     

    • DatabaseHelper

    DatabaseHelper는 com.tigertext.ttandroid.db에 위치해 있으며, 암호화되어 있는 ttandroid.db를 관리하는 Method인것을 알 수 있다.

    DatabaseHelper클래스에 DecryptKey를 생성하는 Method가 있는지 확인해볼 필요가 있다.

     

    • DatabaseHelper Method목록

    해당 클래스의 Method목록을 보면 하나의 Method만 a로 난독화되어 있는것을 확인할 수 있다.

    난독화의 목적이 중요한Method가 외부인에게 분석되는 것을 방지하는 점임을 두고 본다면, 저 난독화된 Method를 의심해볼 여지는 충분하다.

     

    • DatabaseHelper.a( )

    난독화된 a( )는 TT.getInstance( ).getAccountManager( ).getAuthToken( )의 값을 반환해주는 기능을 한다.

     

    • TT.getAuthToken( )

    TT.getAuthToken( )는 SecureSharedPrefsManager.getInstance( ).getAuthToken(this.a)의 값을 반환해주는 기능을 한다.

     

    • SecureSharedPrefsManager.getAuthToken( )

    SecureSharedPrefsManager.getAuthToken( )는 [v0+":"+"v4]포맷으로 값을 반환한다.

    v0값은 getRestKey(arg4)의 반환값 / v4값은 getRestSecret(arg4)의 반환값으로 두개의 키값을 ':' 으로 이어주는 것을 확인할 수 있다.

     

    정리를 하자면, 암호화된 ttandroid.db를 관리하는 클래스에서 난독화된 Method가 있는데, 해당 Method가 하는 일이 RestKey:RestSecret 값을 가져오는 기능을 하고 있다.

    해당 값이 정말 ttandroid.db의 복호화키로 사용되는지 정확하게 판단하려면 더 깊이 분석을 해봐야 알겠지만, 해당 값을 후킹으로 알아내서 바로 확인하는게 더 빠른 방법이 될 수 있다.


    5. Frida Hooking Script 작성

    프로그래밍 언어는 Python을 사용했으며, 에뮬레이터를 사용하지 않고 루팅된 기기를 사용했다.

    먼저 후킹 시나리오는 다음과 같다.

    1) com.tigertext.ttandroid.api.TT.getDatabaseHelper( )를 후킹해서 반환되는 DatabaseHelper객체를 받아온다.
    2) 받아온 DatabaseHelper객체로 a( )를 호출하여 반환값인 [v0:v4]값을 받아와 출력한다.

    후킹 스크립트는 아래와 같다.

     

    - 후킹 스크립트

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    Java.perform(function()
    {
        console.log("[*] Hook IN");
        var tt = Java.use("com.tigertext.ttandroid.api.TT");
        tt.getDatabaseHelper.implementation = function()
        {
            //console.log("[*]IN");
            var retVal = this.getDatabaseHelper();
            
            console.log("[*]retVal:"+retVal);
            var SecretKey = retVal.a();
            console.log("[!] SecretKey:"+SecretKey);                                     
                    
            return retVal;
            
        }
    });
    cs

    • Java.perform( ) 인자에 함수를 정의해서 Java Method를 후킹할 수 있다.

    • Java.use( )로 후킹할 Class에 대한 객체를 받아올 수 있다.

    • implementation으로 원래 Method동작 대신 원하는 동작을 정의할 수 있다.

    • console.log( )로 Python콘솔창에 값을 출력할 수 있다.

    - Frida 셋팅

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    def on_messege(message,data):
        print("{} -> {}".format(message,data))
     
    Package_name = "com.tigertext" # 후킹할 App의 패키지명
    device = frida.get_usb_device() # USB로 연결된 Device Attach
    pid = device.spawn([Package_name]) # App실행 후, PID 저장
    process  = device.attach(pid) # App Attach
    device.resume(pid) # App 재실행
     
    script = process.create_script(hook_code) # JavaScript -> HookingCode로 변환              
    script.on('message',on_messege) # Script 디버깅 함수 지정
    script.load() # Script Load
    sys.stdin.read() # 표준 입력 사용
    cs

    - 전체 후킹 코드

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    import frida
    import sys
     
    hook_code = """
    Java.perform(function()
    {
        console.log("[*] Hook IN");
        var tt = Java.use("com.tigertext.ttandroid.api.TT");
        tt.getDatabaseHelper.implementation = function()
        {
            //console.log("[*]IN");
            var retVal = this.getDatabaseHelper();
            
            console.log("[*]retVal:"+retVal);
            var SecretKey = retVal.a();
            console.log("[!] SecretKey:"+SecretKey);
            
            return retVal;
        }
    });
    """
    def on_messege(message,data):
        print("{} -> {}".format(message,data))
     
    Package_name = "com.tigertext" # 후킹할 App의 패키지명
    device = frida.get_usb_device() # USB로 연결된 Device Attach
    pid = device.spawn([Package_name]) # App실행 후, PID 저장
    process  = device.attach(pid) # App Attach
    device.resume(pid) # App 재실행
     
    script = process.create_script(hook_code) # JavaScript -> HookingCode로 변환              
    script.on('message',on_messege) # Script 디버깅 함수 지정
    script.load() # Script Load
    sys.stdin.read() # 표준 입력 사용
    cs

    해당 스크립트를 실행하면 대상기기에서 TigerText가 실행되고, Python 콘솔창에 DatabaseHelper.a( )의 반환값이 출력된다.

    출력된 Key값은 f0qZLlCzcItJr5tC6SuICkK8SP7cHibv:05AYEjyZjArv5W1OKBTUjC4M4Bv88KDoSMqf2YvTg3yZGpDp 이다.

    DB Browser를 이용해 해당 Key로 ttandroid.db를 복호화 해보면 아래와 같이 정상적으로 복호화되는 것을 확인할 수 있다.


    [ ttandroid.db 복호화 완료 ]

    댓글

Designed by Tistory.