Il sistema operativo e le applicazioni di un computer utilizzano la memoria principale (o RAM) per eseguire varie attività. Questa memoria volatile, contenente una grande quantità di informazioni su applicazioni in esecuzione, connessioni di rete, moduli del kernel, file aperti e praticamente tutto il resto, viene cancellata ogni volta che il computer si riavvia.
Più risorse Linux
- Comandi Linux cheat sheet
- Cheat sheet sui comandi avanzati di Linux
- Corso online gratuito:Panoramica tecnica RHEL
- Cheat sheet della rete Linux
- Cheat sheet di SELinux
- Cheat sheet dei comandi comuni di Linux
- Cosa sono i container Linux?
- I nostri ultimi articoli su Linux
La medicina legale della memoria è un modo per trovare ed estrarre queste preziose informazioni dalla memoria. La volatilità è uno strumento open source che utilizza plug-in per elaborare questo tipo di informazioni. Tuttavia, c'è un problema:prima di poter elaborare queste informazioni, devi scaricare la memoria fisica in un file e Volatility non ha questa capacità.
Pertanto, questo articolo è composto da due parti:
- La prima parte riguarda l'acquisizione della memoria fisica e il dumping in un file.
- La seconda parte usa Volatility per leggere ed elaborare le informazioni da questo dump di memoria.
Ho utilizzato il seguente sistema di test per questo tutorial, ma funzionerà su qualsiasi distribuzione Linux:
$ cat /etc/redhat-release
Red Hat Enterprise Linux release 8.3 (Ootpa)
$
$ uname -r
4.18.0-240.el8.x86_64
$
Una nota di cautela: La parte 1 riguarda la compilazione e il caricamento di un modulo del kernel. Non preoccuparti; non è così difficile come sembra. Alcune linee guida:
- Segui i passaggi.
- Non provare nessuno di questi passaggi su un sistema di produzione o sulla tua macchina principale.
- Utilizza sempre una macchina virtuale (VM) di prova per provare le cose finché non ti senti a tuo agio nell'uso degli strumenti e capisci come funzionano.
Installa i pacchetti richiesti
Prima di iniziare, installa gli strumenti necessari. Se stai usando una distribuzione basata su Debian, usa l'equivalente apt-get
comandi. La maggior parte di questi pacchetti fornisce le informazioni sul kernel e gli strumenti necessari per compilare il codice:
$ yum install kernel-headers kernel-devel gcc elfutils-libelf-devel make git libdwarf-tools python2-devel.x86_64-y
Parte 1:usa LiME per acquisire memoria e scaricarla in un file
Prima di poter iniziare ad analizzare la memoria, è necessario disporre di un dump della memoria. In un vero evento forense, questo potrebbe provenire da un sistema compromesso o violato. Tali informazioni vengono spesso raccolte e archiviate per analizzare come è avvenuta l'intrusione e il suo impatto. Dal momento che probabilmente non hai un dump della memoria disponibile, puoi eseguire un dump della memoria della tua macchina virtuale di prova e utilizzarlo per eseguire analisi forensi della memoria.
Linux Memory Extractor (LiME) è uno strumento popolare per acquisire memoria su un sistema Linux. Ottieni LiME con:
$ git clone https://github.com/504ensicsLabs/LiME.git
$
$ cd LiME/src/
$
$ ls
deflate.c disk.c hash.c lime.h main.c Makefile Makefile.sample tcp.c
$
Costruisci il modulo del kernel LiME
Esegui make
comando all'interno di src
cartella. Questo crea un modulo del kernel con estensione .ko. Idealmente, il lime.ko
il file verrà rinominato utilizzando il formato lime-<your-kernel-version>.ko
alla fine di make
:
$ make
make -C /lib/modules/4.18.0-240.el8.x86_64/build M="/root/LiME/src" modules
make[1]: Entering directory '/usr/src/kernels/4.18.0-240.el8.x86_64'
<< snip >>
make[1]: Leaving directory '/usr/src/kernels/4.18.0-240.el8.x86_64'
strip --strip-unneeded lime.ko
mv lime.ko lime-4.18.0-240.el8.x86_64.ko
$
$
$ ls -l lime-4.18.0-240.el8.x86_64.ko
-rw-r--r--. 1 root root 25696 Apr 17 14:45 lime-4.18.0-240.el8.x86_64.ko
$
$ file lime-4.18.0-240.el8.x86_64.ko
lime-4.18.0-240.el8.x86_64.ko: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), BuildID[sha1]=1d0b5cf932389000d960a7e6b57c428b8e46c9cf, not stripped
$
Carica il modulo del kernel LiME
Ora è il momento di caricare il modulo del kernel per acquisire la memoria di sistema. Il insmod
il comando aiuta a caricare il modulo del kernel; una volta caricato, il modulo legge la memoria primaria (RAM) sul tuo sistema e scarica il contenuto della memoria nel file fornito nel path
directory sulla riga di comando. Un altro parametro importante è format
; mantieni il formato lime
, come mostrato di seguito. Dopo aver inserito il modulo del kernel, verifica che sia stato caricato usando lsmod
comando:
$ lsmod | grep lime
$
$ insmod ./lime-4.18.0-240.el8.x86_64.ko "path=../RHEL8.3_64bit.mem format=lime"
$
$ lsmod | grep lime
lime 16384 0
$
Dovresti vedere che il file fornito al path
comando è stato creato e la dimensione del file è (non sorprendentemente) la stessa della dimensione della memoria fisica (RAM) sul tuo sistema. Una volta che hai il dump della memoria, puoi rimuovere il modulo del kernel usando rmmod
comando:
$
$ ls -l ~/LiME/RHEL8.3_64bit.mem
-r--r--r--. 1 root root 4294544480 Apr 17 14:47 /root/LiME/RHEL8.3_64bit.mem
$
$ du -sh ~/LiME/RHEL8.3_64bit.mem
4.0G /root/LiME/RHEL8.3_64bit.mem
$
$ free -m
total used free shared buff/cache available
Mem: 3736 220 366 8 3149 3259
Swap: 4059 8 4051
$
$ rmmod lime
$
$ lsmod | grep lime
$
Cosa c'è nel dump della memoria?
Questo file di dump è solo dati grezzi, come puoi vedere usando il file
comando qui sotto. Non puoi dargli molto senso manualmente; sì, ci sono alcune stringhe ASCII da qualche parte, ma non puoi aprire il file in un editor e leggerlo. L'output hexdump mostra che i pochi byte iniziali sono EmiL
; questo perché il formato della tua richiesta era "lime" nel comando sopra:
$ file ~/LiME/RHEL8.3_64bit.mem
/root/LiME/RHEL8.3_64bit.mem: data
$
$ hexdump -C ~/LiME/RHEL8.3_64bit.mem | head
00000000 45 4d 69 4c 01 00 00 00 00 10 00 00 00 00 00 00 |EMiL............|
00000010 ff fb 09 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000020 b8 fe 4c cd 21 44 00 32 20 00 00 2a 2a 2a 2a 2a |..L.!D.2 ..*****|
00000030 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a |****************|
00000040 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 00 20 |************* . |
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000080 00 00 00 00 00 00 00 00 00 00 00 00 70 78 65 6c |............pxel|
00000090 69 6e 75 78 2e 30 00 00 00 00 00 00 00 00 00 00 |inux.0..........|
000000a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
$
Parte 2:ottieni la volatilità e usala per analizzare il dump della memoria
Ora che hai un dump di memoria di esempio da analizzare, ottieni il software Volatility con il comando seguente. Volatility è stato riscritto in Python 3, ma questo tutorial utilizza il pacchetto Volatility originale, che utilizza Python 2. Se vuoi sperimentare Volatility 3, scaricalo dal repository Git appropriato e usa Python 3 invece di Python 2 nei seguenti comandi :
$ git clone https://github.com/volatilityfoundation/volatility.git
$
$ cd volatility/
$
$ ls
AUTHORS.txt contrib LEGAL.txt Makefile PKG-INFO pyinstaller.spec resources tools vol.py
CHANGELOG.txt CREDITS.txt LICENSE.txt MANIFEST.in pyinstaller README.txt setup.py volatility
$
Volatility usa due librerie Python per alcune funzionalità, quindi installale usando i seguenti comandi. In caso contrario, potresti visualizzare alcuni errori di importazione quando esegui lo strumento Volatility; puoi ignorarli a meno che tu non stia eseguendo un plugin che necessita di queste librerie; in tal caso, lo strumento emetterà un errore:
$ pip2 install pycrypto
$ pip2 install distorm3
Elenca i profili Linux di Volatility
Il primo comando Volatility che vorrai eseguire elenca quali profili Linux sono disponibili. Il punto di ingresso principale per eseguire qualsiasi comando di Volatility è il vol.py
sceneggiatura. Invocalo usando l'interprete Python 2 e fornisci il --info
opzione. Per restringere l'output, cerca le stringhe che iniziano con Linux. Come puoi vedere, non sono elencati molti profili Linux:
$ python2 vol.py --info | grep ^Linux
Volatility Foundation Volatility Framework 2.6.1
LinuxAMD64PagedMemory - Linux-specific AMD 64-bit address space.
$
Costruisci il tuo profilo Linux
Le distribuzioni Linux sono varie e costruite per varie architetture. Ecco perché i profili sono essenziali:la volatilità deve conoscere il sistema e l'architettura da cui è stato acquisito il dump della memoria prima di estrarre le informazioni. Ci sono comandi di volatilità per trovare queste informazioni; tuttavia, questo metodo richiede tempo. Per velocizzare le cose, crea un profilo Linux personalizzato usando i seguenti comandi.
Passa a tools/linux
directory all'interno del repository Volatility ed eseguire make
comando:
$ cd tools/linux/
$
$ pwd
/root/volatility/tools/linux
$
$ ls
kcore Makefile Makefile.enterprise module.c
$
$ make
make -C //lib/modules/4.18.0-240.el8.x86_64/build CONFIG_DEBUG_INFO=y M="/root/volatility/tools/linux" modules
make[1]: Entering directory '/usr/src/kernels/4.18.0-240.el8.x86_64'
<< snip >>
make[1]: Leaving directory '/usr/src/kernels/4.18.0-240.el8.x86_64'
$
Dovresti vedere un nuovo module.dwarf
file. Hai anche bisogno di System.map
file dal /boot
directory, poiché contiene tutti i simboli relativi al kernel attualmente in esecuzione:
$ ls
kcore Makefile Makefile.enterprise module.c module.dwarf
$
$ ls -l module.dwarf
-rw-r--r--. 1 root root 3987904 Apr 17 15:17 module.dwarf
$
$ ls -l /boot/System.map-4.18.0-240.el8.x86_64
-rw-------. 1 root root 4032815 Sep 23 2020 /boot/System.map-4.18.0-240.el8.x86_64
$
$
Per creare un profilo personalizzato, torna alla directory Volatility ed esegui il comando seguente. Il primo argomento fornisce un .zip personalizzato con un nome file a tua scelta. Ho usato il sistema operativo e le versioni del kernel nel nome. L'argomento successivo è module.dwarf
file creato sopra e l'argomento finale è System.map
file dal /boot
directory:
$
$ cd volatility/
$
$ zip volatility/plugins/overlays/linux/Redhat8.3_4.18.0-240.zip tools/linux/module.dwarf /boot/System.map-4.18.0-240.el8.x86_64
adding: tools/linux/module.dwarf (deflated 91%)
adding: boot/System.map-4.18.0-240.el8.x86_64 (deflated 79%)
$
Il tuo profilo personalizzato è ora pronto, quindi verifica che il file .zip sia stato creato nella posizione indicata sopra. Se vuoi sapere se Volatility rileva questo profilo personalizzato, esegui --info
comando di nuovo. Questa volta, dovresti vedere il nuovo profilo elencato di seguito:
$
$ ls -l volatility/plugins/overlays/linux/Redhat8.3_4.18.0-240.zip
-rw-r--r--. 1 root root 1190360 Apr 17 15:20 volatility/plugins/overlays/linux/Redhat8.3_4.18.0-240.zip
$
$
$ python2 vol.py --info | grep Redhat
Volatility Foundation Volatility Framework 2.6.1
LinuxRedhat8_3_4_18_0-240x64 - A Profile for Linux Redhat8.3_4.18.0-240 x64
$
$
Inizia a utilizzare la volatilità
Ora sei pronto per fare una vera e propria analisi forense della memoria. Ricorda, la volatilità è composta da plug-in personalizzati che puoi eseguire su un dump della memoria per ottenere informazioni. Il formato generale del comando è:
python2 vol.py -f <memory-dump-file-taken-by-Lime> <plugin-name> --profile=<name-of-our-custom-profile>
Armato di queste informazioni, esegui linux_banner plug-in per vedere se riesci a identificare le informazioni distro corrette dal dump della memoria:
$ python2 vol.py -f ~/LiME/RHEL8.3_64bit.mem linux_banner --profile=LinuxRedhat8_3_4_18_0-240x64
Volatility Foundation Volatility Framework 2.6.1
Linux version 4.18.0-240.el8.x86_64 ([email protected]) (gcc version 8.3.1 20191121 (Red Hat 8.3.1-5) (GCC)) #1 SMP Wed Sep 23 05:13:10 EDT 2020
$
Trova plug-in Linux
Ha funzionato bene, quindi ora probabilmente sei curioso di sapere come trovare tutti i nomi di tutti i plugin di Linux. C'è un trucco facile:esegui --info
comando e grep
per linux_
corda. Ci sono una varietà di plugin disponibili per usi diversi. Ecco un elenco parziale:
$ python2 vol.py --info | grep linux_
Volatility Foundation Volatility Framework 2.6.1
linux_apihooks - Checks for userland apihooks
linux_arp - Print the ARP table
linux_aslr_shift - Automatically detect the Linux ASLR shift
<< snip >>
linux_banner - Prints the Linux banner information
linux_vma_cache - Gather VMAs from the vm_area_struct cache
linux_volshell - Shell in the memory image
linux_yarascan - A shell in the Linux memory image
$
Controlla quali processi erano in esecuzione sul sistema quando hai eseguito il dump della memoria utilizzando linux_psaux collegare. Nota l'ultimo comando nell'elenco:è insmod
comando eseguito prima del dump:
$ python2 vol.py -f ~/LiME/RHEL8.3_64bit.mem linux_psaux --profile=LinuxRedhat8_3_4_18_0-240x64
Volatility Foundation Volatility Framework 2.6.1
Pid Uid Gid Arguments
1 0 0 /usr/lib/systemd/systemd --switched-root --system --deserialize 18
2 0 0 [kthreadd]
3 0 0 [rcu_gp]
4 0 0 [rcu_par_gp]
861 0 0 /usr/libexec/platform-python -Es /usr/sbin/tuned -l -P
869 0 0 /usr/bin/rhsmcertd
875 0 0 /usr/libexec/sssd/sssd_be --domain implicit_files --uid 0 --gid 0 --logger=files
878 0 0 /usr/libexec/sssd/sssd_nss --uid 0 --gid 0 --logger=files
<<< snip >>>
11064 89 89 qmgr -l -t unix -u
227148 0 0 [kworker/0:0]
227298 0 0 -bash
227374 0 0 [kworker/u2:1]
227375 0 0 [kworker/0:2]
227884 0 0 [kworker/0:3]
228573 0 0 insmod ./lime-4.18.0-240.el8.x86_64.ko path=../RHEL8.3_64bit.mem format=lime
228576 0 0
$
Vuoi conoscere le statistiche di rete del sistema? Esegui linux_netstat plugin per trovare lo stato delle connessioni di rete durante il dump della memoria:
$ python2 vol.py -f ~/LiME/RHEL8.3_64bit.mem linux_netstat --profile=LinuxRedhat8_3_4_18_0-240x64
Volatility Foundation Volatility Framework 2.6.1
UNIX 18113 systemd/1 /run/systemd/private
UNIX 11411 systemd/1 /run/systemd/notify
UNIX 11413 systemd/1 /run/systemd/cgroups-agent
UNIX 11415 systemd/1
UNIX 11416 systemd/1
<< snip>>
$
Quindi, usa linux_mount plugin per vedere quali filesystem sono stati montati durante il dump della memoria:
$ python2 vol.py -f ~/LiME/RHEL8.3_64bit.mem linux_mount --profile=LinuxRedhat8_3_4_18_0-240x64
Volatility Foundation Volatility Framework 2.6.1
tmpfs /sys/fs/cgroup tmpfs ro,nosuid,nodev,noexec
cgroup /sys/fs/cgroup/pids cgroup rw,relatime,nosuid,nodev,noexec
systemd-1 /proc/sys/fs/binfmt_misc autofs rw,relatime
sunrpc /var/lib/nfs/rpc_pipefs rpc_pipefs rw,relatime
/dev/mapper/rhel_kvm--03--guest11-root / xfs rw,relatime
tmpfs /dev/shm tmpfs rw,nosuid,nodev
selinuxfs /sys/fs/selinux selinuxfs rw,relatime
<< snip>>
cgroup /sys/fs/cgroup/net_cls,net_prio cgroup rw,relatime,nosuid,nodev,noexec
cgroup /sys/fs/cgroup/cpu,cpuacct cgroup rw,relatime,nosuid,nodev,noexec
bpf /sys/fs/bpf bpf rw,relatime,nosuid,nodev,noexec
cgroup /sys/fs/cgroup/memory cgroup ro,relatime,nosuid,nodev,noexec
cgroup /sys/fs/cgroup/cpuset cgroup rw,relatime,nosuid,nodev,noexec
mqueue /dev/mqueue mqueue rw,relatime
$
Sei curioso di sapere quali moduli del kernel sono stati caricati? Volatility ha anche un plugin per questo, giustamente chiamato linux_lsmod :
$ python2 vol.py -f ~/LiME/RHEL8.3_64bit.mem linux_lsmod --profile=LinuxRedhat8_3_4_18_0-240x64
Volatility Foundation Volatility Framework 2.6.1
ffffffffc0535040 lime 20480
ffffffffc0530540 binfmt_misc 20480
ffffffffc05e8040 sunrpc 479232
<< snip >>
ffffffffc04f9540 nfit 65536
ffffffffc0266280 dm_mirror 28672
ffffffffc025e040 dm_region_hash 20480
ffffffffc0258180 dm_log 20480
ffffffffc024bbc0 dm_mod 151552
$
Vuoi trovare tutti i comandi eseguiti dall'utente che sono stati archiviati nella cronologia di Bash? Esegui linux_bash plug-in:
$ python2 vol.py -f ~/LiME/RHEL8.3_64bit.mem linux_bash --profile=LinuxRedhat8_3_4_18_0-240x64 -v
Volatility Foundation Volatility Framework 2.6.1
Pid Name Command Time Command
-------- -------------------- ------------------------------ -------
227221 bash 2021-04-17 18:38:24 UTC+0000 lsmod
227221 bash 2021-04-17 18:38:24 UTC+0000 rm -f .log
227221 bash 2021-04-17 18:38:24 UTC+0000 ls -l /etc/zzz
227221 bash 2021-04-17 18:38:24 UTC+0000 cat ~/.vimrc
227221 bash 2021-04-17 18:38:24 UTC+0000 ls
227221 bash 2021-04-17 18:38:24 UTC+0000 cat /proc/817/cwd
227221 bash 2021-04-17 18:38:24 UTC+0000 ls -l /proc/817/cwd
227221 bash 2021-04-17 18:38:24 UTC+0000 ls /proc/817/
<< snip >>
227298 bash 2021-04-17 18:40:30 UTC+0000 gcc prt.c
227298 bash 2021-04-17 18:40:30 UTC+0000 ls
227298 bash 2021-04-17 18:40:30 UTC+0000 ./a.out
227298 bash 2021-04-17 18:40:30 UTC+0000 vim prt.c
227298 bash 2021-04-17 18:40:30 UTC+0000 gcc prt.c
227298 bash 2021-04-17 18:40:30 UTC+0000 ./a.out
227298 bash 2021-04-17 18:40:30 UTC+0000 ls
$
Vuoi sapere quali file sono stati aperti da quali processi? Usa linux_lsof plug-in per elencare tali informazioni:
$ python2 vol.py -f ~/LiME/RHEL8.3_64bit.mem linux_lsof --profile=LinuxRedhat8_3_4_18_0-240x64
Volatility Foundation Volatility Framework 2.6.1
Offset Name Pid FD Path
------------------ ------------------------------ -------- -------- ----
0xffff9c83fb1e9f40 rsyslogd 71194 0 /dev/null
0xffff9c83fb1e9f40 rsyslogd 71194 1 /dev/null
0xffff9c83fb1e9f40 rsyslogd 71194 2 /dev/null
0xffff9c83fb1e9f40 rsyslogd 71194 3 /dev/urandom
0xffff9c83fb1e9f40 rsyslogd 71194 4 socket:[83565]
0xffff9c83fb1e9f40 rsyslogd 71194 5 /var/log/messages
0xffff9c83fb1e9f40 rsyslogd 71194 6 anon_inode:[9063]
0xffff9c83fb1e9f40 rsyslogd 71194 7 /var/log/secure
<< snip >>
0xffff9c8365761f40 insmod 228573 0 /dev/pts/0
0xffff9c8365761f40 insmod 228573 1 /dev/pts/0
0xffff9c8365761f40 insmod 228573 2 /dev/pts/0
0xffff9c8365761f40 insmod 228573 3 /root/LiME/src/lime-4.18.0-240.el8.x86_64.ko
$
Accedi alla posizione degli script dei plugin di Linux
Puoi ottenere molte più informazioni leggendo il dump della memoria ed elaborando le informazioni. Se conosci Python e sei curioso di sapere come sono state elaborate queste informazioni, vai alla directory in cui sono archiviati tutti i plugin, scegline uno che ti interessa e guarda come Volatility ottiene queste informazioni:
$ ls volatility/plugins/linux/
apihooks.py common.py kernel_opened_files.py malfind.py psaux.py
apihooks.pyc common.pyc kernel_opened_files.pyc malfind.pyc psaux.pyc
arp.py cpuinfo.py keyboard_notifiers.py mount_cache.py psenv.py
arp.pyc cpuinfo.pyc keyboard_notifiers.pyc mount_cache.pyc psenv.pyc
aslr_shift.py dentry_cache.py ld_env.py mount.py pslist_cache.py
aslr_shift.pyc dentry_cache.pyc ld_env.pyc mount.pyc pslist_cache.pyc
<< snip >>
check_syscall_arm.py __init__.py lsmod.py proc_maps.py tty_check.py
check_syscall_arm.pyc __init__.pyc lsmod.pyc proc_maps.pyc tty_check.pyc
check_syscall.py iomem.py lsof.py proc_maps_rb.py vma_cache.py
check_syscall.pyc iomem.pyc lsof.pyc proc_maps_rb.pyc vma_cache.pyc
$
$
Uno dei motivi per cui mi piace Volatility è che fornisce molti plugin di sicurezza. Queste informazioni sarebbero difficili da acquisire manualmente:
linux_hidden_modules - Carves memory to find hidden kernel modules
linux_malfind - Looks for suspicious process mappings
linux_truecrypt_passphrase - Recovers cached Truecrypt passphrases
La volatilità ti consente anche di aprire una shell all'interno del dump della memoria, quindi invece di eseguire tutti i comandi precedenti, puoi invece eseguire i comandi della shell e ottenere le stesse informazioni:
$ python2 vol.py -f ~/LiME/RHEL8.3_64bit.mem linux_volshell --profile=LinuxRedhat8_3_4_18_0-240x64 -v
Volatility Foundation Volatility Framework 2.6.1
Current context: process systemd, pid=1 DTB=0x1042dc000
Welcome to volshell! Current memory image is:
file:///root/LiME/RHEL8.3_64bit.mem
To get help, type 'hh()'
>>>
>>> sc()
Current context: process systemd, pid=1 DTB=0x1042dc000
>>>
Passaggi successivi
L'analisi forense della memoria è un buon modo per saperne di più sugli interni di Linux. Prova tutti i plugin di Volatility e studiane l'output in dettaglio. Quindi pensa ai modi in cui queste informazioni possono aiutarti a identificare un'intrusione o un problema di sicurezza. Scopri come funzionano i plugin e magari prova anche a migliorarli. E se non hai trovato un plugin per quello che vuoi fare, scrivine uno e invialo a Volatility in modo che anche altri possano usarlo.