新しいスレッドの追跡を実際に行っていきましょう。ここでも、序盤は紆余曲折で、何度も実行して大まかにどのようなことをしているのか、ということを把握していきます。やり方は人それぞれとなりますが、今回はルートになる処理からcallしている処理が、概ねどのような処理をしているか、を把握しながら進めていきました。また、その過程で、特異点があればそこから深く掘り下げていくのも方法でしょう。
この再展開され、新しいスレッドで実行されたコードでも、やはりWindows APIは使用されていました。「仮想メモリ内のWindows API使用フロー」でもあったとおり、APIの使用の流れを見ていくことで、処理の流れを掴むことの助けになります。
しかし、「新たな仮想メモリに展開された情報の内容」で抽出したプログラムを解析しても、Importテーブルはありませんでした。ということは、恐らく「仮想メモリ内のWindows APIの使用」と同様のことを行っているだろう、という予想し、調査を進めてみました。すると、「仮想メモリ内のWindows APIの使用」と少し違ったことを行っていました。
その「少し違った」という部分は、「Windows APIのポインタを探しにいく」という点は同じなのですが、それを序盤にまとめて行い、テーブル化していたのです。そのため、実際の処理中は、「仮想メモリ内のWindows APIの使用」のように毎回GetProcAddressを行うのではなく、テーブルのベースポインタから、それぞれのAPIの固定のオフセットの位置からポインタを取得する方法となっています。
テーブルの作成では、テーブルの領域を確保するために、0x0040172Aで「NtAllocateVirtualMemory」のAPIポインタを得るcallを行い、そのポインタを用いて0x0040175Aでメモリの取得を実行し、0x0042FC04に格納します。さらに0x00401765以降で、APIのポインタの取得処理を行っています(【図66】参照)。その結果、APIのポインタテーブルができあがります(【図67】参照)。
【図66】APIのポインタをテーブル用メモリ上に展開する処理
【図67】APIのポインタをテーブル用メモリ上に展開された結果
利用時には、0x004016E0をコールして、APIのポインタテーブルの開始アドレスを取得し、そのアドレスにAPI固有のオフセットを加算してAPIのポインタを取得して、callを実行しています(【図68】参照)。
この自作のImportテーブルは、マルウェアの開発者向けの「キット」の可能性もありますが、「マルウェアの表層解析」でも述べたとおり、Importテーブルには「通常のプログラムではあまり使わないがマルウェアがよく使うAPI」があることが予想されます。そのため、ここに展開されたAPIのリストを作成してみました(【表2】参照)。これが、解析しているCryptoWall亜種の「真のImportテーブル」と言えるのではないかと思います。
表のAPIを見てみると、前半にプロセスやスレッドの制御、それらのメモリの操作、権限の操作、レジストリに関するAPIが多く見られます。中盤は一般的にも使われる文字列操作やファイルに関するAPIが多く見られます。後半にはセキュリティや暗号に関するAPIが多く見られます。
「マルウェアの表層解析」の【図4】のImportテーブルと比べれば差は歴然で、【表2】からはマルウェアが攻撃する気満々なのが見て取れるくらいです。なにしろ、前半部分でマルウェアによるインジェクションや不正プロセスの起動、操作に必要なAPIや自動起動等を設定するためのレジストリ操作に必要なAPIがあり、中間はそこで使用する文字列の編集やファイル作成のAPIがあり、後半はサービスの操作やマルウェアが通信等を行うときに暗号化に利用できるAPIが見られます。また、ランサムウェアの場合は、CryptEncryptを用いている可能性があります。攻撃者にとって、鍵なしでは解読できない十分な強度があれば、APIの利用のほうが省力化になるためです。
では、スレッドの処理の続きを見ていきたいと思います。
< 新しいスレッドの追跡 | 目 次 | PC毎固有の「ハッシュ値」の計算 > |
【表2】自作のImportテーブル
オフセット | Windows API | オフセット | Windows API |
0x0000 | NtClose | 0x0150 | _swprintf |
0x0004 | LdrLoadDll | 0x0154 | sscanf |
0x0008 | LdrGetProcedureAddress | 0x0158 | RtlInitAnsiString |
0x000C | NtAllocateVirtualMemory | 0x015C | RtlInitUnicodeString |
0x0010 | NtFreeVirtualMemory | 0x0160 | RtlAnsiStringToUnicodeString |
0x0014 | NtProtectVirtualMemory | 0x0164 | RtlUnicodeStringToAnsiString |
0x0018 | NtQueryVirtualMemory | 0x0168 | RtlFreeAnsiString |
0x001C | NtWriteVirtualMemory | 0x016C | RtlFreeAnsiString(重複) |
0x0020 | NtReadVirtualMemory | 0x0170 | RtlDosPathNameToNtPathName_U |
0x0024 | (Null) | 0x0174 | RtlConvertSidToUnicodeString |
0x0028 | RltFreeHeap | 0x0178 | RtlQueryEnvironmentVariable_U |
0x002C | memset | 0x017C | RtlCompressBuffer |
0x0030 | memcpy | 0x0180 | RtlDecompressBuffer |
0x0034 | memcmp | 0x0184 | RtlGetCompressionWorkSpaceSize |
0x0038 | memchr | 0x0188 | RtlAddVectoredExceptionHandle |
0x003C | NtCreateEvent | 0x018C | RtlRemoveVectoredExceptionHandle |
0x0040 | NtOpenEvent | 0x0190 | RtlInitializeCriticalSection |
0x0044 | NtSetEvent | 0x0194 | RtlDeleteCriticalSection |
0x0048 | NtWaitForSingleObject | 0x0198 | RtlEnterCriticalSection |
0x004C | NtWaitForMultipleObjects | 0x019C | RtlLeaveCriticalSection |
0x0050 | NtQuerySystemInfomation | 0x01A0 | NtQuerySystemTime |
0x0054 | NtShutdownSystem | 0x01A4 | RtlTimeToSecondsSince1970 |
0x0058 | RtlGetNtProductType | 0x01A8 | NtQueryIntervalProfile |
0x005C | NtOpenProcess | 0x01AC | RtlRandom |
0x0060 | NtTerminateProcess | 0x01B0 | RtlRandomEx |
0x0064 | NtQueryInformationProcess | 0x01B4 | GetTickCount |
0x0068 | NtDelayExcution | 0x01B8 | CreateProcessInternalW |
0x006C | RltAdjustPrivilege | 0x01BC | OutputDebugStringA |
0x0070 | RtlSetProcessIsCritical | 0x01C0 | WinExec |
0x0074 | NtOpenThread | 0x01C4 | CreateFileW |
0x0078 | NtTerminateThread | 0x01C8 | ReadFile |
0x007C | NtResumeThread | 0x01CC | WriteFile |
0x0080 | NtSuspendThread | 0x01D0 | FlushFileBuffers |
0x0084 | NtQueryInformationThread | 0x01D4 | GetFileSize |
0x0088 | NtImpersonateThread | 0x01D8 | SetFilePointer |
0x008C | RtlCreateUserThread | 0x01DC | GetFileSizeEx |
0x0090 | NtCreateThreadEx | 0x01E0 | SetFilePointerEx |
0x0094 | CsrClientCallServer | 0x01E4 | GetFileAttributesW |
0x0098 | (Null) | 0x01E8 | SetFileAttributesW |
0x009C | NtGetContextThread | 0x01EC | SetEndOfFile |
0x00A0 | NtSetContextThread | 0x01F0 | GetFileTime |
0x00A4 | RtlExitUserThread | 0x01F4 | SetFileTime |
0x00A8 | NtQueueApcThread | 0x01F8 | GetLogicalDriveStringsW |
0x00AC | NtSetInformationThread | 0x01FC | GetVolumeInformationW |
0x00B0 | NtOpenProcessToken | 0x0200 | GetDriveTypeW |
0x00B4 | NtQueryInformationToken | 0x0204 | CloseHandle |
0x00B8 | NtCreateFile | 0x0208 | FindFirstFileW |
0x00BC | NtOpenFile | 0x020C | FindNextFileW |
0x00C0 | NtWriteFile | 0x0210 | FindClose |
0x00C4 | NtReadFile | 0x0214 | SetErrorMode |
0x00C8 | NtDeleteFile | 0x0218 | LocalFree |
0x00CC | NtQueryInformationFile | 0x021C | SetPriorityClass |
0x00D0 | NtSetInformationFile | 0x0220 | MoveFileExW |
0x00D4 | NtQueryVolumeInformationFile | 0x0224 | CreateThread |
0x00D8 | NtCreateSection | 0x0228 | CreateRemoteThread |
0x00DC | NtMapViewOfSection | 0x022C | GetCommandLineW |
0x00E0 | NtUnmapViewOfSection | 0x0230 | AllocateAndInitializeSid |
0x00E4 | RtlCreateSecurityDesciptor | 0x0234 | CheckTokenMembership |
0x00E8 | RtlSetDaclSecurityDescriptor | 0x0238 | FreeSid |
0x00EC | NtSetSecurityObject | 0x023C | LookupAccountSidW |
0x00F0 | NtCreateKey | 0x0240 | GetUserNameW |
0x00F4 | NtOpenKey | 0x0244 | OpenSCManagerW |
0x00F8 | NtQueryKey | 0x0248 | OpenServiceW |
0x00FC | NtDeleteKey | 0x024C | QueryServiceStatus |
0x0100 | NtQueryValueKey | 0x0250 | ControlService |
0x0104 | NtSetValueKey | 0x0254 | ChangeServiceConfigW |
0x0108 | NtDeleteValueKey | 0x0258 | CloseServiceHandle |
0x010C | NtRenameKey | 0x025C | CryptAcquireContextW |
0x0110 | NtEnumerateValueKey | 0x0260 | CryptReleaseContext |
0x0114 | NtEnumerateKey | 0x0264 | CryptGenKey |
0x0118 | NtFlushKey | 0x0268 | CryptDestroyKey |
0x011C | strcpy | 0x026C | CryptExportKey |
0x0120 | strncpy | 0x0270 | CryptImportKey |
0x0124 | strcat | 0x0274 | CryptEncrypt |
0x0128 | strcat | 0x0278 | CryptDecrypt |
0x012C | wcscpy | 0x027C | CryptDuplicateKey |
0x0130 | wcsncpy | 0x0280 | CryptCreateHash |
0x0134 | wcscat | 0x0284 | CryptHashData |
0x0138 | wcsncat | 0x0288 | CryptGetHashParam |
0x013C | strcmp | 0x028C | CryptDestroyHash |
0x0140 | strncmp | 0x0290 | CryptSetKeyParam |
0x0144 | wcscmp | 0x0294 | CryptGetKeyParam |
0x0148 | wcsncmp | 0x0298 | GetKeybordLayoutList |
0x014C | sprintf | 0x029C | GetSystemMetrics |