[Frida] Android Permission 필요 동작 후킹하기

Preview

안드로이드 환경에서 Frida와 adb로 상용 앱을 분석할 때 앱 내에서 어떤 동작을 하는지 파악하기가 쉽지 않다. 에러가 발생해서 발생하는 크래시 로그(Crash Log)가 아닌 개발자가 의도한 정상 동작은 어떻게 분석할까? 앱로그, 로그캣에서도 그에 대해 구체적으로 방법을 제시해 주지는 않는다. 그렇다고 실행 시점마다 스크린 샷을 저장해서 일일이 분석할 수도 없다. 이 포스트에서는 앱 내 기능 동작에 대해 분석하는 방법을 제시한다.

 

안드로이드 권한에 대한 정책은 다음과 같다.

  • 안드로이드 5.1 이하(SDK 22이하) - 앱을 설치할 권한 부여
  • 안드로이드 6.0 이상(SDK 23이상) - 앱이 실행되는 도중 권한 요청 거부하더라도 제한된 기능으로 동작 가능
[분석환경]
OSX Big Sur 11.0.1
AVD(Android Virtual Device) : Nexus 4 API 30 x86
[분석도구]
Frida, adb, Python

포스트는 안드로이드 API 레벨 30을 대상으로 작성하였다. 개발자에 따라 구현 방법이 다를 수 있으니 직접 apk 정적 분석 후에 후킹하는 것을 권장한다.

안드로이드 Permission

안드로이드 공식문서에서는 어떤 권한이 위험 권한 및 권한 그룹인지 명시하고 있다. 이러한 권한들은 메타데이터 파일인 AndroidManifest에 선언되어 있어야 하며, 필요 기능 동작 시마다 사용자에게 권한 허용을 받고 사용해야 한다.

adb에서 앱에서 사용하는 권한 목록을 가져오기 위해서 아래의 명령을 사용한다.

adb shell dumpsys package com.packagename | grep "permission"

위험 권한 목록 및 상용앱에서의 권한 목록

카메라(camera)

앱에서 카메라를 사용하는 경우는 사진이나 동영상의 촬영, QR코드의 인식 등이 될 것이다. 이 중 qr코드 인식의 경우를 알아본다. 안드로이드 제공 라이브러리 중 qr코드를 인식하기 위해서 주로 zxing_barcode_scanner를 사용한다. 이 함수의 호출 여부를 확인하면, QR코드를 찍기 위해 카메라를 실행하는지 여부를 확인할 수 있다.

QR 스캔을 위한 BarcodeView 호출

 

QR 코드 스캔을 위한 카메라 호출 뿐만 아니라 일반 사진 촬영을 위한 카메라 실행은 어떻게 후킹할까

    try{
        var contxt = Java.use("android.content.Context");
        contxt.getSystemService.overload("java.lang.String").implementation = function(str){
            var ret = this.getSystemService(str);
            LOG("[+] Context getSystemService", {c:Color.Blue});
            console.log(str.toString());
            return ret;
        }
    } catch(err) {
        console.log('[-] Context getSystemService error');
        console.log(err)
    }

사진 업로드 위한 갤러리, 카메라 호출

위치 정보(Location)

안드로이드에서 위치정보를 얻기 위해서 위도(Latitude)와 경도(Longtitude) 정보를 가져온다. android.location.Location 클래스에 getLatitude()를 이용해서 가져온다. 이 함수를 후킹하면 된다. 작성한 코드는 아래와 같다.

    try{
        var locate = Java.use("android.location.Location");
        locate.getLatitude.implementation = function(){
            console.log("[+] Request GPS Location");
            var ret = this.getLatitude();
            console.log(ret.toString());
            return ret;
        }
    } catch(err) {
        console.log('[-] GPS Location error');
        console.log(err)
    }

앱 내 위치정보 요청 버튼 클릭 및 후킹한 위치 정보

파일 입출력(File I/O)

https://codeshare.frida.re/@FrenchYeti/android-file-system-access-hook/

codeshare에 좋은 코드가 있어 인용하였다. 상용 앱에서 실행 시 너무 많은 호출로 인해 앱 크래시 후 종료된다. 적절한 후킹 시점을 선정하여 후킹 코드를 삽입하여 사용하도록 한다.

 

전화 걸기(Phone Dial / Call)

앱 내에서 전화번호 클릭 시 다이얼 페이지 연결과, 전화 걸기 동작을 수행하는 기능이 있다. 안드로이드 내부 스키마로 "tel://00000"을 통해 Intent를 전달하여 호출한다.

    try{
        var intnt = Java.use("android.content.Intent");
        intnt.getAction.implementation = function(){
            console.log("[+] Context getAction");
            var ret = this.getAction();
            if (ret != null){
                console.log(ret.toString());
                var c = this.getData();
                if ( c != null){
                    console.log(c.toString());
                }
            }
            
            return ret;
        }
    } catch(err) {
        console.log('[-] Intent getAction error');
        console.log(err)
    }

로그에서 알 수 있듯 전화걸기 뿐만 아니라 Intent를 통하 데이터를 전송하는 다른 정보들 까지 확인 할 수 있는 것을 알 수 있다.

 

연락처 저장, 수정, 삭제(Contacts)

    try{
        var cntntResolver = Java.use("android.content.ContentResolver");
        cntntResolver.delete.overload('android.net.Uri', 'java.lang.String', '[Ljava.lang.String;').implementation = function(uri, where, args){
            LOG("[+] ContentResolver.delete", {c:Color.Green});
            console.log(uri.toString());
            console.log(where.toString());
            return this.delete(uri, where, args);
        }
    } catch(err) {
        LOG('[-] ContentResolver.delete error', {c:Color.Red});
        console.log(err)
    }

    try{
        cntntResolver.insert.overload('android.net.Uri', 'android.content.ContentValues').implementation = function(uri, values){
            LOG("[+] ContentResolver.insert", {c:Color.Green});
            console.log(uri.toString());
            console.log(values.toString());
            return this.insert(uri, values);
        }
    } catch(err) {
        LOG('[-] ContentResolver.insert error', {c:Color.Red});
        console.log(err)
    }

연락처에  접근하여 전화번호를 저장, 수정, 삭제하려는 시도가 있을 때 후킹되는 함수이다. 자세한 데이터 포맷은 로그를 분석하면 쉽게 알 수 있다. 사진은 연락처 "추가"를 시도할 때의 모습이다.

 

Review

안드로이드 위험 권한에 대해 알아보고, 위험권한 기능을 후킹하는 프리다 스크립트도 작성해 보았다.

다음 포스트에서는 위험권한이 아닌 일반 메소드이지만, 앱의 기능을 파악할 수 있는 로그를 남기는 법에 대해서 알아본다.

반응형