samedi 28 février 2009

Petit module en C : GeoStr (original, comme nom, pas vrai ?!)

Bien le bonjour/bonsoir.

Je suis encore en vie. J'ai pas encore été empalé par un sabre ou été renversé par un camion de livraison. Je suis là, devant mon PC, et je vais vous parler d'un truc avec un niveau peu élevé (je m'adresse, bien évidemment, aux mofos genre Unknown*Dragoon, shp, et toutes les tapz qui vont rire).

J'ai fait un module pour manipuler des chaînes en C. C'est pas complet, mais ça me sert. A la base, c'était pour un usage perso - flemme de diffuser si c'est pour se recevoir des "mouais, tu réinventes la roue et tu sers à rien" ; c'est pour le plaisir de l'algorithme ! :}

Quatre fonctions :

- int GeoStr_Count(char *chaine, char motif);
Retourne le nombre de motif présent dans chaine.

Exemple : GeoStr_Count("Salutations",'a'); renverra 2.


- int GeoStr_GetIndiceFromMotif(char *chaine, char motif, int pos);
Retourne l'index du posième motif dans chaine

Exemple : GeoStr_GetIndiceFromMotif('Salutations','a',1); renverra l'index du premier 'a', soit 1 ;
GeoStr_GetIndiceFromMotif('Salutations','a',2); renverra l'index du second 'a', soit 5 !

- char *GeoStr_substring(char *chaine, int debut, int combien);
Qui ne connait pas lafonction substring ? Elle renvoit combien octets en partant de l'index debut, dans chaine

Exemple :
*GeoStr_substring('Salutations',3,8); renverra 'lutations'.


- char **GeoStr_explode(char *chaine, char motif);
Le clou du pestacle ! La fonction explode renvoit un tableau de chaines issues de chaine, séparées par motif. Le second argument n'est, malheureusement, pas une chaine de caractère. J'avais pas le courage de faire ça, étant donné que j'ai pondu cette fonction à 2h du matin.

Exemple : GeoStr_explode("02/10/1989",'/') renverra un tableau de chaines :
[0] = "02";
[1] = "10";
[2] = "1989";




Les fichiers constituant le module se trouvent ici : http://venom630.free.fr/geo/?path=tools/GeoStr

Si jamais (et je dis bien, si jamais) vous avez du temps (à perdre ?) pour faire évoluer la bête, n'hésitez pas à me le signaler par mail ou par commentaire. Ca m'intéresserait d'avoir des fonctions que j'ai comprises et dont je peux me servir pour plusieurs trucs, notamment niveau études.

Conclusion


Je suis pas mort, et je code encore. Voilà.

Geo

PS : Je salue NiklosKoda, pour le fun. Et je le soutien pour la parution de son article complet (comme le pain de mie) sur les injections SQL. Je dédierai un article à ce sujet, car ça vaut vraiment le coup pour les débutants.

mercredi 11 février 2009

Sauvegarder sa bdd rapidement et efficacement (ou pas ?)

Salut, la compagnie !
Non, je ne suis pas (encore) mort ! Et si je poste un nouvel article, c'est bien pour vous le montrer.

On va pas y aller avec un gros sujet sensible, je vais juste vous parler d'un petit outil simpliste que j'ai fait. Il permet de sauvegarder une base de données, mais restons modestes : il est à optimiser, et il ne prend pas en charge toutes les structures spécifiques de tables MySQL, à savoir :
- Si y'a des FOREIGN KEY ou non ;
- La valeur actuelle générée par l'AUTO_INCREMENT.

Lien : http://venom630.free.fr/geo/tools/dbsave_php.txt
Bien sûr, c'est à optimiser. On pourrait l'utiliser en CLI en fournissant respectivement en argument l'host, l'utilisateur, le mot de passe et la base de données à sauvegarder. On peut aussi l'adapter pour le web, y'a pas grand souci.

Si y'en a que ça intéresse, la source est dispo, donc, aucun problème de ce côté-là. (Celui qui me fait un reproche sur les noms de variable ambigus, c'est ma poing dans son gueule à ce p'tit con !)

