auditd EXECVE Forensics: auid, ses and Hex Arguments
Reconstruct command lines from Linux audit.log: grouping records by event, EXECVE argument reassembly, hex-encoded arguments, auid and ses across sudo.
TL;DR. With an execve rule loaded, audit.log records every program run on the host. One execution is several records (SYSCALL, EXECVE, CWD, PATH, PROCTITLE) sharing the same msg=audit(sec.msec:serial) stamp. Group by that stamp, decode hex-encoded arguments, and use auid (the login user) and ses (the login session) to follow a user through sudo -i into a root shell, where auth.log goes blind.
Does the host even have it?
auditd is installed and enabled by default on RHEL and Fedora, not on Debian and Ubuntu. Even where it runs, no execve records exist unless a rule asks for them, for example:
-a always,exit -F arch=b64 -S execve -k exec
Read /etc/audit/rules.d/*.rules on the image (and the output of auditctl -l if collected live) before concluding anything from missing records. Without execve rules you still get the user-space events: USER_AUTH, USER_LOGIN, USER_START, USER_END, USER_CMD (sudo), USER_CHAUTHTOK (password change), ADD_USER, and audit configuration changes.
One event, several records
type=SYSCALL msg=audit(1789381120.086:181322): arch=c000003e syscall=59 success=yes exit=0 ppid=3200 pid=3204 auid=1001 uid=0 gid=0 euid=0 tty=pts1 ses=114 comm="tar" exe="/usr/bin/tar" key="exec"
type=EXECVE msg=audit(1789381120.086:181322): argc=4 a0="tar" a1="czf" a2="/tmp/.f.tgz" a3=2F7372762F66696E616E63652F513320636C6F7365
type=CWD msg=audit(1789381120.086:181322): cwd="/home/svc_backup"
type=PATH msg=audit(1789381120.086:181322): item=0 name="/usr/bin/tar" inode=13113204 ... nametype=NORMAL
type=PROCTITLE msg=audit(1789381120.086:181322): proctitle=74617200637A66002F746D702F2E662E74677A002F7372762F66696E616E63652F513320636C6F7365
type=EOE msg=audit(1789381120.086:181322):
All six lines are one event. The stamp 1789381120.086:181322 is epoch seconds (UTC), milliseconds, and a serial number generated by the kernel. The serial restarts at boot, so group by the whole stamp, not the serial alone. Records of different events can interleave in the file; grouping by stamp handles that.
Reassembling the command line
The EXECVE record holds argc and one field per argument:
- Quoted values (
a1="czf") are plain text. - Unquoted hex values (
a3=2F7372...) are hex-encoded because the argument contains a space, a double quote, a control character or non-ASCII bytes. Decoding2F7372762F66696E616E63652F513320636C6F7365gives/srv/finance/Q3 close: one argument with a space, which the plain sudo line in auth.log cannot distinguish from two. - Long arguments are split:
a1_len=Nfollowed bya1[0]=...,a1[1]=...chunks, and a large command line may span several EXECVE records of the same event. Concatenate the chunks in order before decoding. PROCTITLEholds the command line as the process saw it, hex-encoded with NUL separators, and truncated by the kernel for long command lines. Prefer EXECVE when both exist.
CWD gives the working directory, so relative paths in the arguments can be resolved. PATH records list the executable and the loader, with inode and owner.
auid and ses: following the user into root
The SYSCALL record carries two identities:
uid,euid: who the process runs as right now (0 inside a root shell).auid: the audit login UID, set once when the user logs in (theLOGINrecord:old-auid=4294967295 auid=1001) and inherited by every child process, including throughsudoandsu.4294967295means unset: daemons and boot-time processes.
And one session:
ses: the audit session ID, set at the same time. Every command of that login, as the user or as root, carries it.
In practice: auth.log shows svc_backup running sudo -i at 10:04, then nothing until the shell closes. audit.log for ses=114 shows what happened inside that shell:
type=SYSCALL ... auid=1001 uid=0 euid=0 tty=pts1 ses=114 comm="passwd" exe="/usr/bin/passwd"
type=SYSCALL ... auid=1001 uid=0 euid=0 tty=pts1 ses=114 comm="crontab" exe="/usr/bin/crontab" key="exec"
type=EXECVE ... argc=4 a0="crontab" a1="-u" a2="svc_backup" a3="/tmp/.c"
uid=0 says root ran it; auid=1001 says it was svc_backup's login. The journal stores the same values as _AUDIT_LOGINUID and _AUDIT_SESSION, which lets you link journal entries to the audit session.
RAW and ENRICHED
With log_format = ENRICHED (the upstream default in current audit releases; distributions can override it), auditd appends resolved names after a 0x1D byte, in upper case: AUID="svc_backup" UID="root" SYSCALL=execve. These names were resolved on the original host, which makes them more reliable than ausearch -i run on an analysis workstation with a different /etc/passwd. With RAW, resolve UIDs with the image's own /etc/passwd.
ausearch for the classics
ausearch -if audit.log -m EXECVE -ul 1001 -i # everything run under login UID 1001
ausearch -if audit.log --session 114 -i # one login session
ausearch -if audit.log -m USER_CMD -i # sudo commands, hex decoded
ausearch -if audit.log -m CONFIG_CHANGE,DAEMON_END -i # audit tampering
-i interprets values using the analysis host's account files unless the log is ENRICHED.
What to look for
- Reconnaissance right after login:
id,uname,cat /etc/passwd,sudo -l. - Persistence:
crontab,systemctl --user enable, writes under/etc/systemd/systemor~/.config/systemd/user. - Staging and exfiltration:
tar,zip,rclone,curl,scpwith paths to sensitive data. - Anti-forensics:
rmof journal files, scripts run against/var/log/wtmp,ln -sf /dev/null ~/.bash_history,history -c(a builtin, so no execve record),auditctl -Dor-e 0. - Reverse-shell-like command lines: interpreters or network tools whose arguments redirect a shell to a remote address. Treat a pattern match as a lead and read the full argument list.
In the browser
Linux Log Parser groups audit records by stamp, reassembles EXECVE arguments including hex and chunked ones, reads RAW and ENRICHED logs, uses ses to attach commands to rebuilt sessions, and flags persistence, log-clearing commands, suspicious tools and reverse-shell-like patterns. The walkthrough follows ses=114 end to end, and the auditd cheat sheet covers rules, retention and record types.