Those who are, we call them vulnerabilities. Which is not the case of the bug I found in Notepad++ and it’s the subject of this post. The bug is triggered when setting the parsing Language of an opened document to "User-Defined"; exit Notepad++ while the document is still open, and then, start Notepad++. Every time Notepad++ is run it will crash with a message stating the error:
At the crash point we can observe the thread state:
WARNING: Stack unwind information not available. Following frames may be wrong.
000df0d8 1001c863 SciLexer!Scintilla_DirectFunction+0x42e65
000df0f4 1001ca7b SciLexer+0x1c863
000e1090 100044fa SciLexer+0x1ca7b
000e10b8 10025c2b SciLexer+0x44fa
000e10dc 100272ec SciLexer+0x25c2b
000e1190 10029ca7 SciLexer+0x272ec
*** WARNING: Unable to verify checksum for npp.exe
*** ERROR: Module load completed but symbols could not be loaded for npp.exe
000e11a0 0047a597 SciLexer+0x29ca7
000e11c0 004811cd npp+0x7a597
000e11d4 0043b88c npp+0x811cd
000e1698 000e1688 npp+0x3b88c
000e169c 000e19ac 0xe1688
000e16a0 004d0ee8 0xe19ac
000e19ac 00400000 npp+0xd0ee8
000e19b0 00040278 npp
000e19b4 000302a8 0x40278
000e19b8 00000000 0x302a8
eax=00000000 ebx=00000000 ecx=00eadc40 edx=003b0608 esi=000df118 edi=00eaddf0
eip=1006cb0d esp=000def10 ebp=000df0d8 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00010202
1006cb0d 8b38 mov edi,dword ptr [eax] ds:0023:00000000=????????
It seems that we have a null dereferenced pointer in the SciLexer module; with EAX=0, and, as there’s no null page allocated, we get a crash with access denied error. Let’s give it a look. EAX comes from ESI, so let’s see what’s there:
Failed to map Heaps (error 80004005)
Allocation Base: 00e90000
Base Address: 00e90000
End Address: 00eb6000
Region Size: 00026000
Type: 00020000 MEM_PRIVATE
State: 00001000 MEM_COMMIT
Protect: 00000004 PAGE_READWRITE
!heap -x 00eaddf0
Entry User Heap Segment Size PrevSize Unused Flags
00eadde8 00eaddf0 003b0000 00e90000 428 58 18 busy extra fill
There’s no information of interest from the heap allocator as Notepad++ uses its own allocator. So, I started digging a little more to know if I could somehow influence this null reference to become something else more interesting from security viewpoint. Reversing some code of the application and analyzing the dump, I managed to get to some conclusions.
What is happening is that the document parsing language is saved in the session.xml file. The file is kept by Notepad++ in the AppData\Roaming\Notepad++ profile directory. This configuration file is always updated and saved when Notepad++ is closed by the user.
As there’s no “User-Defined” language defined, Notepad++ will allocate a language object that’s initialized with zeros by the time it is allocated. When parsing the file it will apply this empty object without verifying that there’s no valid data in it.
We got a "use an un-initialized object", and in consequence a crash. Although the object is not initialized, "sadly" it isn’t exploitable because as I said it is zeroed out on allocation. This conclusions can be validated by doing the following:
1. Create a user defined language file. Menu View, open User-Defined dialog.
2. Name it User-Defined.
3. Save it.
If you try now to do the same thing as described before, Notepad++ won’t crash anymore. If you go to the Language menu you will see a weird thing, there will be now two “User-Defined” items. Whichever you choose you'll get the same results, it will apply the previously defined "User-Defined" parsing language and no crash.
While the bug is not corrected by the Notepad++ developer team, you can solve this issue just by deleting the session.xml file. It will be recreated next time you start Notepad++.
Again, not all bugs are exploitable. Those who aren't remain just... bugs!