GetLocalTime

この記事をシェア

概要

現在のローカルの日付と時刻を取得するWin32 APIの関数です。取得した日時はSYSTEMTIME構造体に格納されます。

C++

void GetLocalTime(
  [out] LPSYSTEMTIME lpSystemTime
);

マルウェアは以下の理由でこの関数を利用することがあります。
(1) 特定の日時に(または特定の日時以外に)悪性コードを実行する(時限式実行)
(2) コードの実行に掛かる時間を計測し、デバッガー上で実行されていることを検知する
コードの実行に掛かる時間を計測する目的では、GetTickCount関数が使われることもあります。

実装の例

(1) 特定の日時に悪性コードを実行するC++/x86 Assemblyのコード例
実行環境における現在の年が2022年ではない場合、プロセスは終了されます。

C++

SYSTEMTIME st;
GetLocalTime(&st);
if(st.wYear != 2022){
exit(1);
}

Assembly(x86)

lea     eax, [ebp+SystemTime]
push    eax      ; lpSystemTime
call    GetLocalTime
cmp     [ebp+SystemTime.wYear], 2022
jnz     short loc_not_specified_date
loc_not_specified_date:
push    1
call    exit

(2) コードの実行に掛かる時間を計測し、デバッガー上で実行されていることを検知するC++のコード例
ある処理の実行時間が通常時に比べて大きかった場合、isDebugged関数はtrueを返します。

C++

BOOL isDebugged(ULONGLONG estimatedElapsedTime) {
    SYSTEMTIME st1, st2;
    FILETIME ft1, ft2;
    ULARGE_INTEGER ui1, ui2;

    GetLocalTime(&st1);
    //処理に時間の掛かる動作
    GetLocalTime(&st2);

    SystemTimeToFileTime(&st1, &ft1);
    SystemTimeToFileTime(&st2, &ft2);

    ui1.HighPart = ft1.dwHighDateTime;
    ui1.LowPart = ft1.dwLowDateTime;
    ui2.HighPart = ft2.dwHighDateTime;
    ui2.LowPart = ft2.dwLowDateTime;

    return (ui2.QuadPart - ui1.QuadPart) > estimatedElapsedTime;
}

回避手法

GetLocalTimeによるマルウェア解析環境検知を回避し、プログラムを解析する手法を以下に示します。一時的に検出を回避するときには1の手法を、恒久的に検出を回避するときには2の手法を使います。

  • デバッグ中に分岐命令を書き換える
    GetLocalTimeを呼び出した後の分岐命令をJMP命令またはNOP命令に書き換えます。
  • プログラムを書き換える
    GetLocalTimeを呼び出した後の分岐命令をJMP命令またはNOP命令に書き換え、変更を保存します。

検出手法

GetLocalTimeを検出するYARAルールを以下に示します。

YARAルール

rule Win32API_GetLocalTime
{
    strings:
        $str ="GetLocalTime"
    condition:
        $str
}
この記事をシェア
サイバーセキュリティ
情報局の最新情報を
チェック!