Suite au commentaire de Poulet à la suite de mon article sur le développement d’un robot-spam en C, j’ai décidé de m’atteler à la réécriture du billet.
Cette fois, le robot sera en PHP. Il faut avouer que Poulet avait mille fois raison : d’un programme imbuvable en C, on peut très facilement passer à un robot-spam de quelques lignes en PHP sans pour autant perdre le contrôle des requêtes que l’on envoie.
Voila donc une nouvelle version de l’article qui sera, je l’espère, beaucoup plus accessible.
1) Préparer l’environnement de travail en 2 minutes.
Notre robot spam s’exécutera depuis une page PHP. Cette page devra être hébergée soit:
- Sur un serveur web distant : votre hébergeur préféré par exemple. (OVH, Free etc.) Il est très important de noter que les librairies socket doivent être ACTIVÉES sur cet hébergeur, sinon le code ne fonctionnera pas. Pour savoir si les librairies sont actives sur votre hébergeur, voir plus bas.
- Directement sur votre ordinateur. Dans ce cas, vous devrez installer WAMP Server. Ce logiciel est un serveur web. Il permet, grosso-modo, d’exécuter du code php sur votre ordinateur. (chose impossible sans serveur web) En utilisant votre propre serveur web, vous êtes sûr de pouvoir activer les librairies socket et de n’avoir aucun problème pour exécuter le code qui suivra.
Vous avez un hébergeur : A t-il activé la librairie pho_sockets ?
Créez une nouvelle page au format php et placez ici simplement ce code :
[sourcecode language="php"]
<?
phpinfo();
?>
[/sourcecode]
Mettez cette page en ligne sur votre espace web et visitez là. Cherchez la partie « sockets » et regardez si « Sockets Support » est sur « enabled ». Si c’est le cas, alors youpitralala, c’est OK pour vous.
Attention toute fois : certains hébergeurs (comme Free) ont bien chargé la librairie sockets mais la bloque depuis leurs serveurs proxy. Ne pensez même pas à Free pour héberger votre script, c’est mort !
Vous n’avez pas d’hébergeur : Configurer WAMP et activer la librairie socket.
Si votre hébergeur n’a définitivement pas activé la librairie socket, alors optez pour l’installation d’un serveur web sur votre PC. Du coup c’est votre IP qui enverra le spam, pas très judicieux dans le cas d’une véritable application !
Une fois WAMP installé sur votre ordinateur, lancez le. Il se place dans votre barre de tâche, à côté de l’horloge. Faite un clic gauche dessus, puis « PHP » puis « PHP extentions » puis « php_sockets ». Attendez qu’il redémare, et c’est fini ! Refaites un clic gauche sur l’icône, puis choisissez « www directory ». Un dossier s’ouvre : c’est dans ce dossier que vous mettrez les pages PHP du script que nous allons faire. Vous y accéderez par cette URL : http://127.0.0.1.
Faites le test : supprimer le fichier index.php du dossier www et mettez y n’importe quel autre fichier à vous, puis allez sur http://127.0.0.1. Vous retrouverez votre fichier !
2) Préparer la requète à envoyer dans la socket.
Dans l’article précédent, je vous expliquais qu’un socket ce n’était ni plus ni moins qu’un tuyau entre votre PC et un serveur distant. Ce tuyau vous permet d’envoyer des requêtes au serveur pour lui demander, par exemple, de vous envoyer une page (pour l’afficher dans Firefox) ou de valider un formulaire (pour spammer un site ? :-D)
Dans le cadre de notre robot spam, nous allons envoyer des requêtes à un serveur web pour lui demander de remplir et de valider un formulaire. Le formulaire en question, je l’ai crée moi même sur un vieil espace web que j’ai retrouvé pour l’occasion.
Vous pouvez y accéder à cette adresse : http://kaleidoscopique.free.fr/tuto_spambot.php.
Essayez d’y poster un message : il apparaitra directement sur la page principale.
Une requête HTTP ne peut pas être formatée n’importe comment, comme l’expliquait (encore une fois) mon article précédent. Voici à quoi ressemble une requète HTTP qui permet de dire à un serveur web : « Tiens, remplis ce formulaire avec telle, telle et telle valeur, et valide le. »
[sourcecode language="php"]
POST /page.php HTTP/1.1
Host: www.site.com
Connection: Close
Content-type: application/x-www-form-urlencoded
Content-Length: 33
variable=valeur&variable2=valeur2
[/sourcecode]
On va donc prendre modèle sur cette requête, remplacer certaines données par ce dont nous disposons, puis on utilisera un code PHP pour l’envoyer au serveur Free qui héberge mon formulaire.
Certaines lignes sont très simples à éditer. La première ligne doit contenir la page où se situe le formulaire à remplir, la seconde ligne contient l’URL du site. La troisième nous n’y toucherons pas, la quatrième non plus. La cinquième ligne renseigne sur le nombre de caractères que nous enverrons pour remplir notre formulaire, et la septième ligne sur le contenu même du formulaire. Étudions justement cette septième ligne.
3) Étudier les champs du formulaire à spammer.
La fameuse septième ligne de la requète est de cette forme : champs1=valeur1&champs2=valeur2&etc……
Pour connaitre les noms exacts des champs d’un formulaire, il suffit d’aller sur la page du formulaire en question, de sélectionner le champs dont vous souhaitez connaitre le nom et de le sélectionner lui ainsi qu’un bout de texte à côté de lui :
Évidement lorsqu’on sélectionne un champs, il ne se surligne pas comme du texte. Pourtant, sur la screenshot ci-dessus, j’ai bien sélectionné le champs et le texte à côté de lui.
Ensuite, faites un clic droit puis « code source de la sélection ». Le code HTML du champs apparait alors : il est représenté par la balise <input ……..>. Récupéré le « name » présent dans cette balise input : c’est le nom de votre champs.

