Reading one of the last ISC’s diaries reminds a trick we recently encountered during a malicious PDF document’s analysis.
It explains a somewhat special shellcode method in a PDF exploiting the latest 0-day vulnerability in Adobe Reader (Lexsi Ref. ). Indeed, it is very small (38 bytes only), and will search through the memory pages of the process to find a certain pattern, then jump to its address to continue execution. The pattern is in a compressed stream object within the malicious PDF document. The second shellcode decodes and runs two executables, also contained in the PDF. The first will open a non-malicious PDF document, while the second is a malware attempting to connect to a control channel.
The method we encountered is substantially identical. The vulnerability exploited is a heap-based buffer overflow in U3D file management (Lexsi Ref. ), and the heap-spraying trick is used to format the heap for the execution redirection. A quick look at the document shows that the injected shellcode in the heap is as follows:
Once loaded into the debugger, we face with a rather conventional beginning (for details, see this ):
- a loop is responsible for deciphering the shellcode by XOR-ing all the bytes with the value “0xF9″
- then, it will look for the addresses of several Windows API functions
The next step is more interesting: the shellcode will perform a brute-force of open file descriptors until finding one whose header corresponds to a PDF file, then check for some patterns located at certain offsets.
This will allow the shellcode to obtain a handle to the malicious PDF document, and to extract and decode a second shellcode by reading it at a specific offset. The result is very similar to the ISC’s analysis: the second shellcode will open a non-malicious PDF document and run a downloader binary included in the malicious PDF.
This method allows to search a second stage shellcode more reliably than by browsing the memory pages of the process, in which there is a risk of finding a sequence of bytes corresponding to the desired pattern without being the beginning of the shellcode, or trigger an error by accessing unmapped memory.