Gostaria de obter um log de todos os processos iniciados com o tempo em que foram lançados e os argumentos com os quais foram lançados. Isso é possível no Linux?
Gostaria de obter um log de todos os processos iniciados com o tempo em que foram lançados e os argumentos com os quais foram lançados. Isso é possível no Linux?
Respostas:
Seu ponto de partida deve ser auditado.
Tente algo como isto:
apt-get install auditd
auditctl -a task,always
ausearch -i -sc execve
chmod 0750 /sbin/audispd
mas ainda não está funcionando (Debian Wheezy)
Unable to set audit pid, exiting
, mas eu acho que o verdadeiro problema será que o sistema está sendo executado no recipiente LXC
Eu precisava fazer isso, exceto (1) que não precisava do tempo e (2) estava interessado apenas em processos iniciados por um determinado processo e em seus filhos e descendentes subsequentes. Além disso, no ambiente que eu estava usando, não era possível obter auditd
ou accton
, mas havia valgrind
.
Prefixe o seguinte ao processo de interesse na linha de comandos:
valgrind --trace-children=yes
As informações necessárias estarão na saída do log exibida no STDERR.
memcheck
ferramenta. Para desativar a ferramenta e sua logging relacionado, e imprimir apenas a criação de novos comandos (além da saída usual de seu programa), use o seguinte comando: valgrind --tool=none --trace-children=yes [command and args here]
. Sempre que um subprocesso é gerado, o Valgrind registra o comando completo, incluindo os argumentos que foram passados para ele.
Você pode usar snoopy para isso.
É muito simples de instalar e, desde a versão 2.x, pode registrar dados arbitrários (argumentos, variáveis ambientais, cwd, etc.).
Divulgação: mantenedor do Snoopy aqui.
Você pode executar o startmon e seguir sua saída padrão, Ctrl-C quando terminar. Veja como compilar e executar o startmon nas recentes distribuições derivadas da 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
No Debian (e Ubuntu etc), a primeira linha do acima muda para:
sudo apt-get install git cmake g++
Como alternativa, você pode tentar o execsnoop
script em perf-tools, veja esta resposta . Por padrão, apenas os 8 primeiros argumentos são mostrados (9 incluindo o nome do programa); você pode aumentar isso via
sudo ./execsnoop -a 16
Se você não tem acesso root ao sistema, o melhor que você pode fazer é continuar pesquisando /proc
e torcer para que ele consiga tudo (o que não acontecerá), mas, para completar, aqui está um script para fazer isso (coloquei remoção duplicada para simplificar a saída) - embora isso não seja tão bom quanto rastreá-los adequadamente com um dos métodos acima, ele tem a pequena vantagem de exibir inequivocamente separadores entre os argumentos da linha de comando, caso você precise informar o diferença entre espaços dentro de um argumento e espaço entre argumentos. Esse script é ineficiente, pois usa a CPU (bem, um de seus núcleos) 100% do tempo.
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
Você também pode corrigir execsnoop
para dizer mais explicitamente qual argumento é qual:grep -v sub.*arg < execsnoop > n && chmod +x n && mv n execsnoop
CONFIG_FTRACE
e CONFIG_KPROBES
atravésbrendangregg/perf-tools
git clone https://github.com/brendangregg/perf-tools.git
cd perf-tools
git checkout 98d42a2a1493d2d1c651a5c396e015d4f082eb20
sudo ./execsnoop
Em outro shell:
while true; do sleep 1; date; done
O primeiro shell mostra dados 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
Sessão de amostra:
$ 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
expõe os eventos à terra do usuário por meio de um soquete 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);
}
No entanto, acho que não é possível obter dados do processo, como UID e argumentos do processo, porque exec_proc_event
contém muito poucos dados: https://github.com/torvalds/linux/blob/v4.16/include/uapi/linux/cn_proc .h # L80 Poderíamos tentar lê-lo imediatamente /proc
, mas existe o risco de o processo terminar e outro ter seu PID, para que não seja confiável.
Testado no Ubuntu 17.10.
Você pode tentar cat ~/.bash_history
Existe system log viewer
, isso pode ajudá-lo.
~/.bash_history
aparentemente contém apenas comandos que executei em um terminal. Estou procurando um log de todos os programas executados, por exemplo, quando clico em um ícone para abrir meu cliente de e-mail, gedit, ou abro meu navegador, e meu navegador executa outro processo sozinho. A resposta de new123456 fez o truque.
history
é a maneira usual de acessar essas informações.
The audit system is disabled
Onde posso ativá-lo?