W tym miniwpisie opiszę historię z życia – przypadek, kiedy skorzystałem z paru konsolowych programów załączonych do Linuksa.
Dzięki nim zajrzałem „pod maskę” przyjaznego interfejsu pewnego programu i znalazłem sposób na odtworzenie jego działania we własnym, minimalistycznym skrypcie.

Spis treści

Opis problemu

Miałem pewne spakowane, zabezpieczone hasłem archiwum w formacie ZIP. Dajmy na to: archiwum.zip. Wewnątrz niego różne pliki, z którymi chciałem coś porobić.

System Linux Mint (wariant MATE), z którego korzystam, jest bardzo przyjazny codziennym użytkownikom. Mógłbym łatwo rozpakować plik najzwyklejszym klikaniem.

W tym celu wystarczyłoby odnaleźć archiwum w przeglądarce plików, kliknąć je prawym przyciskiem myszy i wybrać opcję Rozpakuj tutaj.

Zrzut ekranu pokazujący fragment rozwijanego menu po kliknięciu na plik ZIP. Widać tam opcję rozpakowania plików

W związku z tym, że to ZIP chroniony hasłem, pojawia się okno z prośbą o jego wpisanie. Jeśli podam poprawne, to zaczyna się rozpakowywanie archiwum. Obok jego ikony pojawią się wszystkie zawarte w nim pliki i foldery.

Zrzut ekranu pokazujący okno proszące o podanie hasła do pliku ZIP

Parę razy rozpakowałem archiwa ręcznie, właśnie w taki sposób. Ale kiedy się okazało, że będę musiał to robić częściej – wraz z powtarzalnymi działaniami na wypakowanych plikach – to wewnętrzny leniuch rzekł stanowczo: „automatyzujmy”.

A do tego przydałyby mi się nazwy programów do wpisywania w konsolę. Zaczęło się szperanie.

Unzip i mylny trop

Wyszukałem w sieci odpowiedzi na pytanie w stylu: „jak rozpakować plik ZIP na systemie Linux”? Któraś z odpowiedzi zasugerowała programik unzip.

Użyłem go przez konsolę na swoim zahasłowanym pliku. O dziwo zadziałało nawet bez pytania o hasło, rozpakowało zawartość… Tyle że były tam same foldery. Nie było natomiast żadnych plików, na których mi zależało.

Wątek prywatnościowy

Nawet plik ZIP zabezpieczony hasłem zawiera na widoku nazwy i hierarchię zawartych w sobie plików i folderów.
To dlatego unzip mógł odtworzyć strukturę folderów – do tego wystarczą same ścieżki. Ale pliki już były zaszyfrowane, więc ich nie tknął.
Wniosek: lepiej nie umieszczać żadnych wrażliwych informacji w nazwach plików wrzucanych do archiwów :wink:
Pomijam już to, że samo hasło do pliku też nieraz łatwo złamać metodami siłowymi, zwłaszcza jeśli zawęzi się przestrzeń możliwości. Fajnie to pokazał ten wpis Informatyka Zakładowego.

Skoro ogólnie unzip działał, a jedynym problemem było hasło, to kolejna rzecz do wyszukania: „jak rozpakować przez unzipa plik chroniony hasłem”. Wpisałem takie coś i… okazało się, że raczej się nie da. Nie przy tym programie i tym szyfrowaniu.

Śledztwo

Tam, gdzie unzip poległ, domyślny program Minta dawał radę. Przyjmował hasło i rozpakowywał archiwum. Jak? Czy dałoby się w prosty sposób włączyć go w moją automatyzację?
Szukając odpowiedzi na te pytania, rozpocząłem krótkie śledztwo.

Ustalenie nazwy programu (xprop)

Zależało mi na nazwie programu, jakiemu odpowiadało okienko interfejsu pytające o hasło.

Mógłbym teoretycznie kliknąć pierwszą opcję z menu z pierwszego screena. Jest tam o otwarciu archiwum, więc mógłbym założyć, że pojawi się ten sam program, który rozpakowuje. Po jego uruchomieniu zajrzałbym w zakładkę O programie i poznał nazwę.

Ale nie zawsze jest możliwość prostego przejścia od okna/opcji do programu. Sposobem bardziej uniwersalnym jest uruchomienie konsoli/terminala (np. kombinacją Ctrl+Alt+T) i użycie polecenia:

xprop | grep WM_CLASS

Są tu dwa programiki: xprop od sprawdzania informacji o wskazanym oknie, grep od wyszukiwania tekstu (tu: WM_CLASS). Rura między nimi sprawia, że informacje ustalone przez pierwszy lecą do drugiego.

Kursor zmienił się w plusa. Kiedy kliknąłem okno pytające o hasło, wyświetliła się nazwa stojącego za nim programu:

Engrampa. Nazwa trochę kojarzy mi się z n-gramami, trochę z dziadkiem – i faktycznie program jest już nieco leciwy. Ale wciąż sprawny.

Krótka lektura dokumentacji

