VC++2015 の ucrtbase のオーバーフロー検出機能がおかしい件

VC++ 2015 のRuntimeの中に ucrtbase.dll というファイルがあるのですがバッファーオーバーフローのチェック機能がなんだかおかしいので紹介します

 EntryPoint:
          mov    edi,edi
          push    ebp
          mov    ebp,esp
          sub    esp,00000030h
          mov    eax,[L100CD000]
          xor    eax,ebp
          mov    [ebp-04h],eax

DLLロード時に スタックに L100CD000 の値を積みます。
バッファーオーバーフローが起こるとこの値が壊れてしまうので検出できるという仕組みなのですが…。

 SUB_L10032BF5:
          mov    edi,edi
          push    ebp
          mov    ebp,esp
          sub    esp,00000014h
          and    dword ptr [ebp-0Ch],00000000h
          and    dword ptr [ebp-08h],00000000h
          mov    eax,[L100CD000]
          push    esi
          mov    esi,BB40E64Eh
          test    eax,eax
          jz     L10032C18
          cmp    eax,esi
          jnz    L10032C6A
 L10032C18:
          lea    eax,[ebp-14h]
          push    eax
          call    [api-ms-win-core-sysinfo-l1-1-0.dll!GetSystemTimeAsFileTime]
          mov    eax,[ebp-10h]
          xor    eax,[ebp-14h]
          mov    [ebp-04h],eax
          call    [api-ms-win-core-processthreads-l1-1-0.dll!GetCurrentProcessId]
          xor    [ebp-04h],eax
          call    [api-ms-win-core-processthreads-l1-1-0.dll!GetCurrentThreadId]
          xor    [ebp-04h],eax
          call    [api-ms-win-core-sysinfo-l1-1-0.dll!GetTickCount]
          xor    eax,[ebp-04h]
          lea    ecx,[ebp-04h]
          xor    eax,ecx
          mov    [ebp-04h],eax
          lea    eax,[ebp-0Ch]
          push    eax
          call    [api-ms-win-core-profile-l1-1-0.dll!QueryPerformanceCounter]
          mov    eax,[ebp-08h]
          xor    eax,[ebp-04h]
          xor    eax,[ebp-0Ch]
          jnz    L10032C65
          mov    eax,esi
 L10032C65:
          mov    [L100CD000],eax

 L10032C6A:
          not    eax
          mov    [L100CD004],eax
          pop    esi
          mov    esp,ebp
          pop    ebp
          retn

プロセスロードの分岐処理を見てみると、スタック積んだ後で値を書き換えてるよ!

 L10026D68:
          call    SUB_L10040280
          mov    ecx,[ebp-04h]
          mov    eax,edi
          pop    edi
          xor    ecx,ebp
          pop    esi
          call    SUB_L10032BE0
          mov    esp,ebp
          pop    ebp
          retn    000Ch

 SUB_L10032BE0:
          cmp    ecx,[L100CD000]
          jnz    L10032BEB
          retn    0000h
;------------------------------------------------------------------------------
 L10032BEB:
          jmp    __report_gsfailure

全ての処理が終わったら、何事もなかったように比較してるけど、値が違うのあたりまえじゃないですか!
このまま処理を進めると 0xc0000409 でクラッシュするのだ
データ実行防止

試しに、スタックオーバーフロー検出値の暗号化処理を無効化してみた
crm2
…動くじゃねーか・ω・;

ちなみに、他のDLLは

 EntryPoint:
          push    ebp
          mov    ebp,esp
          cmp    dword ptr [ebp+0Ch],00000001h
          jnz    L1002843E
          call    SUB_L1002897B -> 暗号化

なので、メインルーチンで暗号化する前に値を使うというアホなことはしてない

XPで動作確認してみると、

         mov    eax,[L100CD000]
          push    esi
          mov    esi,BB40E64Eh

DLLロード時に L100CD000の値が書き換わってしまってるので、暗号化処理が走らない模様

修正した VC++2015 Runtime for Windows 2000を v3で公開したよ ・ω・

Why does use __security_cookie before it calls __security_init_cookie on ucrtbase.dll ?
一応、マイクロソフトのコミュで聞いてみることに

おすすめ

1件の返信

  1. やまちび より:

    お世話になっております。
    早速VC++2015 Runtime for Windows 2000 v3をインストールさせて頂きました。
    NCV α155が無事に動作致しましたことをご報告致します。
    しかし今度は終了時に
    .NET-BroadcastEventWindows.4.0.0.0.14b42a0 アプリケーションエラーが発生します。
    何か心当たりはございますでしょうか?
    こちらはnVideaのデュアルディスプレイ環境です。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です