見出し画像

【オープンソース?】某フィルムアプリを解析してみた備忘録。【Android Studio】

※本記事はあくまで技術的な探求と個人利用の範囲での備忘録であり、不正利用や著作権侵害を推奨するものではありません。

どうも。しばもんです。
X(旧ツイッター) @monsivamon

はじめに

まず最初に明言しておきたい。
私は普段からSEやアプリ開発の現場でコードを書いているプロではない、ただの休日の趣味プログラマーである。
そのため、本記事の技術的な考察や解析内容には誤解や間違いが含まれているかもしれない点はあらかじめご了承いただきたい。

解析のきっかけ

最近、個人的にウォッチしていた某オープンソースのフィルムシミュレーションアプリが、v1.1(記憶曖昧だが)へのアップデートに伴い新たに「Pro版(課金機能)」を実装してきた。

最初は「へえ、面白いの作ったね」くらいにしか思っておらず、特に深く追うつもりもなかった。しかし、GitHubでソースコードが公開されているのを見て、「これ、自分で手元でビルドすればPro版の制限を解除できるのでは?」と軽い気持ちでコンパイルを試みた。

しかし、ビルドに至るまでいくつもの壁があり、結果的にアプリの構造を丸裸にする解析作業が必要になってしまった。本記事は、そのアプリの裏側を覗き見た個人的な備忘録である。

解説

1:オープンソース?

結論から言うと、公開されているソースコードは「全て」ではない
事の発端は、最新のソースコードをローカルのAndroid Studioに落とし込み、ビルドを走らせたことだ。

本来、ソースコードがフルで公開されていれば、そのままコンパイルして動かせるはず。しかし、何度やってもエラーで弾かれる。
原因を調べていくと、GitHubにプッシュされているソースコードは、意図的に一部のファイルが欠落させられていたことに気がついた。

Githubには`.gitignore` というプッシュしないファイルを開発者自ら指定することができるファイルが存在するのだが、これを確認すると、開発者は意図的に特定のソースコードやアセットをGitの管理から外し、手元でビルドしてもクラッシュする状態を作っていたのだと思われる。

具体的に何が欠落しているかは明言を避けるが、例えばある機能の根幹となる定義ファイルがどこにも存在しない。140回以上もコード内で呼び出されているのに、大元のファイルだけが消えている。
結局、欠落していたファイルの構造をエラーログと使用箇所から推測し、自分でファイルを自作し補うことで私はビルドを通すことに成功した。

2:LUTデータとウォーターマークの隠蔽

コンパイルは通ったものの、今度は機能に必要なデータ群が見当たらない。
実は、フィルムシミュレーションの要となる「LUTデータ」や、各スマホメーカーの「ウォーターマーク」などは、Git上ではなくAPK本体の中に直接パックされている。

最終的に、コンパイルを通すために本家のAPKをデコンパイルし、必要だと思われるファイル群を自分のプロジェクトに移植したところ、ようやく機能として動かすことができた。

3:課金システム(Pro版)の仕組み

一番の難所であり、解析していて面白かったのがPro版のアンロックだ。
ソースを追うと、Firebase Firestoreと通信し、特定のコレクション内に自分のメールアドレスが存在するかどうかで権限を判定していた。さらに、改造アプリを弾くための環境チェックまで丁寧に仕込まれていた。

Pro版制限の突破
結論から言うと、このPro版制限の突破自体はそこまで難しくなかった。クライアント(アプリ)側に判定ロジックが委ねられていた為、そこをうまく突けばあっさりとフル機能は解放される。
ただ、ここでその具体的なコードの書き換え箇所を公開してしまうのは、作者のビジネス(収益源)に対するリスペクトに欠けるため、明言は避けることとする。

個人的な懸念
技術的な視点で見れば、Firebaseの認証機能とFirestoreを組み合わせて、個人開発レベルで強固なサブスク管理を構築しているのは「よく考えられている」と素直に感心した。
しかし、いちユーザーの視点に立つと、「得体の知れない個人開発者に対して、自分のプライマリなGoogleアカウント情報(メールアドレス)を直接差し出して紐付ける」という構成には、なんとも言えない薄気味悪さと抵抗感を覚えてしまったのも事実だ。

4:メーカーの著作物では?

アプリの挙動を見ていても明らかではあるが、apkの中にはフィルムシミュレーションの要となる「LUTデータ」や、各スマホメーカーの「ウォーターマーク」が入っている。

おそらく作者がGitから意図的に外した最大の理由は、メーカー著作物(ROMから抽出)を改変したものをオープンソースのリポジトリに置くと、権利侵害で一発BANされるリスクがあるからだろう。

個人で楽しむ分には「まぁいいか」で済むかもしれないが、これをそのまま公開するのはかなり黒に近いグレーだと個人的には感じた。

5:解析を通して学んだ教訓

今回の一件を通して、大きく3つの教訓を得た。

1つ目は、オープンソースプロジェクトの難しさである。
特に、第三者の著作物が混入している現状を見ると、私自身「これ、何かしらのライセンス違反に抵触しているのではないか?」という強い懸念を抱いている。また、公開と秘匿のバランスを間違えれば、リポジトリごと消し飛ぶリスクを孕んでいるのではないかと思われる。

2つ目は、ローカル(クライアント)側のアプリに課金判定の機能を持たせることの構造的なリスクだ。
どれだけコードを複雑化、難読化させ、環境チェックを入れたとしても、実行環境そのものを握っているユーザーには最終的にロジックを上書きされ、突破されてしまうという有料機能をもつアプリ開発の難しさを痛感した。

そして3つ目は、ReVancedや各種MODアプリが、どのように元のアプリを書き換えているのか、その根本的な仕組みを肌で学べたことだ。
これまでブラックボックスに感じていた彼らのパッチ処理やロジック改変の手法が、今回自らの手で解析したことで完全に腑に落ちた。

興味ある方向け

私の記事を読みもし興味がでた方がいらっしゃれば、私のリポジトリをベースに実際にビルドしてみると理解することができるだろう。

ただし、私のリポジトリもそのままではビルドが通らない(README内でも言及しているが)ので、私と同様にエラーログとにらめっこしながらビルドを通す試行錯誤は必要となる点はご了承いただきたい。

超特大ヒントとして、私の環境でビルドに成功した環境のスクリーンショットを一部載せておく。

画像
ビルド環境

作者様へ

記事内で色々と裏側を暴き、権利関係について厳しいことも書いてしまったが、個人でここまでのカメラアプリとライセンス管理の仕組みを作り上げた技術力と情熱には、素直に深い敬意を表したい。
今後もいちユーザーとして密かに楽しみにしている。

【番外編】いたちごっこ?

実は私はv1.1.2の頃からこのアプリの解析とフォークを行っていたのだが、どうやら作者は私のフォークリポジトリの動向を注視していたようだ。
というのもアップデートのたびに、私が突破口に使った認証クラス周りの構造が巧妙に書き換えられ、直近のVerでは環境チェックまで追加された。
毎回微妙にPro認証ロジックを変えてくるせいで、最新版をマージしてビルドを通すだけでも一苦労だった。

最後に

この備忘録を通じて、読者のITリテラシー向上に少しでも役立つことを祈っている。

ではまた。ちゃーお。

いいなと思ったら応援しよう!

コメント

コメントするには、 ログイン または 会員登録 をお願いします。
【オープンソース?】某フィルムアプリを解析してみた備忘録。【Android Studio】|しばもん
word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word

mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1