CTF Secu'RT
Aujourd'hui s'est déroulé le CTF de la Secu'RT à
Montbéliard.
Dans la matinée nous avons pu assister à des
conférences sur le domaine de la sécurité plus
ou moins intéressantes.
C'est vers 14h que les hostilités ont commencé.
Pour information, la Secu'RT a plus pour objectif de
sensibiliser les gens à la sécurité.
C'est donc dans cet optique que les challenges ont été pensés.
J'y ai participé avec les membres de Hackgyver.
Nous avons du nous séparer en deux équipes pour équilibrer les forces.
Equipe 1 : Maijin et Futex (2e au classement) Equipe 2 : deadr0m1`, jvoisin et moi-même (1ère au classement héhé)
Le programme : RootBSD a mis en place les challenges.
Chacun était accessible à l'adresse 192.168.0.13:PORT, avec PORT pour passer
d'une épreuve à l'autre.
SECU'RT : Les épreuves
Trois parties seront abordées lors de la compétition, chacune d'entre elles
traitera un sujet lié à la sécurité informatique.
Le but de chaque épreuve sera d'identifier un code de validation afin de
pouvoir entamer l'épreuve suivante.
Partie 1: Les vulnérabilités du Web
- Épreuve 1 : Le code de validation à récupérer sera sur la page d'administration d'un site web.
- Épreuve 2 : Le code de validation sera dissimulé dans un fichier passwd.php.
- Épreuve 3 : Le code de validation est le mot de passe de l'utilisateur Kevin.
- Épreuve 4 : Comme dans l'épreuve précédente, le code de validation sera un mot de passe qui sert à se connecter à une page d’accueil.
- Épreuve 5 : Cette fois ci le code de validation sera le retour de la commande « /bin/validation/ ».
Partie 2: Computer forensics
- Épreuve 6 : Le code de validation de cette épreuve sera le mot de passe administrateur.
- Épreuve 7 : Pour valider cette épreuve, le code de validation sera le mot de passe de l'administrateur d'un environnement Windows.
- Épreuve 8 : Tout comme l'épreuve précédente, le code de validation sera le mot de passe de l'utilisateur Kevin mais cette fois ci l'environnement sera Linux.
Partie 3: Reverse engineering
Pour chacune de ces épreuves, un mot de passe doit être trouvé, ce mot de passe
est à mettre en argument des binaires.
Si l'épreuve retourne OK, le mot de passe est le bon. Ce mot de passe est le
code de validation.
- Épreuve 9 : binaire Windows
- Épreuve 10 : binaire Windows
- Épreuve 11 : binaire Linux
- Épreuve 12 : binaire Linux
- Épreuve 13 : binaire Linux
Web
Challenge 1
URL: http://192.168.0.13:80/admin.php
Sur cette page on a un formulaire de connexion avec deux champs : Username et
Password.
Mais pas besoin de chercher plus loin, ni de tester des SQLi ou quoi que ce
soit.
En effet, en observant les cookies, un nouveau vient d'apparaitre :
admin=0
On le passe à 1, on refresh et voilà, premier flag.
Code: EAD678UJHDE56
Challenge 2
URL: http://192.168.0.13:81/read.php?id=article1
Sur cette page on peut naviguer entre les différents articles avec article1,
article2, etc.
Pour être honnête, on a mis du temps, beaucoup de temps pour valider cette
épreuve...
read.php?id=passwd.php read.php?id=passwd.php%00 read.php?id=../passwd.php read.php?id=../passwd.php%00 read.php?id=/etc/passwd.php read.php?id=/etc/passwd.php%00 read.php?id=php://filter/convert.base64-encode/resource=passwd.php read.php?id=php://filter/convert.base64-encode/resource=passwd.php%00 <!-- <?php echo file_get_contents('passwd.php'); ?> --> read.php?id=data://text/plain;base64,PD9waHAgZWNobyBmaWxlX2dldF9jb250ZW50cygncGFzc3dkLnBocCcpOyA/Pg0K
Lorsqu'on tentait d'accéder au fichier /passwd.php directement on avait une
erreur 500.
On a donc tenté de modifier les headers de la requètes HTTP pour faire croire
au serveur que la requête venait de l'interne.
Autant dire qu'on n'avait plus vraiment d'idée...
Après moultes essais et un petit coup de pouce, il s'est avéré que le script read.php fonctionnait de la sorte :
<? include('/dir_art/' + $_POST['id'] + '.php'); ?>
Donc les articles étaient dans un dossier plus loin que passwd.php.
La version du serveur ne permettait pas l'insertion du null byte %00.
Ainsi, il fallait donc prendre avantage du script et profiter du hardcoding
de l'extention.
On essaie alors http://192.168.0.13:81/read.php?id=../passwd
deadr0m1` remarque qu'il n'y a plus d'erreur sur la
page comme Cet article n'existe pas... auparavant.
On regarde donc le code source :
<? php code="SDG789997GRDS"; ?>
Challenge 3
URL : http://192.168.0.13:82/index.php?username=USERNAME
Ici la page index.php nous permettait de récupérer des informations sur un
utilisateur.
On se retrouve avec une injection SQL.
On écrit donc dans le champs la requête suivante :
" UNION SELECT password FROM users; --
Information sur l'utilisateur :
" UNION select password from users; --: QSD4876FDSGSazerty
Challenge 4
URL : http://192.168.0.13:83/index.php
Petite sneacky ici.
Un peu comme pour le challenge 2, on se retrouve un peu bloqué ici.
On a tenté pas mal de tests en aveugle, en essayant des failles au hasard.
Après quelques échanges, RootBSD nous a indiqué qu'il fallait plutôt s'orienter sur une malfaçon/manque de rigueur du programmeur.
J'avais d'abord pensé à un exploit Register Globals, en me disant que peut
être, le programmeur passait par une variable globale pour savoir si on était
connecté ou pas.
Après une dizaine d'essaies sur des noms triviaux comme logged, login,
anonymous, visitor, admin, on a abandonné et on est passé à autre chose.
A force d'essayer, je suis tombé sur la solution :
http://192.168.0.13:83/index.php~
On voit alors apparait le flag dans le code source :
if ( $_POST['username'] == "admin" && $_POST['password'] == "SFDG6321FDSQ")
J'ai eu un peu de chance sur celle là car j'avais validé une épreuve similaire sur Root-Me quelques jours auparavant.
Challenge 5
URL : http://192.168.0.13:84/index.php
Sur cette page, un seul champ. L'indice est de récupérer le retour de
/bin/validation.
On peut donc penser que le champ sera placé dans un appel system.
Avec ces indices, jvoisin a trouvé le flag en moins d'une demi seconde :p
&& /bin/validation
On obtient en retour :
Les information sur l'utilisateur sont:FSQFDERergffd09456jkj
Computer forensics
Challenge 6
A notre disposition, une archive kevin.pgz.
Elle contient principalement un dossier .mozilla, qui contient surement un
profile pour Mozilla Firefox.
On l'importe avec le navigateur et on regarde les passwords sauvegardés.
Mais pour les lire, il faut aussi entrer un mot de passe.
On tente des mots de passe triviaux et on trouve kevin. On peut donc afficher les passwords enregistrés.
Voilà, le flag est Thelastone.
Challenge 7
Pour cette épreuve, on nous met à disposition un dump mémoire de Windows.
J'ai donc sorti volatility pour
pouvoir récupérer des informations intéressantes.
En premier, j'ai cherché à savoir de quel version de l'OS venait le dump :
hackgyver$ vol.py imageinfo -f memory.dmp Volatile Systems Volatility Framework 2.0 Suggested Profile(s) : WinXPSP3x86, WinXPSP2x86 (Instantiated with WinXPSP2x86) AS Layer1 : JKIA32PagedMemory (Kernel AS) AS Layer2 : FileAddressSpace (memory.dmp) PAE type : No PAE DTB : 0x39000 KDBG : 0x8054cde0 KPCR : 0xffdff000 KUSER_SHARED_DATA : 0xffdf0000 Image date and time : 2013-02-10 14:39:48 Image local date and time : 2013-02-10 14:39:48 Number of Processors : 1 Image Type : Service Pack 3
Ensuite j'ai voulu regarder les clefs de registre :
hackgyver$ vol.py hivelist --profile WinXPSP3x86 -f memory.dmp Volatile Systems Volatility Framework 2.0 Virtual Physical Name 0xe18d5008 0x09449008 \Device\HarddiskVolume1\Documents and Settings\kevin\Local Settings\Application Data\Microsoft\Windows\UsrClass.dat 0xe17be530 0x07dd5530 \Device\HarddiskVolume1\Documents and Settings\kevin\NTUSER.DAT 0xe15689e8 0x05e549e8 \Device\HarddiskVolume1\Documents and Settings\LocalService\Local Settings\Application Data\Microsoft\Windows\UsrClass.dat 0xe1562008 0x05e47008 \Device\HarddiskVolume1\Documents and Settings\LocalService\NTUSER.DAT 0xe153cb48 0x05845b48 \Device\HarddiskVolume1\Documents and Settings\NetworkService\Local Settings\Application Data\Microsoft\Windows\UsrClass.dat 0xe1535008 0x0576f008 \Device\HarddiskVolume1\Documents and Settings\NetworkService\NTUSER.DAT 0xe1377b60 0x02e86b60 \Device\HarddiskVolume1\WINDOWS\system32\config\software 0xe1375008 0x02df4008 \Device\HarddiskVolume1\WINDOWS\system32\config\SAM 0xe134a6e0 0x025c56e0 \Device\HarddiskVolume1\WINDOWS\system32\config\SECURITY 0xe1375b60 0x02df4b60 \Device\HarddiskVolume1\WINDOWS\system32\config\default 0xe1254a18 0x019d3a18 [no name] 0xe1018258 0x01794258 \Device\HarddiskVolume1\WINDOWS\system32\config\system 0xe1007260 0x01754260 [no name] 0x8068f9bc 0x0068f9bc [no name]
La clef SAM contient les hashs des mots de passe des utilisateurs.
Je l'ai donc extraite :
hackgyver$ vol.py hashdump --profile WinXPSP3x86 -f memory.dmp -y 0xe1018258 -s 0xe1375008
Volatile Systems Volatility Framework 2.0
Administrateur:500:193db29cb51fd313aad3b435b51404ee:aa6d7e7fdad2abead936f133502d49b8:::
On passe ces deux hashs dans un decode online pour LM et NTLM, ce qui nous donne :
193db29cb51fd313aad3b435b51404ee LM: DEMO aa6d7e7fdad2abead936f133502d49b8 NTLM: DEMO
Challenge 8
L'archive donnée contient un fichier .passwd et un script Ruby .tool.
\iam`}tF|W}w{t|t|y&7
On comprend vite que le mot de passe est chiffré et que l'algo utilisé est contenu dans le script.
#!/usr/bin/env ruby require 'highline/import' def get_password(prompt="[sudo] password for kevin: ") ask(prompt) {|q| q.echo = false} end cmd = "/usr/bin/sudo " + ARGV[0] i = 0 password = get_password() File.open('/home/kevin/.password', 'w') do |f| password.each_byte { |x| f.putc x ^ 0x0B + i i = i+1 } end puts 'Sorry, try again.' exec(cmd)
Apparament, peu de monde apprécie le Ruby ici.
La majorité des personnes ayant validé cette épreuve est passé par Python pour
reverse le chiffrage.
So we did :)
#!/usr/bin/env python2.7 passwd = "\iam`}tF|W}w{t|t|y&7" def decrypt(password): decrypted = '' for i in range(len(password)): decrypted += chr(ord(password[i]) ^ 0x0B + i) return decrypted if __name__ == "__main__": print 'Encrypted password:', passwd print 'Decrypted password:', decrypt(passwd)
Ce qui donne :
hackgyver$ ./decrypt.py Encrypted password: \iam`}tF|W}w{t|t|y&7 Decrypted password: WelcomeToChallenge;)
Reverse engineering
Challenge 9
Premier crackme PE, très simple. Un strings suffit pour trouver le flag.
hackgyver$ strings epreuve9.exe h$0@ h-0@ h00@ SDFG456376 libgcj_s.dll _Jv_RegisterClasses %s code ExitProcess GetModuleHandleA GetProcAddress SetUnhandledExceptionFilter __getmainargs __p__environ __p__fmode __set_app_type _cexit _iob _onexit _setmode atexit exit printf puts signal strcmp KERNEL32.dll msvcrt.dll
On l'essaie :
hackgyver$ wine epreuve9.exe SDFG456376
OK
Challenge 10
Ici, strings ne nous permet pas de lire le flag.
Par contre, on remarque que la fonction strcmp est utilisée.
Il suffit donc de poser un break point lors de son appel pour voire ce qui est
comparé.
Pour ce faire, j'ai utilisé OllyDbg.
On essaie sur le binaire.
(Juste pour info, le '\' est là car sinon bash interprète '!7')
hackgyver$ wine epreuve10.exe AFNK1\!7A OK
Challenge 11
Dans ce binaire, le mot de passe n'apparait pas clairement et il n'y a pas de
test avec strcmp.
Le flag est testé dans le fonction check_password. Voyons ça de plus près
avec gdb et
peda.
gdb-peda$ dis check_password Dump of assembler code for function check_password: 0x0804845a <+0>: push ebp 0x0804845b <+1>: mov ebp,esp 0x0804845d <+3>: push edi 0x0804845e <+4>: sub esp,0x4 0x08048461 <+7>: mov eax,DWORD PTR [ebp+0x8] 0x08048464 <+10>: mov DWORD PTR [ebp-0x8],0xffffffff 0x0804846b <+17>: mov edx,eax 0x0804846d <+19>: mov eax,0x0 0x08048472 <+24>: mov ecx,DWORD PTR [ebp-0x8] 0x08048475 <+27>: mov edi,edx 0x08048477 <+29>: repnz scas al,BYTE PTR es:[edi] 0x08048479 <+31>: mov eax,ecx 0x0804847b <+33>: not eax 0x0804847d <+35>: sub eax,0x1 0x08048480 <+38>: cmp eax,0xa 0x08048483 <+41>: je 0x804848f <check_password+53> 0x08048485 <+43>: mov eax,0x0 0x0804848a <+48>: jmp 0x8048541 <check_password+231> 0x0804848f <+53>: mov eax,DWORD PTR [ebp+0x8] 0x08048492 <+56>: movzx eax,BYTE PTR [eax] 0x08048495 <+59>: cmp al,0x41 0x08048497 <+61>: je 0x80484a3 <check_password+73> 0x08048499 <+63>: mov eax,0x0 0x0804849e <+68>: jmp 0x8048541 <check_password+231> 0x080484a3 <+73>: mov eax,DWORD PTR [ebp+0x8] 0x080484a6 <+76>: add eax,0x1 0x080484a9 <+79>: movzx eax,BYTE PTR [eax] 0x080484ac <+82>: movsx edx,al 0x080484af <+85>: mov eax,DWORD PTR [ebp+0x8] 0x080484b2 <+88>: movzx eax,BYTE PTR [eax] 0x080484b5 <+91>: movsx eax,al 0x080484b8 <+94>: add eax,0x5 0x080484bb <+97>: cmp edx,eax 0x080484bd <+99>: je 0x80484c6 <check_password+108> 0x080484bf <+101>: mov eax,0x0 0x080484c4 <+106>: jmp 0x8048541 <check_password+231> 0x080484c6 <+108>: mov eax,DWORD PTR [ebp+0x8] 0x080484c9 <+111>: add eax,0x2 0x080484cc <+114>: movzx eax,BYTE PTR [eax] 0x080484cf <+117>: cmp al,0x6c 0x080484d1 <+119>: je 0x80484da <check_password+128> 0x080484d3 <+121>: mov eax,0x0 0x080484d8 <+126>: jmp 0x8048541 <check_password+231> 0x080484da <+128>: mov eax,DWORD PTR [ebp+0x8] 0x080484dd <+131>: add eax,0x5 0x080484e0 <+134>: movzx eax,BYTE PTR [eax] 0x080484e3 <+137>: cmp al,0x7a 0x080484e5 <+139>: je 0x80484ee <check_password+148> 0x080484e7 <+141>: mov eax,0x0 0x080484ec <+146>: jmp 0x8048541 <check_password+231> 0x080484ee <+148>: mov eax,DWORD PTR [ebp+0x8] 0x080484f1 <+151>: add eax,0x6 0x080484f4 <+154>: movzx eax,BYTE PTR [eax] 0x080484f7 <+157>: movsx eax,al 0x080484fa <+160>: mov edx,DWORD PTR [ebp+0x8] 0x080484fd <+163>: add edx,0x5 0x08048500 <+166>: movzx edx,BYTE PTR [edx] 0x08048503 <+169>: movsx edx,dl 0x08048506 <+172>: add edx,0x1 0x08048509 <+175>: cmp eax,edx 0x0804850b <+177>: je 0x8048514 <check_password+186> 0x0804850d <+179>: mov eax,0x0 0x08048512 <+184>: jmp 0x8048541 <check_password+231> 0x08048514 <+186>: mov eax,DWORD PTR [ebp+0x8] 0x08048517 <+189>: add eax,0x7 0x0804851a <+192>: movzx eax,BYTE PTR [eax] 0x0804851d <+195>: cmp al,0x32 0x0804851f <+197>: je 0x8048528 <check_password+206> 0x08048521 <+199>: mov eax,0x0 0x08048526 <+204>: jmp 0x8048541 <check_password+231> 0x08048528 <+206>: mov eax,DWORD PTR [ebp+0x8] 0x0804852b <+209>: add eax,0x8 0x0804852e <+212>: movzx eax,BYTE PTR [eax] 0x08048531 <+215>: cmp al,0x33 0x08048533 <+217>: je 0x804853c <check_password+226> 0x08048535 <+219>: mov eax,0x0 0x0804853a <+224>: jmp 0x8048541 <check_password+231> 0x0804853c <+226>: mov eax,0x1 0x08048541 <+231>: add esp,0x4 0x08048544 <+234>: pop edi 0x08048545 <+235>: pop ebp 0x08048546 <+236>: ret End of assembler dump.
En premier, la fonction teste la longueur du password d'entrée 0x08048480. Il
doit être composé de 10 caractères.
Ensuite, en suivant les tests un à un, on obtient le flag :
AFlDEz{23J
On teste ça.
hackgyver$ ./epreuve11 AFlDEz{23J OK
Challenge 12
Comme pour le précédent, pas de flag harcodé ni de strcmp en évidence. Par contre on remarque l'appelle de la fonction base64.
gdb-peda$ dis main Dump of assembler code for function main: 0x08048784 <+0>: push ebp 0x08048785 <+1>: mov ebp,esp 0x08048787 <+3>: push edi 0x08048788 <+4>: push esi 0x08048789 <+5>: and esp,0xfffffff0 0x0804878c <+8>: sub esp,0x30 0x0804878f <+11>: cmp DWORD PTR [ebp+0x8],0x1 0x08048793 <+15>: jg 0x80487a2 <main+30> 0x08048795 <+17>: mov eax,DWORD PTR [ebp+0xc] 0x08048798 <+20>: mov eax,DWORD PTR [eax] 0x0804879a <+22>: mov DWORD PTR [esp],eax 0x0804879d <+25>: call 0x8048674 <usage> 0x080487a2 <+30>: mov eax,DWORD PTR [ebp+0xc] 0x080487a5 <+33>: add eax,0x4 0x080487a8 <+36>: mov eax,DWORD PTR [eax] 0x080487aa <+38>: mov DWORD PTR [esp+0x1c],0xffffffff 0x080487b2 <+46>: mov edx,eax 0x080487b4 <+48>: mov eax,0x0 0x080487b9 <+53>: mov ecx,DWORD PTR [esp+0x1c] 0x080487bd <+57>: mov edi,edx 0x080487bf <+59>: repnz scas al,BYTE PTR es:[edi] 0x080487c1 <+61>: mov eax,ecx 0x080487c3 <+63>: not eax 0x080487c5 <+65>: sub eax,0x1 0x080487c8 <+68>: mov edx,eax 0x080487ca <+70>: mov eax,DWORD PTR [ebp+0xc] 0x080487cd <+73>: add eax,0x4 0x080487d0 <+76>: mov eax,DWORD PTR [eax] 0x080487d2 <+78>: mov DWORD PTR [esp+0x4],edx 0x080487d6 <+82>: mov DWORD PTR [esp],eax => 0x080487d9 <+85>: call 0x804869a <base64> 0x080487de <+90>: mov DWORD PTR [esp+0x2c],eax 0x080487e2 <+94>: mov eax,DWORD PTR [esp+0x2c] 0x080487e6 <+98>: mov edx,0x8048909 0x080487eb <+103>: mov ecx,0x15 0x080487f0 <+108>: mov esi,edx 0x080487f2 <+110>: mov edi,eax 0x080487f4 <+112>: repz cmps BYTE PTR ds:[esi],BYTE PTR es:[edi] 0x080487f6 <+114>: seta dl 0x080487f9 <+117>: setb al 0x080487fc <+120>: mov ecx,edx 0x080487fe <+122>: sub cl,al 0x08048800 <+124>: mov eax,ecx 0x08048802 <+126>: movsx eax,al 0x08048805 <+129>: test eax,eax 0x08048807 <+131>: jne 0x8048817 <main+147> 0x08048809 <+133>: mov DWORD PTR [esp],0x804891e 0x08048810 <+140>: call 0x8048590 <puts@plt> 0x08048815 <+145>: jmp 0x8048823 <main+159> 0x08048817 <+147>: mov DWORD PTR [esp],0x8048921 0x0804881e <+154>: call 0x8048590 <puts@plt> 0x08048823 <+159>: mov eax,0x0 0x08048828 <+164>: lea esp,[ebp-0x8] 0x0804882b <+167>: pop esi 0x0804882c <+168>: pop edi 0x0804882d <+169>: pop ebp 0x0804882e <+170>: ret End of assembler dump.
Notre password en entrée est converti en base 64. Ensuite il est comparé à un
autre hash 0x080487e6.
On break sur cet offset pour récupérer le hash du flag de validation et on le
décode avec Python.
>>> import base64 >>> base64.b64decode('RlFTRHFzZGYyMzE1R3NT') 'FQSDqsdf2315GsS'
On essaie le password.
hackgyver$ ./epreuve12 FQSDqsdf2315GsS
OK
Challenge 13
Pas de strings, pas de strcmp mais une fonction decode.
On regarde ce qu'elle contient :
gdb-peda$ dis decode Dump of assembler code for function decode: => 0x0804845a <+0>: push ebp 0x0804845b <+1>: mov ebp,esp 0x0804845d <+3>: mov eax,DWORD PTR [ebp+0x8] 0x08048460 <+6>: movzx eax,BYTE PTR [eax] 0x08048463 <+9>: mov edx,eax 0x08048465 <+11>: xor edx,0x41 0x08048468 <+14>: mov eax,DWORD PTR [ebp+0x8] 0x0804846b <+17>: mov BYTE PTR [eax],dl 0x0804846d <+19>: mov eax,DWORD PTR [ebp+0x8] 0x08048470 <+22>: lea edx,[eax+0x1] 0x08048473 <+25>: mov eax,DWORD PTR [ebp+0x8] 0x08048476 <+28>: add eax,0x1 0x08048479 <+31>: movzx eax,BYTE PTR [eax] 0x0804847c <+34>: xor eax,0x42 0x0804847f <+37>: mov BYTE PTR [edx],al 0x08048481 <+39>: mov eax,DWORD PTR [ebp+0x8] 0x08048484 <+42>: lea edx,[eax+0x2] 0x08048487 <+45>: mov eax,DWORD PTR [ebp+0x8] 0x0804848a <+48>: add eax,0x2 0x0804848d <+51>: movzx eax,BYTE PTR [eax] 0x08048490 <+54>: xor eax,0x43 0x08048493 <+57>: mov BYTE PTR [edx],al 0x08048495 <+59>: mov eax,DWORD PTR [ebp+0x8] 0x08048498 <+62>: lea edx,[eax+0x3] 0x0804849b <+65>: mov eax,DWORD PTR [ebp+0x8] 0x0804849e <+68>: add eax,0x3 0x080484a1 <+71>: movzx eax,BYTE PTR [eax] 0x080484a4 <+74>: xor eax,0x44 0x080484a7 <+77>: mov BYTE PTR [edx],al 0x080484a9 <+79>: pop ebp 0x080484aa <+80>: ret End of assembler dump.
Donc les 4 premières lettres du password est XOR_ed avec _ABCD et le résultat
est comparé à CCBEA (dans le main).
On a donc écrit un script Python pour nous retrouver le password original et
qui donne :
#!/usr/bin/env python2.7 passwd = 'CCBEA' xor_tab = 'ABCD' def decrypt(password): decrypted = '' for i in range(len(xor_tab)): decrypted += chr(ord(xor_tab[i]) ^ ord(passwd[i])) decrypted += passwd[-1] return decrypted if __name__ == "__main__": print 'Encrypted password:', passwd plain = decrypt(passwd) print 'Decrypted password:', [ hex(ord(plain[i])) for i in range(len(plain)) ]
Le script nous retourne :
hackgyver$ ./decrypt.py Encrypted password: CCBEA Decrypted password: ['0x2', '0x1', '0x1', '0x1', '0x41']
On teste tout ça.
hackgyver$ ./epreuve13 $(python2.7 -c "print '\x02\x01\x01\x01\x41'") CCBEA OK
Petits mots de fin
Journée bien sympathique. Certes les challenges n'étaient pas très compliqués,
mais on s'est bien amusé.
Il faut dire que c'était la première fois, en tout cas pour moi, qu'on faisait
un CTF IRL. On peut dire que ça s'est bien passé :)
L'initiative de la Secu'RT est vraiment sympa et je pense qu'il faut que ça
perdure.
J'espère que les gens qui ont assisté aux CTF ont appris quelques tricks et
qu'ils reviendront l'année prochaine.
Sur ce, bonne fin de journée !