-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfindHash.py
More file actions
executable file
·109 lines (103 loc) · 3.53 KB
/
Copy pathfindHash.py
File metadata and controls
executable file
·109 lines (103 loc) · 3.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#! /usr/bin/python2
# -*- coding: utf-8 -*-
#
# Locate 4k fragments of a subject file in one or more other files or
# devices. Only reports two or more consecutive matches.
#
# Copyright (C) 2016, Philip J. Turmel <philip@turmel.org>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import hashlib, sys, datetime
# Read the known file 4k at a time, building a dictionary of
# md5 hashes vs. offset. Use a large buffer for speed.
# Drops any partial block at the end of the file.
d = {}
pos = long(0)
f = open(sys.argv[1], 'r', 1<<20)
b = f.read(4096)
while len(b)==4096:
md5 = hashlib.md5()
md5.update(b)
h = md5.digest()
hlist = d.get(h)
if not hlist:
hlist = []
d[h] = hlist
hlist.append(pos)
pos += 4096
b = f.read(4096)
f.close()
print "%d Unique hashes in %s" % (len(d), sys.argv[1])
def checkAndPrint(match):
if match[2]>4096:
print "%20s @ %12.12x:%12.12x ~= %8.8x:%8.8x" % (fname, match[1], match[1]+match[2]-1, match[0], match[0]+match[2]-1)
# Read the candidate files/devices, looking for possible matches. Match
# entries are vectors of known file offset, candidate file offset, and
# length.
for fname in sys.argv[2:]:
print "\nSearching for pieces of %s in %s:..." % (sys.argv[1], fname)
pos = long(0)
f = open(fname, 'r', 1<<24)
matches = []
b = f.read(4096)
lastts = None
while len(b)==4096:
if not (pos & 0x7ffffff):
ts = datetime.datetime.now()
if lastts:
print "@ %12.12x %.1fMB/s \r" % (pos, 128.0/((ts-lastts).total_seconds())),
else:
print "@ %12.12x...\r" % pos,
sys.stdout.flush()
lastts = ts
md5 = hashlib.md5()
md5.update(b)
h = md5.digest()
if h in d:
i = 0
while i<len(matches):
match = matches[i]
target = match[0]+match[2]
continuations = [x for x in d[h] if x==target]
if continuations:
match[2] += 4096
i += 1
else:
del matches[i]
checkAndPrint(match)
if not matches:
matches = [[x, pos, 4096] for x in d[h]]
else:
for match in matches:
checkAndPrint(match)
matches = []
pos += 4096
b = f.read(4096)
print "End of %s at %12.12x" % (fname, pos)
# show matches that continue to the end of the candidate file/device.
for match in matches:
checkAndPrint(match)
# kate: tab-width 4; indent-width 4; tab-indents on; dynamic-word-wrap off; indent-mode python; line-numbers on;