LoginSignup
0
0

More than 1 year has passed since last update.

Androidで他のアプリの関数をフックしてみた

Last updated at Posted at 2022-02-16

初めに

・初記事になります。拙い文章ですが、暖かい目で見て頂けると幸いです。

用意するもの

・フッキング用ライブラリ
今回はCydia SubstrateのMSHookFunctionを使用させて頂きました。

・普通のAndroid端末

・ApkEditer

#注意
この記事は解説記事ではなく、あくまでやってみたよ~という紹介の記事になります。
ですので、自分なりの解釈と間違っている知識を披露している、説明を省いているなどの場合がありますが、ご了承ください。

方法

対象アプリに攻撃用ライブラリを埋め込んでフックする

①対象アプリを作る

・流石に他の方が作ったアプリをフックする訳には行かないので、今回は自分で対象のアプリを作ります。
zMhEwVCTZ2tF5LW1644887857_1644888039.png
対象アプリのファイル構成はこんな感じです。

MainActivity.java
package xxxxxx.vtable_victim;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Start();//nativeメゾットの呼び出し
    }
    native void Start();//nativeメゾット
}
native-lib.cpp
#include <jni.h>
#include <string>
#include <thread>
#include <pthread.h>
#include <unistd.h>
#include <dlfcn.h>
#define println(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, "VTEST Victim", __VA_ARGS__))

struct Target {
    void TargetHello();
    void Update();
};
void Target::TargetHello()  {
    printB("TargetHello");
}
void Target::Update()  {
    printB("Update");
}
extern "C"
JNIEXPORT void JNICALL
Java_xxxxxx_vtable_1victim_MainActivity_Start(JNIEnv *env, jobject thiz) {

    Target target;
    target.TargetHello();//TargetHello呼び出し

}

javaとcppファイルもこんな感じでセットアップします。

②攻撃用アプリを作る

攻撃用アプリは新しいプロジェクトを作成してcppファイルだけセットアップします。

attack-lib.cpp
#include <jni.h>
#include <string>
#include "Substrate/CydiaSubstrate.h"
#include "android/log.h"
#define println(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, "VTEST Attacker", __VA_ARGS__))

__attribute__((constructor))//System.loadLibraryで読み込まれた時に起動
void OnLoad(){
    void* handle = dlopen("libnative-lib.so",RTLD_LAZY);//ライブラリのハンドル
    MSHookFunction(NULL,NULL,NULL);//↓
}

フック用ライブラリの関数、MSHookFunctionから見ていきます。

void MSHookFunction(void * symbol,void * hook,void ** old);

引用元:http://www.cydiasubstrate.com/api/c/MSHookFunction/

・symbol

The address of code to instrument with replacement code. This is normally, but need not be, a function.

・hook

The address of an ABI-compatible replacement for the code at the address referenced by symbol.

・old

A pointer to a function pointer that will be filled in with a stub which may be used to call the original implementation. This can be NULL if you do not proceed to the original.

それぞれの引数の説明がありました。うーん...なんだこれ...
要約すると

symbolはターゲットの関数のアドレスが入って
hookの所にはターゲットと置き換えたい関数のアドレスが入って
oldの所には置き換えられた元の関数ポインタへのポインタが入る

...のかな?
間違っていたらご指摘お願いいたします。m(__)m

ほんじゃこれに沿って...

attack-lib.cpp
#include <jni.h>
#include <string>
#include "Substrate/CydiaSubstrate.h"
#include "android/log.h"
#define println(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, "VTEST Attacker", __VA_ARGS__))

void (*Target_TargetHello_origin)(void*);//元の関数の関数ポインタ
void Target_TargetHello_hook(void* thiz){//置き換えたい処理
    println("Hook -> Target::TargetHello Called");
}

__attribute__((constructor))//System.loadLibraryで読み込まれた時に起動
void OnLoad(){
    void* handle = dlopen("libnative-lib.so",RTLD_LAZY);
    void* funcaddr = dlsym(handle,"_ZN6Target11TargetHelloEv");//フックする関数のアドレス

    MSHookFunction(funcaddr,(void*)Target_TargetHello_hook,(void**)Target_TargetHello_origin);
    dlclose(handle);
}

こんな感じになりました。
これをlibattack-lib.soにコンパイルします。

③早速フックしてみる

準備が出来たので早速フックしてみようと思います...が。
今回はInjectとか他のアプリからフックするみたいな方法ではなく、
対象アプリに直接埋め込んでフックするという手法を取ります
何故なら、今回使用しているAndroidの端末はroot化していないからです。

さて、対象アプリに埋め込む作業ですが、次の二つの手順を踏んでいきます。

❶コンパイルしたlibattack-lib.soを対象アプリlibフォルダに入れる

