Android 9 이상에서 숨겨진 API 블랙리스트를 우회하는 방법

Google은 Android 9에서 개발자가 API에 액세스할 수 있는 제한 사항을 도입했습니다. 숨겨진 API 제한을 우회하는 방법은 다음과 같습니다.

2018년에 구글은 안드로이드 파이(Android Pie)를 출시했습니다. UI 변경과 새로운 기능 중에는 개발자 측에서도 몇 가지 변경 사항이 있었습니다. 이러한 변경 사항에는 새로운 API, 기존 API에 대한 버그 수정 및 숨겨진 API에 대한 액세스 제한.

다행히도 이러한 제한을 피할 수 있는 방법이 있습니다. 제한 사항을 우회하는 방법을 설명하기 전에 숨겨진 API가 무엇인지, 왜 제한되었는지, 왜 액세스하려는지에 대해 조금 설명해야 합니다.

숨겨진 API는 일반적으로 앱 개발자가 볼 수 없는 Android의 API입니다. AOSP의 코드를 살펴보면 @hide 그 위의 주석 블록 내부에 주석을 추가합니다.

이 주석은 SDK를 컴파일할 때 Google이 사용하는 모든 도구에 해당 항목을 제외하도록 지시합니다. 그런 다음 해당 SDK는 Android Studio를 통해 다운로드한 SDK 내부의 개발자에게 배포됩니다. 수정된 SDK를 사용하지 않는 한 Android Studio는 이러한 숨겨진 항목이 존재하지 않는다고 생각합니다. 직접 사용하려고 하면 빨간색으로 표시되고 컴파일이 거부됩니다.

API가 숨겨져 있는 데에는 여러 가지 이유가 있습니다. 일부 기능은 내부 또는 시스템 앱에서만 사용하도록 되어 있으며 타사 앱에서 사용하는 경우 작동하지 않습니다. 다른 것들은 실험적이거나 불안정하며 향후 제거되거나 변경될 수 있습니다. 일부는 API일 뿐이며 Google은 제거된 경우 일반적인 지원 중단 주기를 적용하고 싶지 않습니다.

표준 Android SDK에는 많은 때로는 그것만으로는 충분하지 않습니다. 때로는 Android에 이미 존재하지만 공개적으로 노출되지 않는 작업이 있을 수 있습니다.

예를 들어, 제가 만드는 많은 앱에는 다음이 포함됩니다. SystemUI 튜너 그리고 잠금화면 위젯, 다양한 숨겨진 API를 활용하세요. SystemUI Tuner는 옵션을 올바르게 추적, 변경 및 재설정하려면 일부에 액세스해야 합니다. 잠금화면 위젯은 무엇보다도 그 아래에 배경화면을 표시하기 위해 일부를 사용합니다.

대부분의 개발자는 숨겨진 API에 액세스할 필요가 없지만 때로는 꽤 유용할 수 있습니다.

Google은 Android 9(Pie) 출시와 함께 숨겨진 API 블랙리스트를 도입했습니다. 숨겨진 API가 모두 포함된 것은 아니며 다양한 수준의 목록이 있었습니다. 화이트리스트에 있는 숨겨진 API는 누구나 액세스할 수 있습니다. 라이트 그레이리스트에 있는 숨겨진 API는 모든 앱에서 액세스할 수 있지만 향후 Android 버전에서는 액세스하지 못할 수도 있습니다. 다크 그레이리스트에 있는 모든 항목은 Pie 이전(즉, API 레벨 28 이전) API 레벨을 대상으로 하는 앱에서만 액세스할 수 있습니다. Pie 이상을 대상으로 하는 앱은 액세스가 거부됩니다. 마지막으로, 블랙리스트에 숨겨진 API는 대상 API에 관계없이 시스템이 아닌(또는 화이트리스트에 없는) 앱에서 액세스할 수 없습니다.

