7 Commits
1.4 ... 1.6.1

Author SHA1 Message Date
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
5 changed files with 155 additions and 17 deletions

View File

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

View File

@@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
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

@@ -28,8 +28,9 @@ from PdfFileTransformer import Pdf
class PolyglotSZipPdf(PolyglotPdfZip): class PolyglotSZipPdf(PolyglotPdfZip):
def __init__(self, Pdf, Zip): def __init__(self, Pdf, Zip, acrobat_compatibility):
super().__init__(Pdf, Zip) super().__init__(Pdf, Zip)
self.acrobat_compatibility = acrobat_compatibility
def get_rebuild_zip_first_part_size(self): def get_rebuild_zip_first_part_size(self):
@@ -80,8 +81,14 @@ class PolyglotSZipPdf(PolyglotPdfZip):
k2_stream_offset = new_pdf.get_first_stream_offset() k2_stream_offset = new_pdf.get_first_stream_offset()
new_pdf.file_offset = 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() pdf_buffer = new_pdf.get_build_buffer()
j2 = pdf_buffer[k2_stream_offset + size_k2_stream:] j2 = pdf_buffer[k2_stream_offset + size_k2_stream:]
if self.acrobat_compatibility:
new_zip.add_data_to_file(b'\x00', j2, True)
else:
new_zip.add_data_to_file(b'', j2, True) new_zip.add_data_to_file(b'', j2, True)
return new_zip.buffer return new_zip.buffer

View File

@@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
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

@@ -6,7 +6,12 @@ import logging
from PdfFileTransformer import Pdf from PdfFileTransformer import Pdf
from ZipFileTransformer import Zip 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(): def main():
@@ -16,10 +21,18 @@ def main():
'* zippdf: Generate a file valid as ZIP and PDF.' + '* zippdf: Generate a file valid as ZIP and PDF.' +
' The format is closest to ZIP.\n' + ' The format is closest to ZIP.\n' +
'* szippdf: Generate a file valid as ZIP and PDF.' + '* szippdf: Generate a file valid as ZIP and PDF.' +
' The format is strictly a ZIP.' + ' The format is strictly a ZIP.\n' +
' Archive is modified.') ' Archive is modified.\n' +
'* pdfany: Generate a valid PDF file with payload1' +
' file content as first object\n' +
' or/and payload2 file' +
' content as last oject.\n' +
'* zipany: Generate a valid ZIP file with payload1' +
' file content at start of file\n' +
' or/and payload2 file content between' +
' LFH and CD.\n')
usage_str = '%(prog)s format [options] output-file' usage_str = '%(prog)s format [options] output-file'
epilog_str = 'TruePolyglot v1.3' epilog_str = 'TruePolyglot v1.6.1'
frm = argparse.RawTextHelpFormatter frm = argparse.RawTextHelpFormatter
parser = argparse.ArgumentParser(description=description_str, parser = argparse.ArgumentParser(description=description_str,
epilog=epilog_str, epilog=epilog_str,
@@ -27,14 +40,24 @@ def main():
formatter_class=frm) formatter_class=frm)
parser.add_argument('format', nargs='+', choices=["pdfzip", parser.add_argument('format', nargs='+', choices=["pdfzip",
"zippdf", "zippdf",
"szippdf"], "szippdf",
"pdfany",
"zipany"],
help='Output polyglot format') help='Output polyglot format')
parser.add_argument('--pdffile', dest='pdffile', parser.add_argument('--pdffile', dest='pdffile',
help='PDF input file') help='PDF input file')
parser.add_argument('--zipfile', dest='zipfile', parser.add_argument('--zipfile', dest='zipfile',
help='ZIP input file') 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 start for Acrobat Reader compatibility with szippdf format',
action='store_true')
parser.add_argument('--verbose', dest='verbose', parser.add_argument('--verbose', dest='verbose',
help='Verbosity level (default: debug)', help='Verbosity level (default: info)',
default="info", default="info",
choices=["none", "error", "info", "debug"]) choices=["none", "error", "info", "debug"])
parser.add_argument('output_file', nargs='+', parser.add_argument('output_file', nargs='+',
@@ -42,12 +65,15 @@ def main():
args = parser.parse_args() args = parser.parse_args()
formats = ["pdfzip", "zippdf", "szippdf"] if args.acrobat_compatibility and args.format[0] != "szippdf":
if args.format[0] in formats: parser.error('--acrobat-compatibility is for szippdf only')
if args.pdffile is None: if "pdf" in args.format[0] and args.pdffile is None:
parser.error('pdffile is required') parser.error('pdffile is required')
if args.zipfile is None: if "zip" in args.format[0] and args.zipfile is None:
parser.error('zipfile is required') 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": if args.verbose == "none":
logging.basicConfig(level=logging.CRITICAL) logging.basicConfig(level=logging.CRITICAL)
@@ -58,14 +84,26 @@ def main():
if args.verbose == "debug": if args.verbose == "debug":
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG)
if args.format[0] == "pdfzip":
p = Pdf(args.pdffile) p = Pdf(args.pdffile)
z = Zip(args.zipfile) z = Zip(args.zipfile)
if args.format[0] == "pdfzip":
a = PolyglotPdfZip(p, z) a = PolyglotPdfZip(p, z)
if args.format[0] == "zippdf": if args.format[0] == "zippdf":
p = Pdf(args.pdffile)
z = Zip(args.zipfile)
a = PolyglotZipPdf(p, z) a = PolyglotZipPdf(p, z)
if args.format[0] == "szippdf": 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.generate()
a.write(args.output_file[0]) a.write(args.output_file[0])