veridex 툴을 사용하여 non-SDK API 사용 확인법
android 2019. 8. 20. 22:31Android 9.0 ( APL Level 28 ) 부터 public API가 아닌 API 사용에 대해서 제한이 생긴다. 그럼 pubic API가 아닌건 어떤 것일까?
Android의 View.java 파일을 보면 아래처럼 @hide로 주석이 달려 있는 코드들이 있다.
/**
* Set an observer to collect stats for each frame rendered for this view.
*
* @hide
*/
public void addFrameMetricsListener(Window window,
Window.OnFrameMetricsAvailableListener listener,
Handler handler) {
if (mAttachInfo != null) {
if (mAttachInfo.mThreadedRenderer != null) {
if (mFrameMetricsObservers == null) {
mFrameMetricsObservers = new ArrayList<>();
}
FrameMetricsObserver fmo = new FrameMetricsObserver(window,
handler.getLooper(), listener);
mFrameMetricsObservers.add(fmo);
mAttachInfo.mThreadedRenderer.addFrameMetricsObserver(fmo);
} else {
Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
}
} else {
if (mFrameMetricsObservers == null) {
mFrameMetricsObservers = new ArrayList<>();
}
FrameMetricsObserver fmo = new FrameMetricsObserver(window,
handler.getLooper(), listener);
mFrameMetricsObservers.add(fmo);
}
}
이런 함수(또는 필드)들은 public 접근자로 되어 있는데도 사용할 수 가 없다. 바로 이런것들이 non-public function 가 되는 것이고, 이러한 함수와 필드(변수)를 통틀어서 non-SDK Interface 라고 부른다.
이렇게 숨겨진 함수들을 java의 reflection을 통해서 사용하는 방법이 있다. 그런데, 어떤 특정 기능을 구현할때 이런 함수들을 사용하면 상당히 편리한 경우가 있는데, 구글에서는 이런 편법적인 사용을 금지한 것이다. 이유는 public 으로 오픈한 함수가 아니라서 구글에서는 해당 함수이름을 변경하거나 삭제하거나 맘대로 하게 되는데, 특정 App에서 non-SDK Interface를 사용하였다면 문제가 발생하기 때문이다.
그리고 구글에서는 non-SDK Interface에 대해서 아래처럼 3가지로 구분하고 있다.
블랙리스트 : 앱의 target API와 상관없이 사용하면 안되는 리스트
다크그레이 리스트 : target API를 28로 설정하는 경우에 사용에 제한이 되는 리스트
라이트그레이 리스트 : target API를 28로 설정하는 경우에 사용은 가능하지만 잠제적으로 문제가 될 수 있는 리스트
그리고 android 9.0부터는 이러한 non-SDK를 사용했을때 발생하는 문제는 아래와 같다.
액세스 수단 | 결과 |
---|---|
필드를 참조하는 Dalvik 명령어 | NoSuchFieldError 발생 |
메소드를 참조하는 Dalvik 명령어 | NoSuchMethodError 발생 |
Class. 또는 Class. 를 통한 리플렉션 | NoSuchFieldException 발생 |
Class. , Class. 를 통한 리플렉션 | NoSuchMethodException 발생 |
Class. , Class. 를 통한 리플렉션 | 결과에 비 SDK 구성원 없음 |
Class. , Class. 를 통한 리플렉션 | 결과에 비 SDK 구성원 없음 |
env->GetFieldID() 를 통한 JNI | NULL 이 반환되고 NoSuchFieldError 발생 |
env->GetMethodID() 를 통한 JNI | NULL 이 반환되고 NoSuchMethodError 발생 |
target API를 28로 설정하것이 아니면 일단은 블랙리스트의 사용 여부만 검점하면 되는데, 이건 검사해 주는 도구가 veridex 도구 이다.
또는 StrictMode의 detectNonSdkApiUsage
을 사용해도 되는데, 이방법은 실행시간에 오류를 알려 주게 되므로 모든 기능을 다 사용해 봐야 어느 정도 검증을 할 수 있게 된다. 그래서 target API를 28로 올리는 시점에는 veridex로 한번 체크하는것을 권한다.
위의 경로에서 다운받고 압축을 푼 뒤에, 아래의 명령으로 실행하면 된다.
./appcompat.sh --dex-file=test.apk
apk를 압축해제한후 직접 dex파일을 지정해도 되지만, 편리하게 그냥 apk 이름을 넣으면 알아서 검사를 해준다. 검사결과는 대략 아래처럼 표시된다.
--- 중략 ---
다행이도 아직 target API가 28이 아니라서 큰 문제는 없다.
그리고 veridex사용지 주의점이 있는데 완벽하게 체크해주는게 아니라는..
2019.8.20 기준으로 veridex의 한계점은 아래와 같다.
- JNI를 통한 호출은 감지할 수 없습니다.
- 리플렉션을 통한 호출의 경우 일부만 감지할 수 있습니다.
- 비활성 코드 경로 분석이 API 수준 검사로 제한됩니다.
즉, 완벽한게 아니라서, veridex로 검사하고, StrictMode로 같이 체크하는 수 밖에.. ㅠㅠ