Comments 35
Приятно видеть людей которые безвозмездно делают мир чуточку лучше.
Надо было баг-репорт отправлять прям на dmitriyap.dyndns.org, разработчики немного бы удивились :)
В момент исследования dmitriyap.dyndns.org был в глухом офлайне :) Да и моей целью было не показать разработчикам Яндекс.Денег какой я типа крутой хакер, а помочь сделать их продукт чуть лучше. Вроде получилось :)
Награду то пообещали?)
Если Вы о конкурсе «Охота за ошибками», то Яндекс.Деньги в нем не участвуют (странно, да?). Так что нет, награды мне не будет. Ну да мне и плевать если честно )
Вас не попытались захантить? :)
Я не очень понимаю, любой нормальный компилятор отбрасывает неиспользуемый код, попутно выводя warning. Чей косяк, Android SDK, JDK?
Или этот метод всё же где-то вызывается...? Поэтому в версии 1.80 весь код и обсфуцировали. (Пробую найти теорию заговора ))
Думаю этот код не был отброшен из-за (пишу псевдокодом, так короче и понятнее, кому интересно — сам посмотрит как это выглядит в Smali):
Обратите внимание на метод
Если класс получен успешно (см. дальше условия
Но есть одно «но»! Если посмотреть на метод
Поэтому класс никогда не будет получен, а следовательно activity не стартует и метод
Я не стал включать все эти исследования в статью — решил ограничится общей фразой про то что мол тщательное исследование кода приложения заставляет думать что ля-ля-ля…
public class CoreApplication implements LocationListener {
// ...неинтересный код был тут
public static CoreApplication getCoreApplication() {
if (coreApplication == null)
throw new RuntimeException("here CoreApplication must exists!");
return coreApplication;
}
private static void onNativeCrashed() {
Class localClass = getCoreApplication().params.getCrashHandlerClass();
if ((localClass != null) && (!getAppBuildIdFromNative().contains("master_market"))) {
new RuntimeException("crashed here (native trace should follow after the Java trace)");
new StringBuilder("App name is ").append(getAppNameFromNative());
new StringBuilder("Build ID is ").append(getAppBuildIdFromNative());
if (getAppBuildIdFromNative().length() > 32)
applicationContext.startActivity(new Intent(applicationContext, localClass).setFlags(268435456));
}
// ...неинтересный код был тут
}
Обратите внимание на метод
onNativeCrashed()
. Он вызывается при краше native библиотеки которая работает с Яндекс.Картами. Метод получает класс, унаследованный от CrashHandler (в котором и как раз и живет тот самый безобразный метод sendBug(String paramString)
) путём вызоваClass localClass = getCoreApplication().params.getCrashHandlerClass();
Если класс получен успешно (см. дальше условия
if ((localClass != null)...
) и если native-библиотека которая отвечает за взаимодействие с Яндекс.Картами вернула правильный пароль :) — стартует activity, из которой потом можно будет вызвать этот самый гадкий sendBug(String paramString)
.Но есть одно «но»! Если посмотреть на метод
getCrashHandlerClass()
, то мы увидим что он всегда возвращает null:public class MapsCoreApplicationParams extends CoreApplicationParams
{
// ...ля-ля-ля, не важно
public Class getCrashHandlerClass()
{
return null;
}
// ...ля-ля-ля, тоже не важно
}
Поэтому класс никогда не будет получен, а следовательно activity не стартует и метод
sendBug(String paramString)
никогда не будет вызван. Как видите, тут все запутано как бразильском сериале :) Думаю поэтому компилятор не смог до конца вкурить все эти связи и стремный код на всякий случай оставил.Я не стал включать все эти исследования в статью — решил ограничится общей фразой про то что мол тщательное исследование кода приложения заставляет думать что ля-ля-ля…
Возможно, нормальный компилятор так и делает, если это сильно связанный код, но писать такой код сейчас не принято.
А принимать решение за разработчика, и выкидывать public и protected методы нормальный компилятор не должен.
А принимать решение за разработчика, и выкидывать public и protected методы нормальный компилятор не должен.
Компилятор в принципе не может определить, вызывается ли метод. По причине Reflection например в случае Явы. Неиспользуемый код убирается только в пределах одного метода (и то бывает чревато).
Хм, а в SDK нет штатного механизма отправки багрепортов? Мне кажется довольно логичным иметь возможность получить из системных логов все записи своего приложения за предыдущие N минут, и как-то через гугель закинуть их разработчику приложив к traceback'у с места падения.
Небольшой поиск в Google дает — а поиск Яндекс не дает?))
Вроде бы тоже даёт (ну по крайней мере нужный твиттер в первой десятке). Но с Google у меня как-то лучше любовь складывается, поэтому пользуюсь в основном им :)
Извиняюсь, проглядел абзац, мне показалось, что вы работаете в Яндексе. Троллинг не получился.
«Пароль „Рыба-меч“»? :)
Да, он. Помнится, там ещё во время взлома какая-то девушка хакеру делала мине… ну в общем отвлекала хакера от процесса :)
UFO just landed and posted this here
А та девушка видимо была HR-менеджер :)
В «Социальной сети», помнится, конкурс для программистов включал работу после выпивания спиртного.
Осталось объединить идеи :)
Осталось объединить идеи :)
Так вот для чего каждое второе приложение из гуглплея хочет смотреть логкат. Правда я такие приложения все равно не ставлю.
Ну в logcat логе только системный лог (например такая-то activity стартовала, такой-то процесс завершился и т.п.) и то что приложения сами пишут туда с помощью методов из
android.util.Log
. По идее приложение не должно писать в лог никакой конфиденциальной информации, но на практике разработчики часто используют методы из android.util.Log
в процессе разработки с целью отладки, а потом забывают убрать вызовы этих методов из релиза. Я подозреваю что с Яндекс.Деньгами 1.71 так и получилось. В версии 1.80 это пофиксили.Sign up to leave a comment.
Как мирный reverse engineering помог чуть-чуть улучшить приложение Яндекс.Деньги