Twitterに書ききれないこと

イベントや技術的なことを記したい・・・

IsDebuggerPresentに釣られた件

IsDebuggerPresentってデバッグ検知以外にもお目にかかることがあるのねというお話。

デバッグ検知用のAPIとして有名なものにIsDebuggerPresentがある。デバッグされている場合はTrueを返して、デバッグされていない場合はFalseを返す。マルウェア解析・リバースエンジニアニングの書籍には必ずと言ってもいいほど登場するやつですね。

あるマルウェアの解析中に以下のようなコードがあった。

f:id:pinksawtooth:20150805233506p:plain

デバッグ検知用で使われるIsDebuggerPresent以外にもSetUnhandledExceptionFilter・UnhandledExceptionFilterとGetCurrentProcess・TerminateProcessがある。

SetUnhandledExceptionFilter・UnhandledExceptionFilterもアンチデバッグで使用されるAPIで,GetCurrentProcess・TerminateProcessはプロセス終了のために使用するAPIである。

なんとなく怪しい気がする・・・

しかし、このコードではIsDebuggerPresentの結果に関係なくプロセスが終了する。なんだろうこのコードは・・・

ということで調べてみた。

       

どうやらVisual Studioで/GS(バッファーのセキュリティチェック)オプションを指定してコンパイルした際に追加される__security_check_cookieのものらしい。

Visual Studioで/GSオプションを有効にして、___security_check_cookieが呼ばれるプログラムをコンパイルしてみた。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>


int main(void) {

    int n;

    scanf("%d", &n);
    printf("%d", n);

    return 0;

}

アセンブル結果を見ると___security_check_cookieやらが追加されている。

f:id:pinksawtooth:20150806015714p:plain

辿って行くと__raise_securityfailureで類似する処理を発見。

f:id:pinksawtooth:20150806020147p:plain

C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\crt\src\vcruntime\gs_report.cに逆アセンブル結果に対応するコードらしきものがあった。

// __raise_securityfailure() - Raises a security failure and terminates the process.
//
// Invokes the unhandled exception filter using the provided exception pointers and
// then terminates the process.
#if !defined _CRT_APP && (defined _M_IX86 || defined _M_X64)

    __declspec(noreturn) void __cdecl __raise_securityfailure(
        PEXCEPTION_POINTERS const exception_pointers
        )
    {
        #ifdef _VCRT_BUILD
        DebuggerWasPresent = IsDebuggerPresent();
        _CRT_DEBUGGER_HOOK(_CRT_DEBUGGER_GSFAILURE);
        #endif // _VCRT_BUILD

        SetUnhandledExceptionFilter(NULL);
        UnhandledExceptionFilter(exception_pointers);

        #ifdef _VCRT_BUILD
        // If we make it back from Watson, then the user may have asked to debug
        // the app.  If we weren't under a debugger before invoking Watson,
        // re-signal the VS CRT debugger hook, so a newly attached debugger gets
        // a chance to break into the process.
        if (!DebuggerWasPresent)
        {
            _CRT_DEBUGGER_HOOK(_CRT_DEBUGGER_GSFAILURE);
        }
        #endif // _VCRT_BUILD

        TerminateProcess(GetCurrentProcess(), STATUS_SECURITY_CHECK_FAILURE);
    }

マルウェアのコードと若干違うのはVCのバージョンの違いなのかな・・・(よくわからない) ほかの検体で__security_check_cookieに同じコードがあったのでsecurity_check_cookieなのは確か。

  IsDebuggerPresentとか有名どころのAPIがこんなところで使われていたのか・・・というお話でした。