15 Commits
1.3 ... master

Author SHA1 Message Date
ben
3541e4a963 Update URL and Copyright 2025-09-01 20:45:35 +02:00
Ben
e92c8b5d4c Fix URLs in Readme 2021-08-29 23:13:27 +02:00
ben
ed510d928a Increase version for license. 2019-07-06 23:20:43 +02:00
ben
c914a2a6d5 Add LICENSE file. 2019-07-06 23:14:33 +02:00
ben
2b0737dd90 Fix readme. 2019-07-06 23:01:14 +02:00
ben
f8b968fa94 Add licence and fix readme. 2019-07-06 22:58:49 +02:00
ben
bc359714d7 Fix help. 2018-09-29 23:42:07 +02:00
ben
875747ad7a Add zipany format. v1.6 2018-09-29 23:37:54 +02:00
ben
200508be7f Fix PDF offset with acrobat-compatibility option. 2018-09-29 22:04:05 +02:00
ben
fc7e44a646 Rename pdfraw to pdfany and allow 2 payloads. v1.5.2 2018-09-29 14:06:08 +02:00
ben
04eb07f321 Fix help message 2018-09-29 00:17:53 +02:00
ben
caaaaafeb0 Add pdfraw format, v1.5 2018-09-29 00:12:49 +02:00
ben
7e962d60ad Add acrobat reader compatibility for szipdf format 2018-09-28 22:55:53 +02:00
ben
79ddd879c3 Change README 2018-09-28 22:24:40 +02:00
ben
3111008246 Clean source, remove website from src. 2018-09-28 22:21:03 +02:00
39 changed files with 509 additions and 423 deletions

24
LICENSE Normal file
View File

@@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>

View File

@@ -1,5 +1,32 @@
# -*- coding: utf-8 -*-
"""
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
"""
import logging
import re
import tempfile

View File

@@ -1,7 +1,8 @@
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
from .polyglotpdfzip import PolyglotPdfZip
from .polyglotpdfany import PolyglotPdfAny
from .polyglotzippdf import PolyglotZipPdf
from .polyglotszippdf import PolyglotSZipPdf
from .polyglotzipany import PolyglotZipAny

View File

@@ -0,0 +1,76 @@
# -*- coding: utf-8 -*-
"""
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
"""
import logging
'''
|-------------------------------| -
|--------- PDF Header ----------K1 | J1
|-------------------------------| -
|---- PDF OBJ 1 = Payload 1 ----K2 |
|-------------------------------| -
|---- Original PDF Ojbects -----K3 | J2
|-------------------------------| -
|-- PDF Last OBJ = Payload 2 ---K4 |
|-------------------------------| |
|---------- Xref Table ---------| |
|-------------------------------K5 |
|----------- Trailer -----------| |
|-------------------------------| |
'''
class PolyglotPdfAny():
from PdfFileTransformer import Pdf
def __init__(self, Pdf, payload1filename, payload2filename):
self.buffer = bytearray()
self.pdf = Pdf
self.payload1 = bytearray()
if payload1filename is not None:
with open(payload1filename, "rb") as f:
self.payload1 = f.read()
self.payload2 = bytearray()
if payload2filename is not None:
with open(payload2filename, "rb") as f:
self.payload2 = f.read()
def generate(self):
k2stream = self.payload1
if len(k2stream) > 0:
self.pdf.insert_new_obj_stream_at_start(k2stream)
k4stream = self.payload2
if len(k4stream) > 0:
self.pdf.insert_new_obj_stream_at_end(k4stream)
self.buffer = self.pdf.get_build_buffer()
def write(self, filename):
fd = open(filename, "wb")
fd.write(self.buffer)
fd.close()

View File

