CVE: CVE-2020-0961
Tested Versions:
- msexcl40.dll 4.0.9801.17
Product URL(s):
Description of the vulnerability
msexcl40.dll
is a part of Microsoft Jet Excel, it is responsible for to process excel files when opening a specially crafted .xls file, an memory corruption will occur.
The crash occurs at msexcl40!memcpy+0x2a
:
(42b8.1bc0): Access violation - code c0000005 (first/second chance not available)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=9f33c218 ebx=00000004 ecx=00000004 edx=00000004 esi=9f33c214 edi=00b3e080
eip=5374abda esp=00b3e00c ebp=00b3e1cc iopl=0 nv up ei pl nz ac pe cy
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000217
msexcl40!memcpy+0x2a:
5374abda f3a4 rep movs byte ptr es:[edi],byte ptr [esi]
0:000> kb
# ChildEBP RetAddr Args to Child
00 00b3e010 5373b647 00b3e080 9f33c214 00000004 msexcl40!memcpy+0x2a
01 00b3e028 5372cd8d 25111a7a 00b3e080 00000004 msexcl40!BFReadFile+0x57
02 00b3e1cc 537276c4 251117de 5375c770 00000000 msexcl40!ExcelScanFile+0x12d
03 00b3e1e0 53727c8e 25111776 00000000 00b3e324 msexcl40!NextName+0x24
04 00b3e200 5371cc1a 25111776 00b3e324 00000100 msexcl40!WorkbookNameFirst+0x2e
05 00b3e524 5371dc52 251127a6 256a6168 00b3e54c msexcl40!LocateTableInDatabase+0x28a
06 00b3eb6c 7b8bb575 20a16f20 00000001 256a6168 msexcl40!WBDBDeleteTable+0x1f2
07 00b3eb80 7b89b716 20a16f20 000000ff 256a6168 msjet40!ErrDispDeleteTable+0x35
08 00b3eb9c 7b978e1a 20a16f20 000000ff 256a6168 msjet40!ErrDeleteTable+0x56
09 00b3ed98 7b9449c8 20a16f20 000000ff 000007ff msjet40!ErrExecuteDDL+0xe2e
0a 00b3edc8 7b94634d 20a16f20 000000ff 000007ff msjet40!ErrExecuteTempQuery+0xa0
0b 00b3edf8 7b7f5d40 20a16f20 000000ff 000007ff msjet40!JetExecuteTempQuery+0x90
0c 00b3eea4 7b64d303 25630ff0 25652f34 7b5c48bc msjetoledb40!CImpICommandText::Execute+0x390
0d 00b3efdc 00707521 25648fdc 00000000 0079ae58 oledb32!CCommandText::Execute+0x313
From the crash, we get to know that the source address of memcpy
is wrong. In our case, it is 0x9f33c214
. Through reverse engineering, we found this value comes from [EDI+0x8]
at 0x1002B611
:
.text:1002B60A push edi
.text:1002B60B mov edi, [esp+8+arg_0]
.text:1002B60F mov eax, [edi]
.text:1002B611 mov ecx, [edi+8]// dirty value
After some further analysis, we found out that the dirty value was written at msexcl40!BFSetFilePosition+0x54
:
0:000> r
eax=00000000 ebx=80000000 ecx=9f33c214 edx=80000000 esi=25111a7a edi=251117de
eip=5373b857 esp=00b3e024 ebp=60cc3dec iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
msexcl40!BFSetFilePosition+0x57:
5373b857 5e pop esi
0:000> kb3
# ChildEBP RetAddr Args to Child
00 00b3e02c 5372cd26 25111a7a 00000000 00000000 msexcl40!BFSetFilePosition+0x57
01 00b3e1cc 537276c4 251117de 5375c770 00000000 msexcl40!ExcelScanFile+0xc6
02 00b3e1e0 53727c8e 25111776 00000000 00b3e324 msexcl40!NextName+0x24
We can know this value is related to lDistanceToMove
, so we will look further. When we look at msexcl40!BFSetFilePosition+0x4d
:
eax=7fffffff ebx=80000000 ecx=1f33c214 edx=80000000 esi=25111a7a edi=00000000
eip=5373b84d esp=00b3e020 ebp=60cc3dec iopl=0 nv up ei ng nz ac po cy
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000293
msexcl40!BFSetFilePosition+0x4d:
5373b84d 2bcb sub ecx,ebx
We can easily see that ecx-ebx
will result in a negative value, which causes an integer overflow. Next, we are going to see what is ebx: ebx
retrieved its value from msexcl40+0x2B817
, and ebp
is related with [esi+54]
:
.text:1002B80C mov edx, [esi+54h]
.text:1002B80F mov ebp, edx
.text:1002B811 sub ebp, [esi+4]
.text:1002B814 mov ecx, [esi+8]
.text:1002B817 lea ebx, [ecx+ebp]
.text:1002B81A test eax, eax
0:000> dd esi+54
25111ace 80000000 00001c00 00000000 00000002
25111ade 00000838 00000000 00000000 00000000
25111aee 00000000 00000000 00000000 00000000
That’s weird that a file position related value is so huge. We set several access breakpoints
to trace the value and finally found that it comes from 0x1f33c2a2
:
0:000> dd 1f33c2a2
1f33c2a2 80000000 00020042 000d04e4 00010002
1f33c2b2 0002000c 000f0064 00010002 00020011
1f33c2c2 00100000 a9fc0008 624dd2f1 005f3f50
1f33c2d2 00010002 0002000e 00220001 00010002
When we set an access breakpoint at 0x1f33c2a2
:
0:000> r
eax=00000000 ebx=0000fde8 ecx=0000fd58 edx=0000fde8 esi=1f33c214 edi=1f33c2a4
eip=5374b224 esp=00b3d2b0 ebp=251117f2 iopl=0 nv up ei pl nz na pe cy
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000207
msexcl40!memset+0x24:
5374b224 f3aa rep stos byte ptr es:[edi]
0:000> kb3
# ChildEBP RetAddr Args to Child
00 00b3d2b0 537421eb 1f33c214 00000000 0000fde8 msexcl40!memset+0x24
01 00b3d2cc 5373b244 0000fde8 251117de 25111862 msexcl40!AllocateFromGlobalHeap+0x3b
02 00b3d2dc 5372b98f 25111862 00000012 251117f2 msexcl40!BFOpenFile+0x74
We can see BFOpenFile
in the call stack, then we infer that the program is trying to read the file. When we go back to see the memory at 0x1f33c2a2
. We found the content of this block is the same in the PoC.
Timeline:
- 2019-11-13 Vendor disclosure
- 2020-04-14 Vendor patched
Vendor Response
The vendor has patched the Component plugin and acknowledged the security issues at https://msrc.microsoft.com/update-guide/vulnerability/CVE-2020-0961.