Zrzuć pamięć procesu linux do pliku

Odpowiedzi:

46

Nie jestem pewien, w jaki sposób zrzucasz całą pamięć do pliku, nie robiąc tego wielokrotnie (jeśli ktoś zna automatyczny sposób, aby zmusić gdb do zrobienia tego, daj mi znać), ale poniższe działania działają dla każdej partii pamięci, zakładając, że wiesz pid:

$ cat /proc/[pid]/maps

Będzie to miało format (przykład):

00400000-00421000 r-xp 00000000 08:01 592398                             /usr/libexec/dovecot/pop3-login
00621000-00622000 rw-p 00021000 08:01 592398                             /usr/libexec/dovecot/pop3-login
00622000-0066a000 rw-p 00622000 00:00 0                                  [heap]
3e73200000-3e7321c000 r-xp 00000000 08:01 229378                         /lib64/ld-2.5.so
3e7341b000-3e7341c000 r--p 0001b000 08:01 229378                         /lib64/ld-2.5.so

Wybierz jedną partię pamięci (na przykład 00621000-00622000), a następnie użyj gdb jako root, aby dołączyć do procesu i zrzucić tę pamięć:

$ gdb --pid [pid]
(gdb) dump memory /root/output 0x00621000 0x00622000

Następnie przeanalizuj / root / wyjście za pomocą polecenia strings, mniej niż chcesz PuTTY na całym ekranie.

James L.
źródło
1
Czy istnieje sposób na zrobienie tego w bash / sh bez gdb?
Programming4life
3
@ Programming4life gcore (1)
Julian
51

Stworzyłem skrypt, który wykonuje to zadanie.

Pomysł pochodzi z odpowiedzi Jamesa Lawrie i tego posta: http://www.linuxforums.org/forum/programming-scripting/52375-reading-memory-other-processes.html#post287195

#!/bin/bash

grep rw-p /proc/$1/maps \
| sed -n 's/^\([0-9a-f]*\)-\([0-9a-f]*\) .*$/\1 \2/p' \
| while read start stop; do \
    gdb --batch --pid $1 -ex \
        "dump memory $1-$start-$stop.dump 0x$start 0x$stop"; \
done

umieść to w pliku (np. „dump-all-memory-of-pid.sh”) i uczyń go wykonywalnym

stosowanie: ./dump-all-memory-of-pid.sh [pid]

Dane wyjściowe są drukowane do plików o nazwach: pid-startaddress-stopaddress.dump

Zależności: gdb

A. Nilsson
źródło
2
Niesamowite! Po prostu użyłem go, aby dowiedzieć się, który skrypt uruchomił tajemniczą instancję bash.
Tobia,
Dlaczego tylko szukacie i zrzucacie zakresy z rw-puprawnieniami?
mxmlnkn
@mxmlnkn To dane ( rw-p), pozostałe zakresy dotyczą kodu ( r-xp). Jeśli chcesz rzucić jedno i drugie, idź dalej i wymień grepna np cat.
A. Nilsson,
39

próbować

    gcore $pid

gdzie $pidjest faktyczna liczba pid; Aby uzyskać więcej informacji zobacz:info gcore

zrzut może zająć trochę czasu, a część pamięci może nie być czytelna, ale jest wystarczająco dobra ... pamiętaj, że może tworzyć duże pliki, właśnie utworzyłem w ten sposób plik 2 GB ...

Wodnik Moc
źródło
1
Czy gcorezrzut jest rzadki?
CMCDragonkai
3

man proc mówi:

/ proc / [pid] / mem Ten plik może być używany do uzyskiwania dostępu do stron pamięci procesu poprzez open (2), read (2) i lseek (2).

Może to może ci pomóc

Dom
źródło
1
To nie wystarczy, odczyt innego procesu wymaga kombinacji / proc / <pid> / {mem, * map}, ptrace i pewnej obsługi sygnałów, aby uniknąć zawieszenia procesu docelowego.
Tobu,
@Tobu Rzeczywiście . Napisałem skrypt sprawdzający koncepcję .
Gilles „SO- przestań być zły”
3

Stworzyłem również własny program do zrzucania całej pamięci procesu, jest on w C, więc można go skompilować krzyżowo na Androida, czego potrzebowałem.

Możesz także podać adres IP i port TCP. Kod źródłowy tutaj .

Tal Aloni
źródło
2

Rozwiązanie Pure Bash:

procdump () 
{ 
    cat /proc/$1/maps | grep "rw-p" | awk '{print $1}' | ( IFS="-"
    while read a b; do
        count=$(( bd-ad ))
        ad=$(printf "%llu" "0x$a")
        bd=$(printf "%llu" "0x$b")
        dd if=/proc/$1/mem bs=1 skip=$ad count=$count of=$1_mem_$a.bin
    done )
}

Zastosowanie: procdump PID

dla czystszego zrzutu:

procdump () 
{ 
    cat /proc/$1/maps | grep -Fv ".so" | grep " 0 " | awk '{print $1}' | ( IFS="-"
    while read a b; do
        ad=$(printf "%llu" "0x$a")
        bd=$(printf "%llu" "0x$b")
        dd if=/proc/$1/mem bs=1 skip=$ad count=$(( bd-ad )) of=$1_mem_$a.bin
    done )
}
Zibri
źródło
Z tego, co rozumiem, idea czystszego zrzutu polega na tym, że tylko pliki w pamięci mają rozmiar dołączony do obszaru pamięci w przeciwieństwie do rzeczywistej pamięci aplikacji, która ma rozmiar 0 (ponieważ rozmiar faktycznie używany rozmiar jest nieznany przez OS).
mxmlnkn
Jednym ze problemów, które mam z tym skryptem, jest to, że rozmiar bloku 1 prowadzi do przepustowości niedopuszczalnie powolnej ~ 30kB / s w porównaniu do użycia rozmiaru bloku równego rozmiarowi strony (4096 dla mnie), dla którego dostaję ~ 100MB / s! Zobacz tutaj . getconf PAGESIZEsłuży do uzyskania rozmiaru strony, a następnie adresy i liczby są przez niego dzielone.
mxmlnkn
0

Jeśli chcesz zrzucić oddzielny segment pamięci uruchomionego procesu bez tworzenia ogromnego pliku podstawowego (powiedzmy z gcore), możesz użyć małego narzędzia z tego miejsca . W README znajduje się również jeden wiersz, jeśli chcesz zrzucić wszystkie czytelne segmenty do osobnych plików.

Nopius
źródło