Android log in release

Logcat

В Android SDK входит набор инструментов, предназначенных для отладки. Самый важный инструмент при отладке — это LogCat (очень красивое название, которое можно перевести как Логичный Кот). Он отображает сообщения логов (журнал логов), рассылаемые при помощи различных методов.

Рассмотрим на примере. Очень часто программисту нужно вывести куда-то промежуточные результаты, чтобы понять, почему программа не работает. Особо хитрые временно размещают на экране текстовую метку и выводят туда сообщение при помощи метода textView.setText(«Здесь был Васька»). Но есть способ лучше. В Android есть специальный класс android.util.Log для подобных случаев.

Класс android.util.Log позволяет разбивать сообщения по категориям в зависимости от важности. Для разбивки по категориям используются специальные методы, которые легко запомнить по первым буквам, указывающие на категорию:

  • Log.e() — ошибки (error)
  • Log.w() — предупреждения (warning)
  • Log.i() — информация (info)
  • Log.d() — отладка (degub)
  • Log.v() — подробности (verbose)
  • Log.wtf() — очень серьёзная ошибка! (What a Terrible Failure!, работает начиная с Android 2.2)
  • Log.meow() — когда жрать дадут? (MEOW!) Недокументированный метод, используйте на свой страх и риск. Работает не на всех устройствах

В первом параметре метода используется строка, называемая тегом. Обычно принято объявлять глобальную статическую строковую переменную TAG в начале кода:

Некоторые в сложных проектах используют следующий вариант, чтобы понимать, в каком классе происходит вызов:

Далее уже в любом месте вашей программы вы вызываете нужный метод журналирования с этим тегом:

Также используется в исключениях:

Пользователи не видят этот журнал. Но, вы, как разработчик, можете увидеть его через программу LogCat, доступный в Android Studio.

Полный вид сообщения выглядит следующим образом.

03-09 20:44:14.460 3851-3879 / ru.alexanderklimov.cat I/OpenGLRenderer : Initialized EGL, version 1.4

  • 03-09 20:44:14.460 Date/Time
  • 3851-3879 Process & Thread IDs
  • ru.alexanderklimov.cat Package name
  • I/OpenGLRenderer Tag
  • Initialized EGL, version 1.4 Message

Подобные длинные сообщения не всегда удобны для чтения. Вы можете убрать ненужные элементы. Для этого выберите значок LogCat Header в виде шестерёнки и уберите флажки у опций.

В LogCat вы можете отфильтровать сообщение по заданному типу, чтобы видеть на экране только свои сообщения. Для этого выберите нужный тип тега из выпадающего списка Verbose.

Типы сообщений можно раскрасить разными цветами через настройки File | Settings | Editor | Colors Scheme | Android Logcat.

Для отслеживания сообщений с заданным текстом введите в поле поиска нужную строку и нажмите Enter.

Также активно используйте варианты из других выпадающих списков. Например, выбирайте свой пакет из второй колонки, а в последней выбирайте Show only selected application. Для более точной настройки используйте Edit Fiter Configuration.

По умолчанию, окно LogCat выводится в нижней части студии. При желании, можно выбрать другие варианты через значок настроек окна.

LogCat также можно запустить из командной строки:

Параметры командной строки смотрите в документации.

Быстрое отключение журналирования

Настоятельно рекомендуется удалять все вызовы LogCat в готовых приложениях. Если проект очень большой и вызовы журналирования разбросаны по всем местам кода, то ручное удаление (или комментирование) становится утомительным занятием. Многие разработчики используют следующую хитрость — создают обёртку вокруг вызова методов LogCat.

Теперь остаётся только присвоить нужное значение переменной isDebug перед созданием готового apk-файла для распространения.

Способ устарел. В 17-й версии Android Build Tools появился класс BuildConfig, содержащий статическое поле DEBUG. Можно проверить следующим образом:

Способ для продвинутых — например, требуется релиз с выводом в лог, или наоборот — debug с выключенным выводом. В этом случае можно создать собственный параметр и добавить его в секцию buildType gradle-файла:

В этом случае конфигурация releaseWithLog будет являться релизной сборкой с ведением логов. Естественно, в коде слегка поменяется проверка:

LogCat на устройстве