Android 10에서는 목록 구성 방식을 변경하고 약간 단순화했지만 아이디어는 동일하게 유지되었습니다. 특정 숨겨진 API는 앱에서 액세스할 수 있었지만 다른 API는 차단되었습니다. 안드로이드 11 접근 감지 강화 에게 우회를 차단하다 Pie와 10에 사용됩니다.

모든 Android 버전에서 타사 앱이 블랙리스트에 포함된 숨겨진 API에 액세스하려고 시도할 때마다 Android에서 적절한 '찾을 수 없음' 오류가 발생합니다.

실제로 숨겨진 API 블랙리스트를 통과하는 방법에는 여러 가지가 있습니다. 필요에 따라 모든 Android 버전에서 작동하는 버전, Android 9 및 10에서만 작동하는 버전, 네이티브 C++ 코드를 사용하는 버전, 완전한 Java 기반 버전을 선택할 수 있습니다. ADB를 사용하는 개발 전용 해결 방법도 있습니다.

ADB 해결 방법

기기에서 Android Pie를 실행 중인 경우 다음 두 가지 ADB 명령을 실행하여 숨겨진 API 액세스를 활성화하세요.

adb shell settings put global hidden_api_policy_pre_p_apps 1
adb shell settings put global hidden_api_policy_p_apps 1

기기에서 Android 10 이상을 실행하는 경우 다음 ADB 명령을 실행하여 숨겨진 API 액세스를 활성화하세요.

adb shell settings put global hidden_api_policy 1

기본 동작으로 되돌리려면 다음을 바꾸십시오. put ~와 함께 delete 그리고 제거 1.

분명히 이러한 명령은 프로덕션 앱에 유용하지 않습니다. ADB 사용법을 사용자에게 제대로 가르치는 것이 엄청나게 어렵다는 것을 직접 말씀드릴 수 있습니다. 하지만 새로운 제한 사항을 준수하기 위해 기존 앱을 업데이트해야 하는 경우 유용할 수 있습니다.

네이티브/JNI 해결 방법

Android 앱에서 JNI를 사용하여 숨겨진 API 블랙리스트를 우회할 수 있는 방법에는 두 가지가 있습니다. 하나는 Android 9 및 10에서 작동하고 다른 하나는 Android 9 이상에서 작동합니다.

안드로이드 9 및 10

앱의 기본 부분이 이미 있는 경우 쉽게 구현할 수 있습니다. 그냥 사용 JNI_OnLoad() 기능.

정적 예술:: 런타임* 런타임 = nullptr;

extern "C"jint JNI_OnLoad(JavaVM *vm, void *reserved){
...
runtime = reinterpret_cast<: javavmext>(vm)->GetRuntime();
runtime->SetHiddenApiEnforcementPolicy(art:: hiddenapi:: EnforcementPolicy:: kNoChecks);
...
}

이 방법은 Android 9 및 10에서만 작동합니다.

안드로이드 9 이상

모든 Android 버전에서 숨겨진 API 제한을 우회하기 위해 FreeReflection 및 RestrictionBypass라는 두 가지 라이브러리를 선택할 수 있습니다.

둘 다 구현하고 사용하기 쉽습니다.

FreeReflection을 구현하려면, 모듈 수준 build.gradle에 종속성을 추가합니다.

implementation 'me.weishu: free_reflection: 3.0.1'

그런 다음 재정의 attachBaseContext() 응용 프로그램 클래스에서.

@Override
protectedvoidattachBaseContext(Context base){
super.attachBaseContext(base);
Reflection.unseal(base);
}

Application 클래스가 없는 경우 매우 쉽게 추가할 수 있습니다. 확장되는 새 클래스 만들기 Application 그런 다음 AndroidManifest.xml에서 이를 가리킵니다.

예:

publicclassAppextendsApplication{
...
@Override
protectedvoidattachBaseContext(Context base){
super.attachBaseContext(base);

Reflection.unseal(base);
}
}

<manifest>
...
...
name=".App">
...
application>
manifest>