Voilà. (C'était une conclusion du tonnerre, il faut le dire !)

Geo

samedi 24 janvier 2009

ROOT@LOCALHOST a dit... faites le chien !

Et c'est là que tout le monde se met à aboyer, qui qu'on soit. Ca serait amusant, comme spectacle !
Bon, ok, le titre n'est pas très original, mais j'essayais de me faire comprendre de quelque manière que ce soit ; ce tutoriel traitera des injections SQL possibles quand on a les privilèges root avec.

Petit préambule pour ceux qui veulent pratiquer en même temps que l'article. Je suppose que vous avez un environnement apache + mysql + php à disposition. Connectez-vous en ROOT, et faites les requêtes suivantes :
CREATE USER SecondRoot IDENTIFIED BY 'toor';
CREATE DATABASE BaseDeRoot;
GRANT ALL PRIVILEGES ON BaseDeRoot.* TO 'SecondRoot'@'%';


Trois lignes de requêtes :
- La première créé un utilisateur sql nommé SecondRoot, dont le mot de passe sera toor. Cet utilisateur sera dépourvu de droit, il n'en aura AUCUN ;
- la seconde ligne créé une base de données BaseDeRoot ;
- la troisième ligne assigne tous les privilèges SecondRoot pour manipuler la base BaseDeRoot.

C'est un peu comme ça que font les hébergeurs web pour vous créer une base de données, en fait.

Ce qu'il faut savoir
Il existe des méta-bases, pour mysql. L'une d'elles s'appelle tout simplement mysql, et renferme les informations des utilisateurs, des privilèges etc... Une autre s'appelle information_schema, qui renferme les informations sur le nom des bases de données, des tables etc...

Aucun utilisateur autre que root lui-même - si les autres n'ont pas les mêmes droits que root - ne peut adresser de requête à la base mysql.

Faisons, par exemple, la requête suivante une fois connecté sous root :
SELECT Host, User, Password FROM mysql.user


Résultat :
+-----------+------------+-------------------------------------------+
| Host | User | Password |
+-----------+------------+-------------------------------------------+
| localhost | root | *9CFBBC772F3F6C106020035386DA5BBBF1249A11 |
| % | SecondRoot | *9CFBBC772F3F6C106020035386DA5BBBF1249A11 |
+-----------+------------+-------------------------------------------+


On obtient la liste des utilisateurs. On s'aperçoit que root et secondroot on le même mot de passe, mais ça, on s'en fout. Ce qu'on aperçoit, surtout, c'est qu'on ne peut se connecter en root qu'à partir de localhost, donc impossible à distance. Quant à SecondRoot, on peut faire ça de partout. Allons un peu plus loin, et regardons les privilèges de chaque utilisateur :

SELECT User, Select_priv, Insert_priv, Update_priv, Delete_priv FROM mysql.user;


Résultat :
+------------+-------------+-------------+-------------+-------------+
| User | Select_priv | Insert_priv | Update_priv | Delete_priv |
+------------+-------------+-------------+-------------+-------------+
| root | Y | Y | Y | Y |
| SecondRoot | N | N | N | N |
+------------+-------------+-------------+-------------+-------------+


Voilà, c'était juste un exemple.

Imaginez le code suivant :
<?php
mysql_connect("localhost","root","toor");
mysql_select_db("BaseDeRoot");
//...
?>


On remarque que le script php se connecte avec les droits root. On peut donc aisément interroger la base mysql pour obtenir des informations sensibles, d'où le pass de root.

Exemples de requêtes :
UPDATE membre SET age=19
-- Et là, l'injection
, profil= (SELECT Password FROM mysql.user LIMIT 0,1) WHERE pseudo='Geo'; /*
-- La suite de la requête (par exemple)
WHERE pseudo='Geo';


Dans mon profil apparaîtra le hash de root. Il ne manque plus qu'à le casser, et ça peut prendre 10 minutes comme une décennie.

Conclusion ?



L'article n'était pas très long et explicatif, mais il nous a montré qu'il fallait plutôt passer par un utilisateur autre que root si nous voulons, à la base, manipuler une base de données associée. On peut, certes, accéder à information_schema (ce que nous n'avons pas vu, mais peut-être plus tard) mais en aucun cas à mysql.

Geo

(D'un côté, ça prouve que je suis encore en vie, hahaha !)

dimanche 18 janvier 2009

Petit délire d'ASCII art

Salut, salut !
Histoire de poster un truc pour vous montrer que le blog n'est pas encore mort, je vais vous parler d'un petit script à la con que j'ai fait hier en même pas 15 minutes. Ca m'a permis de pratiquer un peu la bibliothèque GD de php.

Je préviens, au passage, que je vois déjà ma monture - UnKnOwN*DrAgOoN - se foutre de ma gueule. :]

Le script a pour fonction de prendre quatre arguments en méthode GET :
- La skin a afficher en ascii art ;
- la couleur de fond sur laquelle afficher l'ascii art ;
- les coordonnées x de la frame ;
- les coordonnées y de la frame.

Imaginez la skin suivante :


Le but du script serait de prendre une frame (celle de face, par exemple) et de l'afficher en ascii art avec les couleurs. On imagine donc bien l'algorithme qui :
- se positionne au 1er pixel de la frame ;
- lit, de façon séquentielle, la couleur des pixels ;
- affiche des caractères HTML colorés.

J'ai donc déjà au moins ça :
<?php
if(!empty($_GET['bgcolor'])) {
$colordefault = "#".htmlentities($_GET['bgcolor']);
} else {
$colordefault = "#000000";
}
echo
"<body bgcolor=\"".$colordefault."\" text=\"#FFFFFF\">";



J'avoue que ça doit pas être très optimisé niveau sécu' ou quoi, mais c'est juste que, sur le moment, je me faisais chier comme pas possible.

Ensuite, sachant qu'une frame fait 24 pixels sur la largeur et 32 pixels sur la longueur, on peut continuer là-dessus :
if(isset($_GET['skin'])) {
$MyImage = @imagecreatefrompng($_GET['skin']);

if(isset($_GET['x'])) {
$framex = abs(intval($_GET['x']));
} else {
$framex = 0;
}

if(isset($_GET['y'])) {
$framey = abs(intval($_GET['y']));
} else {
$framey = 0;
}

$debutx = 24*$framex;
$debuty = 32*$framey;

$dest = imagecreatetruecolor(24,32);
imagecopymerge($dest, $MyImage, 0, 0, $debutx, $debuty, 24, 32, 100);
// ...



On créer une petite image de destination aux dimensions 24x32 et on y copie la frame à afficher. C'est inutile mais ça m'a permis de faire du pas à pas.

Voici en suite la portion de code qui servirait à afficher l'ascii art coloré :
echo "<font size=\"1\" face=\"Courier New\">";
for($j = 0; $j <= 32; $j++) {
for($i = 0; $i <= 24; $i++) {
$color = imagecolorat($dest,$i,$j);
$r = ($color >> 16) & 0xFF;
$g = ($color >> 8) & 0xFF;
$b = $color & 0xFF;
if($color) {
echo "<font color=\"#".
($r <= 15 ? "0".dechex($r) : dechex($r)).
($g <= 15 ? "0".dechex($g) : dechex($g)).
($b <= 15 ? "0".dechex($b) : dechex($b))."\">0101</font>";
} else {
echo "<font color=".$colordefault.">0101</font>";
}
}
echo "<br />";
for($i = 0; $i <= 24; $i++) {
$color = imagecolorat($dest,$i,$j);
$r = ($color >> 16) & 0xFF;
$g = ($color >> 8) & 0xFF;
$b = $color & 0xFF;
if($color) {
echo "<font color=\"#".
($r <= 15 ? "0".dechex($r) : dechex($r)).
($g <= 15 ? "0".dechex($g) : dechex($g)).
($b <= 15 ? "0".dechex($b) : dechex($b))."\">0101</font>";
} else {
echo "<font color=".$colordefault.">0101</font>";
}
}
echo "<br />";
}
echo "</font>";



Petites explications : On balaye chaque ligne, on lit la couleur des pixels et on l'affiche en <font color="couleur lue">ascii art</font>. Si je fais deux boucles for() sur la largeur, c'est pour éviter que l'ascii art soit trop tassé.

On peut terminer avec une petite notice d'utilisation - flemme d'avoir codé un formulaire html...
} else {
echo "<pre>Utilisation : script.php?skin=skin.png[&bgcolor=couleur_hexa][&x=valeur][&y=valeur]</pre>";
}
?>


Comme quoi, c'est juste pour le délire que j'ai fait ça.
Un petit aperçu ? :]

hebergé sur tof.center.free.fr


Voili voulou. Et, vu que j'aurais pas écrit beaucoup de choses, autant publier mes résultats merdiques du BTS blanc :
- Droit : 4,25 ;
- Economie : 8,5 ;
- Comptabilité : 8,5 ;
- Architecture matérielle : 9 ;
- Français : 10,7 ;
- Anglais : 12 ;
- Analyse (Méthode merise) : 13,5 ;
- Architecture logicielle (SQL, excel...) : 16,5 ;
- Algorithmie : 18,5 ;
- Maths : 18,5 ;
- GEOSI (Gestion des entreprise et organisation des systèmes d'information) : 20,5, car, en fait, la notation a été revue pour être sur 23. Ca me fait 0.5 point de bonus.

Ca me fait une moyenne de merde, les matières informatiques étant regroupées dans un coefficient global de 5. L'éco-droit, coeff 3 (Aïe !), et tout le reste coeff 2.

C'était... ma vie passionnante ! C'est bien la dernière fois que je dis des trucs qui n'ont rien à voir avec le blog...

Conclusion ?


Pour en revenir au sujet de l'article, celui-ci ne sert un peu à rien comparé aux autres - sh4ka m'a même dit qu'il préférait la crypto. Néanmoins, c'est toujours ça de plus de coder des petits trucs pour en tirer une petite satisfaction. Je sais pas pour vous, mais, ça m'a fait délirer de faire de l'ascii art (premier truc que j'ai fait).

Geo


PS : Ajout de kmkz dans la liste des copains. Blog sympathique (comme les autres) à aller voir !
PS2 : Ajout du site de shp - mon sacalain, ma propriété privée - dans la liste des copains. Je t'aime, mon bichon.
PS3 : Ajout du blog de 5m0k3, mon prédécesseur, dans la liste des copains.

samedi 10 janvier 2009

StegaWav beta v0.1 - "J'ai rien entendu !"

Les week-ends... Ils ont leurs avantages tout comme leurs inconvénients ; c'est reposant, mais parfois, on peut s'faire chier comme un rat mort.

Il n'y a pas si longtemps que ça, je me suis mis en tête de coder un petit programme qui se sert du bit de poids faible d'un fichier x pour y dissimuler tous le contenu d'un fichier y. Une technique de stéganographie efficace mais très connue. Pour savoir ce qu'est - en détail - la stéganographie, je vous redirige sur ce lien :
http://fr.wikipedia.org/wiki/St%C3%A9ganographie

Je reprends... Je me suis donc mis en tête de coder l'outil pour cacher les informations, et l'autre pour les extraire.

J'élabore un petit cahier des charges dans ma tête. Pourquoi wav ? Parce que, généralement, les fichiers de ce type sont volumineux, car non compressés. En plus, il faudrait élaborer un petit truc sympa. Je me suis donc dit que je cacherai carrément un fichier dans le son. On commencerait donc par cacher des en-têtes, du genre :

Name: fichier.txt\n
Taille : 15\0

Ainsi, on cache le contenu. Ca peut servir pour l'extracteur, qui va lire le nom du fichier et qui ira ensuite extraire suivant la taille.

Ayant eu un souci en C auquel j'ai été confronté longtemps sans trouver de solution, je demande de l'aide sur #nibbles. Ivanlef0u, j0rn, Baboon et Deimos se penchent sur mon problème ; en fait, ça viendrait de fseek(), une fonction dont je me sers pour parcourir le fichier. Résultat, personne ne trouve malgré les théories élaborées, et ça finit en gentil troll.

J'ai plus qu'à faire ça en PHP. :(


J'ai commencé par pondre des scripts en console. Pour les télécharger, c'est ici :
http://venom630.free.fr/geo/?path=tools/StegaWav

Utilisez-les en CLI. De toute façon, z'avez pas le choix.

Je les compile avec bambalam, content de moi. Effectivement, je pourrai les diffuser aux gens (coucou Tybalt !) qui n'ont pas PHP d'installé sur leur bécane ! \o/

Oui, j'étais content de mon petit machin débile. Je l'ai donc fait essayer à certains amis qui avaient le temps, mais, le souci, c'est qu'ils n'avaient pas l'habitude d'utiliser la console. Donc, je me suis dit... Pourquoi ne pas leur faire d'interface graphique avec winbinder ?

C'est ce que j'ai fait !

Avantages :
- Prise en main facile ;
- programmation facile.

Inconvénients :
- Lent ;
- pas portable ;
- Eventuellement quelques bugs.
- Ca se peut que ça ne marche pas... Je suis pas pro en portabilité de winbinder.

Vous pouvez donc télécharger l'archive à cette adresse :
http://venom630.free.fr/geo/?path=tools/StegaWav_Gui

Elle contient :
- Les exécutables (quand même !) ;
- Les sources.

Ce que je prévois pour la suite :
- Vérification des fichiers : il faut que le fichier son soit environ neuf fois plus gros que le fichier à cacher (pas huit, parce que j'ai envie) ;
- Cacher plusieurs fichiers à la suite ? Eventuellement, faire un header principal du genre "NombreDeFichiers: 3"... ;
- Proposez-moi vos idées ? De toute façon, les sources sont diffusées. Vous faites ce que vous voulez.


Rien de compliqué, donc je vais, à votre plus grand malheur, m'arrêter là.

Geo

mardi 6 janvier 2009

Fyury's challenge - Keygenme

Il m'a sauvé la vie, le dude. Et moi qui pensait rouiller avec du php... C'est en cette soirée du 06 janvier 2009 que je me résigne à visiter son blog, et là, je tombe sur son challenge de crackme :
Après un petit rappelle de xylitol (merci), je viens vous mettre mon foome I ..

Je l'avais présenté sur FC et donc je n'ai pas vu d'importance à l'exposer sur le blog (vu les critiques :p) .

level : 0.5 || 1
secure : no package ..
Anti debugger (mal implémenté)

Objectifs :

- faire un keygen. ( 1 )
- trouver le serial pour son pseudo. (0.5 )


Article en question : http://fyury.blogspot.com/2008/11/foome-part-i.html.

Je télécharge l'archive sans trop lire les infos, je me focalise juste sur ça :

- faire un keygen. ( 1 )
- trouver le serial pour son pseudo. (0.5 )


Je me suis dit, au début, que je n'arriverai pas à faire le keygen. J'y suis finalement arrivé, après plusieurs essais car je suis quelqu'un de trop pressé.

Allez, je décompresse l'archive dans un dossier, et je lance foome.exe.
C:\Documents and Settings\Geoffrey\Bureau\foome>"foome {part I}.exe"
[ foome part I by fyuw]

Login : Geo0w
pwd : 15612


Une fenêtre apparaît, et me dit "t4pz" avec pour titre "Iz N0t da g00d password". Put*** de foome de m****, j'vais te montrer qui c'est la tapz ! <>

Je me précipite pour ouvrir le bordel avec ollydbg. Je ne tarde pas à trouver la section de code la plus intéressante :
00401431  |> C70424 2C30400>MOV DWORD PTR SS:[ESP],foome_{p.0040302C ; ||||ASCII "                 [ foome part I by fyuw]

Login : "
00401438 |. E8 C7060000 CALL <JMP.&msvcrt.printf> ; |||\printf
0040143D |. 8D85 88FEFFFF LEA EAX,DWORD PTR SS:[EBP-178] ; |||
00401443 |. 894424 04 MOV DWORD PTR SS:[ESP+4],EAX ; |||
00401447 |. C70424 5F30400>MOV DWORD PTR SS:[ESP],foome_{p.0040305F ; |||ASCII "%s"
0040144E |. E8 A9060000 CALL <JMP.&msvcrt.scanf> ; ||\scanf
00401453 |. 8D85 88FEFFFF LEA EAX,DWORD PTR SS:[EBP-178] ; ||
00401459 |. 890424 MOV DWORD PTR SS:[ESP],EAX ; ||
0040145C |. E8 93060000 CALL 00401461 |. 83F8 04 CMP EAX,4 ; |
00401464 |. 77 1B JA SHORT foome_{p.00401481 ; |
00401466 |. C70424 6230400>MOV DWORD PTR SS:[ESP],foome_{p.00403062 ; |ASCII "Need more 5 char..."
0040146D |. E8 92060000 CALL <JMP.&msvcrt.printf> ; \printf
00401472 |. C785 84FEFFFF >MOV DWORD PTR SS:[EBP-17C],0
0040147C |. E9 F5000000 JMP foome_{p.00401576
00401481 |> 8D85 88FEFFFF LEA EAX,DWORD PTR SS:[EBP-178] ; ||
00401487 |. 890424 MOV DWORD PTR SS:[ESP],EAX ; ||
0040148A |. E8 65060000 CALL 0040148F |. 83F8 0B CMP EAX,0B ; |
00401492 |. 76 1B JBE SHORT foome_{p.004014AF ; |
00401494 |. C70424 7630400>MOV DWORD PTR SS:[ESP],foome_{p.00403076 ; |ASCII "Need less 10 char..."
0040149B |. E8 64060000 CALL <JMP.&msvcrt.printf> ; \printf
004014A0 |. C785 84FEFFFF >MOV DWORD PTR SS:[EBP-17C],0
004014AA |. E9 C7000000 JMP foome_{p.00401576
004014AF |> C70424 8B30400>MOV DWORD PTR SS:[ESP],foome_{p.0040308B ; |||||ASCII "pwd : "
004014B6 |. E8 49060000 CALL <JMP.&msvcrt.printf> ; ||||\printf
004014BB |. 8D85 B4FEFFFF LEA EAX,DWORD PTR SS:[EBP-14C] ; ||||
004014C1 |. 894424 04 MOV DWORD PTR SS:[ESP+4],EAX ; ||||
004014C5 |. C70424 9230400>MOV DWORD PTR SS:[ESP],foome_{p.00403092 ; ||||ASCII "%d"
004014CC |. E8 2B060000 CALL <JMP.&msvcrt.scanf> ; |||\scanf
004014D1 |. 0FBE9D 8AFEFFF>MOVSX EBX,BYTE PTR SS:[EBP-176] ; |||
004014D8 |. 8D85 88FEFFFF LEA EAX,DWORD PTR SS:[EBP-178] ; |||
004014DE |. 890424 MOV DWORD PTR SS:[ESP],EAX ; |||
004014E1 |. E8 0E060000 CALL 004014E6 |. 89C2 MOV EDX,EAX ; ||
004014E8 |. 89D0 MOV EAX,EDX ; ||
004014EA |. 01C0 ADD EAX,EAX ; ||
004014EC |. 01D0 ADD EAX,EDX ; ||
004014EE |. C1E0 09 SHL EAX,9 ; ||
004014F1 |. 01D0 ADD EAX,EDX ; ||
004014F3 |. 01C3 ADD EBX,EAX ; ||
004014F5 |. 8B85 A0FEFFFF MOV EAX,DWORD PTR SS:[EBP-160] ; ||
004014FB |. 890424 MOV DWORD PTR SS:[ESP],EAX ; ||
004014FE |. E8 F1050000 CALL <JMP.&msvcrt.strlen> ; |\strlen
00401503 |. 29C3 SUB EBX,EAX ; |
00401505 |. 89D8 MOV EAX,EBX ; |
00401507 |. 83C0 0C ADD EAX,0C ; |
0040150A |. 3985 B4FEFFFF CMP DWORD PTR SS:[EBP-14C],EAX ; |
00401510 |. 74 33 JE SHORT foome_{p.00401545 ; |
00401512 |. C74424 0C 0000>MOV DWORD PTR SS:[ESP+C],0 ; |
0040151A |. C74424 08 9530>MOV DWORD PTR SS:[ESP+8],foome_{p.004030>; |ASCII "Iz N0t da g00d password"
00401522 |. C74424 04 2730>MOV DWORD PTR SS:[ESP+4],foome_{p.004030>; |ASCII "t4pZ"
0040152A |. C70424 0000000>MOV DWORD PTR SS:[ESP],0 ; |
00401531 |. E8 06060000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
00401536 |. 83EC 10 SUB ESP,10
00401539 |. C785 84FEFFFF >MOV DWORD PTR SS:[EBP-17C],0
00401543 |. EB 31 JMP SHORT foome_{p.00401576
00401545 |> C74424 0C 0000>MOV DWORD PTR SS:[ESP+C],0 ; |
0040154D |. C74424 08 AD30>MOV DWORD PTR SS:[ESP+8],foome_{p.004030>; |ASCII "U win.. make a keygen"
00401555 |. C74424 04 2730>MOV DWORD PTR SS:[ESP+4],foome_{p.004030>; |ASCII "t4pZ"
0040155D |. C70424 0000000>MOV DWORD PTR SS:[ESP],0 ; |
00401564 |. E8 D3050000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA


Je fais un break sur l'adresse 004014CC, qui va appeler la fonction scanf lors de l'input du password. Je lance, et là, une autre fenêtre avec titre "U sUck" et qui m'affiche de nouveau un "t4pZ". Mais quelle connasse ! (même plus envie de censurer, c'est plus fort que moi)

Je me dis donc - toujours sans avoir lu qu'il y avait un antidebuger mal implémenté - qu'il y a une protection à contourner. Miracle, je repère ce bout de code :

00401324  |. C785 98FEFFFF >MOV DWORD PTR SS:[EBP-168],foome_{p.0040>; |ASCII "OLLYDBG.EXE"
0040132E |. C785 9CFEFFFF >MOV DWORD PTR SS:[EBP-164],foome_{p.0040>; |ASCII "idag.exe"
00401338 |. C785 A0FEFFFF >MOV DWORD PTR SS:[EBP-160],foome_{p.0040>; |ASCII "windbg.exe"


Sans hésitation, je modifie les valeurs dans le dump :
- "OLLYDBG.EXE" devient "tasoeur.EXE" ;
- "idag.exe" devient "stfu.exe" ;
- "windbg.exe" devient "azerty.exe".

Je relance, et là... Pas de fenêtre ! C'est qui la tapz ?! Haha !

Je rentre donc en login : Geo0w, et en pwd : 2151 (truc au pif, quoi).

Je continue...

Sans rentrer dans les détails, j'arrive à la ligne suivante après quelques coups de F8 (pour tracer le code sans s'attarder dans les CALLs) :
0040150A  |. 3985 B4FEFFFF  CMP DWORD PTR SS:[EBP-14C],EAX  


Je regarde eax, et il contient 00001E76. En décimal, ça donne : 7798.
Je ferme ollydbg et tout le bordel, puis je relance foome.exe en ligne de commande :


C:\Documents and Settings\Geoffrey\Bureau\foome>"foome {part I}.exe"
[ foome part I by fyuw]

Login : Geo0w
pwd : 7798


Encore une fenêtre, sauf que, dorénavant, son titre est différent : "U win.. make a keygen", puis, elle affiche encore un "t4pZ". Cette saloperie mériterait que je l'insulte comme un DR_KILLER. Au passage, make me a sandwich, saloperie !

Bon, désolé pour la vulgarité, mais bon... C'est éprouvant, ça sera mon premier keygen de ma vie ! Oui, je suis énervé et j'oublie le fait d'avoir pensé tout à l'heure que je n'y arriverai pas. Je fonce, tête baissée !

Je réouvre mon copain ollydbg, je remodifie les valeurs dans le dump :
- "OLLYDBG.EXE" devient "tasoeur.EXE" ;
- "idag.exe" devient "stfu.exe" ;
- "windbg.exe" devient "azerty.exe".

Puis, cette fois, je break sur :
004014CC  |. E8 2B060000    CALL <JMP.&msvcrt.scanf>                 ; |||\scanf


Cette ligne correspond au CALL juste après l'input du password. Hop, je lance, je rentre "albert" en login et "11111" en pwd, puis ça break. Je trace le code :
004014E6  |. 89C2           MOV EDX,EAX                              ; ||
004014E8 |. 89D0 MOV EAX,EDX ; ||
004014EA |. 01C0 ADD EAX,EAX ; ||
004014EC |. 01D0 ADD EAX,EDX ; ||
004014EE |. C1E0 09 SHL EAX,9 ; ||
004014F1 |. 01D0 ADD EAX,EDX ; ||
004014F3 |. 01C3 ADD EBX,EAX ; ||
004014F5 |. 8B85 A0FEFFFF MOV EAX,DWORD PTR SS:[EBP-160] ; ||
004014FB |. 890424 MOV DWORD PTR SS:[ESP],EAX ; ||
004014FE |. E8 F1050000 CALL <JMP.&msvcrt.strlen> ; |\strlen
00401503 |. 29C3 SUB EBX,EAX ; |
00401505 |. 89D8 MOV EAX,EBX ; |
00401507 |. 83C0 0C ADD EAX,0C ; |
0040150A |. 3985 B4FEFFFF CMP DWORD PTR SS:[EBP-14C],EAX ; |


C'est à la dernière ligne que notre password entré est comparé à la clef véritable. Donc, j'analyse le code assembleur au-dessus, et j'en viens à traduire cela en l'algorithme suivant (après plusieurs sessions de debugging) :

keygen <- longueur(login)
keygen <- keygen * 3
keygen <- keygen * 512
keygen <- keygen + longueur(login) (merci à UnKnOwN*DrAgOoN pour avoir signalé l'oubli)
keygen <- keygen + (valeur entière)login[3]
keygen <- keygen - longueur_chaine("windbg.exe")
keygen <- keygen + 12


Au final, je fais mon keygen :
http://venom630.free.fr/geo/autre_chose/foome__fyuw/keygen_c.txt

Il marche niquel.


Conclusion ?


Eprouvant, très éprouvant. Fyury, si tu passes sur ce blog, je tenais à te remercier d'avoir mis à disposition un tel challenge. J'espère résoudre d'autres de tes oeuvres avec une difficulté croissante ; c'est en forgeant qu'on devient forgeron.

Geo

Edit : ajout de http://xylitol.free.fr/Home/index.php dans la liste des copains. Superbe site sur le reverse engineering à visiter !

"Bambalam!" ou "compile-moi du PHP !"

Mon DS d'éco-droit ayant été littéralement... Foiré, et n'ayant pas envie de réviser mes maths pour demain, je décide de consacrer un article toujours aussi simpliste qui traitera de Bambalam.

Non, ce n'est pas de la musique. Voici, d'ailleurs, en premier lieu, l'URL du site du projet :
http://www.bambalam.se/bamcompile/


On voit en gros sur la page :
Bambalam PHP EXE Compiler/Embedder


Alors que PHP est censé être un langage interprété, on peut le compiler pour :
- Masquer du code ;
- Faire des applications windows portables ;
- (théoriquement) accroître la vitesse d'exécution.

Elle est pas belle, la vie ?

Et puis, si vous utilisez linux, il y a la source du projet à télécharger !

Allez, on télécharge l'archive, on l'extrait dans un dossier, et on regarde le contenu :
- readme.txt : on passe ;
- project_template.bcp : on passe ;
- bamcompile.exe : le fichier qui va recevoir plein d'arguments pour "compiler" notre php ;
- examples : un dossier contenant plein d'exemples intéressants. Je vous laisse regarder.

Pour nous mettre à l'aise, créons un dossier projets. Dans ce dossier projets, créons un dossier hello et allons dans celui-ci. Maintenant, dans ce dossier, créons un fichier nommé hello.php Et mettons-y le code suivant :
<?php
echo 'Hello!';
?>


Il va maintenant falloir le compiler. Tout d'abord, vous avez le choix entre :
- Aller en ligne de commande pour vous déplacer dans le dossier de bambalam puis rentrer vos options à la main ;
- Faire un fichier batch qui va exécuter de façon séquentielle vos commandes et en garder une trace.

Pour ma part, je penche pour la seconde option.

Voyons ce qu'on nous dit sur le site du projet :
Usage:
bamcompile [-options] infile.php [outfile.exe]
bamcompile [-options] project_directory mainfile.php [outfile.exe]
bamcompile projectfile.bcp

Options:
-w Hide console window for windowed applications
-c Compress output exe (using UPX)
-d Do not encode PHP files
-e:extension.dll Embed and use PHP extension
-i:icon.ico Add icon to exe


Testons la première ligne pour compiler notre unique fichier PHP ! Créons un fichier nommé make.bat dans le dossier courant, et mettons-y les lignes de code suivantes :
@echo off
"../../bamcompile.exe" hello.php
rem On va éviter de fermer la console automatiquement
pause


Eh oui, il faut veiller à mettre ../../ pour remonter dans le dossier parent ; je ne vous prends pas pour des imbéciles non plus, mais pensons-y par réflexe !

On lance make.bat et on n'a même pas le temps de dire "Agaga poireau." :
Bambalam PHP EXE Compiler/Embedder 1.21

Mainfile: hello.php
Outfile: hello.exe

Encoding and embedding hello.php

hello.exe created successfully!
Appuyez sur une touche pour continuer...



On a un superbe exécutable qui s'est créé dans le même dossier. On l'ouvre, et il se ferme à la vitesse de l'éclair ; normal.

On va voir ce que ça donne en ligne de commande :
C:\bamcompile1.21\projets\hello>hello.exe

Hello!


La classe, Matias !
Bon, ok, y'a une ligne vide au-dessus de notre phrase, mais on s'en fout pas mal.

Revenons dans le dossier projets, faisons un second dossier nommé age. On va dedans, et on va créer deux fichier :
- main.php (le fichier principal)
<?php
require_once('age.php');
if($_SERVER['argc'] < 2) {
    echo "Utilisation : ".$_SERVER['argv'][0]." [nombre]\n";
    exit(-1);
}
echo AfficherSuivantAge(abs($_SERVER['argv'][1]));
?>


J'explique le code vite fait. On commence par inclure le fichier age.php (qu'on va écrire après), on vérifie qu'on a entré l'argument en ligne de commandes - qui correspond à l'âge d'une personne - et, en suite, on appelle la fonction AfficherSuivantAge() qui sera définie dans le fichier age.php. Enfin, la fonction intval() permet de s'assurer que l'argument sera une valeur numérique, et abs() pour qu'elle soit positive (vous avez déjà vu des gens âgés de -15 ans ? Tss... Menteurs !)

Passons au fichier age.php :
<?php
if(!defined("AGE_PHP")) {
    define("AGE_PHP",TRUE);
    function AfficherSuivantAge($var) {
        return $var >= 18 ? "Tu es majeur" : "Tu es mineur";
    }
}
?>


En bref, je protège le fichier des inclusions multiples (même si ça sert pas à grand-chose ici) et je définis ma fonction. Car, si on définit la fonction avec le même nom plus d'une fois, ça plante ; normal. La fonction retourne une chaîne de caractère :
- "Tu es majeur" si l'âge est supérieur ou égal à 18 ;
- "Tu es mineur" si l'âge est strictement inférieur à 18.

Pour ceux qui ne comprennent pas le principe de l'instruction ternaire, elle consiste à affecter une valeur à une variable suivant une condition. Exemple :
$variable = condition ? "valeur_si_condition_vraie" : "valeur_si_condition_fausse";


Ca me rappelle la terminale, où on faisait du C en électronique logique. J'ai utilisé des instructions ternaires, et le prof m'a sorti "Mais, ça, c'est pas du C !". Enfin, bref. (xD)

Le code équivalent est le même que pour l'exemple ci-dessus :
if(condition)
    $variable = "valeur_si_condition_vraie";
else
    $variable = "valeur_si_condition_fausse";


Une ligne pour l'instruction ternaire ; quatre pour le test de condition ci-dessus. Ca explique pourquoi j'ai choisi l'expression ternaire.

Mais enfin, ne dérivons pas du sujet.

Maintenant, ce que nous allons faire, c'est revenir dans le dossier où se trouve bamcompile.exe. Créons un fichier nommé make_age.bat et mettons-y le code suivant :
@echo off
bamcompile.exe projets/age main.php projets/age/age.exe
pause


En effet, sur le site de bambalam, on nous dit qu'on peut utiliser :
bamcompile [-options] project_directory mainfile.php [outfile.exe]


Par identification :
project_directory = projets/age ;
mainfile.php = main.php ;
outfile.exe (argument optionnel) = projets/age/age.exe

On lance donc notre fichier batch et c'est l'extase (normalement !).

Bambalam PHP EXE Compiler/Embedder 1.21

Mainfile: main.php
Outfile: projets/age/age.exe
Project dir: projets/age

Embedding age.exe
Encoding and embedding age.php
Encoding and embedding main.php

projets/age/age.exe created successfully!
Appuyez sur une touche pour continuer...


On va exécuter age.exe en CLI :

C:\bamcompile1.21\projets\age>age.exe 18
Tu es majeur
C:\bamcompile1.21\projets\age>age.exe 16
Tu es mineur
C:\bamcompile1.21\projets\age>age.exe aaa
Tu es mineur
C:\bamcompile1.21\projets\age>age.exe -4
Tu es mineur
C:\bamcompile1.21\projets\age>age.exe -18
Tu es majeur
C:\bamcompile1.21\projets\age>age.exe 32
Tu es majeur


Ok, le programme n'a pas beaucoup d'intérêt, mais c'est déjà un bon exemple !


J'ai le regret de vous annoncer que le tour de manège est terminé. Disons que cet article m'a occupé à vous présenter un outil que j'adore vraiment (j'ai pu envoyer un exe sympathique à une copine, y'a longtemps) et qui m'amuse toujours autant !

Regardez la section examples, ça vaut le coup. Il y a même un exemple de calculatrice codée avec winbinder - extension PHP pour faire de l'interface graphique. Bref, tout cela pour dire que ça vaut absolument le coup pour ceux qui font des scripts PHP en CLI et qui voudraient les partager avec des utilisateurs qui n'ont pas forcément PHP d'installé sur leur ordinateur.

C'est tout. A la revoyure !

Geo