【Android】難読化した結果、アプリが上手く動作しなくなった話

対象読者は?

  • Androidアプリ開発者

何が書かれている?

  • 難読化を実装した際の注意点

経緯:バグ調査

新規案件で、すでにAndoidアプリは別の会社が作成済み。
こちらで追加修正して、apkファイルをビルドして渡す。

で、、渡した結果。

修正したところとは全く別のところが動作してない
調査して欲しい

とのこと。

問題点:ビルドタイプの違い&難読化が影響

了解!ってことで、自分でビルドして動作確認すると動く

あれ??なんで???ビルドタイプの違い??

自分がビルドしたのは、デバックビルド。
お客さんに渡したのは、リリースビルド。

いやいや、まさかー。

う、、動かない。。。
スタックトレースを確認すると、、、NULLで落ちてる!?

しかも、中身がaとかbとかよくわからんことになってる??

よくよく調べてみると、リリースビルド時のみ難読化などを行っていましたorz

難読化

難読化の目的は大きく2つあります。

  1. クラス名、メソッド名などをaとかbとかに置き換えて、リバースエンジニアリングを防ぐ
  2. クラス名、メソッド名を短くすることでアプリ自体のサイズを小さくする

解決方法:keepルールの追加

Androidの公式ページを参照すると、難読化する時に注意しないといけないポイントがあるみたいです

注意するべきポイント

難読化によりコードのさまざまな部分の名前が変更されるので、スタック トレースの検査などの特定のタスクで追加のツールが必要になります。

アプリのメソッドやクラスに予測可能な命名規則を使用している場合(リフレクションを使用している場合など)、それらのシグネチャをエントリ ポイントとして扱い、保持するコードのカスタマイズ方法で説明したように keep ルールを指定する必要があります

簡単に要約すると

  • スタックトレースなどで処理を追う場合は、追加ツール使って見てね
  • 予測可能な命名規則を使っている場合は、keepルールを使用してね

参考:アプリの圧縮、難読化、最適化

1つ目はわかりやすいですね。

スタックトレースで処理を追っていた時に、aとかbとか出ていたのは難読化が原因だったようです。

2つ目。今回の原因がこれでした。

予測可能な命名規則を使っている場合(リフレションなど)

「リフレクション」というのが、クラス名・メソッド名・変数名などを文字列として指定して動的に実行するための仕組みです。

メソッド名などを文字列で判定して実行するので、難読化しちゃうとそこでの判定ができなくなってしまう。文字列までは一緒に難読化してくれないですからね。。。

例)リフレクションでtest()メソッドを使うよう文字列指定→test()メソッド自体が難読化されて名称変わるので使えない。。

で、今回の問題ですが、、、リフレクション使ってましたorz

クラス自体をkeepするように変更。
追加したことで、このクラス自体が難読化されないようにすることで解決としました。

(Android 9からリフレクションを使用すること自体に制限かかってますから、リフレクション自体は使わない方が良さそうみたいですね。。)

まとめ

  • リフレクションは使用しない
  • 難読化するときは、難読化した影響も考慮する
  • テストするときは、難読化した状態で!!

本来であれば、リフレクションを使わないようにして一緒に難読化してあげるのがベストなのでしょうが、、、そこまでする時間はありませんでした。。

難読化は今までしたことなかったので勉強になりました。

ただ、書いてて思ったのがテスト

デバックビルドでテストしたらこの難読化問題は気づけないし、自動テストで書いてた場合ってどうなるんだろ。。。これも検知が難しいような気がしてなりません。

、、、ってことは、リリースビルドかつ実機でのテストが必須?

ふ、、不便。。orz

この辺知見ある方いましたらそっと教えてもらえると幸いですm(_ _)m

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です