※当ブログではアフィリエイト広告を利用しています。
通常iOSではファイルシステムが閲覧できないため、iPhone・iPadのアプリは内部構造がわかりにくく安全性が高いです。
しかし特殊なツールを使うと、アプリの作りによってはデータの改ざんや、ゲームにおけるチートができてしまうケースがあります。最近でもそれができてしまうアプリがたまにあるため、大切なアプリ・サービスを守るためにデータ書き換えの初歩的な手法と防衛の考え方についてメモします。
概要
本エントリではアプリ内のデータ参照・書き換えについて以下の流れで記載しています。あくまで初歩的な手法についてであり、脱獄が必要な手法には触れていません。
- iOSのファイルシステムと主なデータ保存の方法
- ユーザがアプリ内データを書き換えできると何がまずいか
- 未脱獄でのアプリ内部のデータ参照
- 初歩的なアプリ内部のデータ書き換え方法
- アプリのデータ改ざんを防ぐために
iOSのファイルシステムと主なデータ保存の方法
iOSではアプリを終了すると保存していないデータは消えてしまいます。ゲームのセーブデータや設定などが消えてしまっては困るため、データを永続的に保存しておく必要があります。その中でもデータを保存できる領域は決まっています。
iOSのファイルシステム
iOSではアプリごとにサンドボックスと呼ばれる専用の領域が与えられます。以下がそのイメージ図です。
一般的に各アプリがデータを書き込めるディレクトリはサンドボックス内のDocuments
,Library
,tmp
です。ディレクトリごとに書き込むデータの種類は異なりますが、一時的に使用するもの以外はDocuments
,Library
のどちらかが使用されます。
各ディレクトリの利用方法はApple公式ドキュメントのファイルシステム プログラミングガイドから参照できます。
主なデータの保存方法
アプリ内部にデータを永続的に保持しておくためには主に以下のような方法があります。
NSUserDefaultsクラスを使ったデータ保存
最も手軽に使用できるデータ保存方法です。「キー:値」の形式で簡単にデータの保存・取り出しができます。
以下はNSUserDefaults
クラスの使用例です。たとえば金額:100を表す値を保存したい場合は任意のキーGold
に100
を指定します。
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; [userDefaults setInteger:100 forKey:@"Gold"];
値の保存が完了すると下記のパスにプロパティリスト(*.plist
)形式のファイルが保存されます。このファイルに実際の値が保存されています。
<Application_Home>/Library/Preferences/
保存されたデータはアプリを終了しても消えないため、次回のアプリ起動時にも値を読み出すことができます。
CoreDataフレームワークを使ったデータ保存
CoreDataと呼ばれるモデルオブジェクトを保存するためのフレームワークを使う方法です。データ保存形式はいくつかありますが、SQLiteのデータベース形式で保存するのが一般的です。
CoreDataの使い方はA Day In The Life様の下記の記事が参考になります。
サルでもわかる Core Data 入門【概念編】
ユーザがアプリ内データを書き換えできると何がまずいか
例えばゲーム等でユーザに変更されては良くない値は以下のようなものです。
ゲーム内通貨の金額
もし変更できてしまうと早くクリアできてしまい、ユーザに長く遊んでもらえなくなるかもしれません。またゲーム内通貨の購入にアプリ内課金が必要な場合、課金しなくてもお金が増やせてしまいます。
時間で回復する行動力(スタミナ)
ソーシャルゲームによくある行動力です。これも変更できてしまうのは開発者の意図に反しています。また、行動力回復にアプリ内課金が必要な場合、課金しなくてもスタミナが回復できてしまいます。
「アプリ内サービスを買った」という情報
機能制限があり課金で制限解除するアプリの場合、「機能制限解除がされている」という情報をアプリ内部に持ってしまっていると、この情報が変更された場合アプリ内課金をしていないにもかかわらず機能制限解除と同じ状態になってしまうかもしれません。
他にもユーザ同士が競うようなゲームの場合は一部のユーザだけが有利になり、他のユーザが離れていく原因にもなり得ます。
未脱獄でのiPhone内部のデータ参照(iOS8.3未満)
脱獄していない状態でのiFunBoxでのアプリ内データ参照はiOS8.3以降不可能になりました。以下はiOS8.3未満でのみ使用可能だった方法です。
iFunBoxというツールを使用すると、未脱獄でも本来見ることのできないiPhone内部のファイルを参照したり書き換えることができます。Windows・MACで使えます。
PC・MACにiPhoneやiPadをUSB接続した状態でiFunBoxを起動すると、左ペインのUser Applicationsにインストールされたアプリが一覧表示されます。
さらにアプリを選択して階層を掘り下げると、その中のファイル一つ一つも閲覧できます。また、ファイルをPC・MACにコピーすることも可能です。
初歩的なPhone内部のデータ書き換え方法
アプリの永続的なデータ保存にNSUserDefaults
やCoreData
が使用されている場合、これらのデータが保存されている場所をiFunBoxで開き、データをPC・MACにコピーし編集した後、元の場所に上書きすることでデータの書き換えが可能です。それぞれの一例を示します。
以下の作業をするとアプリが起動しなくなったりiPhoneが壊れたりするかもしれません。お約束ですがやる場合は自己責任で。
NSUserDefaults(*.plist)の保存データ書き換え
NSUserDefaults
を使用してデータ保存しているアプリの場合、下記のフォルダにプロパティリスト形式(*.plist)のファイルが存在します。
<Application_Home>/Library/Preferences/
プロパティリストの実体はXMLファイルのため、テキストエディタで開くことができます。変更したい箇所の値を書き換えて保存した後、iFunBoxでファイルを元の場所に戻せばデータの書き換えが可能です。
CoreData(SQLite)の保存データ書き換え
CoreData
を使用してデータ保存しているアプリの場合、大体Documents
フォルダのどこかにSQLiteデータベース形式のファイルが存在します。
テキストファイルではないのでテキストエディタでは編集できませんが、sqlite3
コマンドでファイルを開けばSQLのSELECT
でデータの参照、UPDATE
でデータの更新が可能です。
2014/07/24追記
GUIでSQLiteファイルが簡単に編集できるツール「SQLite Database Browser」であればさらに簡単にデータの書き換えが可能です。「SQLite Database Browser」についてはこちらのエントリにダウンロード・インストール方法をまとめています。
アプリのデータ改ざんを防ぐために
上記のとおり、何も対策していないと比較的簡単にアプリ内部に保存したデータは変更できてしまいます。もし大事なデータが書き換えられてしまうと開発者にとって良いことはありません。
書き換えられてはいけない大事なデータは以下の方法で保存するのが良いと思われます。
データを暗号化する
AES等のアルゴリズムを使用してデータを暗号化して書き込み、アプリ内で値が必要な時には復号して使う方法です。データを保存しているファイルの中身を見られても第三者には内容をわからなくすることができます。
Objective-CでのAESを使用した暗号化については下記サイトが参考になります。
iPhone で暗号化
またiOSにはデータを安全に保存するKeychain Servicesという仕組みがあります。暗号化されユーザが参照できない領域にデータを保存できるため、特に安全に保存したいデータを格納するのに適しています。
キーチェーンサービスについてはCocoaの日々様で詳しく解説されています。
[iOS] Keychain Services とは
データをオンラインのサーバー等に保存する
いくらデータを暗号化しておいても、アプリ内部にあれば復号したり全く別の方法で書き換えができてしまうかもしれません。アプリ内部には書き換えられてはいけないデータを保存せず、オンラインのサーバーやクラウドサービスへ保存すればデータを変更されるリスクは大幅に減らすことができます。
自前でサーバーを用意しなくても、クラウドサービスのデータストア機能(ニフティクラウドのモバイルバックエンドサービス等)を使用すればそれほど時間をかけずに実装できます。パズドラ等のソーシャルゲームや、オンラインゲーム等のデータの取り扱いが重要なアプリはほとんどこの方法がとられています。
まとめ
最近では本エントリのような方法でデータの変更ができるアプリは少なくなったと思われます。しかし未だに通用してしまうアプリも少なからず存在します。
サーバーへのデータ保存については費用がかかる場合もあるのでケースバイケースかもしれませんが、時間をかけて構想・作成したアプリを守るために、データの取り扱いには気を付けたいですね。