Zapis do nieistniejącego
pliku
Dziś zagadał do mnie kumpel na jabberze z ciekawym pytaniem:
<Maho> wiesz może jak dobrać się do pliku którego znam inode
<Maho> ale plik już nie ma nazwy?
Chodziło o to, żeby zapisać coś do pliku, otwartego przez jakiś proces, ale już skasowanego z systemu plików. Alternatywą było zapisanie coś do rurki (pipe) między dwoma procesami.
Pierwsze co mi przyszło do głowy, to
, ale kumpel stwierdził, że to nie zadziała, bo
w echo "cokolwiek" >>
/proc/${pid}/fd/${fd}/proc są symlinki (o tym dalej).
No to trzeba było wymyślić coś innego. Skoro jakiś proces może zapisywać do tego pliku, no najlepiej byłoby zmusić ten proces do zapisania tego co chcemy. Ale jak się podpiąć pod działający proces? Prosto: gdb.
No to przygotujmy sobie środowisko testowe, dwa skrypty:
- skrypt1.sh:
#!/bin/sh while : ; do echo PUK sleep 1 done | ./skrypt2.sh - skrypt2.sh:
#!/bin/sh cat
Drugiego skryptu mogłoby nie być -- wystarczył by sam 'cat', ale niech
będzie, że to dwa skrypty się ze sobą komunikują. Po uruchomieniu,
skrypt1.sh uruchamia skrypt2.sh i wysyła do niego
PUK
co sekundę. skrypt2.sh po prostu wypluwa to "PUK" na
standardowe wyjście.
No więc próbujemy, w jednym terminalu uruchamiamy skrypt1.sh:
$ ./skrypt1.sh PUK PUK PUK PUK PUK
Teraz spróbujmy zlokalizować tę rurkę między skryptami:
$ /usr/sbin/lsof -c skrypt1.sh | grep pipe skrypt1.s 11108 jacek 1w FIFO 0,5 40246 pipe skrypt1.s 11108 jacek 14w FIFO 0,5 40246 pipe
Są dwie, mniejsza z tym skąd, spróbujemy się podpiąć pod tę drugą. Znamy identyfikator procesu (pid=10980) oraz numer deskryptora pliku (fd=14). To powinno wystarczyć. No to podpinamy się pod proces:
$ gdb --pid=11108 GNU gdb 6.5 Copyright (C) 2006 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i686-pld-linux". Attaching to process 11108 Reading symbols from /bin/ksh...(no debugging symbols found)...done. Using host libthread_db library "/lib/libthread_db.so.1". Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done. Loaded symbols for /lib/libc.so.6 Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done. Loaded symbols for /lib/ld-linux.so.2 warning: Lowest section in system-supplied DSO at 0xffffe000 is .hash at ffffe0b4 (no debugging symbols found) 0xffffe405 in __kernel_vsyscall () (gdb)
No to się podpięliśmy... Skrypt został zatrzymany i przestał wyświetlać
PUK
. Teraz tylko należy wywołać funkcję write(). Ale jak?
Wydaje się, że nie ma żadnego polecenia do uruchamiania funkcji systemowych,
czy bibliotecznych... Ale jest print, który pozwala wyświetlić
wartość wyrażenia w C... a wyrażeniem może być wywołanie funkcji...
spróbujmy:
(gdb) print write(14, "BU!\n", 4) $1 = 4
...czyli jakby zadziałało i zapisało 4 znaki. No to co jest na terminalu ze
skryptami? Oczywiście wysłane właśnie BU!
. Można jeszcze sobie coś tak
popisać, a potem wznowić wykonywanie skryptu:
(gdb) quit The program is running. Quit anyway (and detach it)? (y or n) y Detaching from program: /bin/ksh, process 11108
A teraz, wróćmy do wspomnianego
... Przed napisaniem tego wpisu jeszcze sprawdziłem jaki do da efekt. I: echo "cokolwiek" >>
/proc/${pid}/fd/${fd}
$ echo "cokolwiek" > /proc/11108/fd/14
Dało na terminalu ze skryptami:
PUK PUK cokolwiek PUK PUK
A więc /proc/.../fd/... działa wystarczająco dobrze! Jednak
sztuczka z gdb i tak mi się spodobała, więc ją tu opisałem. Ma
swój potencjał, bo oprócz pisania do pliku pozwala na różne inne rzeczy.
Oczywiście, krzywdę sobie w ten sposób też można zrobić. :-)
Śledzenie komentarzy (RSS)
Jesteście obserwowani...
13 września 2007 22:27:45
No dobra, a coś takiego: mam plik film.avi i odpalam go mplayerem:
mplayer plik.avi
i na drugiej konsoli go kasuję. teraz pliku nie ma, ale mplayer jeszcze go czyta, czy da się podpiąć pod inode, gdzie leży ten plik (bo jeszcze leży, póki działa mplayer) i odzyskać? :)