コラム概要
■こんな方におすすめ:
- iOSアプリの動的な解析手法を知りたい
- iOSアプリの動的改ざんに対する脆弱性について知識をつけたい
- 開発/技術担当の方
■難易度:★☆☆
■ポイント:
Frida traceによって、iOSアプリを簡単に動的解析、改ざんできる。
また、悪意あるコードの実行も可能となるため、適切に対策することが重要である。
1.はじめに
前回のコラムでは、Windowsのアプリを動的に改ざんする方法とその対策について解説しました。
本コラムでは、同様の手法でiOSのアプリを動的に改ざんする方法とその対策について解説します。
使用するツールは、前回・前々回のコラムと同じくFridaです。
2.Fridaとは
Frida ( https://frida.re/ ) とはアプリの動的解析ツールです。
今回もfrida-traceを使用します。今回のAPIフックの対象は、iOSアプリです。
frida-trace は、API呼び出しを動的にトレースするツールです。
frida-traceを使用することにより、APIフックを行うことができます。
3.APIフックとは
Android・Windowsといった他のOSと同様に、
iOSにおいてもアプリを開発するためのインターフェースとしてAPIが存在します。
APIフックは、APIが呼び出される際に処理を横取りする仕組みのことです。
APIフックを使用して独自の処理を追加することにより、動的な解析や改ざんが可能となります。
4.アプリに対する動的解析、改ざん例
App StoreのiOSアプリはデバッグ不可能な状態で配布されています。
iOSアプリ用のFridaを使用するためには、対象アプリがデバッグ可能な状態である必要があります。
今回は説明のために自作のiOSアプリ「FridaTarget」を使用します。
ボタンをタップすると、ラベルの文字列が変わるごく単純なアプリです。
動的解析を行うために、FridaTargetをあらかじめ起動しておきます。
このアプリでは、ラベルの文字列を変更する際に
_builtinStringLiteral:utf8CodeUnitCount:isASCIIというAPIが、内部的に使用されています。
早速このAPIをフックしてみましょう。
まずは以下のコマンドを実行し、フックした際に実行するハンドラーファイルを作成します。
% frida-trace -Un FridaTarget -i "*_builtinStringLiteral*"
Instrumenting...
$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC: Loaded handler at "(frida-traceを実行したディレクトリ)/__handlers__/libswiftCore.dylib/_sSS21_builtinStringLiteral17utf_854bf879.js"
この時点で_builtinStringLiteral:utf8CodeUnitCount:isASCIIがフックされ、
呼び出し時にハンドラーファイル(_sSS21_builtinStringLiteral17utf_854bf879.js)が実行されるようになっています。
作成されたハンドラーファイルには、呼び出されたときにAPI名を標準出力する処理が書かれています。
_sSS21_builtinStringLiteral17utf_854bf879.js
{
onEnter(log, args, state) {
log('$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC()');
},
onLeave(log, retval, state) {
}
}
初めに、このコードを書き換えて、ラベルの文字列を改ざんしてみます。
_builtinStringLiteral:utf8CodeUnitCount:isASCIIは、
第一引数で文字列リテラル、第二引数でサイズ、第三引数でASCII文字列フラグを受け取ります。
ハンドラーファイルのonEnter関数では、フックされたAPIのすべての引数がargs変数に渡されているため、
以下のようにしてそれぞれを変更します。
_sSS21_builtinStringLiteral17utf_854bf879.js
{
onEnter(log, args, state) {
if (args[0].readUtf8String() == 'Hello, world!') {
this.newText = Memory.allocUtf8String('API Hooked!');
args[0] = this.newText; //StringLiteral
args[1] = ptr('0xb'); //byteSize
args[2] = ptr('0x1'); //isASCII
}
}
ボタンを押してみると、本来は"Hello, world!"と表示されるべきところが
"API Hooked!"と表示されるようになったのが分かります。
5.アプリに対する動的解析、改ざん例 (応用編)
この仕組みを使用することにより、データの改ざんだけでなく任意のコードを実行することも可能です。
以下のコードはUIAlertControllerクラスなどを使用してアラートを表示する例です。
(参考:https://frida.re/docs/examples/ios/ )
_sSS21_builtinStringLiteral17utf_854bf879.js
{
onEnter(log, args, state) {
if (args[0].readUtf8String() == 'Hello, world!') {
const handler = new ObjC.Block({
retType: 'void',
argTypes: ['object'],
implementation() {
}
});
const UIAlertController = ObjC.classes.UIAlertController;
const UIAlertAction = ObjC.classes.UIAlertAction;
const UIApplication = ObjC.classes.UIApplication;
ObjC.schedule(ObjC.mainQueue, () => {
const alert = UIAlertController.alertControllerWithTitle_message_preferredStyle_('Frida', 'API Hooked!', 1);
const action = UIAlertAction.actionWithTitle_style_handler_('OK', 0, handler);
alert.addAction_(action);
UIApplication.sharedApplication().keyWindow().rootViewController().presentViewController_animated_completion_(alert, true, NULL);
});
}
},
onLeave(log, retval, state) {
}
}
ボタンを押した際にアラートを表示させることができました。
6. 動的解析・動的改ざんの対策
このように、デバッグ可能な状態のiOSアプリについて、Fridaで動的解析や改ざんが行えることがわかりました。
では、どのような対策方法があるのでしょうか。
例として、以下のようなものがあります。
①外部ツールからの介入の阻止
今回のように外部ツールが使用されると容易に解析などが可能となります。
外部ツールからの介入を阻止することが効果的です。
②パッチの阻止
App Storeで配信されているiOSアプリに対してFridaで動的解析や動的改ざんを行うためには、
アプリにパッチを当てる必要があります。
アプリへのパッチを阻止することが効果的です。
③想定外の動作の検知
動的改ざんが行われた場合、アプリは想定の動作を行わない可能性があります。
動作が想定通りかチェックする機能などを取り入れることが効果的です。
このような対策を複数組み合わせることにより、動的解析や改ざんの難易度を上げることができます。
7. 参考
Frida公式サイト:
https://frida.re
当サイトでは、アプリのセキュリティについて詳しくわかる資料をご用意しています。
アプリのセキュリティや対策についてご興味を持たれた方は、
ぜひダウンロードしていただけますと幸いです。
また、弊社では
アプリへの不正な解析・改ざん行為(クラッキング)を防ぐ対策製品
「CrackProof」の開発・販売を行っております。
詳しく話を聞いてみたいと思われた方は、
当サイトからお気軽にお問い合わせください。
お問い合わせはこちら