Попался в сети пример для просмотра сообщений LogCat на устройстве. С примером не разбирался, оставлю здесь на память.

Источник

Better Logging In Android Using Timber

While developing android applications we as developers tend to put in a lot of logs with in different different priorities for this sake android sdk comes in with a utility class Log, which does have utility methods to log our messages with different priorities the most common methods that we use for different cases like we uses Log.e(TAG,”message”) in the cases we want to show some error (this usually appears in red color in the logcat window of android studio), or Log.d(TAG, «message») when we want to print some message for the purpose of debugging, like value of some data.

Usually when the application development is completed and its the time to release the app on the play store, we need to remove all Log statement from the app, so that none of the application data such as user information, hidden application data, auth-tokens are available to user in logcat as plain text and this becomes a cumbersome task

There are several ways to tackle this problem

1. Condition based logging

In this we can make a public static boolean variable in Application class like in the below code snippet.

Читайте также:  Cooking with pinkie pie андроид

and use this variables value as check for logging like the code snippet below

and use this boolean variable at every place where you want to put a log message, and once you are ready to release the app, just set isDebug = false in the application class, but this approach puts in an extra line of code, which is completely unnecessary and can be avoided.

This simply can be achieved using android’s in built build configuration, BuildConfig. DEBUG can be used instead of that boolean variable for checking if the build type is release or debug.

2. ProGuard

This approach is all also a solution to this problem, you can render the Log class ineffective and can remove those statement in the release build by putting in

into the proguard rules file.

Here comes Timber, the best solution to tackle this problem

What if I tell you there exists a simple library called “Timber” which can log your messages and gives you the control over the flow of logs. Timber is a yet another cool library developed by an awesome developer Jake Wharton.

Adding timber to you project

To add timber to your android studio project, just paste in the below line in to /app/build.gradle file and sync the project.

Once the project is synced just plant a timber debug tree in the Application class, because as per the instruction on Timber’s github page and I quote it

Installation of Tree should be done as early as possible. The onCreate of your application is the most logical choice.

Here, Timber.DebugTree() prints the logs when your application type is debug application.

And that’s all we need to do in order to use timber. Wherever you have used that Log…(…) statement just remove that tag parameter and replace Log with Timber.

as you can see in the above gist, that it is not required to pass in the tag parameter in the Timber.d(. ) or Timber.e(. ) statement, as Timber automatically detects the class in which logs were written.

But there might me requirement when you need to specify a custom tag which can be simply achieved by

as shown in the above gist. More about Timber can be found at :

Источник

How to enable logging on any released Android app

Disclaimer: This article was written solely for entertainment and educational purposes. Do not attempt to reverse engineer and inject code into apps to which you don’t have the rights. Everything that I have described here you do at your own risk.

Welcome to a series of Spy security articles where we’ll learn how to hack an APK and modify it for educational purposes.

Today we’ll look at how to eavesdrop and spy on your competitors, enemies, ex-colleagues or anyone else in order to obtain their trade secrets, classified algorithms, funny puns and do a lot of other crazy things.

In this article we’ll discuss how we can enable logging on any kind of obfuscated release APK.

Note : we’ll be looking at logging with Timber library. The same approach can be used for other logging libraries with minor changes.

Long story short

In order to enable logging we need to decompile the APK, then replace the specific code which is responsible for turning off logs and compile it back.

If you’re not really a hacker and don’t want to decompile different apps for any educational reason whatsoever, I would still recommend that you read this article as it will highlight a lot of interesting things about your app as well!

Part 1: Theory

First, let’s start with some theory

  • Why can’t I read logs right from the start?

Actually you can! But there aren’t so many apps like that. Usually anyone who calls himself an Android developer should disable logging before releasing the application. So usually logs are disabled.

  • How is the release build created and how does it differ from the debug build?

The difference is that the release build doesn’t have features which you need for debugging — like logs or Developer options. It is also obfuscated and optimised with all unreachable code removed and the majority of the code fields replaced with some unreadable names — like a , b , a1 , b1 and so on. Sometimes some classes can also be moved into different packages and split into different parts. And, of course, release build is signed with a developer release certificate.

  • Are there different ways to obfuscate your code?