RestrictionBypass를 구현하려면, 프로젝트 수준 build.gradle에 JitPack 저장소를 추가합니다.

allprojects {
repositories {
...
maven { url "https://jitpack.io" }
}
}

그런 다음 모듈 수준 build.gradle에 종속성을 추가합니다.

implementation 'com.github.ChickenHook: RestrictionBypass: 2.2'

그리고 그게 다야. 이 라이브러리는 블랙리스트 제한을 자동으로 제거합니다.

자바 해결 방법

JNI 솔루션은 효과적이지만 네이티브 코드를 사용하고 싶지 않은 경우도 있습니다. 아직 C++로 작업을 수행하지 않는 경우 플랫폼 제한과 함께 불필요한 크기가 앱에 추가될 수 있습니다. 다행히도 Java만 사용하여 숨겨진 API 블랙리스트를 우회할 수 있는 방법이 있습니다.

안드로이드 9 및 10

Android 9 및 10에서는 이중 반사 또는 메타 반사라고 불리는 기능을 사용하여 숨겨진 API 블랙리스트를 우회할 수 있습니다. 시스템은 타사 앱이 호출하는 것만 확인하기 때문에 이중 반사는 시스템이 숨겨진 API 호출을 하고 있다고 생각하도록 속입니다.

이 트릭은 앱에 적절한 이름의 숨겨진 API 예외를 제공하는 메서드를 호출하는 데 사용할 수 있습니다. setHiddenApiExemptions(). 앱 라이프사이클 초기(예: 애플리케이션의 라이프사이클)에 다음 코드를 추가하기만 하면 됩니다. onCreate() 방법), 블랙리스트 우회를 처리합니다.

Method forName = Class.class.getDeclaredMethod("forName", String.class);
Method getDeclaredMethod = Class.class.getDeclaredMethod("getDeclaredMethod", String.class, Class[].class);

Class vmRuntimeClass = (Class) forName.invoke(null, "dalvik.system.VMRuntime");
Method getRuntime = (Method) getDeclaredMethod.invoke(vmRuntimeClass, "getRuntime", null);
Method setHiddenApiExemptions = (Method) getDeclaredMethod.invoke(vmRuntimeClass, "setHiddenApiExemptions", newClass[] { String[].class} );

Object vmRuntime = getRuntime.invoke(null);
setHiddenApiExemptions.invoke(vmRuntime, newString[][] { newString[] { "L" } });

앱이 Android 9 미만 버전과 호환되는 경우 이를 버전 확인에 포함해야 합니다.

안드로이드 9 이상

Android 9 및 이후 버전에서 숨겨진 API 블랙리스트를 우회하려면 LSPosed의 라이브러리를 사용할 수 있습니다. 이 라이브러리는 Java의 Unsafe API를 사용하므로 깨지는 일이 거의 없습니다.

이를 구현하려면 모듈 수준 build.gradle에 종속성을 추가하기만 하면 됩니다.

implementation 'org.lsposed.hiddenapibypass: hiddenapibypass: 2.0'

그런 다음 이를 사용하여 블랙리스트를 우회합니다.

HiddenApiBypass.addHiddenApiExemptions("L");

앱이 Android 9 미만 버전과 호환되는 경우 이를 버전 확인에 포함해야 합니다.

결론 및 추가 정보

어떤 플랫폼 버전을 대상으로 하거나 사용하든 관계없이 Android에서 숨겨진 API 블랙리스트를 우회할 수 있는 옵션이 많이 있습니다. 이러한 메서드와 라이브러리의 작동 방식에 대해 자세히 알아보려면 다음 링크를 확인하세요.

  • 내 스택 오버플로 Q&A.
  • GitHub에 있는 LSposed의 Hidden API Bypass 라이브러리.
  • GitHub의 ChickenHook RestrictionBypass 라이브러리.
  • GitHub에 있는 tiann의 FreeReflection 라이브러리.
  • 숨겨진 API 블랙리스트에 대한 Google 문서.