I read something very interesting in “Windows via C/C++” today: starting with Windows Vista, CreateProcess can start a program where you specify the parent process! This is something forensic investigators must be aware of when they analyse processes running on a Windows machine.
Normally the parent process of a new process is the process that created the new process (via CreateProcess). But when using STARTUPINFOEX with the right LPPROC_THREAD_ATTRIBUTE_LIST to create a process, you can arbitrarely specify the parent process, provided you have the rights (i.e. it’s your process or you have debug rights).
I developed a small tool to start a program while specifying its parent process: SelectMyParent. Here I use it to start notepad as a child of lsass.exe:
2 remarks about this example:
- to make lsass.exe a parent process, you need to use SelectMyParent with admin rights and elevate its rights (Run as administrator)
- the notepad process takes over the parent process’ account: NT AUTHORITY\SYSTEM
I don’t know how one can detect that a process’ parent is not the process that created it, because a process has no access to its extended startup info (only to its startup info). And it is the extended startup info that contains the attribute list with the handle to the parent process.
SelectMyParent version 0.0.0.1 is available here.
There are no real changes in this new version of bpmtk, only a new DLL (hook-createprocess.dll) was added. You can use this DLL to protect your Windows machine from getting infected by the current malicious documents found in-the-wild.
You can download bpmtk version 0.1.6.0 here.
Hook-createprocess.dll is a DLL that patches the process into which it is loaded to prevent it from creating new processes. It does this by patching the Import Address Table of kernel32.dll for ntdll.dll to hook API functions NtCreateProcessEx, NtCreateProcess and NtCreateUserProcess.
Calls to these functions are intercepted and not passed on to the original functions. Instead, a code is returned indicating that the operation was blocked. The result is that functions in kernel32 used to create new processes fail (like WinExec) and hence that the patched process can’t create new processes.
This is all it takes to block most shellcode found in malicious documents like PDF malware. Shellcode like this does the following:
Of course, since this protective measure is taken by patching the process, shellcode could undo this patching and bypass our protection. Or it could use the ntdll API and not be hindered by our patch. But actual malware found in-the-wild doesn’t do this (not talking about targeted attacks) and is thus prevented from executing the trojan it just downloaded or extracted from the PDF document.
If you want better protection, you’ll have to use something that works at the level of the kernel, like sandboxing software.
However, this patch comes with some drawbacks, because it also blocks bening new processes. For example, the update function of Adobe Acrobat requires the creation of a new process. To reenable the creation of processes, you have to unload hook-createprocess.dll (unloading removes the hooks). bpmtk has a function to unload DLLs from a process (reject).
There are a couple of trick to load this DLL with the program you want to protect. I’ll describe a generic method in an upcoming post, but now I want to explain it for a specific program.
Programs have a list of DLLs they need for their execution. We will use a PE-file editor to add our hook-createprocess.dll to this list. hook-createprocess.dll exports a dummy function (_Dummy) just so you can add to the imports table of an executable. We will use LordPE to add hook-createprocess.dll with _Dummy to Adobe Reader:
Right-click the Import table:
And don’t forget to save…
Here’s some Python code (it uses my mPDF module) to append a new PDF document to an existing PDF document to “hide” the original document. Recovering the original is trivial, you open the PDF document with a HEX-editor and delete the appended document (starting after the second %%EOF counting from the end of the file). This trick uses incremental updates.
__description__ = 'make-pdf-hide-original, use it to "hide" the original PDF document'
__author__ = 'Didier Stevens'
__version__ = '0.0.1'
__date__ = '2009/11/07'
Source code put in public domain by Didier Stevens, no Copyright
Use at your own risk
oParser = optparse.OptionParser(usage='usage: %prog [options] pdf-file\n' + __description__, version='%prog ' + __version__)
oParser.add_option('-s', '--line', default='Hello World', help='The line of text to print on the screen (default Hello World')
(options, args) = oParser.parse_args()
if len(args) != 1:
print ' %s' % __description__
print ' Source code put in the public domain by Didier Stevens, no Copyright'
print ' Use at your own risk'
print ' https://DidierStevens.com'
pdffile = args
oPDF = mPDF.cPDF(pdffile)
oPDF.stream(5, 0, 'BT /F1 24 Tf 100 700 Td (%s) Tj ET' % options.line)
oPDF.xrefAndTrailer('1 0 R')
if __name__ == '__main__':
The Extensible Metadata Platform is an Adobe standard to represent metadata with XML.
More than a year ago, I added an XML-bomb to XMP-data inside a PDF document:
As this made Adobe Reader 8 & 9 crash, I reported it to Adobe. It has been fixed with the last patch cycle.
Why do I disclose the details of this vulnerability? Because XMP is not only intended to be used in PDF documents, but many other file formats. So be sure to check your software for this vulnerability.