Normally, there are three ways:

  1. By using Proguard or R8— the most popular method. It’s free and obfuscation is quite good. However, as we’ll prove in this article, it’s very easy to understand and to find useful information.
  2. By using Dexguard — the paid version of Proguard. The difference is that it doesn’t only obfuscate classes and fields, it also flattens the structure by moving all classes into one package, encodes constants and uses a lot of other powerful features. You can find more information about Dexguard here.
  3. By obfuscating your code right from the start — by using a , b variables, fun1 , fun2 methods, keeping all of your classes in one package etc. Oh, this is the hardest case. No solution for that code, it is irreversible.
Читайте также:  Виртуальная линейка для андроид

In this article we’ll talk about Proguard or R8 obfuscation. Dexguard is quite hard to get and requires some advanced skills. If you still haven’t got what obfuscation is, I recommend you read this article.

Ok, enough theory, let’s HACK! But first, we need to understand what we have to do.

Part 2: How to enable logs

To understand how logging can be enabled, we need to think about how it’s disabled first.

As a developer you might think — that’s easy, we just have to use Build.DEBUG flag and either turn logs on or off. The key words here is TURN them OFF or ON. If it’s turned OFF, it can be turned back ON, right?

Let’s have a look at the most popular library for logging — Timber. This is how we enable/disable logging in it:

And this is how we use it for logging:

What we’re doing here is just planting different trees for debug / release, but we DON’T remove logs from the release build! They are still there! We just plant different trees and through those trees we send our logs to the Firebase or your own logging system. Otherwise, how do you think you’re able to get crash reports? Moreover, you get them in normal, not-obfuscated view. But it is a completely different story.

OK, so what does it have to do with our task?

This is exactly the thing which we need to look at! We need to replace the release CrashReportingTree with our own custom tree, which will just print all the logs into console!

Our algorithm will look like this:

  1. Locate the part which is responsible for setting TimberTree
  2. Create a mocked Tree
  3. Replace the release tree with our mocked tree.

Ok, let’s HACK! But first, we need to understand what we need to replace and how.

Part 3: Decompiling

I have prepared a simple project especially for this tutorial, which we’ll use for our experiment. All it does is create an activity with a fragment, which posts simple information into logs.

I would really love to show you the real application, but due to different terms and legal agreements which exist (I think) I cannot do that (I think). In my opinion it’s also much easier to understand everything with a smaller example.

For disabling logs we’ll use Timber library, and we will have a custom tree for release logs.

We’ll plant different Timber trees inside onCreate method of our MyApplication , as it’s done in most projects in one way or another.

DebugTree is a standard Timber tree for debugging, CrashReportingTree is our mock tree for Release build

What we’ll be doing inside MainFragment is showing a simple message “MainFragment created” .

The full Dummy project you can find HERE.

We’ll create a release build, which will be optimised, obfuscated and signed. After that we’ll decompile it and compare it. I won’t go into the details of how to create the release build, just assume that it is release-ready and that it has just come from Google Play.

Fortunately for us hackers (and unfortunately for us developers) we can decompile the APK by simply dropping it into Android Studio.

After dropping it what we can see there is:

Let’s just go briefly through the contents of our decompiled APK . We have .dex files ( in this example it’s one file, but there can be as many as you can imagine (around 65k)), resources and AndroidManifest — all the rest is not important.

What we’ll be looking at is classes.dex and AndroidManifest .

As we can see inside classes.dex , some packages are obfuscated — they are called a , b , c , d , etc. Do not doubt that everything inside is obfuscated as well. Huh, it’s really hard to find something inside this mess. However, there are some classes which will never be obfuscated — the entry points of our app!

Classes like Application , Activities , Services , BroadcastReceivers , ContentProviders should not be obfuscated. Otherwise Android will not know anything about them.

Fragments on the other hand, will be, because they’re not used by Android OS. Let’s find these classes. I think I know exactly where they are! Of course in AndroidManifest !

Seems like it was not obfuscated at all! And we also found the entries to our app — MyApplication and MainActivity .

Let’s open MyApplication class. What we see inside is:

HINT : to open decompiled class — right click on the class → show byteCode

Oh, wait, its not Java! Yes, you’re right, it’s Smali. If you don’t know what Smali is and how to read it, you can find more information HERE.