❷System.loadLibraryでlibattack-lib.soを読み込ませる

❶は簡単にできますが、❷はjavaをsmailにデコンパイルして、それを編集しなければいけません。

❶からやっていきます。
といっても、簡単な作業ですので、ファイル構成だけ載せていきます。

ファイル構成
============APKの中身=============
assert
res
lib
  ┗armeabi-v7a
        ┣libnative-lib.so
        ┗libattack-lib.so ←移植
AndroidManifest.xml
...
=================================

libattack-lib.soを移植しましたら❷に行きます
❷はsmaliファイルを編集するのですが、少し注意点があります。

・対象ライブラリが読み込まれてからフックする
・対象ライブラリ内でメゾットが読み込まれる前にフックする
・MainActivity.smaliに埋め込み用コードを挿入する

埋め込み用コード
    const-string v0, "attack-lib" 

    invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V

先ほどの注意点を踏まえて編集していきます。

上記埋め込み用コードですが、MainActivity.javaのsetContentViewメゾットの後に挿入します。
MainActivity.javaをsmaliに変換して....

MainActivity.smali
.class public Lxxxxxx/vtable_victim/MainActivity;
.super Landroidx/appcompat/app/AppCompatActivity;
.source "MainActivity.java"


# direct methods
.method static constructor <clinit>()V
    .registers 1

    const-string v0, "native-lib"

    invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V

    return-void
.end method

.method public constructor <init>()V
    .registers 1

    invoke-direct {p0}, Landroidx/appcompat/app/AppCompatActivity;-><init>()V

    return-void
.end method


# virtual methods
.method native Start()V
.end method

.method protected onCreate(Landroid/os/Bundle;)V
    .registers 3

    invoke-super {p0, p1}, Landroidx/appcompat/app/AppCompatActivity;->onCreate(Landroid/os/Bundle;)V

    const v0, 0x7f0b001c

    invoke-virtual {p0, v0}, Lxxxxxx/vtable_victim/MainActivity;->setContentView(I)V

    

    invoke-virtual {p0}, Lxxxxxx/vtable_victim/MainActivity;->Start()V

    return-void
.end method

こ↑こ↓と書かれている部分に挿入します。

MainActivity.smali(挿入後onCreate)
.method protected onCreate(Landroid/os/Bundle;)V
    .registers 3

    invoke-super {p0, p1}, Landroidx/appcompat/app/AppCompatActivity;->onCreate(Landroid/os/Bundle;)V

    const v0, 0x7f0b001c

    invoke-virtual {p0, v0}, Lxxxxxx/vtable_victim/MainActivity;->setContentView(I)V

    const-string v0, "attack-lib" 

    invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V

    invoke-virtual {p0}, Lxxxxxx/vtable_victim/MainActivity;->Start()V

    return-void
.end method

これでOKです。
そしたらApk EditerでApkを組み上げまして....
完成です!

④試運転

それでは起動して動作を確認してみます。
・フック前
スクリーンショット 2022-02-16 114600.png
・フック後スクリーンショット 2022-02-16 114459.png

これでフックが出来ました。おしまい。

ではなく、これには__重大な問題__が残っています。それは....

元の関数が呼び出せてないという問題です。
これでは元々あった処理が呼び出されず、危険です。
というわけで、元の関数を呼び出していきましょう。

⑤元の関数を呼び出してみる

MsHookFunctionの三番目の引数に入っていた謎の関数ポインタ君がカギです。
元の関数の関数ポインタを関数として呼び出すことによって、元の関数を呼び出すことが出来ます。

attack-lib.cpp
#include <jni.h>
#include <string>
#include "Substrate/CydiaSubstrate.h"
#include "android/log.h"
#define println(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, "VTEST Attacker", __VA_ARGS__))

void (*Target_TargetHello_origin)(void*);//元の関数の関数ポインタ
void Target_TargetHello_hook(void* thiz){//置き換えたい処理
    println("Hook -> Target::TargetHello Called");
    Target_TargetHello_origin(thiz);//元の関数を呼び出す
}

__attribute__((constructor))//System.loadLibraryで読み込まれた時に起動
void OnLoad(){
    void* handle = dlopen("libnative-lib.so",RTLD_LAZY);
    void* funcaddr = dlsym(handle,"_ZN6Target11TargetHelloEv");//フックする関数のアドレス

    MSHookFunction(funcaddr,(void*)Target_TargetHello_hook,(void**)Target_TargetHello_origin);
    dlclose(handle);
}

結果スクリーンショット 2022-02-16 122316.png
これで無事に呼び出せました

⑥最後に

まだ試したいことや、もっと幅広くできることもありますので、また時間があれば書きたいと思います。
読みにくい私の記事を読んでいただいてありがとうございました。

それでは~

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0