This article describes the NDH2010 wargame level3 solution. The interest stands in the search of a password generated by a substitution of the user characters.
solution
level3@srv-public:~$ python /tmp/lvl3.py
mot de passe
You entered: YOU>are\A^tRuE[ 33 z
Ciphered: 2:8vytm&*9|)].l(ol;a
We want: 2:8vytm&*9|)].l(ol;a
Good Job!
YOU>are\A^tRuE[ 33 z
[89, 79, 85, 62, 97, 114, 101, 92, 65, 94, 116, 82, 117, 69, 91, 17, 51, 51, 23, 122]
howto
first list the current directory.
level3@srv-public:~$ ls -all
total 32
dr-xr-x--- 2 level3 level3 4096 24 juin 13:24 .
drwxr-x--x 24 root root 4096 18 juin 18:19 ..
lrwxrwxrwx 1 root root 9 28 mai 16:09 .bash_history -> /dev/null
-rw-r--r-- 1 root root 220 12 mai 2008 .bash_logout
-rw-r--r-- 1 root root 3116 12 mai 2008 .bashrc
---s--x--- 1 level4 level3 5966 16 juin 09:55 crackme
-r--r----- 1 level3 level3 7 1 janv. 2008 passwd
-rw-r--r-- 1 root root 675 12 mai 2008 .profile
crackme can't be read, only executed. Try it:
level3@srv-public:~$ ./crackme 00000000000000000000
You entered: 00000000000000000000
Ciphered: YE]|(68JYW8K8[!'ni>+
We want: 2:8vytm&*9|)].l(ol;a
It's incorrect n00b!
Use a differential cryptanalysis on the plain characters:
You entered: 01111111111111111111
Ciphered: YD\{)79KZV9J9Z"(mj=,
You can observe that first character "Y" of the cipher is not modified. See if it is still true for next chars:
You entered: 00111111111111111111
Ciphered: YE\{)79KZV9J9Z"(mj=,
Last attempt with third char:
You entered: 00011111111111111111
Ciphered: YE]{)79KZV9J9Z"(mj=,
It looks like a Vigenere or Cesar encryption, ie a substitution of each character independently from the others.
See if Python can be used:
level3@srv-public:~$ python
Python 2.5.5 (r255:77872, Apr 21 2010, 08:44:16)
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
See if /tmp can be used:
level3@srv-public:~$ echo "print 'coucou'" > /tmp/essai
level3@srv-public:~$ python /tmp/essai
coucou
Here is a Python script to bruteforce each character using the output of the program as oracle. Test the script on a local program:
$ cat essai.sh
#!/bin/bash
echo "You entered: $1"
echo "Ciphered: $1"
echo "We want: 2:8vytm&*9|)].l(ol;a"
echo "It's incorrect n00b!"
Here is the script:
#!/bin/python
# solution level3 wargame NDH 2010 par t0ka7a
import string, os
clair = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
cipher = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
solution = [ord('2'),ord(':'),ord('8'),ord('v'),ord('y'),ord('t'),ord('m'),ord('&'),ord('*'),ord('9'),ord('|'),ord(')'),ord(']'),ord('.'),ord('l'),ord('('),ord('o'),ord('l'),ord(';'),ord('a')]
cipher_string = ''
# pour chaque caractere de la solution
for i in range(20):
# pour chaque entier de la table ASCII sauf 0
for j in range(1,256):
# exclure LF et '
if j==10: j+=1
if j==39: j+=1
clair[i] = j
# construction de l'entree de la commande
cmd = "./essai.sh '"
# pour chaque caractere du clair
for k in range(20):
cmd += chr(clair[k])
cmd += "'"
out = os.popen(cmd).readlines()
# pour reperer quand la sortie de la commande change
if out[0].split(' ')[0] == "You":
# cipher_string = 2eme mot de la 2eme ligne de la sortie de la commande
cipher_string = out[1].split(' ')[1]
# si le caractere cipher est un retour chariot, la longueur de la chaine sera plus petite
if len(cipher_string) == 21:
for k in range(20):
cipher[k] = ord(cipher_string[k])
if cipher[i] == solution [i]:
break
else:
for line in out:
print line
break
# affichage du clair pour faire joli
sortie = ''
for k in range(20):
sortie += chr(clair[k])
print sortie
Do not forget to replace essai.sh by crackme and copy the script in /tmp
$ vim /tmp/lvl3.py
i
SHIFT-INSERT
ESC
:wq
Aucun commentaire:
Enregistrer un commentaire