Читая stackoverflow, узнал о существовании Amazon Appstore App for Android и о том, что Amazon инжектит в каждое приложение свой код. Мне стало интересно, зашел на сайт
Просят зайти с девайса по ссылке
Amazon Appstore требует авторизации, приложения скачанные с одного аккаунта, не будут работать на другом. Это и есть DRM защита, которую можно и не использовать, убрав галочку при публикации. Еще мы видим, что амазон переподписывает все апк своим ключом, так как инжектится дополнительный код.
Интересно, что именно и как инжектит код амазон. О том, как именно он это делает, можно понять из документации к публикации приложений. Здесь говориться, что если у вас в приложении почти 65К методов, то засабмитить неполучится. Это говорит о том, что амазон инжектит код в ваши классы и добавляет свои, а не использует метод с добавление своего dex файла.
Главное окно приложения
Appstore содержит довольно много платных приложений. Вместе с DRM'ом, все приложения скачанные через этот appstore не работают без него. Давайте проверим это, скачаем рандомное приложение
Откроем стартовый Activity приложения ES Explorer под названием com.estrongs.android.pop.app.openscreenad.NewSplashActivity. Имя берем из манифеста. В методе OnCreate():
Самая первая строка была добавлена амазоном, вызывается onCreate() у какого-то Kiwi и передается вторым параметром true. Открываем Kiwi
Вызов конструктора, который принимает Application
Здесь видно, что второй параметр отвечает за DRM, в предыдущем коде мы видели, что передавалось true, значит это приложение поддерживает DRM. Далее выводится информация в лог.
Мы видим это в logcat, после запуска приложения
Далее вызывается метод
Откроем метод C4882c.mo27440a()
Здесь происходит "регистрация" своих амазоновских классов. Все классы находятся в com.amazon.*. По названию можно понять, что эти классы являются не родными для нашего приложения и были добавлены Амазоном.
Чтобы понять, что такое регистрация классов, надо заметить, в ней участвует класс C4849a. Откроем его
Видим, что под регистрацией подразумевается проверка на null, то есть амазон проверяет целостность и наличие своих классов. Далее приложение ES Explorer биндится к сервису, который запускается приложением Amazon App Store, что еще раз явно указывает на то, что без него приложения не работают. Изначально, когда я это увидел, была мысль просто имитировать этот сервис самописным приложениям, но оказалось все проще.
Отвязка приложения
Как вы уже догадались, все очень просто и элементарно - все эти проверки начинаются с активити Kiwi, и мы видели в начале, что вызов этого активити внедряется в каждый активити приложения. Напомню ,выглядит примерно вот так
Мы просто берем и выпиливываем это из каждого активити и наше приложение больше не привязан к Amazon App Store.
Автор @Thatskriptkid
источник https://github.com/thatskriptkid
Просят зайти с девайса по ссылке
Amazon Appstore требует авторизации, приложения скачанные с одного аккаунта, не будут работать на другом. Это и есть DRM защита, которую можно и не использовать, убрав галочку при публикации. Еще мы видим, что амазон переподписывает все апк своим ключом, так как инжектится дополнительный код.
Интересно, что именно и как инжектит код амазон. О том, как именно он это делает, можно понять из документации к публикации приложений. Здесь говориться, что если у вас в приложении почти 65К методов, то засабмитить неполучится. Это говорит о том, что амазон инжектит код в ваши классы и добавляет свои, а не использует метод с добавление своего dex файла.
Главное окно приложения
Appstore содержит довольно много платных приложений. Вместе с DRM'ом, все приложения скачанные через этот appstore не работают без него. Давайте проверим это, скачаем рандомное приложение
Откроем стартовый Activity приложения ES Explorer под названием com.estrongs.android.pop.app.openscreenad.NewSplashActivity. Имя берем из манифеста. В методе OnCreate():
Код:
/* access modifiers changed from: protected */
public void onCreate(Bundle bundle) {
Kiwi.onCreate((Activity) this, true);
boolean z = false;
this.f8682k = false;
setContentView((int) R.layout.activity_splash_view);
super.onCreate(bundle);
this.f8681j = getIntent().getStringExtra("key_from");
if (!C3729h.m15797c(this)) {
z = true;
}
this.f8683l = z;
}
Код:
public static void onCreate(Activity activity, boolean z) {
long currentTimeMillis = System.currentTimeMillis();
if (!isInitialized()) {
INSTANCE = new Kiwi(activity.getApplication(), z);
}
if (preProcess("onCreate", activity)) {
INSTANCE.contextManager.onCreate(activity);
}
if (KiwiLogger.TRACE_ON) {
LOGGER.trace("Kiwi.ActivityOnCreate Time: " + (System.currentTimeMillis() - currentTimeMillis));
}
}
Код:
INSTANCE = new Kiwi(activity.getApplication(), z);
Код:
private Kiwi(Application application2, boolean z) {
long currentTimeMillis = System.currentTimeMillis();
this.drmEnabled = z;
if (KiwiLogger.TRACE_ON) {
LOGGER.trace("Starting initialization process for application: " + application2.getPackageName());
LOGGER.trace("DRM enabled: " + z);
}
instantiateTheWorld(application2);
if (KiwiLogger.TRACE_ON) {
LOGGER.trace("Kiwi.Constructor Time: " + (System.currentTimeMillis() - currentTimeMillis));
}
}
Далее вызывается метод
Код:
private void instantiateTheWorld(Application application2) {
C4882c cVar = new C4882c();
cVar.mo27440a(application2);
cVar.mo27440a(new C4883a());
cVar.mo27440a(new C4957a());
cVar.mo27440a(new C4854c());
cVar.mo27440a(new C4863d());
cVar.mo27440a(new PromptManagerImpl());
cVar.mo27440a(new C4951b());
cVar.mo27440a(new C4844a());
cVar.mo27440a(new C4964c());
cVar.mo27440a(new C4888c());
cVar.mo27440a(new C4934c());
cVar.mo27440a(new C4891f());
cVar.mo27439a();
cVar.mo27441b(this);
}
Код:
public final void mo27440a(Object obj) {
if (KiwiLogger.TRACE_ON) {
f15117a.trace("Registering resource: " + obj);
}
C4849a.m19515a();
if (this.f15119c) {
throw new IllegalStateException("Attempt made to register resource after population has begun!");
}
C4849a.m19516a(obj, "resource");
C4849a.m19519b(m19561a(obj.getClass()) != null, "Resource already registered: " + obj);
this.f15118b.add(obj);
}
Чтобы понять, что такое регистрация классов, надо заметить, в ней участвует класс C4849a. Откроем его
Код:
ublic final class C4849a {
/* renamed from: a */
public static void m19515a() {
long id = Looper.getMainLooper().getThread().getId();
if (Thread.currentThread().getId() != id) {
m19517a("Executing thread must be thread: " + id + ", was: " + Thread.currentThread().getId());
}
}
/* renamed from: a */
public static void m19516a(Object obj, String str) {
if (obj == null) {
m19517a("Argument: " + str + " cannot be null");
}
}
/* renamed from: a */
private static void m19517a(String str) {
throw new C4850b(str);
}
/* renamed from: a */
public static void m19518a(boolean z, String str) {
if (!z) {
m19517a(str);
}
}
/* renamed from: b */
public static void m19519b(boolean z, String str) {
if (z) {
m19517a(str);
}
}
}
- Проверяется наличие com.amazon.venezia, этот package относится к приложению Amazon App Store
- После этих процедур, запускается родной активити приложения
Отвязка приложения
Как вы уже догадались, все очень просто и элементарно - все эти проверки начинаются с активити Kiwi, и мы видели в начале, что вызов этого активити внедряется в каждый активити приложения. Напомню ,выглядит примерно вот так
Код:
public void onCreate(Bundle bundle) {
Kiwi.onCreate((Activity) this, true);
...
super.onCreate(bundle);
...
}
Автор @Thatskriptkid
источник https://github.com/thatskriptkid