Me gustaría obtener un registro de todos los procesos que se inician con el momento en que se iniciaron y los argumentos con los que se iniciaron. ¿Es esto posible en Linux?
Me gustaría obtener un registro de todos los procesos que se inician con el momento en que se iniciaron y los argumentos con los que se iniciaron. ¿Es esto posible en Linux?
Respuestas:
Su punto de partida debe ser auditado.
Intenta algo como esto:
apt-get install auditd
auditctl -a task,always
ausearch -i -sc execve
chmod 0750 /sbin/audispd
pero todavía no funciona (Debian Wheezy)
Unable to set audit pid, exiting
pero supongo que el verdadero problema será que el sistema se está ejecutando en un contenedor LXC
Necesitaba hacer esto, excepto que (1) no necesitaba el tiempo y (2) solo estaba interesado en los procesos que se inician en un proceso determinado, y sus hijos y descendientes posteriores. Además, en el entorno que estaba usando, no fue posible conseguir auditd
o accton
, pero no había valgrind
.
Prefije lo siguiente al proceso de interés en la línea de comando:
valgrind --trace-children=yes
La información que necesita estará en la salida del registro que se muestra en STDERR.
memcheck
herramienta. Para desactivar la herramienta y su registro correspondiente, y sólo imprimir la creación de nuevos comandos (además de la salida habitual de su programa), utilice el siguiente comando: valgrind --tool=none --trace-children=yes [command and args here]
. Cada vez que se genera un subproceso, Valgrind registrará el comando completo, incluidos los argumentos que se le pasaron.
Podrías usar snoopy para esto.
Es muy simple de instalar, y desde 2.x puede registrar datos arbitrarios (argumentos, variables ambientales, cwd, etc.).
Divulgación: Snoopy mantenedor aquí.
Puede ejecutar startmon y seguir su salida estándar, Ctrl-C cuando haya terminado. Aquí se explica cómo compilar y ejecutar startmon en distribuciones recientes derivadas de Red Hat (RHEL, Fedora, CentOS):
sudo yum install git cmake gcc-c++
git clone https://github.com/pturmel/startmon
cd startmon
cmake .
make
sudo ./startmon -e
En Debian (y Ubuntu, etc.), la primera línea de lo anterior cambia a:
sudo apt-get install git cmake g++
Alternativamente, puede probar el execsnoop
script en perf-tools, vea esta respuesta . Por defecto, solo se muestran los primeros 8 argumentos (9 incluyendo el nombre del programa); puedes aumentar esto a través de
sudo ./execsnoop -a 16
Si no tiene acceso de root al sistema, lo mejor que puede hacer es seguir sondeando /proc
y esperar que detecte todo (lo que no hará), pero para completar, aquí hay una secuencia de comandos para hacerlo (he puesto la eliminación de duplicados para simplificar la salida): aunque esto no es tan bueno como rastrearlos correctamente con uno de los métodos anteriores, tiene la ligera ventaja de mostrar separadores sin ambigüedades entre los argumentos de la línea de comandos, en caso de que alguna vez necesite decirle al diferencia entre espacios dentro de un argumento y espacio entre argumentos. Este script es ineficiente ya que usa la CPU (bueno, uno de sus núcleos) el 100% del tiempo.
function pstail () { python -c 'import os
last=set(os.listdir("/proc")) ; o=x=""
while True:
pids=set(os.listdir("/proc"))
new=pids.difference(last);last=pids
for n in new:
try: o,x=x,[j for j in open("/proc/"+n+"/cmdline")
.read().split(chr(0)) if j]
except IOError: pass
if x and not o==x: print n,x' ; }
pstail
También puede parchear execsnoop
para decirle más explícitamente qué argumento es cuál:grep -v sub.*arg < execsnoop > n && chmod +x n && mv n execsnoop
CONFIG_FTRACE
y a CONFIG_KPROBES
través debrendangregg/perf-tools
git clone https://github.com/brendangregg/perf-tools.git
cd perf-tools
git checkout 98d42a2a1493d2d1c651a5c396e015d4f082eb20
sudo ./execsnoop
En otro caparazón:
while true; do sleep 1; date; done
El primer shell muestra datos de formato:
Tracing exec()s. Ctrl-C to end.
Instrumenting sys_execve
PID PPID ARGS
20109 4336 date
20110 4336 sleep 1
20111 4336 date
20112 4336 sleep 1
20113 4336 date
20114 4336 sleep 1
20115 4336 date
20116 4336 sleep 1
CONFIG_PROC_EVENTS
Sesión de muestra:
$ su
# ./proc_events &
# /proc_events.out &
set mcast listen ok
# sleep 2 & sleep 1 &
fork: parent tid=48 pid=48 -> child tid=56 pid=56
fork: parent tid=48 pid=48 -> child tid=57 pid=57
exec: tid=57 pid=57
exec: tid=56 pid=56
exit: tid=57 pid=57 exit_code=0
exit: tid=56 pid=56 exit_code=0
CONFIG_PROC_EVENTS
expone los eventos a userland a través de un socket de netlink .
proc_events.c adaptado de: https://bewareofgeek.livejournal.com/2945.html
#define _XOPEN_SOURCE 700
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/connector.h>
#include <linux/cn_proc.h>
#include <signal.h>
#include <errno.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
static volatile bool need_exit = false;
static int nl_connect()
{
int rc;
int nl_sock;
struct sockaddr_nl sa_nl;
nl_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
if (nl_sock == -1) {
perror("socket");
return -1;
}
sa_nl.nl_family = AF_NETLINK;
sa_nl.nl_groups = CN_IDX_PROC;
sa_nl.nl_pid = getpid();
rc = bind(nl_sock, (struct sockaddr *)&sa_nl, sizeof(sa_nl));
if (rc == -1) {
perror("bind");
close(nl_sock);
return -1;
}
return nl_sock;
}
static int set_proc_ev_listen(int nl_sock, bool enable)
{
int rc;
struct __attribute__ ((aligned(NLMSG_ALIGNTO))) {
struct nlmsghdr nl_hdr;
struct __attribute__ ((__packed__)) {
struct cn_msg cn_msg;
enum proc_cn_mcast_op cn_mcast;
};
} nlcn_msg;
memset(&nlcn_msg, 0, sizeof(nlcn_msg));
nlcn_msg.nl_hdr.nlmsg_len = sizeof(nlcn_msg);
nlcn_msg.nl_hdr.nlmsg_pid = getpid();
nlcn_msg.nl_hdr.nlmsg_type = NLMSG_DONE;
nlcn_msg.cn_msg.id.idx = CN_IDX_PROC;
nlcn_msg.cn_msg.id.val = CN_VAL_PROC;
nlcn_msg.cn_msg.len = sizeof(enum proc_cn_mcast_op);
nlcn_msg.cn_mcast = enable ? PROC_CN_MCAST_LISTEN : PROC_CN_MCAST_IGNORE;
rc = send(nl_sock, &nlcn_msg, sizeof(nlcn_msg), 0);
if (rc == -1) {
perror("netlink send");
return -1;
}
return 0;
}
static int handle_proc_ev(int nl_sock)
{
int rc;
struct __attribute__ ((aligned(NLMSG_ALIGNTO))) {
struct nlmsghdr nl_hdr;
struct __attribute__ ((__packed__)) {
struct cn_msg cn_msg;
struct proc_event proc_ev;
};
} nlcn_msg;
while (!need_exit) {
rc = recv(nl_sock, &nlcn_msg, sizeof(nlcn_msg), 0);
if (rc == 0) {
/* shutdown? */
return 0;
} else if (rc == -1) {
if (errno == EINTR) continue;
perror("netlink recv");
return -1;
}
switch (nlcn_msg.proc_ev.what) {
case PROC_EVENT_NONE:
printf("set mcast listen ok\n");
break;
case PROC_EVENT_FORK:
printf("fork: parent tid=%d pid=%d -> child tid=%d pid=%d\n",
nlcn_msg.proc_ev.event_data.fork.parent_pid,
nlcn_msg.proc_ev.event_data.fork.parent_tgid,
nlcn_msg.proc_ev.event_data.fork.child_pid,
nlcn_msg.proc_ev.event_data.fork.child_tgid);
break;
case PROC_EVENT_EXEC:
printf("exec: tid=%d pid=%d\n",
nlcn_msg.proc_ev.event_data.exec.process_pid,
nlcn_msg.proc_ev.event_data.exec.process_tgid);
break;
case PROC_EVENT_UID:
printf("uid change: tid=%d pid=%d from %d to %d\n",
nlcn_msg.proc_ev.event_data.id.process_pid,
nlcn_msg.proc_ev.event_data.id.process_tgid,
nlcn_msg.proc_ev.event_data.id.r.ruid,
nlcn_msg.proc_ev.event_data.id.e.euid);
break;
case PROC_EVENT_GID:
printf("gid change: tid=%d pid=%d from %d to %d\n",
nlcn_msg.proc_ev.event_data.id.process_pid,
nlcn_msg.proc_ev.event_data.id.process_tgid,
nlcn_msg.proc_ev.event_data.id.r.rgid,
nlcn_msg.proc_ev.event_data.id.e.egid);
break;
case PROC_EVENT_EXIT:
printf("exit: tid=%d pid=%d exit_code=%d\n",
nlcn_msg.proc_ev.event_data.exit.process_pid,
nlcn_msg.proc_ev.event_data.exit.process_tgid,
nlcn_msg.proc_ev.event_data.exit.exit_code);
break;
default:
printf("unhandled proc event\n");
break;
}
}
return 0;
}
static void on_sigint(__attribute__ ((unused)) int unused)
{
need_exit = true;
}
int main()
{
int nl_sock;
int rc = EXIT_SUCCESS;
signal(SIGINT, &on_sigint);
siginterrupt(SIGINT, true);
nl_sock = nl_connect();
if (nl_sock == -1)
exit(EXIT_FAILURE);
rc = set_proc_ev_listen(nl_sock, true);
if (rc == -1) {
rc = EXIT_FAILURE;
goto out;
}
rc = handle_proc_ev(nl_sock);
if (rc == -1) {
rc = EXIT_FAILURE;
goto out;
}
set_proc_ev_listen(nl_sock, false);
out:
close(nl_sock);
exit(rc);
}
Sin embargo, no creo que pueda obtener datos de proceso como UID y argumentos de proceso porque exec_proc_event
contiene muy pocos datos: https://github.com/torvalds/linux/blob/v4.16/include/uapi/linux/cn_proc .h # L80 Podríamos intentar leerlo de inmediato /proc
, pero existe el riesgo de que el proceso finalice y otro tome su PID, por lo que no sería confiable.
Probado en Ubuntu 17.10.
Puedes probar cat ~/.bash_history
Hay system log viewer
, esto puede ayudarte.
~/.bash_history
solo contiene comandos que he ejecutado en una terminal, aparentemente. Estoy buscando un registro de todos los programas ejecutados, por ejemplo, cuando hago clic en un icono para abrir mi cliente de correo electrónico, gedit, o abro mi navegador, y mi navegador ejecuta otro proceso por sí mismo. La respuesta de new123456 hizo el truco.
history
es la forma habitual de acceder a esta información.
The audit system is disabled
¿Dónde puedo habilitarlo?