
この脆弱性は、韓国語版Windows 10 1909 x64(コードページ949)にインストールされたOutlook 2019(16.0.12624.20424)で発生します。

この脆弱性を使用してASLRを回避することはできませんでしたが、起動時に固定されるシステムライブラリのアドレスを使用して、Outlook 2019 32bit版で電卓を起動するエクスプロイトを作成しました。 また、この脆弱性はゼロクリック脆弱性です。"outlook.com"以外のメールサービスのアカウントがIMAPを使用してOutlook 2019にリンクされている場合、メールを受信するだけでトリガーされます。
v26 = IsDBCSLeadByte(*v13);
v12 = 0;
if ( v26 )
{
LODWORD(v5) = v5 - 1;
*v11++ = *v13++;
--v8;
}
LODWORD(v5) = v5 - 1;
*v11++ = *v13++;
--v8;
goto LABEL_51;
[OUTLMIME!CloseAllSockets+0x50804 疑似コード]
クラッシュが発生し、脆弱性が存在する部分は上記の通りです。解析されたToヘッダーまたはFromヘッダーの文字列がマルチバイトの場合、残りの解析対象文字列をカウントする変数が2減算され、変数が1のときに変数を2減算することで整数のアンダーフローが発生します。
if ( v23 != '=' )
{
if ( v23 == 34 )
v15 = 6;
goto LABEL_48;
}
v15 = 1;
}
if ( v15 )
goto LABEL_40;
[OUTLMIME!CloseAllSockets+0x50804 疑似コード]
LABEL_40:
v24 = v13[v14];
if ( v24 )
{
if ( v5 == v14 )
goto LABEL_52;
if ( v8 != v14 )
{
v25 = IsDBCSLeadByte(v24);
v12 = 0;
if ( v25 )
++v14;
++v14;
}
}
goto LABEL_51;
}
[OUTLMIME!CloseAllSockets+0x50804 疑似コード]
LABEL_51:
if ( v5 <= v14 )
goto EXIT_0;
}
[OUTLMIME!CloseAllSockets+0x50804 疑似コード]
if ( v15 )
{
if ( v15 == 1 )
{
v15 = 2;
v21 = v13[v14];
v22 = v14 + 1;
if ( v21 != '?' )
v22 = v14;
if ( v21 != '?' )
v15 = v12;
v14 = v22;
}
[OUTLMIME!CloseAllSockets+0x50804 疑似コード]
else if ( v15 > 1 )
{
if ( v15 <= 3 )
{
v18 = v13[v14];
v19 = v14 + 1;
if ( v18 != '?' )
v19 = v14;
v14 = v19;
v20 = v15 + 1;
if ( v18 != '?' )
v20 = v15;
v15 = v20;
}
[OUTLMIME!CloseAllSockets+0x50804 疑似コード]
if ( v15 == 4 )
{
if ( v13[v14] == '?' )
v15 = 5;
LABEL_40:
v24 = v13[v14];
if ( v24 )
{
if ( v5 == v14 )
goto LABEL_52;
if ( v8 != v14 )
{
v25 = IsDBCSLeadByte(v24);
v12 = 0;
if ( v25 )
++v14;
++v14;
}
}
goto LABEL_51;
}
[OUTLMIME!CloseAllSockets+0x50804 疑似コード]
if ( v15 == 5 )
{
v16 = v14;
v17 = v14 + 1;
v30 = v13[v16];
if ( v30 == '=' )
{
*v11++ = 34;
--v8;
}
memcpy(v11, v13, v17);
v13 += v17;
v11 += v17;
LODWORD(v5) = v5 - v17;
v8 -= v17;
if ( v30 == '=' )
{
*v11++ = 34;
--v8;
}
v12 = 0;
v14 = 0;
v15 = 0;
goto LABEL_51;
}
[OUTLMIME!CloseAllSockets+0x50804 疑似コード]
else
{
v23 = v13[v14];
if ( v23 != '=' )
{
if ( v23 == '"' )
v15 = 6;
goto LABEL_48;
}
v15 = 1;
}
if ( v15 )
goto LABEL_40;
[OUTLMIME!CloseAllSockets+0x50804 疑似コード]
LABEL_48:
v26 = IsDBCSLeadByte(*v13);
v12 = 0;
if ( v26 )
{
LODWORD(v5) = v5 - 1;
*v11++ = *v13++;
--v8;
}
LODWORD(v5) = v5 - 1;
*v11++ = *v13++;
--v8;
goto LABEL_51;
[OUTLMIME!CloseAllSockets+0x50804 疑似コード]
しかし、上記のバグを使用してヒープオーバーフローをトリガーする際、ループから再び抜ける条件を満たすことができなかったため、思うように部分的な上書きを行うことができませんでした。そのため、ループから抜ける特定の条件を満たす入力を見つける必要がありました。同じ理由から、周辺のコード部分を厳密に監査しましたが、ループから脱出できる入力値を見つける代わりに、特殊な文字列を処理する際にインデックスが増加せず書き込みも行われず無限ループに陥るバグを発見しました。

ヒープスプレーとヒープフェンシュイを実行した後、上記のバグを使用して無限ループに陥っていなかった別のスレッドで実行中のオブジェクトのvftableを上書きすることで、EIPハイジャックに成功しました。