import ctypes
import io
from functools import reduce, partial
+import mmap
import os
import struct
import sys
###############################################################################
+## restoration
+###############################################################################
+
+class Location (object):
+ n = 0
+ offset = 0
+
+def restore_loc_fmt (loc):
+ return "%d off:%d" \
+ % (loc.n, loc.offset)
+
+def locate_hdr_candidates (fd):
+ """
+ Walk over instances of the magic string in the payload, collecting their
+ positions. If the offset of the first found instance is not zero, the file
+ begins with leading garbage.
+
+ :return: The list of offsets in the file.
+ """
+ cands = []
+
+ mm = mmap.mmap(fd, 0, mmap.MAP_SHARED, mmap.PROT_READ)
+ pos = 0
+ while True:
+ pos = mm.find (PDTCRYPT_HDR_MAGIC, pos)
+ if pos == -1:
+ break
+ cands.append (pos)
+ pos += 1
+
+ return cands
+
+
+###############################################################################
## passthrough / null encryption
###############################################################################
PDTCRYPT_SUB_PROCESS = 0
PDTCRYPT_SUB_SCRYPT = 1
+PDTCRYPT_SUB_SCAN = 2
PDTCRYPT_SUB = \
{ "process" : PDTCRYPT_SUB_PROCESS
- , "scrypt" : PDTCRYPT_SUB_SCRYPT }
+ , "scrypt" : PDTCRYPT_SUB_SCRYPT
+ , "scan" : PDTCRYPT_SUB_SCAN }
PDTCRYPT_SECRET_PW = 0
PDTCRYPT_SECRET_KEY = 1
print (out)
+def mode_scan (pw, fname, nacl=None):
+ """
+ Dissect a binary file, looking for PDTCRYPT headers and objects.
+ """
+ try:
+ fd = os.open (fname, os.O_RDONLY)
+ except FileNotFoundError:
+ noise ("PDT: failed to open %s readonly" % fname)
+ noise ("")
+ usage (err=True)
+
+ try:
+ if PDTCRYPT_VERBOSE is True:
+ noise ("PDT: scan for potential sync points")
+ cands = locate_hdr_candidates (fd)
+ if len (cands) == 0:
+ noise ("PDT: scan complete: input does not contain potential PDT "
+ "headers; giving up.")
+ return -1
+ if PDTCRYPT_VERBOSE is True:
+ noise ("PDT: scan complete: found %d candidates" % len (cands))
+ finally:
+ os.close (fd)
+
def usage (err=False):
out = print
noise ("PDT: scrypt output format “%s”" % scrypt_format)
else:
bail ("ERROR: unexpected positional argument “%s”" % arg)
+ elif subcommand == PDTCRYPT_SUB_SCAN:
+ pass
if secret is None:
if PDTCRYPT_VERBOSE is True:
elif mode & PDTCRYPT_DECRYPT:
bail ("ERROR: encryption requested but no password given")
+ if subcommand == PDTCRYPT_SUB_SCAN:
+ if insspec is None:
+ bail ("ERROR: please supply an input file for scanning")
+ if insspec == '-':
+ bail ("ERROR: input must be seekable; please specify a file")
+ return True, partial (mode_scan, secret [1].encode (), insspec, nacl)
+
if subcommand == PDTCRYPT_SUB_SCRYPT:
if secret [0] == PDTCRYPT_SECRET_KEY:
bail ("ERROR: scrypt mode requires a password")