The following crash was observed in MS Office 2007 running under Windows 2003 x86. Microsoft Office File Validation Add-In is disabled for testing and reproduction. This sample did not reproduce in Office 2010 on Windows 7 x86. There may be difficulties triggering this crash multiple times if Office attempts to repair the document. You can rename the crashing file to a unique name with each open to prevent this.
The attached minimized PoC that produces the crash is a 1 bit change from the original file. OffViz identifies this offset (0xEF4) as the least significant byte in: stPapxFKPs[2].PAPXKFP[0].PAPXINFKP[2].ggpprlInPapx.grpprl[8].PRL[5].sprm.operand
Attached files:
Fuzzed and minimized PoC: 3471051319_crash.doc
Fuzzed non-minimized PoC: 3471051319_fuzzed.doc
Original non-mutated file: 3471051319_orig.doc
Observed crash:
eax=00000011 ebx=012c0550 ecx=03321a20 edx=33513a02 esi=012c0540 edi=03320410
eip=326a9754 esp=0012b414 ebp=0012b428 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010202
mso!Ordinal4328+0x153:
326a9754 ff5024 call dword ptr [eax+24h] ds:0023:00000035=????????
0:000> k
ChildEBP RetAddr
WARNING: Stack unwind information not available. Following frames may be wrong.
0012b428 3280c0f8 mso!Ordinal4328+0x153
0012b440 327ad143 mso!Ordinal7740+0x1a1
0012b478 326dc30b mso!Ordinal7069+0x74
0012b488 326dbbc5 mso!Ordinal3891+0x605
0012b498 326dbeb4 mso!Ordinal3805+0x56b
326a9749 8b0e mov ecx,dword ptr [esi]
326a974b ff7508 push dword ptr [ebp+8]
326a974e 83e1fe and ecx,0FFFFFFFEh
326a9751 8b01 mov eax,dword ptr [ecx]
326a9753 57 push edi
326a9754 ff5024 call dword ptr [eax+24h] ds:0023:00000035=????????
ecx is set to 03321a20 which contains the value 00000011.
Restarting and setting a write memory access breakpoint with "ba w 1 03321a20" shows that the first usage of this heap address is a call to memset(). The stack trace shows this call coming from mso.dll similar to the crashing call stack. It is likely that this is where our object is initialized. The next breakpoint hit shows a constant value being set at instruction 32695985. The call stack here also shows this value being set with calls from mso.dll as well.
Breakpoint 0 hit
eax=032a2a20 ebx=00000000 ecx=0012beb0 edx=00000000 esi=032a2a20 edi=00000020
eip=3269598b esp=0012bea0 ebp=0012beb4 iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212
3269597e 83c40c add esp,0Ch
32695981 56 push esi
32695982 8d4dfc lea ecx,[ebp-4]
=> 32695985 c706344fa732 mov dword ptr [esi],offset mso!Ordinal2940+0xbfde0 (32a74f34)
3269598b 895e04 mov dword ptr [esi+4],ebx ds:0023:032a2a24=00000000
The constant value (32a74f34) appears to be a vtable pointer because it contains pointers to the following function start addresses:
32a74f34 3276f9c9 mso!Ordinal7518
32a74f38 32695b54 mso!Ordinal8791+0x635
32a74f3c 32695d6e mso!Ordinal8791+0x84f
32a74f40 3263cca7 mso!Ordinal5455
32a74f44 3271522a mso!Ordinal6935+0x7b
32a74f48 327f8efb mso!Ordinal8490+0x121
32a74f4c 3339109a mso!Ordinal4570+0x158
32a74f50 3269618b mso!Ordinal7282+0x78
32a74f54 327ad69d mso!Ordinal1715+0x23f
32a74f58 326a989d mso!Ordinal4328+0x29c
32a74f5c 32697acc mso!Ordinal6617+0x225
32a74f60 32725a7c mso!Ordinal5274+0x35
32a74f64 32699abd mso!Ordinal8336+0x785
32a74f68 3284dcad mso!Ordinal9267+0x5f
32a74f6c 3271b4a6 mso!Ordinal329+0xee9
32a74f70 3280ce05 mso!Ordinal8127+0x72
32a74f74 32697209 mso!Ordinal8136+0x68
32a74f78 327089da mso!Ordinal2426+0xb8e
32a74f7c 00000000
The next access to this memory address is on a memcpy() from wwlib.dll. The vtable pointer is gone at this point. Continuing, we see our watch access address being set with a mov [eax], ecx also from wwlib.dll. The value being written in this write look to be flag values at this point. Continuing once more we see:
Breakpoint 0 hit
eax=032a2a20 ebx=00000000 ecx=00000011 edx=00000001 esi=00000000 edi=00000100
eip=31249f2a esp=001284f0 ebp=001284f4 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
31249f13 3b560c cmp edx,dword ptr [esi+0Ch]
31249f16 8d44961c lea eax,[esi+edx*4+1Ch]
31249f1a 0f83c2900400 jae wwlib!FMain+0x4ea2b (31292fe2)
31249f20 33f6 xor esi,esi
31249f22 8b4d08 mov ecx,dword ptr [ebp+8]
31249f25 2bce sub ecx,esi
31249f27 5f pop edi
=> 31249f28 8908 mov dword ptr [eax],ecx
31249f2a 5e pop esi
0:000> k
ChildEBP RetAddr
WARNING: Stack unwind information not available. Following frames may be wrong.
001284f4 320c436f wwlib!FMain+0x5973
00128558 320c5c36 wwlib!DllGetClassObject+0xf70f
00128fe0 320c3d45 wwlib!DllGetClassObject+0x10fd6
0012937c 312ff5c6 wwlib!DllGetClassObject+0xf0e5
0:000> dd 32a2a20
032a2a20 00000011 00000001 0000000e 0000000e
032a2a30 00000000 000000ad 00000000 000000cd
032a2a40 00000030 00300000 00000000 00024000
This 00000011 value is the value used in the call [eax+24h] that we saw in the original crash. Indeed, if we continue one last time we end up back at the original crashing instruction. The analysis here shows that an object with a corrupted vtable is being called. The call was intended to go to the function at 326a989d (mso!Ordinal4328+0x29c). This is suggestive of a UAF or memory corruption vulnerability.
DLL version information is:
wwlib.dll: 12.0.6720.5000
mso.dll: 12.0.6718.5000
This bug is subject to a 90 day disclosure deadline. If 90 days elapse without a broadly available patch, then the bug report will automatically become visible to the public.