volatilityfoundation / volatility3

Volatility 3.0 development
http://volatilityfoundation.org/
Other
2.72k stars 461 forks source link

Add Linux ptrace plugin #1288

Closed gcmoreira closed 1 month ago

gcmoreira commented 1 month ago

This PR adds the linux.ptrace plugin to enumerate tracer and tracee tasks. Ptrace is often leveraged by attackers to gather credentials and other sensitive information.

Example 1: strace

Let's take a random process thread:

$ ps -eLf
UID        PID  PPID   LWP  C NLWP STIME TTY          TIME CMD
root       955     1  1047  0    3 05:34 ?        00:00:00 /usr/lib/accountsservice/accounts-daemon
...

Let's ptrace the thread/task 1047

$ sudo strace -p 1047
...
$ ps -eLf
UID        PID  PPID   LWP  C NLWP STIME TTY          TIME CMD
root      2963  2961  2963  0    1 05:38 pts/1    00:00:00 strace -p 1047
...
$ sudo cat /proc/1047/status
Name:   gmain
Umask:  0022
State:  S (sleeping)
Tgid:   955
Ngid:   0
Pid:    1047
PPid:   1
TracerPid:  2963
...
 $ ./vol.py -r pretty \
    -f ../dump_ubuntu180464bit_5.4.0-117-generic_ptrace.core \
    linux.ptrace 
Volatility 3 Framework 2.10.0        
  | Process |  PID |  TID | Tracer TID | Tracee TID |                                                            Flags
* |   gmain |  955 | 1047 |       2963 |          - | PT_SEIZED|PT_TRACE_EXIT|PT_TRACE_EXEC|PT_TRACESYSGOOD|PT_PTRACED
* |  strace | 2963 | 2963 |          - |       1047 |                                                                -

Example 2: gdb

$ sudo gdb -p 1047
$ ps -eLf | grep gdb
UID        PID  PPID   LWP  C NLWP STIME TTY          TIME CMD
...
root      4278  4277  4278  1    1 09:42 pts/1    00:00:00 gdb -p 1047
$ sudo cat /proc/1047/status
Name:   gmain
Umask:  0022
State:  t (tracing stop)
Tgid:   955
Ngid:   0
Pid:    1047
PPid:   1
TracerPid:  4278
...
$ ./vol.py -r pretty \
    -f ./dump_ubuntu180464bit_5.4.0-117-generic_ptrace_gdb.core \
    linux.ptrace 
Volatility 3 Framework 2.10.0
  | Process |  PID |  TID | Tracer TID | Tracee TID |                                                                                                    Flags
* |   gmain |  955 | 1047 |       4278 |          - | PT_TRACE_VFORK_DONE|PT_TRACE_EXEC|PT_TRACE_CLONE|PT_TRACE_VFORK|PT_TRACE_FORK|PT_TRACESYSGOOD|PT_PTRACED
* |     gdb | 4278 | 4278 |          - |       1047 |                                                                                                        -

Example 3: Ptracing from a thread

For this example, I wrote a simple C program that spawns a pthread and attaches to the same thread as described above. This shows that the information is always related to TID (and not to user PID / kernel TGID). This aligns with our discussion with @eve-mem here:

$ sudo ./pthread_ptraced 
Enter the TID of the process to attach to: 1047
$ ps -efL
UID        PID  PPID   LWP  C NLWP STIME TTY          TIME CMD
...
root      9491  2928  9491  0    1 10:32 pts/1    00:00:00 sudo ./pthread_ptraced
root      9492  9491  9492  0    2 10:32 pts/1    00:00:00 ./pthread_ptraced
root      9492  9491  9600  0    2 10:32 pts/1    00:00:00 ./pthread_ptraced
$ sudo cat /proc/1047/status
Name:   gmain
Umask:  0022
State:  t (tracing stop)
Tgid:   955
Ngid:   0
Pid:    1047
PPid:   1
TracerPid:  9600
...

As you can see, PID in TracerPid actually refers to the user TID, representing the internal kernel PID, and not the kernel TGID which corresponds to the user PID. Confused? Please refer to the links above for clarification.

$ ./vol.py -r pretty \
    -f ./dump_ubuntu180464bit_5.4.0-117-generic_ptrace_from_thread.core \
    linux.ptrace
Volatility 3 Framework 2.10.0
  |         Process |  PID |  TID | Tracer TID | Tracee TID |      Flags
* |           gmain |  955 | 1047 |       9600 |          - | PT_PTRACED
* | pthread_ptraced | 9492 | 9600 |          - |       1047 |          -

Example 4: Ptracing multiple threads using PTRACE_O_TRACECLONE

$ sudo ./fork_seized
tracer: 1174, tracee: 1175
[*] Wait for the child process to stop
[1175] Tracee - Launching the 3 threads
Thread 0 created
Thread 1 created
Thread 2 created
[1175] Tracee - Waiting
[*] Joining 3 threads
$ ps -efL | grep fork_seized
...
root      1172  1146  1172  0    1 04:20 pts/0    00:00:00 sudo ./fork_seized
root      1174  1172  1174  0    1 04:20 pts/0    00:00:00 ./fork_seized
root      1175  1174  1175  0    4 04:20 pts/0    00:00:00 ./fork_seized
root      1175  1174  1176  0    4 04:20 pts/0    00:00:00 ./fork_seized
root      1175  1174  1177  0    4 04:20 pts/0    00:00:00 ./fork_seized
root      1175  1174  1178  0    4 04:20 pts/0    00:00:00 ./fork_seized
$ sudo grep -H TracerPid /proc/1175/task/*/status
/proc/1175/task/1175/status:TracerPid:  1174
/proc/1175/task/1176/status:TracerPid:  1174
/proc/1175/task/1177/status:TracerPid:  1174
/proc/1175/task/1178/status:TracerPid:  1174
$ python ./vol.py -r pretty \
    -f ./dump_ubuntu180464bit_5.4.0-117-generic_ptrace_seize_multiple.core \
    linux.ptrace 
Volatility 3 Framework 2.10.0           
     |     Process |  PID |  TID | Tracer TID | Tracee TID |                               Flags
*    | fork_seized | 1174 | 1174 |          - |       1178 |                                   -
**   | fork_seized | 1174 | 1174 |          - |       1177 |                                   -
***  | fork_seized | 1174 | 1174 |          - |       1176 |                                   -
**** | fork_seized | 1174 | 1174 |          - |       1175 |                                   -
*    | fork_seized | 1175 | 1175 |       1174 |          - | PT_SEIZED|PT_TRACE_CLONE|PT_PTRACED
*    | fork_seized | 1175 | 1176 |       1174 |          - | PT_SEIZED|PT_TRACE_CLONE|PT_PTRACED
*    | fork_seized | 1175 | 1177 |       1174 |          - | PT_SEIZED|PT_TRACE_CLONE|PT_PTRACED
*    | fork_seized | 1175 | 1178 |       1174 |          - | PT_SEIZED|PT_TRACE_CLONE|PT_PTRACED
gcmoreira commented 1 month ago

Hey @ikelos it's now ready to go, see the example 4 with multiple rows.

BTW, it seems black installation psf/black@stable is broken.

EDIT: Black issue fixed in https://github.com/volatilityfoundation/volatility3/pull/1301

gcmoreira commented 1 month ago

@ikelos The re-run jobs button on GitHub continues using the previous configuration. To ensure it picked up the fix from #1301, I bumped the patch version temporarily and then rolled it back to zero.