This page contains a patch to the bash UNIX shell to make it log startup messages via syslog.
It was created with bash v4.2.37
Copy the blocked text below to a file called logstartup.diff. After doing so, check that the syslog() line gets copied as a single line instead of as multiple lines shown here (due to it being wrapped to fit in the HTML page). See the original blog post if you want to confirm that the line is correct before applying the patch.
If you are applying this patch manually, and not as part of a Debian dpkg-buildpackage command then cd to the directory containing shell.c and run patch -p2 < …/logstartup.diff
--- a/bash/shell.c 2011-01-03 08:04:51.000000000 +1100 +++ b/bash/shell.c 2013-02-05 10:05:04.389866563 +1100 @@ -39,6 +39,7 @@ #include <errno.h> #include "filecntl.h" #include <pwd.h> +#include <syslog.h> #if defined (HAVE_UNISTD_H) # include @@ -365,6 +366,51 @@ env = environ; #endif /* __OPENNT */ + /* reconstruct the command line from the argv[] array */ + char cmdline[256]; + memset(cmdline,0,sizeof(cmdline)); + for (i = 0;i < argc;i++) { + strncat(cmdline,argv[i],sizeof(cmdline) - strlen(cmdline) - 1); + cmdline[strlen(cmdline)] = ' '; + cmdline[strlen(cmdline) + 1] = ''; + } + + /* get our process id and that of our parent process */ + int mypid = getpid(); + int ppid = getppid(); + + /* used to obtain process names from pids */ + char procpath[128]; + char myexe[128]; + char pexe[128]; + + /* zero the buffers used for the strings */ + /* to make sure there will be a NULL byte */ + /* before the end, to terminate the string */ + memset(procpath,0,sizeof(procpath)); + memset(myexe,0,sizeof(myexe)); + + /* we need to use the /proc/ filesystem to determine */ + /* the process names. The snprintf() call creates the */ + /* path to the /proc//exe symlink which we will use */ + snprintf(procpath,sizeof(procpath) - 1,"/proc/%d/exe",mypid); + + /* the readlink() call finds the destination of the symlink */ + /* which in this case is the full path to the process' image file */ + /* note that readlink() doesn't append a terminating null byte */ + /* to the string that it creates -- this is the main reason we used */ + /* memset() above to fill the buffer with null bytes */ + readlink(procpath,myexe,sizeof(myexe) - 1); + + /* rinse and repeat for our parent process */ + memset(pexe,0,sizeof(pexe)); + snprintf(procpath,sizeof(procpath) - 1,"/proc/%d/exe",ppid); + readlink(procpath,pexe,sizeof(pexe) - 1); + + /* log the information via syslog */ + openlog("bash",LOG_PID,LOG_USER); + syslog(LOG_USER | LOG_NOTICE,"%s (%d) invoked by %s (%d), with uid/euid/gid/egid %d/%d/%d/%d:%s",myexe,mypid,pexe,ppid,getuid(),geteuid(),getgid(),getegid(),cmdline); + USE_VAR(argc); USE_VAR(argv); USE_VAR(env);
Pingback: Logging the Creation of Shell Processes « Malware Musings