Wiedziałem z doświadczenia, że programy mają czasem dwa oblicza:

  • Graficzne

    Uruchamiane przez kliknięcie jakiejś ikony wewnątrz systemu; czasem również przez wpisanie w konsolę samej nazwy programu.

  • Konsolowe

    Dopisując po nazwie programiku dodatkowe opcje, da się z niego korzystać w sposób niestandardowy, na przykład robiąć coś całkowicie w tle, bez interfejsu graficznego.

Gdybym po prostu wpisał w konsolę engrampa archiwum.zip, to otwarłoby interfejs graficzny od przeglądania – nawet nie znajome okno pytające o hasło.
Ja natomiast liczyłem na możliwość zrobienia czegoś takiego:

Czy moje oczekiwania miały szansę się spełnić? Nie wiedziałem tego, bo każdy program może działać po swojemu. Musiałem poznać możliwości Engrampy. Na przykład takim poleceniem.

engrampa --help
Parę uwag

Nie każdy program da się wołać samą nazwą. Żeby się dało, musi się znajdować w którymś z folderów szybkiego dostępu. W innym razie trzeba podać jego pełną ścieżkę.

Poza tym nie każdy wyświetla dostępne opcje po dopisaniu --help. To popularna konwencja, ale nie wszyscy twórcy się jej trzymają.

Przy Engrampie miałem to szczęście, że obie rzeczy się sprawdziły.

Wyświetliło mi garść informacji po angielsku. W tym jedną z dostępnych opcji, która brzmiała interesująco:

Opcja --extract-here pasowała idealnie do tego, co chciałem zrobić. Ale używając jej na swoim archiwum, po prostu przywołałem znajome okno pytające o hasło.
Nie było to samo w sobie takie złe. Tyle że mnie, przypomnę, najbardziej pasowałoby rozwiązanie w całości konsolowe.

Spróbowałem jeszcze zajrzeć do dokładniejszej instrukcji, wpisując:

man engrampa

Programik man (skrót od manual) to uniwersalny sposób na otwarcie instrukcji programów konsolowych.

W tym wypadku instrukcja była dość lakoniczna i zawierała właściwie te same informacje co skrócona pomoc konsolowa.

Na tym etapie mógłbym odpuścić i pogodzić się z tym, że moją automatyzację będzie przerywało jedno graficzne okno. Albo znaleźć inny program rozpakowujący.
Ale postanowiłem trochę drążyć. Sięgnąłem po program konsolowy strace.

Program pod obserwacją (strace)

Strace to linuksowy odpowiednik agenta wysyłanego na przeszpiegi. Notującego z ukrycia wszystko, o co Engrampa prosi jądro systemu. Może to pozwoli rozpracować naszego odpakowywacza.

Żeby użyć strace’a, wystarczy dopisać po nim komendę, którą chciałoby się śledzić. Odpowiednie polecenie dla Engrampy ustaliłem parę akapitów wyżej. Dodałem jeszcze parę parametrów dla strace’a i uzyskałem takie polecenie:

strace -f -o zapis.txt engrampa --extract-here archiwum.zip

Po wykonaniu polecenia uruchomiło się to samo okienko pytające o hasło co poprzednio. Wpisałem je, poczekałem aż rozpakuje mi ZIP-a. Programik z powodzeniem zakończył działanie, a strace skończył notować.

W folderze, w którym użyłem konsoli, powstał plik liczący aż 4,5 MB. Szczegółowy zapis wszystkich interakcji Engrampy z systemem podczas tej krótkiej sesji.

Przeszukanie zapisków (grep)

Miałem pełną historię, mogłem teraz wyciągnąć z niej różne informacje.

Tak duży plik byłby jednak uciążliwy do przeglądania w domyślnym Notatniku Xedzie. Nawet przez programik less, który ładuje pliki na raty, ręczne szukanie byłoby żmudne.

Może dałoby się wyjść od czegoś jak najbliżej momentu rozpakowania?
Wiedziałem, jakie podałem hasło do ZIP-a, więc spróbowałem je sobie wyszukać w obszernych zapiskach:

grep HASŁO zapis.txt

…I faktycznie, wyskoczyło kilka linijek, w których się pojawiło! Aż się zdziwiłem.

Kilka pierwszych, zawierających różne ścieżki, kończyło się tekstem Nie ma takiego pliku ani katalogu. Sugeruje to, że strace bezskutecznie szukał. Aż dotarło do linijki, która chyba zakończyła się sukcesem:

execve("/usr/lib/7zip/7z", ["/usr/lib/7zip/7z", "x", "-bd", "-bb1", "-y", "-pHASŁO", "-o", "--", ".zip"], 0x576555d87ee8 /* 52 vars */) = 0

Włączyłem zawijanie tekstu, żeby wszystko się zmieściło, za cenę lekkiego chaosu; ciemniejszym szarym wyróżniłem ścieżki, czerwonym hasło.

Początek linijki, execve, wskazuje na wołanie przez śledzony proces Engrampy innego programu.

Pierwszą rzeczą w nawiasie jest ścieżka wołanego programu (gdzie /usr/lib/7zip to ścieżka do folderu, zaś 7z to konsolowa nazwa popularnego programu 7-Zip).

