
Exploit de prueba de concepto para CVE-2020-1349, un desbordamiento de montón de cero clics en el análisis MIME de Outlook 2019, logrando control del EIP mediante heap spray y feng shui en Windows 10 x64 coreano.
Esta vulnerabilidad ocurre en Outlook 2019 (16.0.12624.20424) instalado en Windows 10 1909 x64 coreano, página de códigos 949.

No he podido evitar ASLR usando esta vulnerabilidad, pero he escrito un exploit de Outlook 2019 de 32 bits que abre una calculadora usando la dirección de una biblioteca del sistema que está fija al inicio. Y esta vulnerabilidad es de cero clics. Si la cuenta de un servicio de correo diferente a la cuenta 'outlook.com' está vinculada con Outlook 2019 usando IMAP, se activa solo con recibir correo.
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 Código pseudo]
El fallo ocurre, y la parte donde existe la vulnerabilidad es la anterior. Cuando la cadena del encabezado To o From analizado es Multibyte, la variable que cuenta las cadenas restantes por analizar se decrementa en 2, y se produce un desbordamiento de entero al disminuir la variable en 2 cuando la variable es 1.
if ( v23 != '=' )
{
if ( v23 == 34 )
v15 = 6;
goto LABEL_48;
}
v15 = 1;
}
if ( v15 )
goto LABEL_40;
[OUTLMIME!CloseAllSockets+0x50804 Código pseudo]
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 Código pseudo]
LABEL_51:
if ( v5 <= v14 )
goto EXIT_0;
}
[OUTLMIME!CloseAllSockets+0x50804 Código pseudo]
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 Código pseudo]
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 Código pseudo]
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 Código pseudo]
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 Código pseudo]
else
{
v23 = v13[v14];
if ( v23 != '=' )
{
if ( v23 == '"' )
v15 = 6;
goto LABEL_48;
}
v15 = 1;
}
if ( v15 )
goto LABEL_40;
[OUTLMIME!CloseAllSockets+0x50804 Código pseudo]
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 Código pseudo]
Sin embargo, al desencadenar un desbordamiento de heap usando el error anterior, no pude satisfacer la condición de salir del bucle nuevamente, por lo que no pude realizar la sobrescritura parcial tanto como quería. Así que tuve que encontrar una entrada que satisficiera una condición específica para salir del bucle. Por la misma razón que antes, audité estrictamente la parte de código circundante, y en lugar de encontrar el valor de entrada que pueda escapar del bucle, se encontró el error de caer en un bucle infinito sin incrementar el índice o escribir al procesar una cadena especial.

Después de realizar heap spray y heap feng shui, se logró el secuestro de EIP sobrescribiendo la vftable del objeto en ejecución en otro hilo que no quedó atrapado en un bucle infinito usando el error anterior.