Jakiś czas temu zauważyłem, że nazwy użytkowników i hasła podane curl
jako argumenty wiersza poleceń nie pojawiają się w ps
danych wyjściowych (chociaż oczywiście mogą pojawiać się w twojej historii bashów).
Podobnie nie pojawiają się w /proc/PID/cmdline
.
(Można jednak określić długość połączonego argumentu nazwa użytkownika / hasło.)
Pokaz poniżej:
[root@localhost ~]# nc -l 80 &
[1] 3342
[root@localhost ~]# curl -u iamsam:samiam localhost &
[2] 3343
[root@localhost ~]# GET / HTTP/1.1
Authorization: Basic aWFtc2FtOnNhbWlhbQ==
User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.15.3 zlib/1.2.3 libidn/1.18 libssh2/1.4.2
Host: localhost
Accept: */*
[1]+ Stopped nc -l 80
[root@localhost ~]# jobs
[1]+ Stopped nc -l 80
[2]- Running curl -u iamsam:samiam localhost &
[root@localhost ~]# ps -ef | grep curl
root 3343 3258 0 22:37 pts/1 00:00:00 curl -u localhost
root 3347 3258 0 22:38 pts/1 00:00:00 grep curl
[root@localhost ~]# od -xa /proc/3343/cmdline
0000000 7563 6c72 2d00 0075 2020 2020 2020 2020
c u r l nul - u nul sp sp sp sp sp sp sp sp
0000020 2020 2020 0020 6f6c 6163 686c 736f 0074
sp sp sp sp sp nul l o c a l h o s t nul
0000040
[root@localhost ~]#
Jak osiąga się ten efekt? Czy jest to gdzieś w kodzie źródłowym curl
? (Zakładam, że jest to curl
funkcja, a nie ps
funkcja? A może to jakaś funkcja jądra?)
Ponadto: czy można to osiągnąć spoza kodu źródłowego binarnego pliku wykonywalnego? Np. Używając poleceń powłoki, prawdopodobnie w połączeniu z uprawnieniami roota?
Innymi słowy, czy mógłbym w jakiś sposób maskować argument pojawiający się w danych wyjściowych /proc
lub ps
wyjściowych (myślę, że to samo), które przekazałem do dowolnego polecenia powłoki? (Sądzę, że odpowiedź na to pytanie brzmi „nie”, ale wydaje się, że warto uwzględnić to dodatkowe pół pytania).
environ
bezpośrednio z dostępu do zmiennych środowiskowych? - dolny wiersz: lista argumentów, podobnie jak lista zmiennych środowiskowych, znajduje się w pamięci procesu odczytu / zapisu użytkownika i może być modyfikowana przez proces użytkownika.grep
wzorca klasą postaci. Np.ps -ef | grep '[c]url'
curl
pasuje,curl
ale[c]url
nie pasuje[c]url
. Jeśli potrzebujesz więcej szczegółów, zadaj nowe pytanie, a chętnie odpowiem.Odpowiedzi:
Kiedy jądro wykonuje proces, kopiuje argumenty wiersza poleceń do pamięci odczytu i zapisu należącej do procesu (na stosie, przynajmniej w Linuksie). Proces może zapisywać do tej pamięci, jak każda inna pamięć. Kiedy
ps
wyświetla argument, odczytuje z powrotem, co jest zapisane w tym konkretnym adresem w pamięci procesu. Większość programów zachowuje oryginalne argumenty, ale można je zmienić. Opis POSIX zps
państw, którePowodem tego jest fakt, że większość wariantów Uniksa odzwierciedla zmianę, ale implementacje POSIX na innych typach systemów operacyjnych mogą tego nie robić.
Ta funkcja ma ograniczone zastosowanie, ponieważ proces nie może dokonywać dowolnych zmian. Przynajmniej całkowitej długości argumentów nie można zwiększyć, ponieważ program nie może zmienić lokalizacji, w której
ps
będą pobierane argumenty i nie może rozszerzyć obszaru poza swój pierwotny rozmiar. Długość można skutecznie zmniejszyć, umieszczając na końcu puste bajty, ponieważ argumenty są łańcuchami zakończonymi zerami w stylu C (jest to nie do odróżnienia od wielu pustych argumentów na końcu).Jeśli naprawdę chcesz kopać, możesz spojrzeć na źródło implementacji typu open source. W Linuksie źródło
ps
nie jest interesujące, wszystko, co tam zobaczysz, to to, że czyta argumenty wiersza poleceń z systemu plików proc , w . Kod generujący zawartość tego pliku znajduje się w jądrze, w . Część pamięci procesu (dostępna za pomocą ) przechodzi z adresu do ; adresy te są zapisywane w jądrze podczas uruchamiania procesu i nie można ich później zmienić./proc/PID/cmdline
proc_pid_cmdline_read
fs/proc/base.c
access_remote_vm
mm->arg_start
mm->arg_end
Niektóre demony używają tej zdolności do odzwierciedlenia swojego statusu, np. Zmieniają
argv[1]
ciąg na taki jakstarting
lubavailable
lubexiting
. Wiele wariantów uniksowych masetproctitle
do tego funkcję. Niektóre programy wykorzystują tę zdolność do ukrywania poufnych danych. Zauważ, że ma to ograniczone zastosowanie, ponieważ argumenty wiersza poleceń są widoczne podczas uruchamiania procesu.Większość języków wysokiego poziomu kopiuje argumenty do obiektów łańcuchowych i nie daje możliwości modyfikacji oryginalnej pamięci. Oto program w C, który demonstruje tę zdolność poprzez
argv
bezpośrednią zmianę elementów.Przykładowe dane wyjściowe:
Możesz zobaczyć
argv
modyfikację w kodzie źródłowym curl. Curl definiuje funkcję,cleanarg
wsrc/tool_paramhlp.c
której służy do zmiany argumentu na wszystkie spacje za pomocąmemset
. Wsrc/tool_getparam.c
tej funkcji korzysta się kilka razy, np. Poprzez redagowanie hasła użytkownika . Ponieważ funkcja jest wywoływana z parsowania parametrów, dzieje się to na początku wywołania curl, ale zrzucenie wiersza poleceń, zanim to nastąpi, nadal spowoduje wyświetlenie haseł.Ponieważ argumenty są przechowywane we własnej pamięci procesu, nie można ich zmienić z zewnątrz, chyba że za pomocą debugera.
źródło
ps
argumentów Raport z tego kawałka pamięci jądra, ignorując wszelkie zmiany dokonane w procesach odczytu i zapisu pamięci? Ale (jeśli mam rację?) Większość odmian systemu UNIX nawet nie robi tego pierwszego, więc nie można zrobićps
implementacji tego drugiego bez modyfikacji jądra, ponieważ oryginalne dane nigdzie nie są przechowywane?argv
wpisów zostać zmieniony (nie można ustawićargv[i]
, ale można napisaćargv[i][0]
? Poprzezargv[i][strlen(argv[i])]
), więc nie musi być kopią w pamięci procesu.ps
wyjściu wiele pustych argumentów wygląda na to, że nic tam nie ma, ale tak, robi to różnicę, jeśli sprawdzisz, ile jest spacji i możesz obserwować bardziej bezpośrednio z/proc/PID/cmdline
.Inne odpowiedzi dobrze odpowiadają na pytanie w sposób ogólny. Aby dokładnie odpowiedzieć „ Jak osiągnąć ten efekt? Czy jest to gdzieś w kodzie źródłowym curl? ”:
W sekcji przetwarzania argumentów z kodu źródłowego curl The
-u
opcja jest obsługiwana w sposób następujący:A
cleanarg()
funkcja jest zdefiniowana w następujący sposób:Możemy więc wyraźnie zobaczyć, że argument nazwa użytkownika: hasło w
argv
jest zastąpiony spacjami, jak opisano w innych odpowiedziach.źródło
cleanarg
wyraźnie stwierdza, że robi to, o co pyta pytanie!Proces może nie tylko odczytać jego parametry, ale także je zapisać.
Nie jestem programistą, więc nie znam tych rzeczy, ale może być możliwe z zewnątrz z podejściem podobnym do zmiany parametrów środowiska:
https://stackoverflow.com/questions/205064/is-there-a-way-to-change-another-processs-environment-variables
źródło
bash -c 'awk 1 /proc/$$/cmdline; set -- something; awk 1 /proc/$$/cmdline'
Pokazuje, że przynajmniej w powłoce ustawienie parametrów różni się od modyfikacji tego, co jądro postrzega jako parametry procesu.