As you can see, our onCreate method is still there, but it looks really different. By comparing this code to Java, we can guess that b/b/a/a and d/a/a are what we need to check.

Читайте также:  Роббо скретч 3 для андроида

HINT : To have this code close at hand it’s better to copy it somewhere. You can either use any kind of editor, or Android Studio scratch files , which I recently discovered thanks to this tweet by Lara Martin .

This is what we find there:

I haven’t listed the full decompiled classes here because it is not important and takes up a lot of space. I have put the most important parts for us.

Looks like this is our release Tree! “Log was secured” — this is exactly the same message which we used inside our release tree. Looks like a() method is log() method of Timber.Tree .

Interesting discovery: LogNotTimber annotation has not been removed — for some reason it is still there, even in optimised code.

OK, next let’s check d/a/a

“Cannot plant Timber into itself.” — looks exactly the same as the string which is used inside the Timber.plant method !

Seems that d/a/a is our Timber class.

Ok, let’s sum up what we have discovered from this decompiling —

  • com/lolkek/secure/MyApplication.onCreate — place where Timber tree is set
  • b.b.a.a — class which we need to replace
  • d.a.a — obfuscated Timber class.

Now we have to think about how we can enable logging. We have two options:

  1. We create a custom Timber tree, and replace or add it into MyApplication.onCreate where we’ll set our tree into d.a.a (Timber) class
  2. We rewrite release timber tree ( b.b.a.a ) with our custom implementation, and that’s it.

We’re going to apply the second option.

OK, finally, let’s HACK!

Part 4: Hacking

For modifying the APK we are going to use DexPatcher tool.

Dexpatcher tool has a lot of very useful examples. We’ll take one of them and modify it for our needs.

You can find the complete source of this project HERE.

This is what we’ll do:

  1. Put our release APK into app/apk folder
  2. Create MyApplication class (name should be the same as in hackable APK) and put it into the same package — com.lolkek.secure
  3. Create a.java class ( yes, class with a name a ) and put it in the same package as the original one

This is how a.java looks like :

Notice that we’re not using Kotlin. Can you guess why? OK, I’ll give you a hint.This is what a decompiled bytecode from Kotlin class (exactly the same as a.java ) looks like:

Suddenly, the name of the method a was converted into a$app . In a slightly different example it had a name a$debug . But it has to be exactly a ! I have no idea why it happens. If someone knows why, please write it in the comments. Probably some annotations could help, but I didn’t want to deal with it.

In MyApplication we’ll just add a log message which will show that this app has been definitely hacked

It’s not really necessary to override this class. I just wanted to show you a couple of additional features.

OK, we’re ready to go. Compile and start — this is what we see in the logs. Mission completed!

Conclusion

In this simple example we have proved that ̶h̶a̶c̶k̶i̶n̶g̶ modifying app code is easy. We have become familiar with obfuscated code, how to read it and find a lot of useful information in it.

We have discovered that logs, even when they are turned off by developers, can easily be turned back on. As well we have also played with a tool with which we can easily modify the necessary code.

Notice that we have only looked at the example where Timber was used as a logging wrapper. In certain cases custom logging wrappers can be used. In general these solutions are more secure because it’s much harder to find the necessary information in the obfuscated code, also still possible.

  • If you want to decompile any type of APK I would not recommend that you download it from different web sites. Who knows what code has been injected into these APKs (as you now know it’s really easy to do). It’s better and easier to use GooglePlay and then adb for downloading this APK onto your computer as shown here.
  • During decompiling of different APKs you can come across a lot of different issues. Almost all of them are covered in different Dexpatcher examples, but if you still experience problems you can ask for help on xPDA Forum.
  • With the introduction of app-bundles, apps can be split into different APKs. As a result, different code can be located in different files. You should not only find the APK where you want to replace some code, but you should also sign other APKs with the same certificate.

Thanks to Lanchon for creating and supporting DexPatcher tool which really simplified decompiling and modifying APK sources.

Feel free to ask any questions in the comments below or on Twitter!

Please Clap 👏 50 times if you have really enjoyed reading this article. More claps — more motivation I have to write other interesting stuff about Android.

Источник

Оцените статью