Хакота

written on Thursday, March 21, 2013

Вчора застосував адський рівень червоноокості — дістав вбитий файл через дебагер. Справа була так: качаю собі великий довгий файл через торренти на хуйовому інтернеті (відсутність оптики на острові мене їбе і ностальгірую). Скачав. Тут рука промахується в історії команд, і замість відкриття файлу в плеєрі я різко грохаю його через rm. Упс.

Можна, звісно, перекачати, але це довго, я вже настроївся подивитися цю серію. І обидно. Але я ж в курсі, як у юніксах працюють файлові системи, і знаю, що поки торрент-клієнт відкритий, файл ще нікуди не дівся.

Був би лінукс — скопіював би через /proc/$pid/fd/$n. Але на жаль, це злобна макось, і /proc тут немає. Зате є lsof і gdb.

GDB

Цепляюся до процесу торрент-клієнта через gdb -p pid, дивлюся номер дескриптора, який відповідає видаленому файлу, через lsof:

Transmiss 45382 muromec 28r REG 1,2 635760707 66811886 блаблабла.mkv

Ну окей, файл ще живий, треба всього-то зробити хардлінк. Іду в гугл і стековерфлоу шукати, як робляться хардлінки на файловий дескриптор.

А ніяк. Ну або я тупий і не знайшов. link() хоче два шляхи — і все.

Паралельно дізнався, що в лінуксі більше немає рута, все переробили на capabilities.

Code inject

Через gdb можна нагло залізти в пам'ять процесу і посмикати функції. Оскільки виконання програми зупинено, вона навіть не впаде, поки дебагер її не відпустить.

І так, у мене є номер дескриптора і можливість смикати функції. Далі все нудно. Робимо копію файлового дескриптора, ставимо позицію у файлі на 0 і починаємо read-write цикл (лог gdb записано приблизно і по пам'яті): [code] (gdb) print (int)dup(28)

[/code]

$1 = 30 (gdb) print lseek(30, 0,) $2 = 0 (gdb) print (long)malloc(0x3200000) $3 = 4389474304 (gdb) print (int)open("copy.mkv", 0x202) $4 = 31 (gdb) print (int)read(30, 4389474304, 0x3200000) $5 = 52428800 (gdb) print (int)write(31, 4389474304, 0x3200000) $6 = 52428800

Ну і так далі. Іноді воно чомусь ловило SIGPIPE, і доводилося руками ставити правильний offset через lseek(), тому що я не розумів, у який момент і нахуя цей сигнал прилетів.

В кінці цього дійства я смикнув close() і пішов дивитися відновлений файл. Тільки виставив на нього нормальні пермішени — і все.

This entry was tagged