@@ -1,5 +1,32 @@
# -*- coding: utf-8 -*-
"""
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
"""
import logging
'''

View File

@@ -1,5 +1,32 @@
# -*- coding: utf-8 -*-
"""
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
"""
from .polyglotpdfzip import PolyglotPdfZip
import logging
import tempfile
@@ -28,8 +55,9 @@ from PdfFileTransformer import Pdf
class PolyglotSZipPdf(PolyglotPdfZip):
def __init__(self, Pdf, Zip):
def __init__(self, Pdf, Zip, acrobat_compatibility):
super().__init__(Pdf, Zip)
self.acrobat_compatibility = acrobat_compatibility
def get_rebuild_zip_first_part_size(self):
@@ -80,9 +108,15 @@ class PolyglotSZipPdf(PolyglotPdfZip):
k2_stream_offset = new_pdf.get_first_stream_offset()
new_pdf.file_offset = offset
if self.acrobat_compatibility:
new_pdf.file_offset = new_pdf.file_offset + 1
pdf_buffer = new_pdf.get_build_buffer()
j2 = pdf_buffer[k2_stream_offset + size_k2_stream:]
new_zip.add_data_to_file(b'', j2, True)
if self.acrobat_compatibility:
new_zip.add_data_to_file(b'\x00', j2, True)
else:
new_zip.add_data_to_file(b'', j2, True)
return new_zip.buffer

View File

@@ -0,0 +1,69 @@
# -*- coding: utf-8 -*-
"""
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
"""
import logging
'''
|-------------------------------| -
|---------- Payload 1 ----------K1 | J1
|-------------------------------| -
|---- ZIP Local File Header ----K2 |
|-------------------------------| -
|---------- Payload 2-----------K3 | J2
|-------------------------------| -
|---- ZIP Central Directory ----K4 |
|-------------------------------| |
|--- End of Central Directory --K5 |
|-------------------------------| |
'''
class PolyglotZipAny():
from ZipFileTransformer import Zip
def __init__(self, Zip, payload1filename, payload2filename):
self.buffer = bytearray()
self.zip = Zip
self.payload1 = bytearray()
if payload1filename is not None:
with open(payload1filename, "rb") as f:
self.payload1 = f.read()
self.payload2 = bytearray()
if payload2filename is not None:
with open(payload2filename, "rb") as f:
self.payload2 = f.read()
def generate(self):
self.zip.add_data_to_file(self.payload1, self.payload2, True)
self.buffer = self.zip.buffer
def write(self, filename):
fd = open(filename, "wb")
fd.write(self.buffer)
fd.close()

View File

@@ -1,5 +1,32 @@
# -*- coding: utf-8 -*-
"""
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
"""
from .polyglotpdfzip import PolyglotPdfZip

112
README.md
View File

@@ -1,3 +1,111 @@
# TruePolyglot
Truepolyglot is polyglot file generator project. It means the generated file is composed of several file formats. The same file can be opened as a ZIP file and as a PDF file for example. The idea of this project comes from the work of [Ange Albertini](https://github.com/corkami), [International Journal of Proof-of-Concept or Get The Fuck Out](https://www.alchemistowl.org/pocorgtfo/pocorgtfo07.pdf) and [Julia Wolf](https://www.troopers.de/wp-content/uploads/2011/04/TR11_Wolf_OMG_PDF.pdf) that explain how we can build a polyglot file.
Polyglot file can be boring to build, even more if you want to respect the file format correctly.
That's why I decided to build a tool to generate them.
My main motivation was the technical challenge.
## Features and versions ##
| Description | Version |
| ----------- | ------- |
| Build a polyglot file valid as PDF and ZIP format and that can be opened with 7Zip and Windows Explorer | POC |
| Add a stream object in the PDF part | POC |
| Polyglot file checked without warning with [pdftocairo](https://poppler.freedesktop.org/) | >= 1.0 |
| Polyglot file checked without warning with [caradoc](https://github.com/ANSSI-FR/caradoc) | >= 1.0 |
| Rebuild the PDF Xref Table | >= 1.0 |
| Stream object with the correct length header value | >= 1.0 |
| Add the format "zippdf", file without offset after the Zip data | >= 1.1 |
| Polyglot file keeps the original PDF version | >= 1.1.1 |
| Add the "szippdf" format without offset before and after the Zip data | >= 1.2 |
| Fix /Length stream object value and the PDF offset for the szippdf format | >= 1.2.1 |
| PDF object numbers reorder after insertion | >= 1.3 |
| Add the format "pdfany" a valid PDF with custom payload content in the first and the last objet | >= 1.5.2 |
| Add "acrobat-compatibility" option to allow szippdf to be read with Acrobat Reader (thanks Ange Albertini)| >= 1.5.3 |
| Add the format "zipany" a valid ZIP with custom payload content at the start and between LHF and CD | >= 1.6 |
## Polyglot file compatibility ##
| Software | Formats | status |
| -------- | ------- | ------ |
| Acrobat Reader | pdfzip, zippdf, szippdf, pdfany | OK |
| Sumatra PDF | pdfzip, zippdf, szippdf, pdfany | OK |
| Foxit PDF Reader | pdfzip, zippdf, szippdf, pdfany | OK |
| Edge | pdfzip, zippdf, szippdf, pdfany | OK |
| Firefox | pdfzip, zippdf, szippdf, pdfany | OK |
| 7zip | pdfzip, zippdf, zipany | OK with warning |
| 7zip | szippdf | OK |
| Explorer Windows | pdfzip, zippdf, szippdf, pdfany, zipany | OK |
| Info-ZIP (unzip) | pdfzip, zippdf, szippdf, pdfany, zipany | OK |
| Evince | pdfzip, zippdf, szippdf, pdfany | OK |
| pdftocairo -pdf | pdfzip, zippdf, szippdf, pdfany | OK |
| caradoc stats | pdfzip, pdfany | OK |
| java -jar | szippdf | OK |
## Examples ##
| First input file | Second input file | Format | Polyglot | Comment |
| ---------------- | ----------------- | ------ | -------- | ------- |
| [doc.pdf](https://truepolyglot.hackade.org/samples/pdfzip/poc1/doc.pdf) | [archive.zip](https://truepolyglot.hackade.org/samples/pdfzip/poc1/archive.zip) | pdfzip | [polyglot.pdf](https://truepolyglot.hackade.org/samples/pdfzip/poc1/polyglot.pdf) | PDF/ZIP polyglot - 122 Ko |
| [orwell\_1984.pdf](https://truepolyglot.hackade.org/samples/pdfzip/poc2/orwell_1984.pdf) | [file-FILE5\_32.zip](https://truepolyglot.hackade.org/samples/pdfzip/poc2/file-FILE5_32.zip) | pdfzip | [polyglot.pdf](https://truepolyglot.hackade.org/samples/pdfzip/poc2/polyglot.pdf) | PDF/ZIP polyglot - 1.3 Mo |
| [x86asm.pdf](https://truepolyglot.hackade.org/samples/pdfzip/poc3/x86asm.pdf) | [fasmw17304.zip](https://truepolyglot.hackade.org/samples/pdfzip/poc3/fasmw17304.zip) | pdfzip | [polyglot.pdf](https://truepolyglot.hackade.org/samples/pdfzip/poc3/polyglot.pdf) | PDF/ZIP polyglot - 1.8 Mo |
| [doc.pdf](/samples/zippdf/poc4/doc.pdf) | [archive.zip](/samples/zippdf/poc4/archive.zip) | zippdf | [polyglot.pdf](/samples/zippdf/poc4/polyglot.pdf) | PDF/ZIP polyglot - 112 Ko |
| [electronics.pdf](https://truepolyglot.hackade.org/samples/szippdf/poc5/electronics.pdf) | [hello\_world.jar](https://truepolyglot.hackade.org/samples/szippdf/poc5/hello_world.jar) | szippdf | [polyglot.pdf](https://truepolyglot.hackade.org/samples/szippdf/poc5/polyglot.pdf) | PDF/JAR polyglot - 778 Ko |
| [hexinator.pdf](https://truepolyglot.hackade.org/samples/pdfzip/poc6/hexinator.pdf) | [eicar.zip](https://truepolyglot.hackade.org/samples/pdfzip/poc6/eicar.zip) ([scan virustotal.com](https://www.virustotal.com/#/file/2174e17e6b03bb398666c128e6ab0a27d4ad6f7d7922127fe828e07aa94ab79d/detection)) | pdfzip | [polyglot.pdf](https://truepolyglot.hackade.org/samples/pdfzip/poc6/polyglot.pdf) ([scan virustotal.com](https://www.virustotal.com/#/file/f6fef31e3b03164bb3bdf35af0521f9fc0c518a9e0f1aa9f8b60ac936201591a/detection)) | PDF/ZIP polyglot with the Eicar test in Zip - 2.9 Mo |
| [doc.pdf](https://truepolyglot.hackade.org/samples/pdfany/poc7/doc.pdf) | [page.html](https://truepolyglot.hackade.org/samples/pdfany/poc7/page.html) | pdfany | [polyglot.pdf](https://truepolyglot.hackade.org/samples/pdfany/poc7/polyglot.pdf) | PDF/HTML polyglot - 26 Ko |
| [logo.zip](https://truepolyglot.hackade.org/samples/zipany/poc8/logo.zip) | [nc.exe](https://truepolyglot.hackade.org/samples/zipany/poc8/nc.exe) | zipany | [polyglot.zip](https://truepolyglot.hackade.org/samples/zipany/poc8/polyglot.zip) | PDF/PE polyglot - 96 Ko |
## Usage ##
```
usage: truepolyglot format [options] output-file
Generate a polyglot file.
Formats availables:
* pdfzip: Generate a file valid as PDF and ZIP. The format is closest to PDF.
* zippdf: Generate a file valid as ZIP and PDF. The format is closest to ZIP.
* szippdf: Generate a file valid as ZIP and PDF. The format is strictly a ZIP. Archive is modified.
* pdfany: Generate a valid PDF file with payload1 file content as the first object or/and payload2 file content as the last object.
* zipany: Generate a valid ZIP file with payload1 file content at the start of the file or/and payload2 file content between LFH and CD.
positional arguments: {pdfzip,zippdf,szippdf,pdfany,zipany}
Output polyglot format
output_file Output polyglot file path
optional arguments:
-h, --help show this help message and exit
--pdffile PDFFILE PDF input file
--zipfile ZIPFILE ZIP input file
--payload1file PAYLOAD1FILE Payload 1 input file
--payload2file PAYLOAD2FILE Payload 2 input file
--acrobat-compatibility Add a byte at the start for Acrobat Reader compatibility with the szippdf format
--verbose {none,error,info,debug} Verbosity level (default: info)
TruePolyglot v1.6.2
```
## Code ##
```
git clone https://git.sr.ht/~hackade/truepolyglot
```
or download [truepolyglot-1.6.2.tar.gz](https://git.sr.ht/~hackade/truepolyglot/archive/1.6.2.tar.gz)
## How to detect a polyglot file ? ##
You can use [binwalk](https://github.com/ReFirmLabs/binwalk) on a file to see if composed of multiple files.
## Contact ##
[truepolyglot@hackade.org](mailto:truepolyglot@hackade.org)
## Credits ##
Copyright © 2018-2025 ben@hackade.org
TruePolyglot is released under [Unlicence](https://unlicense.org/) except for the following libraries:
* [PyPDF2](https://github.com/mstamy2/PyPDF2/blob/master/LICENSE)
* [zipfile.py (cpython)](https://github.com/python/cpython/blob/master/LICENSE)
See webiste at https://truepolyglot.hackade.org

View File

@@ -1,5 +1,32 @@
# -*- coding: utf-8 -*-
"""
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
"""
import logging
import re

BIN
caradoc

Binary file not shown.

View File

@@ -23,6 +23,10 @@ EXAMPLES
# see https://github.com/mstamy2/PyPDF2/LICENSE
from __future__ import print_function
import sys
sys.path.append("../")
import argparse
from PdfFileTransformer.PyPDF2.pagerange import PAGE_RANGE_HELP

View File

@@ -1,12 +1,44 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
"""
import argparse
import logging
from PdfFileTransformer import Pdf
from ZipFileTransformer import Zip
from PolyglotFile import PolyglotZipPdf, PolyglotPdfZip, PolyglotSZipPdf
from PolyglotFile import PolyglotZipPdf
from PolyglotFile import PolyglotPdfZip
from PolyglotFile import PolyglotSZipPdf
from PolyglotFile import PolyglotPdfAny
from PolyglotFile import PolyglotZipAny
def main():
@@ -16,10 +48,18 @@ def main():
'* zippdf: Generate a file valid as ZIP and PDF.' +
' The format is closest to ZIP.\n' +
'* szippdf: Generate a file valid as ZIP and PDF.' +
' The format is strictly a ZIP.' +
' Archive is modified.')
' The format is strictly a ZIP.\n' +
' Archive is modified.\n' +
'* pdfany: Generate a valid PDF file with payload1' +
' file content as the first object\n' +
' or/and payload2 file' +
' content as the last oject.\n' +
'* zipany: Generate a valid ZIP file with payload1' +
' file content at the start of the file\n' +
' or/and payload2 file content between' +
' LFH and CD.\n')
usage_str = '%(prog)s format [options] output-file'
epilog_str = 'TruePolyglot v1.3'
epilog_str = 'TruePolyglot v1.6.2'
frm = argparse.RawTextHelpFormatter
parser = argparse.ArgumentParser(description=description_str,
epilog=epilog_str,
@@ -27,14 +67,24 @@ def main():
formatter_class=frm)
parser.add_argument('format', nargs='+', choices=["pdfzip",
"zippdf",
"szippdf"],
"szippdf",
"pdfany",
"zipany"],
help='Output polyglot format')
parser.add_argument('--pdffile', dest='pdffile',
help='PDF input file')
parser.add_argument('--zipfile', dest='zipfile',
help='ZIP input file')
parser.add_argument('--payload1file', dest='payload1file',
help='Payload 1 input file')
parser.add_argument('--payload2file', dest='payload2file',
help='Payload 2 input file')
parser.add_argument('--acrobat-compatibility',
dest='acrobat_compatibility',
help='Add a byte at the start for Acrobat Reader compatibility with the szippdf format',
action='store_true')
parser.add_argument('--verbose', dest='verbose',
help='Verbosity level (default: debug)',
help='Verbosity level (default: info)',
default="info",
choices=["none", "error", "info", "debug"])
parser.add_argument('output_file', nargs='+',
@@ -42,12 +92,15 @@ def main():
args = parser.parse_args()
formats = ["pdfzip", "zippdf", "szippdf"]
if args.format[0] in formats:
if args.pdffile is None:
parser.error('pdffile is required')
if args.zipfile is None:
parser.error('zipfile is required')
if args.acrobat_compatibility and args.format[0] != "szippdf":
parser.error('--acrobat-compatibility is for szippdf only')
if "pdf" in args.format[0] and args.pdffile is None:
parser.error('pdffile is required')
if "zip" in args.format[0] and args.zipfile is None:
parser.error('zipfile is required')
if ("any" in args.format[0] and args.payload1file is None and
args.payload2file is None):
parser.error('payload1file or payload2file is required')
if args.verbose == "none":
logging.basicConfig(level=logging.CRITICAL)
@@ -58,14 +111,26 @@ def main():
if args.verbose == "debug":
logging.basicConfig(level=logging.DEBUG)
p = Pdf(args.pdffile)
z = Zip(args.zipfile)
if args.format[0] == "pdfzip":
p = Pdf(args.pdffile)
z = Zip(args.zipfile)
a = PolyglotPdfZip(p, z)
if args.format[0] == "zippdf":
p = Pdf(args.pdffile)
z = Zip(args.zipfile)
a = PolyglotZipPdf(p, z)
if args.format[0] == "szippdf":
a = PolyglotSZipPdf(p, z)
p = Pdf(args.pdffile)
z = Zip(args.zipfile)
a = PolyglotSZipPdf(p, z, args.acrobat_compatibility)
if args.format[0] == "pdfany":
p = Pdf(args.pdffile)
a = PolyglotPdfAny(p, args.payload1file, args.payload2file)
if args.format[0] == "zipany":
z = Zip(args.zipfile)
a = PolyglotZipAny(z, args.payload1file, args.payload2file)
a.generate()
a.write(args.output_file[0])

View File

@@ -1,63 +0,0 @@
html {
background-color: black;
font-family: Consolas,monaco,monospace;
color: #92D050;
}
body {
background-color: black;
font-family: Consolas,monaco,monospace;
color: #92D050;
}
td {
background-color: black;
font-family: Consolas,monaco,monospace;
color: #92D050;
}
th {
background-color: black;
font-family: Consolas,monaco,monospace;
color: #92D050;
}
h1 {
color: white;
}
a:link {
color: #47B8C7;
}
a:visited {
color: #47B8C7;
}
a:active {
color: #47B8C7;
}
table {
border-collapse: collapse;
}
table, th, td {
border: 1px solid white;
}
th {
background-color: #92D050;
color: black;
}
th {
padding-left: 0.5em;
padding-right: 0.5em;
padding-top: 0.5em;
padding-bottom: 0.5em;
}
td {
padding-left: 0.5em;
padding-right: 0.5em;
padding-bottom: 0.5em;
padding-top: 0.5em;
text-align: left;
}
.font_reduce {
font-size: 75%;
}
.warning {
color: #ffb833;
}

View File

@@ -1,61 +0,0 @@
html {
background-color: black;
font-family: Consolas,monaco,monospace;
color: #92D050;
}
body {
background-color: black;
font-family: Consolas,monaco,monospace;
color: #92D050;
}
td {
background-color: black;
font-family: Consolas,monaco,monospace;
color: #92D050;
}
th {
background-color: black;
font-family: Consolas,monaco,monospace;
color: #92D050;
}
a:link {
color: #47B8C7;
}
a:visited {
color: #47B8C7;
}
a:active {
color: #47B8C7;
}
table {
border-collapse: collapse;
}
table, th, td {
border: 1px solid white;
}
th {
background-color: #92D050;
color: black;
}
th {
padding-left: 0.5em;
padding-right: 0.5em;
padding-top: 0.5em;
padding-bottom: 0.5em;
}
td {
padding-left: 0.5em;
padding-right: 0.5em;
padding-bottom: 0.5em;
padding-top: 0.5em;
text-align: left;
}
th a:link {
color: black;
}
th a:visited {
color: black;
}
th a:active {
color: black;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 318 B

View File

@@ -1,21 +0,0 @@
#!/bin/bash
find -type f -name 'polyglot.pdf' -delete
mkdir -p ./samples/pdfzip/poc1/
../truepolyglot pdfzip --pdffile ./samples/pdfzip/poc1/doc.pdf --zipfile ./samples/pdfzip/poc1/archive.zip ./samples/pdfzip/poc1/polyglot.pdf
mkdir -p ./samples/pdfzip/poc2/
../truepolyglot pdfzip --pdffile ./samples/pdfzip/poc2/orwell_1984.pdf --zipfile ./samples/pdfzip/poc2/file-FILE5_32.zip ./samples/pdfzip/poc2/polyglot.pdf
mkdir -p ./samples/pdfzip/poc3/
../truepolyglot pdfzip --pdffile ./samples/pdfzip/poc3/x86asm.pdf --zipfile ./samples/pdfzip/poc3/fasmw17304.zip ./samples/pdfzip/poc3/polyglot.pdf
mkdir -p ./samples/zippdf/poc4/
../truepolyglot zippdf --pdffile ./samples/zippdf/poc4/doc.pdf --zipfile ./samples/zippdf/poc4/archive.zip ./samples/zippdf/poc4/polyglot.pdf
mkdir -p ./samples/szippdf/poc5/
../truepolyglot szippdf --pdffile ./samples/szippdf/poc5/electronics.pdf --zipfile ./samples/szippdf/poc5/hello_world.jar ./samples/szippdf/poc5/polyglot.pdf
mkdir -p ./samples/pdfzip/poc6/
../truepolyglot pdfzip --pdffile ./samples/pdfzip/poc6/hexinator.pdf --zipfile ./samples/pdfzip/poc6/eicar.zip ./samples/pdfzip/poc6/polyglot.pdf

View File

@@ -1,251 +0,0 @@
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<title>TruePolyglot</title>
<meta name="description" content="TruePolyglot project website">
<meta name="author" content="hackade">
<link rel="stylesheet" href="css/styles.css">
<link rel="shortcut icon" href="/favicon.ico">
</head>
<body>
<h1>TruePolyglot</h1>
Truepolyglot is polyglot file generator project.
This means that the generated file is composed of several file formats. The same file can be opened as a ZIP file and as a PDF file for example.
The idea of this project comes from work of <a href="https://github.com/corkami">Ange Albertini</a>, <a href="https://www.alchemistowl.org/pocorgtfo/pocorgtfo07.pdf">International Journal of Proof-of-Concept or Get The Fuck Out</a> and <a href="https://www.troopers.de/wp-content/uploads/2011/04/TR11_Wolf_OMG_PDF.pdf">Julia Wolf</a> that explain how we can build a polyglot file.<br>
Polyglot file can be fastidious to build, even more if you want to respect correctly file format. That's why I decided to build a tool to generate them.<br>
My main motivation was the technical challenge.
<br>
<h2>Features and changelog</h2>
<div class="font_reduce">
<table>
<tr>
<th>Description</th>
<th>Version</th>
</tr>
<tr>
<td>Build a polyglot file valid as PDF and ZIP format and that can be opened with 7Zip and Windows Explorer</td>
<td>POC</td>
</tr>
<tr>
<td>Add a stream object in PDF part</td>
<td>POC</td>
</tr>
<tr>
<td>Polyglot file checked without warning with <a href="https://poppler.freedesktop.org/">pdftocairo</a></td>
<td> &gt;= 1.0</td>
</tr>
<tr>
<td>Polyglot file checked without warning with <a href="https://github.com/ANSSI-FR/caradoc">caradoc</a></td>
<td> &gt;= 1.0</td>
</tr>
<tr>
<td>Rebuild PDF Xref Table</td>
<td>&gt;= 1.0</td>
</tr>
<tr>
<td>Stream object with correct length header value</td>
<td>&gt;= 1.0</td>
</tr>
<tr>
<td>Format "zippdf", file without offset after Zip data</td>
<td>&gt;= 1.1</td>
</tr>
<tr>
<td>Polyglot file keep original PDF version</td>
<td>&gt;= 1.1.1</td>
</tr>
<tr>
<td>Add "szippdf" format without offset before and after Zip data</td>
<td>&gt;= 1.2</td>
</tr>
<tr>
<td>Fix /Length stream object value and PDF offset for szippdf format</td>
<td>&gt;= 1.2.1</td>
</tr>
<tr>
<td>PDF object numbers reorder after insertion</td>
<td>&gt;= 1.3</td>
</tr>
</table>
</div>
<h2>Polyglot file compatibility</h2>
<div class="font_reduce">
<table>
<tr>
<th>Software</th>
<th>Formats</th>
<th>status</th>
</tr>
<tr>
<td>Acrobat Reader</td>
<td>pdfzip, zippdf</td>
<td>OK</td>
</tr>
<tr>
<td>Acrobat Reader</td>
<td>szippdf</td>
<td><span class="warning">KO</span></td>
</tr>
<tr>
<td>Sumatra PDF</td>
<td>pdfzip, zippdf, szippdf</td>
<td>OK</td>
</tr>
<tr>
<td>Edge</td>
<td>pdfzip, zippdf, szippdf</td>
<td>OK</td>
</tr>
<tr>
<td>Firefox</td>
<td>pdfzip, zippdf, szippdf</td>
<td>OK</td>
</tr>
<tr>
<td>7zip</td>
<td>pdfzip, zippdf</td>
<td><span class="warning">OK with warning</span></td>
</tr>
<tr>
<td>7zip</td>
<td>szippdf</td>
<td>OK</td>
</tr>
<tr>
<td>Explorer Windows</td>
<td>pdfzip, zippdf, szippdf</td>
<td>OK</td>
</tr>
<tr>
<td>Info-ZIP (unzip)</td>
<td>pdfzip, zippdf, szippdf</td>
<td>OK</td>
</tr>
<tr>
<td>Evince</td>
<td>pdfzip, zippdf, szippdf</td>
<td>OK</td>
</tr>
<tr>
<td>pdftocairo -pdf</td>
<td>pdfzip, zippdf, szippdf</td>
<td>OK</td>
</tr>
<tr>
<td>caradoc stats</td>
<td>pdfzip</td>
<td>OK</td>
</tr>
<tr>
<td>java</td>
<td>szippdf</td>
<td>OK</td>
</tr>
</table>
</div>
<h2>Examples</h2>
<ul>
<li><a href="/samples/">Polyglot files repository</a></li>
</ul>
<div class="font_reduce">
<table>
<tr>
<th>PDF input file</th>
<th>Zip input file</th>
<th>Format</th>
<th>Polyglot</th>
<th>Comment</th>
</tr>
<tr>
<td><a href="/samples/pdfzip/poc1/doc.pdf">doc.pdf</a></td>
<td><a href="/samples/pdfzip/poc1/archive.zip">archive.zip</a></td>
<td>pdfzip</td>
<td><a href="/samples/pdfzip/poc1/polyglot.pdf">polyglot.pdf</a></td>
<td>PDF/ZIP polyglot - 122 Ko</td>
</tr>
<tr>
<td><a href="/samples/pdfzip/poc2/orwell_1984.pdf">orwell_1984.pdf</a></td>
<td><a href="/samples/pdfzip/poc2/file-FILE5_32.zip">file-FILE5_32.zip</a></td>
<td>pdfzip</td>
<td><a href="/samples/pdfzip/poc2/polyglot.pdf">polyglot.pdf</a></td>
<td>PDF/ZIP polyglot - 1.3 Mo</td>
</tr>
<tr>
<td><a href="/samples/pdfzip/poc3/x86asm.pdf">x86asm.pdf</a></td>
<td><a href="/samples/pdfzip/poc3/fasmw17304.zip">fasmw17304.zip</a></td>
<td>pdfzip</td>
<td><a href="/samples/pdfzip/poc3/polyglot.pdf">polyglot.pdf</a></td>
<td>PDF/ZIP polyglot - 1.8 Mo</td>
</tr>
<tr>
<td><a href="/samples/zippdf/poc4/doc.pdf">doc.pdf</a></td>
<td><a href="/samples/zippdf/poc4/archive.zip">archive.zip</a></td>
<td>zippdf</td>
<td><a href="/samples/zippdf/poc4/polyglot.pdf">polyglot.pdf</a></td>
<td>PDF/ZIP polyglot - 112 Ko</td>
</tr>
<tr>
<td><a href="/samples/szippdf/poc5/electronics.pdf">electronics.pdf</a></td>
<td><a href="/samples/szippdf/poc5/hello_world.jar">hello_world.jar</a></td>
<td>szippdf</td>
<td><a href="/samples/szippdf/poc5/polyglot.pdf">polyglot.pdf</a></td>
<td>PDF/JAR polyglot - 778 Ko</td>
</tr>
<tr>
<td><a href="/samples/pdfzip/poc6/hexinator.pdf">hexinator.pdf</a></td>
<td><a href="/samples/pdfzip/poc6/eicar.zip">eicar.zip</a>&nbsp;(<a href="https://www.virustotal.com/#/file/2174e17e6b03bb398666c128e6ab0a27d4ad6f7d7922127fe828e07aa94ab79d/detection">scan virustotal.com</a>)</td>
<td>pdfzip</td>
<td><a href="/samples/pdfzip/poc6/polyglot.pdf">polyglot.pdf</a>&nbsp;(<a href="https://www.virustotal.com/#/file/f6fef31e3b03164bb3bdf35af0521f9fc0c518a9e0f1aa9f8b60ac936201591a/detection">scan virustotal.com</a>)</td>
<td>PDF/ZIP polyglot with Eicar test in Zip - 2.9 Mo</td>
</tr>
</table>
</div>
<h2>Manual</h2>
<pre>
usage: truepolyglot format [options] output-file
Generate a polyglot file.
Formats availables:
* pdfzip: Generate a file valid as PDF and ZIP. The format is closest to PDF.
* zippdf: Generate a file valid as ZIP and PDF. The format is closest to ZIP.
* szippdf: Generate a file valid as ZIP and PDF. The format is strictly a ZIP. Archive is modified.
positional arguments:
{pdfzip,zippdf,szippdf}
Output polyglot format
output_file Output polyglot file path
optional arguments:
-h, --help show this help message and exit
--pdffile PDFFILE PDF input file
--zipfile ZIPFILE ZIP input file
--verbose {none,error,info,debug}
Verbosity level (default: info)
TruePolyglot v1.3
</pre>
<h2>Code</h2>
<pre>
git clone <a href="https://git.hackade.org/truepolyglot.git/">https://git.hackade.org/truepolyglot.git/</a>
</pre>
<h2>Contact</h2>
On <a href="https://webchat.freenode.net/">IRC Freenode</a> my nickname is hackade or by mail at <a href="mailtp:truepolyglot@hackade.org">truepolyglot@hackade.org</a>.
</body>
</html>

View File

@@ -1,2 +0,0 @@
User-agent: *
Disallow: /

Binary file not shown.

Binary file not shown.

View File

@@ -1,3 +0,0 @@
#!/bin/bash
echo "http://127.0.0.1:8000"
python -m SimpleHTTPServer 8000

View File

@@ -1,2 +0,0 @@
#!/bin/bash
rsync -av --progress ./ -e ssh dragon:/var/www/html/truepolyglot/