Faites ça avec les 3 champs du formulaire à remplir. Vous trouverez les noms suivants :
- Le champs « Votre email » s’appelle email.
- Le champs « Sujet du mail » s’appelle sujet.
- Le champs « Message » s’appelle message.
Pas très original je vous l’accorde. Ça ne sera pas toujours aussi évident, croyez moi.
La 7ème ligne de notre requète HTML va donc ressembler à :
email=votre@mail.com&sujet=SUJET DU MESSAGE&message=VOTRE SPAM
4) Code PHP et envoi de la requète !
Le code PHP qui suit est entier, et très commenté. Cliquez pour voir le code sans commentaire.
[sourcecode language="php"]
<?php
error_reporting(E_ALL);
echo "<h3>Envoi d’une requète POST via HTTP.</h3><br />";
/*
—————————
CONFIGURATION DE LA SOCKET
—————————
*/
// On crée deux variables : $port et $ip.
// $port contiendra le port sur lequel se "branchera" notre socket.
// $adresse contiendra l’IP du serveur web avec lequel nous allons communiquer. (celui qui héberge le formulaire)
$port = getservbyname(‘www’,'tcp’);
$ip = gethostbyname("kaleidoscopique.free.fr");
// On initialise notre socket dans la variable $socket grâce à la fonction socket_create().
// socket_create() ne connecte pas la socket, mais la crée juste.
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
/*
—————————————————-
GESTION DES ERREURS LORS DE LA CREATION DE LA SOCKET
—————————————————-
*/
// La fonction socket_create() utilisée plus haut peut retourner deux choses :
// – Une valeur négative si la socket n’a pas pu être crée.
// – Un message dont on se fou, si tout s’est bien passé
// On va donc tester le contenu de $socket pour être sûr que tout a bien marché :
if ($socket < 0)
echo "socket_create() n’a pas fonctionné. Motif : " . socket_strerror($socket) . "<br />";
else
echo "La socket a pu être créée.<br />";
echo "Essai de connexion à ‘$ip’ sur le port ‘$port’ …";
/*
————————-
CONNEXION DE NOTRE SOCKET
————————-
*/
// Let’s go, on connecte notre socket grâce à socket_connect() en spécifiant :
// – La socket crée dans $socket.
// – L’IP du serveur que nous solicitions, stockée dans $ip.
// – Le port sur lequel nous allons nous brancher, stocké dans $port.
$resultat = socket_connect($socket, $ip, $port);
/*
—————————————————–
GESTION DES ERREURS LORS DE LA CONNEXION DE LA SOCKET
—————————————————–
*/
// Même chose qu’avant, on teste le contenu de $resultat pour savoir si tout s’est bien passé :
if ($resultat < 0)
echo "socket_connect() n’a pas fonctionné. Motif : " . socket_strerror($resultat) . "<br />";
else
echo "La socket a pu être connectée.<br />";
/*
———————————————————————
ECRITURE ET ENVOI DE LA REQUETE A ENVOYER POUR VALIDER LE FORMULAIRE
———————————————————————
*/
echo "Envoi de la requête HTTP en cours…..";
// On stock le contenu du formulaire à remplir dans une variable à part
$contenu_du_formulaire = "email=stephane@viagra.com&message=VISIT MY WEBSITE http://www.mangetamain.fr&sujet=SPAMED";
// On stock notre requête dans la variable $envoi
$envoi = "POST /tuto_spambot.php HTTP/1.1\r\n";
$envoi .= "Host: kaleidoscopique.free.fr\r\n";
$envoi .= "Connection: Keep-alive\r\n";
$envoi .= "Content-type: application/x-www-form-urlencoded\r\n";
$envoi .= "Content-Length: ".strlen($contenu_du_formulaire)."\r\n\r\n";
$envoi .= $contenu_du_formulaire;
$envoi .= "\r\n";
// On envoie notre requête via la socket (autrement dit "dans le tuyau") grâce à socket_write()
socket_write($socket, $envoi, strlen($envoi));
echo "La requête HTTP a été envoyé avec succès.<br />";
echo "Fermeture de la socket ouvert au préalable….. ";
socket_close($socket);
echo "Fermeture réussie.";
?>
[/sourcecode]
Deux choses que je n’ai pas expliqué dans les commentaires : pour que la requète soit comprise par le serveur, il ne faut pas oublier les sauts de ligne !!! Si vous oubliez un saut de ligne ou si vous n’en mettez qu’un alors qu’il en faut deux, le serveur ne comprendra rien.
Vous l’aurez probablement compris : un saut de ligne est matérialisé par le symbole \r\n. Soyez vigilent avec ça, une erreur est vite commise. Aussi, n’oubliez pas de terminer votre requête par un saut de ligne.
Avant dernière chose : une requête type POST contient une ligne assez particulière : celle avec « Content-Length ». Après le content-length, vous devez donner le nombre de caractères que vous envoyez au formulaire. En l’occurrence, le nombre de caractères contenu dans la chaine $contenu_du_formulaire ! La fonction strlen($contenu_du_formulaire) est là pour ça.
Enfin, si vous souhaitez récupérer la réponse du serveur suite à votre requête, il vous suffit d’ajouter le code suivant avant la fermeture du socket :
[sourcecode language="php"]
// On initialise une variable $reponse
$reponse = »;
echo "Réponse du serveur WEB : <br /><br />";
// On boucle tant que le serveur à quelque chose à nous dire et on affiche.
while ($reponse= socket_read($socket, 2048))
{
echo $reponse;
}
[/sourcecode]
5) Comment transformer ce robot inoffensif en un dangereux robot spam ?
Simplement grâce à une boucle ! Faites boucler votre code autant de fois que vous souhaitez envoyer la requête, et le tour est joué.
Quelques indications importantes pour réussir :
- Votre boucle prendra quasiment l’intégralité du code, sauf la partie qui ferme la socket ! Sinon, votre socket se fermera à chaque nouveau tour de boucle…. !
- Votre requête possède un paramètre « Connection: close ». Remplacez le close par Keep-alive pour ne pas que la connexion se ferme après le premier envoi !
Je publierai le code avec la boucle dans le prochain article. Ce prochain billet permettra de faire le bilan sur ce robot, chercher des améliorations envisageables et discuter de ses défauts avérés.
J’éspère aussi vous faire prendre conscience des méthodes de protection anti-spam : celles qui marchent, celles qui marchent moins bien, celles qui ne marchent pas du tout.
On se revoit très vite pour le dernier article de cette série ! A bientôt, et amusez vous bien.
N'oubliez pas de montrer à vos copains que vous lisez des articles intelligents :
Ces boutons de partage garantissent votre sécurité et votre vie privée.
Cliquez ici pour comprendre comment et pourquoi...
Ho, si ce billet vous a plu, pensez à vous abonner pour ne pas rater le prochain !
Je clash et je discute sur Twitter
Je publie les nouveaux billets sur ma page FB
... et bien sûr, vous pouvez vous abonner par e-mail ou par RSS !







