Skip to content

Instantly share code, notes, and snippets.

@kj7rrv
Last active March 31, 2024 03:01
Show Gist options
  • Save kj7rrv/08dc5cb20673542c4ddf3dfe44f8c803 to your computer and use it in GitHub Desktop.
Save kj7rrv/08dc5cb20673542c4ddf3dfe44f8c803 to your computer and use it in GitHub Desktop.
disk_searcher - data recovery tool

disk_searcher

This is a tool for recovering data from corrupted disks. It relies on you knowing an exact UTF-8 string that appears in the file, and the file being contiguous on disk.

Please note that it has some known bugs, although as far as I am aware there is no case in which it would cause data loss. (As stated in the license's disclaimer, however, I am not responsible if you do lose data!) I wrote this a few months ago for personal use, without intending to distribute it, so it's not as polished as I would normally make software for distribution.

In particular, disk_searcher will crash with an exception if you move the start of a window before the start of the disk, the end of a window after the end of the disk, or the end of a window before the start of the window.

Usage

disk_searcher <path> <data>

path is the path to either the disk's block device in /dev, or an image of the disk (.img or .iso file); data is the known string to look for.

After disk_searcher scans your disk, it will present the matches, one by one. Just press Enter if a match doesn't look right. If one does look right, and you want to resize the window that is shown, press any other key, then Enter.

The program will then prompt you with commands. Your commands must consist of either s or e, followed by a positive or negative integer. This will move either the start (s) or end (e) of the window forward by the specified number of bytes; use negative numbers to go backward.

License

Copyright (c) 2023-2024 Samuel Sloniker

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

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 OR COPYRIGHT HOLDERS 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.

#!/usr/bin/env python3
# disk_searcher
# Copyright (c) 2023-2024 Samuel Sloniker
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# 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 OR COPYRIGHT HOLDERS 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.
import math
import sys
import os
file_name = sys.argv[1]
pattern = sys.argv[2].encode("utf-8")
base_block_size = 1024**2
def findall(pattern, string, offset):
index = string.find(pattern)
while index != -1:
yield index + offset
index = string.find(pattern, index + 1)
def get_size(f):
f.seek(0, os.SEEK_END)
return f.tell()
def get_blocks(size, base_block_size, pattern_length):
block_size = base_block_size + pattern_length
block_count = size // base_block_size
for i in range(block_count):
start = i * base_block_size
yield (
start,
block_size,
)
final_start = block_count * base_block_size
final_block_size = size - final_start
yield (
final_start,
final_block_size,
)
with open(file_name, "rb") as f:
size = get_size(f)
pattern_length = len(pattern)
blocks = list(get_blocks(size, base_block_size, pattern_length))
locations = []
index_pad_length = len(str(len(blocks)))
try:
for index, (block_start, block_size) in enumerate(blocks):
f.seek(block_start)
block = f.read(block_size)
if pattern in block:
locations += list(findall(pattern, block, block_start))
percent = index / len(blocks) * 100
print(
f"{percent:6.2f}% {str(index).rjust(index_pad_length)}/{len(blocks)}"
)
except KeyboardInterrupt:
pass
print(locations)
for location in locations:
print(location)
start = location - 500
length = 1000
f.seek(start)
print(f.read(length))
if input("Press Enter to skip, any key then enter to adjust frame: "):
while True:
command = input("> ").strip().lower()
if not command:
break
try:
if command[0] == "s":
start += int(command[1:])
elif command[0] == "e":
length += int(command[1:])
else:
print("invalid command")
except ValueError:
print("invalid command")
f.seek(start)
print(f.read(length))
<Strings in <angle brackets> are added notes; strings in {curly brackets} are typed by the user. All other text is program output.>
0.00% 0/262145
0.00% 1/262145
0.00% 2/262145
0.00% 3/262145
0.00% 4/262145
<snip>
100.00% 262140/262145
100.00% 262141/262145
100.00% 262142/262145
100.00% 262143/262145
100.00% 262144/262145
[59318165504, 59418869760, 59435646976, 59502686208, 59521970176, 71698251812]
59318165504
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Although election procedures vary from state to state, the method used to tally\nvotes is quite consistent: each voter chooses one candidate, and the person\nwith the most votes wins the election. This may seem like an obvious fact: how\nelse could a democratic election work? However, there is actually an\n alternative procedure available, and it has many benefits. This method is\n known as ranked-choice voting (RCV), and as its name implies, it allows\n voters, instead of selecting one candi'
Press Enter to skip, any key then enter to adjust frame:
59418869760
b'te, Content-Length, Content-Range, X-Content-Duration, X-Cache\r\ntiming-allow-origin: *\r\naccept-ranges: bytes\r\nX-Firefox-Spdy: h2\r\n\x00ctid\x003\x00net-response-time-onstart\x0039\x00net-response-time-onstop\x0044\x00\x00\x00\x02\xcb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Although election procedures vary from state to state, the method used to tally\nvotes is quite consistent: each voter chooses one candidate, and the person\nwith the most votes wins the election. This may seem like an obvious fact: how\nelse could a democratic election work? However, there is actually an\nalternative procedure available, and it has many benefits. This method is\nknown as ranked-choice voting (RCV), and as its name implies, it allows\nvoters, instead of selecting one candidate, to ran'
Press Enter to skip, any key then enter to adjust frame: <any key>
> {s+600}
b"stent: each voter chooses one candidate, and the person\nwith the most votes wins the election. This may seem like an obvious fact: how\nelse could a democratic election work? However, there is actually an\nalternative procedure available, and it has many benefits. This method is\nknown as ranked-choice voting (RCV), and as its name implies, it allows\nvoters, instead of selecting one candidate, to rank them from favorite to\nleast favorite. In the 2024 general election, there will be a referendum on\nOregon voters' ballots to begin using RCV starting in 2028. Oregon should\nadopt ranked-choice voting because it resists spoiler effects, gives more\nchoices to voters, and opens the possibility of ending the two-party\nsystem.\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
> s-100
b"Although election procedures vary from state to state, the method used to tally\nvotes is quite consistent: each voter chooses one candidate, and the person\nwith the most votes wins the election. This may seem like an obvious fact: how\nelse could a democratic election work? However, there is actually an\nalternative procedure available, and it has many benefits. This method is\nknown as ranked-choice voting (RCV), and as its name implies, it allows\nvoters, instead of selecting one candidate, to rank them from favorite to\nleast favorite. In the 2024 general election, there will be a referendum on\nOregon voters' ballots to begin using RCV starting in 2028. Oregon should\nadopt ranked-choice voting because it resists spoiler effects, gives more\nchoices to voters, and opens the possibility of ending the two-party\nsystem.\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
> {e-100}
b"Although election procedures vary from state to state, the method used to tally\nvotes is quite consistent: each voter chooses one candidate, and the person\nwith the most votes wins the election. This may seem like an obvious fact: how\nelse could a democratic election work? However, there is actually an\nalternative procedure available, and it has many benefits. This method is\nknown as ranked-choice voting (RCV), and as its name implies, it allows\nvoters, instead of selecting one candidate, to rank them from favorite to\nleast favorite. In the 2024 general election, there will be a referendum on\nOregon voters' ballots to begin using RCV starting in 2028. Oregon should\nadopt ranked-choice voting because it resists spoiler effects, gives more\nchoices to voters, and opens the possibility of ending the two-party\nsystem.\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
<continue adjusting the end of the window until you have only the desired content>
b"Although election procedures vary from state to state, the method used to tally\nvotes is quite consistent: each voter chooses one candidate, and the person\nwith the most votes wins the election. This may seem like an obvious fact: how\nelse could a democratic election work? However, there is actually an\nalternative procedure available, and it has many benefits. This method is\nknown as ranked-choice voting (RCV), and as its name implies, it allows\nvoters, instead of selecting one candidate, to rank them from favorite to\nleast favorite. In the 2024 general election, there will be a referendum on\nOregon voters' ballots to begin using RCV starting in 2028. Oregon should\nadopt ranked-choice voting because it resists spoiler effects, gives more\nchoices to voters, and opens the possibility of ending the two-party\nsystem.\n"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment