Snoozy

1.Sleep-inducing; tedious.

int3でデバッガー検出

eagle0wl氏のcrackmeでバイナリ解析を学んでいます。 解析対象内にint3命令でデバッガーを検知するコードを確認しました。興味深い手法のように思いましたので、実際にどういう方法で行われているのか検証してみることにしました。

#include <stdio.h>

using namespace std;

class some_exception
{
    private:
        const char *msg;
    public:
        some_exception(const char *msg) : msg(msg) {}
        const char *what() { return msg; }
};

int main() {
    int isDebug = 1;

    try {
        asm volatile("int3");
    }
    catch (some_exception) {
        isDebug = 0;
    }

    if (isDebug) {
        printf("Debuger detected!\n");
        return 0;
    }

    printf("flag{Conglatulation!}");
    return 0;
}

このような処理だと考えました。 このコードを書くにあたって、まずデバッガーについて次の前提知識が必要でした。 デバッガーでコードをトレース中、デバッガーはint3やint1命令を通過するとき例外処理を基本的にしないというものです。今回のデバッガー検知もこれを利用したものです。

順に見ていきましょう。 tryの中にint3をおくことで、必ず例外が発生するようにしています。例外発生後、catch内でisDebugに0を格納します。if文は非のためprintfは実行されず、flagが表示されプログラムは終了します。 次いでデバッガーを検知する仕組みです。 まず前述したデバッガーの性質により、デバッガーがアタッチ中のプログラムでは例外処理がされません。これにより、isDebugは1のままとなりif文内が実行されます。 以上の方法により、このコードが挿入されたプログラムは自身がデバッガーによってトレースされているかどうかを検知します。

なかなか面白い手法でしたので共有いたしました。 間違いや勘違いなどがありましたら指摘のほどよろしくお願いいたします。