Pingback : Les tweets qui mentionnent Création d’un robot-spam en C, partie II : envoyez votre premier spam. | MANGE TA MAIN ! -- Topsy.com
14 mai 2010 à 19 h 11 min
Je trouve ça moyen de balancer des trucs comme ça, même à visée pédago, non ? J’dis ça, j’dis rien, mais bon :)
14 mai 2010 à 19 h 13 min
Je suis d’accord avec kyotoweb, c’est pas dur non plus de voir la doc de php mais bon, la le boulot est mâché.
14 mai 2010 à 19 h 27 min
Ouip, à la limite un code C n’est pas accessible à tout le monde, mais un code PHP, sans compilation requise, tel que, c’est un peu trop simple ^^ .
14 mai 2010 à 19 h 48 min
@Kyotoweb : essais ce script ne serait-ce que sur un WordPress, tu auras du mal à le faire fonctionner convenablement sans l’avoir largement travaillé. Ce n’est donc absolument pas dangereux. Je ne me permettrai pas!
@creatix @nclsto : ici, l’intérêt n’est pas d’apprendre le PHP, mais de comprendre le principe d’envoi de requêtes via une socket HTTP. Le code C était interessant d’un point de vue C, mais absolument laborieux en ce qui concernait l’objectif principal : comprendre comment fonctionne un robot en socket.
J’ai donc préféré simplifier le côté programmation pour ne laisser que le loisir de comprendre le côté réseau.
14 mai 2010 à 20 h 14 min
Personnellement je n’y connais pas grand chose en PHP, donc j’ai vaguement compris le code avec les commentaires. Mais sinon merci pour cet article, c’est intéressant !
Pingback : Création d’un robot-spam en PHP, le code de mangetamain.fr amélioré (merci @kaleidoscopique) | max:imax86.com
15 mai 2010 à 15 h 49 min
@creatix @nclsto @Kyotoweb Je n’ai que vaguement regardé le code et il reste tout à fait simpliste, même dans de mauvaise main ça ne fera que très peu de dégât.
En effet ce genre de script permet de flooder un formulaire qui ne possède aucune protection. Déjà le bot présenté ici ne fonctionnera pas si le site qu’il essai de flooder empêche le multi post sur une même ip…
Si un ajoute à cela un captcha graphique…
Enfin bref tout ça pour dire que je trouve ça pas mal pour comprendre un peu mieux le concept des sockets et comment fonctionne un robot spammer.
19 mai 2010 à 20 h 36 min
Note, c’est « php_sockets » et non « pho_sockets » (ces DLLs ou SO sont normalement incluses dans PHP nativement, si ce n’est pas activé et que c’est une machine dédiée, il faut les chercher dans PECL, ou re-compiler les binaires de PHP).
J’ai fait une version améliorée, que Stéphane a refusé de publier ici, mais j’insiste, à des fins pédagogiques (aussi), mais aussi pour plus de simplicité, on doit pouvoir faire une vérification automatique de la présence de l’extension sockets sur PHP.
Si les fonctions sockets_* sont inexistantes, il n’y a pas de php_sockets.
Le code se trouve ici : http://www.imax86.com/2010/05/15/creation-dun-robot-spam-en-php-le-code-de-mangetamain-fr-ameliore-merci-kaleidoscopique/
23 mai 2010 à 22 h 14 min
Je pense que tel qu’il est ce script n’est pas utilisable dans beaucoup de cas. Pour être vraiment dangereux il faudrait qu’il puisse décrypter les captcha’s. ou alors l’allier à un script de crawl qui trouve les blogs intéressants pour y créer des BL’s. Mais dans 1 cas comme dans l’autre c’est plus la même histoire ;)
16 juin 2010 à 13 h 55 min
Quel intérêt de balancer un article de ce genre sur le net ?
On a déjà assez de problèmes en tant que blogueur à gérer le fléau…
25 juin 2010 à 16 h 21 min
<script>alert(« bonjour »)</script>
13 juillet 2010 à 15 h 19 min
Bonsoir,
je début avec les sockets. Mes recherches m’ont conduit à ton tutoriel.
Au fait j’aimerais cochet un checkbox à travers le socket. J’ai donc implémenté une requête à partir de ton tuto et d’autre mais j’arrive pas cochez le checkbox.
Le code source de la page à cocher révèle ce qui suit:
lorsque le checkbox n’est pas coché
<td class= »font_white »><input type= »checkbox » onClick= »document.select_trade.submit() »name= »tradech » value= »YES » /></td>
lorsque le checkbox est coché
td class= »font_white »><input type= »checkbox » onClick= »document.select_trade.submit() » name= »tradech » value= »NO » checked= »checked » /></td>
Voici la fonction que j’ai concocté pour faire cette action:
$_SESSION['scanner_email']=’winner@gmail.com’;
$_SESSION['scanner_session']=’531999c0c716d3dba525c89485770359′;
$host = ‘borealis.eu2.looki.fr’;
$header = ‘Cookie: login_email=’.str_replace(‘@’, ‘%40′, $_SESSION['scanner_email']).’; testcookie=1; PHPSESSID=’.$_SESSION['scanner_session']. »\r\n »;
function PutUrl($host, $url, $headers=false, $action=false) {
// return ‘nothing yet’;
// Exemple de récupération d’un document via HTTP en utilisant directement les sockets.
echo ‘<font color=white>’;
if ( ($fp = fsockopen($host, 80, $errno, $errstr, 10)) === false) return false;
$in = « POST $url HTTP/1.1\r\n »;//
$in .= « Host: $host\r\n »;
$in .= ‘User-Agent: ‘.$_SERVER['HTTP_USER_AGENT']. »\r\n »;
$in .= ‘Accept: ‘.$_SERVER['HTTP_ACCEPT']. »\r\n »;
$in .= ‘Accept-Language: ‘.$_SERVER['HTTP_ACCEPT_LANGUAGE']. »\r\n »;
$in .= ‘Accept-Charset: ‘.$_SERVER['HTTP_ACCEPT_CHARSET']. »\r\n »;
$in .= « Accept-Encoding: chunked\r\n »;
if ($headers) $in .= $headers;
$in .= « Connection: Keep-alive\r\n »;
if($action)
{//ajout l’action à faire. à revoir
$in .= « Content-type: application/x-www-form-urlencoded\r\n »;
$in .= « Content-Length: « .strlen($action). »\r\n\r\n »;
$in .= $action. »\r\n »;//corps du message
}
//Marque la fin des entêtes
//Envoi de données au serveur
if (fwrite($fp, $in) === false) return false;
$h=$b=$d= »;
while (!feof($fp)) {
$d = fgets($fp, 2048);
if (stripos($h, »\r\n\r\n ») === false)
$h .= $d;
else
$b .= $d;
}
fclose($fp);
if ( trim($b) == ») $b = false;
return $b;
}
//Déclaration de la variable action:
$action= »… »???? c’est ce que je n’arrive pas à trouver en supposant que le code implémenté est correcte.
Merci pour vos réponses.
13 juillet 2010 à 15 h 24 min
Je rappelle juste que j’arrive à afficher la page, en faisant echo($page) qui est le résultat de l’appelle de la fonction précédente mais l’action de cocher ou décocher le checkbox ne marche pas. Quelqu’un peut il m’orienté un peu?
16 août 2010 à 0 h 48 min
@Malibu –> Vas y molo sur les malibus !
@Pyrrah –> Ce n’est pas parce que l’on ferme les yeux sur un problème qu’il n’existe pas !
Bref … Sacrilège ! Il lui manque un petit nom à ce robot ;p
26 août 2010 à 2 h 21 min
Honnêtement la plupart des spammeurs que je vois passer par chez moi ne procède pas de la sorte (trop visible et trop lente);
Ils font directement une boucle dans un CGI hébergé qui fait (attention, suspeeeense):
for () { mail();}
Incroyable non ? :)
Et généralement ces gentils messieurs apprécient le fait de coller 1000 Cc: dans leur charmant emails, pourquoi se casser la tête à recoder un programme d’envoi quand un existe déjà ? (pas fous ces spammeurs!) ;)
30 août 2010 à 18 h 26 min
Très bon article surtout pour les spammeurs.
Je vois pas l’intêret de poster un article de ce genre là, on est tous des bloggers ici, en postant ce type d’article, vous permettez aux spammeurs d’être encore plus ch**nts!
25 octobre 2010 à 16 h 19 min
j’ai une petite question:
pourquoi utiliser les sockets
25 octobre 2010 à 16 h 19 min
?
12 janvier 2011 à 9 h 05 min
Moi je dit c’est un explme mintenan a vous de faire marché votre tete pour fair de cette information une réel utilitée pck spamé c bien mais ……….. c mieux ^^
7 mars 2011 à 2 h 48 min
Slt
sVp repondez Màlibu càr sà kestio né tres interessànte ,g le meme Blem!!!