Potem miałem serię nawiasów kwadratowych. A to, co między nimi, było tak naprawdę pełną listą opcji (argumentów) przekazanych „podwykonawcy”, czyli 7-Zipowi.

Mogłem to sobie skopiować, oczyścić z cudzysłowów podwójnych oraz przecinków, zastąpić ścieżki zmiennymi… i tak oto zdobyłem polecenie rozpakowujące plik.

/usr/lib/7zip/7z x -bd -bb1 -y -pHASŁO -o -- .zip
Omówienie

Znaczenie większości opcji z komendy (zwanych zwyczajowo argumentami) mogłem łatwo poznać, wpisując 7z --help. I tak oto, po kolei:

  • /usr/lib/7zip/7z to po prostu pełna ścieżka do programu 7-Zip na moim Mincie.
  • x każe programowi działać w trybie rozpakowywania plików.
  • -bd ukrywa konsolowy wskaźnik postępów w rozpakowywaniu.
  • -bb1 wskazuje, jak szczegółowe (w skali od 0 do 3, tu 1) mają być informacje wyświetlane przez program.
  • -y sprawia, że program nie pyta, czy na pewno chcę coś zrobić, tylko zawsze to robi.
  • -p to hasło; tutaj zapisane od razu po nazwie argumentu, więc ciut się z nim zlewa.
  • -o to ścieżka i nazwa folderu wyjściowego; tutaj taka sama jak nazwa archiwum (tyle że bez .zip na końcu).
  • podwójna kreska (--) wskazuje, że to koniec ustawiania opcji. Po niej jest już tylko główny „wsad” do programu – ścieżka do archiwum.

Użyłem na próbę tego polecenia (zamiast HASŁO dając oczywiście prawdziwe hasło do pliku, a zamiast PLIK jego pełną ścieżkę, ale bez rozszerzenia .zip).
Zadziałało, moje archiwum zostało rozpakowane w aktywnym folderze. Bez udziału interfejsu graficznego. Programem domyślnie zainstalowanym na systemie.

Kwestia prywatności

Choć możliwość wołania 7-Zipa przez konsolę jest bardzo wygodna i fajnie się integruje ze skryptami, warto zwrócić uwagę na możliwą ciemną stronę tego ułatwienia.

Jak widać w powyższym przypadku – wynik strace’a zawierał na widoku hasło, którego używałem do rozpakowania pliku.

Strace dla wielu osób nie będzie czymś, z czego korzysta się na co dzień… Ale zdarza się, że po wrzuceniu swojego problemu z komputerem na forum publiczne dostaje się prośbę właśnie o wynik działania strace’a (bo jego szczegółowość ułatwia rozwiązywanie problemów). Szkoda by było, gdyby zaplątało się tam coś, czego się nie chce ujawniać.

Widzę tu pewien potencjał na tryb prywatny strace’a albo chociaż nakładkę, która pozwoliłaby wyłapywać właśnie takie przypadki i nieco cenzurować zapiski.
Przy okazji mogłaby ukrywać nazwę użytkownika, również widoczną wewnątrz ścieżek do plików i mogącą ujawniać tożsamość; u mnie był to tylko domyślny mint, u kogoś będzie arek-przykładnik.

Ciekawostka

Na Cinnamonie, czyli innym wariancie Minta, nie byłem w stanie powtórzyć działań z tego wpisu.
Zamiast Engrampy jest tam inny program, o nazwie file-roller (wedle pliku pomocy: to na jego kodzie opiera się Engrampa). Wygląda ciut inaczej, dając między innymi możliwość wyświetlania hasła podczas wpisywania.
…No i chyba więcej ukrywa, bo w zapiskach strace’a nie znalazłem ani wołania 7-Zipa, ani użytego hasła. Ale dokładnego mechanizmu działania jeszcze nie rozgryzłem, więc różnica niekoniecznie gwarantuje prywatnościową przewagę Cinnamona.

Podsumowanie

Na systemie Linux Mint MATE interfejs graficzny od pracy z plikami ZIP nazywa się Engrampa. Wykonawcą jego woli, wysyłanym do praktycznej roboty, jest natomiast 7-Zip.

Jak się okazuje, strace był strzałem w dziesiątkę, pozwalającym nie tylko odkryć tę zależność, ale nawet bezpośrednio zdobyć polecenie konsolowe, pomijające interfejs graficzny.
Mogłem je skopiować i wykorzystać wewnątrz własnego skryptu, żeby usprawnić pracę z zawartością archiwów.

Przy okazji wyszło na jaw, że w wynikach strace’a może się chować hasełko. Nie jest to może powód do bicia na alarm, ale warto to uwzględnić, udostępniając innym wyniki do celów debugowania.

Podobne wpisy

Niedawno próbowałem też zbadać, co się dzieje za kulisami podczas zmiany języka na polski na systemie Mint Cinnamon.
W tamtym przypadku sprawa okazała się nieco bardziej złożona i nie znalazłem szybkiego rozwiązania, więc jeszcze do niej wrócę.
Tym niemniej: jest tam jeszcze więcej konsolowej analizy. Jak ktoś lubi, to zapraszam.