Skip to content

Commit aaf89ec

Browse files
author
RedTeam Pentesting GmbH
committed
Refactoring, Readme, added scripts for attaching files to the output PDF
1 parent 24f8788 commit aaf89ec

8 files changed

+135
-0
lines changed

README.md

+99
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,102 @@ This repository contains PostScript examples useful for attacking Ghostscript.
22

33
For details see the corresponding blog post:
44
https://blog.redteam-pentesting.de/2023/ghostscript-overview/
5+
6+
## `print_version.ps`
7+
8+
Modified version of `print_version.ps` from [ghostinthepdf](https://github.com/neex/ghostinthepdf). Prints useful information about the configuration of Ghostscript.
9+
10+
## `list_files.ps`
11+
12+
Prints all filenames contained in the specified directory (by default `/tmp/`) to the output page.
13+
14+
### Variables
15+
16+
```
17+
% how many chars per line at most
18+
/charactercount 100 def
19+
20+
% Which directory should be listed
21+
/target_directory (/tmp/*) def
22+
```
23+
24+
## `print_file.ps`
25+
26+
Writes the content of the specified file to the page. The used function needs to be specified at the end of the code:
27+
28+
- `PrintFileBase64`: Prints files encoded as Base64 onto the page, useful for binary files.
29+
30+
```
31+
(/usr/bin/bash) PrintFileBase64
32+
```
33+
34+
- `PrintFileAsText`: Prints the content of files onto the page, respects newlines. Useful for simple text files, but binary files can also be printed if needed.
35+
36+
```
37+
(/etc/passwd) PrintFileAsText
38+
```
39+
40+
### Variables
41+
42+
```
43+
% how many chars per line at most
44+
/charactercount 100 def
45+
```
46+
47+
## `embed_files_in_pdf.ps`
48+
49+
This script embeds all files in the specified directory (by default `/tmp/`) in the output PDF file using PDFMark.
50+
Only works with `pdfwrite` device for that reason.
51+
Use `extract_pdf_attachments.py` to extract all files from the PDF, or any capable PDF reader.
52+
53+
### Variables
54+
55+
```
56+
% How many files can be included at most
57+
/maxFileCount 100 def
58+
59+
% The folder with wildcard which will be embedded
60+
/targetFolder (/tmp/*) def
61+
62+
% Enables printing error information to the page
63+
/printErrors false def
64+
```
65+
66+
## `long_running_embed_files.ps`
67+
68+
Similar to `embed_files_in_pdf.ps`, but runs for a specified amount of time and collects short-lived files by scanning the specified directory in regular intervals.
69+
70+
### Variables
71+
72+
```
73+
% how often files should be checked
74+
/totalRounds 1000 def
75+
76+
% How many milliseconds to sleep inbetween rounds
77+
/sleepDuration 10 def
78+
79+
% How many files can be included at most
80+
/maxFileCount 100 def
81+
82+
% The folder with wildcard which will be embedded
83+
/targetFolder (/tmp/*) def
84+
85+
% Enables printing error information to the page
86+
/printErrors false def
87+
```
88+
89+
## `write_file.ps`
90+
91+
Writing files onto the disk. The used function needs to be specified at the end of the code:
92+
93+
- Writing plaintext: Useful for simple and short text file:
94+
95+
```
96+
outfile (Output string which will be written to outfile) writestring
97+
```
98+
99+
- `base64Decode`: Base64 decodes the input string. Useful for embedding (binary) files in PostScript. Decoding and writing to file:
100+
101+
```
102+
(SGFsbG8gV2VsdAo=) base64Decode { outfile exch write } forall
103+
```

embed_files_in_pdf.ps

4.92 KB
Binary file not shown.

extract_pdf_attachments.py

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/usr/bin/python3
2+
# very slightly modified version of https://gist.github.com/kevinl95/29a9e18d474eb6e23372074deff2df38 with cmd arguments and by default no output
3+
import PyPDF2
4+
import sys
5+
from pathlib import Path
6+
7+
8+
def getAttachments(reader):
9+
"""
10+
Retrieves the file attachments of the PDF as a dictionary of file names
11+
and the file data as a bytestring.
12+
:return: dictionary of filenames and bytestrings
13+
"""
14+
catalog = reader.trailer["/Root"]
15+
fileNames = catalog["/Names"]["/EmbeddedFiles"]["/Kids"][0].getObject()["/Names"]
16+
attachments = {}
17+
for f in fileNames:
18+
if isinstance(f, str):
19+
name = f
20+
dataIndex = fileNames.index(f) + 1
21+
fDict = fileNames[dataIndex].getObject()
22+
fData = fDict["/EF"]["/F"].getData()
23+
attachments[name] = fData
24+
return attachments
25+
26+
27+
handler = open(sys.argv[1], "rb")
28+
reader = PyPDF2.PdfFileReader(handler)
29+
dictionary = getAttachments(reader)
30+
31+
# print(dictionary)
32+
for fName, fData in dictionary.items():
33+
path = Path.cwd() / ("." + str(Path(fName).resolve()))
34+
path.parent.mkdir(parents=True, exist_ok=True)
35+
with open(path, "wb") as outfile:
36+
outfile.write(fData)

list_files.ps

1.2 KB
Binary file not shown.

long_running_embed_files_in_pdf.ps

5.85 KB
Binary file not shown.

print_file.ps

572 Bytes
Binary file not shown.

print_version.ps

1.51 KB
Binary file not shown.

write_file.ps

239 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)