
Exploit per la vulnerabilità zero-click di Outlook 2019 CVE-2020-1349, che utilizza bug di parsing dell'header MIME per ottenere heap overflow e controllo EIP tramite sovrascrittura della vftable.
Questa vulnerabilità si verifica in Outlook 2019 (16.0.12624.20424) installato su Windows 10 1909 x64 coreano, codepage 949.

Non sono riuscito a bypassare ASLR usando questa vulnerabilità, ma ho scritto un exploit per Outlook 2019 a 32 bit che fa apparire una calcolatrice usando l'indirizzo di una libreria di sistema che è fissa al momento dell'avvio. Inoltre, questa vulnerabilità è a zero click. Se l'account di un servizio di posta diverso da "outlook.com" è collegato a Outlook 2019 tramite IMAP, viene attivata semplicemente ricevendo una mail.
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 Pseudo codice]
Il crash si verifica e la parte in cui esiste la vulnerabilità è come sopra. Quando la stringa dell'intestazione To o From analizzata è multibyte, la variabile che conta le stringhe rimanenti da analizzare viene decrementata di 2, e si verifica un underflow intero decrementando la variabile di 2 quando la variabile è 1.
if ( v23 != '=' )
{
if ( v23 == 34 )
v15 = 6;
goto LABEL_48;
}
v15 = 1;
}
if ( v15 )
goto LABEL_40;
[OUTLMIME!CloseAllSockets+0x50804 Pseudo codice]
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 Pseudo codice]
LABEL_51:
if ( v5 <= v14 )
goto EXIT_0;
}
[OUTLMIME!CloseAllSockets+0x50804 Pseudo codice]
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 Pseudo codice]
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 Pseudo codice]
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 Pseudo codice]
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 Pseudo codice]
else
{
v23 = v13[v14];
if ( v23 != '=' )
{
if ( v23 == '"' )
v15 = 6;
goto LABEL_48;
}
v15 = 1;
}
if ( v15 )
goto LABEL_40;
[OUTLMIME!CloseAllSockets+0x50804 Pseudo codice]
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 Pseudo codice]
Tuttavia, quando si innesca un heap overflow usando il bug sopra, non sono riuscito a soddisfare la condizione per uscire dal ciclo, quindi non ho potuto eseguire la sovrascrittura parziale quanto desiderato. Ho dovuto quindi trovare un input che soddisfacesse una condizione specifica per uscire dal ciclo. Per lo stesso motivo, ho verificato rigorosamente la parte di codice circostante e, invece di trovare il valore di input che potesse uscire dal ciclo, ho scoperto il bug che causa un ciclo infinito senza aumentare l'indice o scrivere durante l'elaborazione di una stringa speciale.

Dopo aver eseguito heap spray e heap feng shui, l'hijacking di EIP è stato ottenuto sovrascrivendo la vftable dell'oggetto in esecuzione in un altro thread che non era rimasto intrappolato in un ciclo infinito usando il bug sopra.