Записать случайные данные в случайные сектора жесткого диска
У меня поврежден жесткий диск, и прежде чем отправить его на RMA, я хочу стереть с него как можно больше данных. Я попытался использовать утилиты Windows, а также сделал дд /dev/random. Проблема в том, что я не могу дождаться, пока ни одно из этих решений не завершится, поскольку причина в том, что RMA пишет с максимальной скоростью 1 МБ / с. Это займет более 140 часов только для одного прохода 500 ГБ жесткого диска.
Я искал утилиту (или даже скрипт bash на linux), которая бы выбирала сектора случайным образом и записывала случайные данные (или даже нули) в эти сектора. Я надеюсь, что если я запустлю это в течение 24 часов, это приведет к стиранию примерно 80 ГБ данных. Так как он будет выбран случайным образом, все большие файлы будет невозможно восстановить, а меньшие будут либо удалены, либо будут пропущены фрагменты, либо, возможно, будут восстановлены. Это, к сожалению, оптимальное решение для меня на данный момент.
РЕШЕНИЕ
Благодаря "evildead" я смог получить много данных на диске, которые можно было случайно заполнить мусором из /dev/urandom. Скрипт bash на тот случай, если он кому-нибудь понадобится, находится ниже:
#!/bin/bash
while (true); do
randnum=${RANDOM}${RANDOM}
number=$((10#$randnum%976773168))
echo -e $number >> progress.txt
dd if=/dev/urandom of=/dev/sdx1 skip=$number count=1
done
Вам нужно будет заменить 976773168 количеством блоков на вашем диске. Первоначально я пытался $RANDOM в bash, но это только 16-битное int и, следовательно, только 32 КБ. Поскольку мне нужно было число, превышающее 900 миллионов, я объединил два значения $RANDOM, поэтому, например, если мои случайные числа равны 22861 и 11 111, я получаю 2 286 111 111, а затем подгоняя его под размер моего блока, я получаю довольно случайное значение в моем диапазоне. У него нет идеальной энтропии, но опять же, что действительно случайно на компьютере?;) 10# существует в случае, если первое случайное число равно 0, оно заставляет bash использовать основание 10, а не основание 8, что и используется, если он считает, что число является восьмеричным (ведущий ноль). Я также записываю случайные числа в файл для последующего анализа, чтобы узнать, каков был спред. Если вам это не нужно, вы можете просто вынуть
echo -e $number >> progress.txt
и он будет работать нормально. Также не забудьте заменить sdx1 реальным диском или разделом, с которым вы хотите работать. Я надеюсь, что это полезно для кого-то, я знаю, что это было действительно полезно для меня.
6 ответов
Вы можете использовать скрипт в сочетании с дд.
например
while (true); do
number=$((($RANDOM * 32768 + $RANDOM)))
dd if=/dev/urandom of=/dev/sdx1 seek=$number count=1
done
Вам нужно всего лишь изменить число, которое генерируется из $RANDOM, чтобы соответствовать вашим блокам.
РЕДАКТИРОВАТЬ 2016: Обратите внимание, что старое решение было неверным. Поскольку мы хотим перезаписать байт в произвольной позиции в выходном потоке, мы должны использовать поиск вместо пропуска, как упоминалось в комментариях.
Скрипт Python 3 с:
- осведомленность о размере блочного устройства
- проверка размера блочного устройства путем записи байтов на границах
- гарантия уничтожения первого и последнего байта
- случайные данные перезаписываются
- случайное смещение
- случайные размеры партий
Если вам нужен Python 2, то его будет легко скрыть, используя "".format() вместо f"" строк.
import subprocess
import random
REPS = 100
CRASH_ON_FIRST_FAILURE = True # change to False if the device is not reliable
def run(*cmd, assert_returncode=None, print_stderr=False):
completed = subprocess.run(cmd, capture_output=True)
if assert_returncode:
assert completed.returncode == assert_returncode, f"Unexpected return code (got={assert_returncode}, expected={assert_returncode})"
if print_stderr:
print(str(completed.stderr))
return completed.stdout
def part_size(part):
"""
Partition size in bytes
"""
return int(run("blockdev", "--getsize64", part))
def destroy_block(part, bs, seek, assert_returncode=None, print_result=False):
run(
"dd", f"bs={bs}", "if=/dev/urandom", f"of={part}", f"seek={seek}", "count=1",
assert_returncode=assert_returncode
)
if print_result:
print(f"Destroyed bs={bs} of={part} seek={seek}")
def destory_random_block(part, part_size, bs):
"""
bs=1 destroys bytes sized block
bs=1024 destroys KB sized block
etc.
"""
seek_max = int(part_size / bs)
seek = random.randint(0, seek_max)
if CRASH_ON_FIRST_FAILURE:
assert_returncode = 0
else:
assert_returncode = None
destroy_block(part, bs=bs, seek=seek, assert_returncode=assert_returncode)
def destroy(part):
"""
part - partition to be destroyed
"""
s = part_size(part)
destroy_block(part, bs=1, seek=s, assert_returncode=1) # "test" destroying 1 byte at size boundary, should fail
destroy_block(part, bs=1, seek=(s - 1), assert_returncode=0, print_result=True) # "test" destroying 1 bytes before boundary, should pass
destroy_block(part, bs=1, seek=0, assert_returncode=0, print_result=True) # "test" destroying first 1 byte
while True:
print(f"Destroying {REPS} byte-sized blocks")
for _ in range(REPS):
destory_random_block(part, part_size=s, bs=1)
print(f"Destroying {REPS} KB-sized blocks")
for _ in range(REPS):
destory_random_block(part, part_size=s, bs=1024)
print(f"Destroying {REPS} MB-sized blocks")
for _ in range(REPS):
destory_random_block(part, part_size=s, bs=(1024 * 1024))
rand_size = random.randint(1, 1024 * 1024)
print(f"Destroying {REPS} {rand_size}-sized blocks")
for _ in range(REPS):
destory_random_block(part, part_size=s, bs=rand_size)
print("\nRise and repeat\n\n")
destroy("/dev/sdb1")
Пример вывода:
# "test" destroying 1 byte at size boundary, should fail
# "test" destroying 1 bytes before boundary, should pass
Destroyed bs=1 of=/dev/sdb1 seek=10736369663
# "test" destroying first 1 byte
Destroyed bs=1 of=/dev/sdb1 seek=0
Destroying 100 byte-sized blocks
Destroying 100 KB-sized blocks
Destroying 100 MB-sized blocks
Destroying 100 875091-sized blocks
Rise and repeat
Destroying 100 byte-sized blocks
Destroying 100 KB-sized blocks
Destroying 100 MB-sized blocks
Destroying 100 1028370-sized blocks
Rise and repeat
Бежать:
- Скопируйте исходный код все, кроме последней строки
- На хосте жертвы войдите в систему как root
- На хосте жертвы запустите:
python3
- Вставьте код из шага 1
- Тип
destroy("/dev/XYZ")
и верните ключ дважды - Через несколько часов нажмите Ctrl-c
ПРИМЕЧАНИЕ. "/ Dev/XYZ" - это имя раздела, в котором будут потеряны данные.
ВНИМАНИЕ! Остерегайтесь ошибок типа "жирный палец". Данные исчезнут навсегда, поэтому еще раз проверьте, какой раздел вы вводите.
ПРЕДУПРЕЖДЕНИЕ. Выполнение этого сценария в течение нескольких дней в облачных службах может стоить, если вы платите за IOP записи на диск.
Моя система не сломана и пишет с /dev/random
составляет около 650 Кбит / с. Запись от /dev/urandom
7 Кбит / с.
Я работал над этой проблемой для себя, и для решения чисто bash вы должны быть реалистичными в отношении того, что является вашей целью, потому что, если ваша цель не состоит в том, чтобы научиться делать это в bash, потому что смысл в том, чтобы делать это ВСЕ в bash, цель Безопасное удаление диска лучше выполнить другими способами, хотя bash полезен в решении.
Алгоритм bash evildead по случайному выбору места, куда dd будет записывать на диск, работает, однако, / dev / urandom значительно медленнее, чем / dev / random, и я думаю, что менее безопасно перетаскивать диск кусками случайных данных, и я думаю, что это будет Труднее получить данные с стертого диска, если вы быстро сделаете два прохода, записав на него свои нули, а затем нули.
Для себя я написал их на диск с:
tr '\0' '\377' < /dev/zero | pv > /dev/sdz
Затем я записал нули на диск:
pv < /dev/zero > /dev/sdz
Обратите внимание на использование PV. Это отличная программа, хотя вы должны установить ее на большинстве систем. Легко найти, кажется, не входит в справочную страницу, но есть одна онлайн. Он показывает ход прохождения данных по каналу, и с помощью некоторых программ вы даже можете настроить его остановку после прохождения определенного объема данных.
ТОЛЬКО из-за того, что меня раздражало то, что ни одно решение bash не будет писать случайные числа так быстро, как это делала бы любая из приведенных выше записей, я написал небольшую программу на C, называемую svrandom, для генерации случайных чисел QUICKLY, которую я вызвал из bash следующим образом:
while :; do ./svrandom; done | pv > /dev/sdz
В моей системе это заполняет диск / dev / sdz случайными числами так же быстро, как запись / dev / zero. Цель - стереть диск со случайными числами и использовать bash в решении.
/* svrandom
a small program from shadowvision.com September 2015 to generate strings of random numbers.
the default setting of 10000000 gives about 453 megs, adjust as
needed */
#include <stdio.h>
#include <stdlib.h>
int main()
{
int r,a,b;
/* adjust following number as needed to suit your string length */
for(a=0;a<10000000;a++)
{
for(b=0;b<5;b++)
{
r=rand();
printf("%d",r);
}
}
return(0);
}
В источнике я упоминаю, что вы можете контролировать длину строки случайных чисел, регулируя число. Если вы вызываете его из цикла while, вам это не нужно, хотя в конце каждого цикла может быть возврат каретки, но если вы хотите одну непрерывную строку только из программы, вам придется изменить номер.
чик! оглядываясь вокруг, я нашел это решение на https://superuser.com/questions/19326/how-to-wipe-free-disk-space-in-linux
openssl enc -aes-256-ctr -pass pass: "$ (dd if = / dev / urandom bs = 128 count = 1 2> / dev / null | base64)" -nosalt dev/zero |pv > /dev/ сд {х}
и, как сказал парень, я не могу поверить, насколько это быстро. Он записывает на диск быстрее, чем я думал, максимальная скорость записи дисков была.
Мне кажется, что эта команда использует openssl для шифрования строки нулей из / dev / zero, используя / dev / urandom в качестве начального числа, но я не уверен на 100%. мое решение с программой C для записи случайных чисел записывает в мою систему со скоростью 82 Мбит / с, это решение openssl пишет со скоростью 100 Мбит / с. Вот Это Да!
Лучшее программное обеспечение, которое автоматизирует этот процесс - это Darik's Boot and Nuke (он же DBAN)
Это загрузочный компакт-диск с широким спектром механизмов очистки дисков, начиная с агрессивности (и времени, затрачиваемого на стирание диска)
Это доступно на http://www.dban.org/
Если у вас есть мощный магнит, вы можете физически стереть его.
Я разбираю старые, мертвые жесткие диски и достаю магниты звуковой катушки из узла позиционирования головы. Это редкоземельные магниты, и от обычного 3,5-дюймового диска они достаточно мощные, чтобы стереть достаточное количество следов сервопривода на жестком диске, чтобы его можно было полностью использовать.
Так или иначе, возьмите магнит, протрите его взад и вперед через верхнюю крышку привода, и менее чем через минуту у вас будет мертвый диск. Так как в любом случае это RMA, им все равно.
Спасибо за решение сверху!
Поскольку мне не разрешено комментировать ответ сценарием, я должен сам добавить крошечное улучшение.
Я просто немного настроил его для большего удобства, чтобы определить устройство. fdisk доставит количество секторов:
#!/bin/bash
# add device to mangle
# example:
# disk=/dev/sde
disk=
# get number of sectors
sectors=$(fdisk $disk -l| head -1| awk '{print $7}')
# run
while (true); do
randnum=${RANDOM}${RANDOM}
number=$((10#$randnum%$sectors))
echo -e $number >> progress.txt
dd if=/dev/urandom of=$disk skip=$number count=1
done
Опция dban является правильным ответом на эту проблему.
Запись "случайных" данных из /dev/random приведет к проблемам в большинстве систем, потому что вы исчерпаете энтропию в системе и очень медленно будете записывать данные.
Почти так же "случайно", как и из /dev/random, шифровать строку нулей случайной парольной фразой. Для этого вы можете использовать dd и openssl, и это позволяет вам копировать диски так быстро, как система может записывать на диск (вместо ожидания на /dev/random). Вы сможете запускать это 3-5 раз в то же время, когда запускаете что-то, что просто dding из /dev/random.
dd if=/dev/zero | openssl des > /dev/hda13