TD9 corrections and rewords
This commit is contained in:
parent
60aecd0591
commit
d4fb4c586a
1 changed files with 76 additions and 55 deletions
|
@ -11,7 +11,7 @@ author:
|
|||
|
||||
### Première exécution du programme
|
||||
|
||||
Le programme demande à l'utilisateur une saisir, lorsque je rentre un texte, il
|
||||
Le programme demande à l'utilisateur une saisie, lorsque je rentre un texte, il
|
||||
répond `Nope`:
|
||||
|
||||
```
|
||||
|
@ -41,7 +41,7 @@ retour.
|
|||
|
||||
### avec strings
|
||||
|
||||
L'exécution de `strings hackme` montre des choses interessantes. On y voit des
|
||||
L'exécution de `strings hackme` montre des choses intéressantes. On y voit des
|
||||
traces des fonctions `wprintf` (qui pourrait être utile pour la suite),
|
||||
`strlen`. `getline`. On voit aussi tout un tas d'autres chaines qui semble être
|
||||
des mots de passe:
|
||||
|
@ -65,8 +65,8 @@ GCC: (Debian 8.3.0-6) 8.3.0
|
|||
[...]
|
||||
```
|
||||
|
||||
`IAmSuperSecure` parait relativement intéressant. mais à ce state rien n'est
|
||||
sûr. Mais juste comme ça essayons tout de même un `lstrace` sur nore programme:
|
||||
`IAmSuperSecure` parait relativement intéressant. Mais à ce stade rien n'est
|
||||
sûr. Mais juste comme ça essayons tout de même un `lstrace` sur notre programme:
|
||||
|
||||
```
|
||||
ltrace ./hackme
|
||||
|
@ -84,7 +84,7 @@ exit(1 <no return ...>
|
|||
|
||||
La sortie de `ltrace` une fois la saisie effectuée, montre qu'elle est comparée
|
||||
avec `IAmSuperSecure`, un essai le confirme. Comme dirait Bernard dans <u>Day of
|
||||
the Tentacle</u>: *This is all too easy!* :
|
||||
the Tentacle</u>: *"This is all too easy!"* :
|
||||
|
||||
```
|
||||
./hackme
|
||||
|
@ -136,7 +136,7 @@ $2 = 0x804d030 <p> "HelloDad"
|
|||
```
|
||||
|
||||
Nous avons notre mot de passe `HelloDad`. Mais cette chaine ne figure pas dans
|
||||
la liste des chaines données par la commande `strings`, elle est donc obsurcie.
|
||||
la liste des chaines données par la commande `strings`, elle est donc obscurcie.
|
||||
Essayons donc de comprendre comment. Recommençons l'exécution avec un `watch`
|
||||
la chaine contenue sur le programme:
|
||||
|
||||
|
@ -184,12 +184,12 @@ Dump of assembler code for function z:
|
|||
|
||||
En observant le contenu de cette fonction, on comprend alors que le
|
||||
déchiffrement du mot de passe du niveau 2 se fait en retirant `0x9` à chaque
|
||||
caractère de la chaine contenue dans le programme. On retrouv
|
||||
caractère de la chaine contenue dans le programme.
|
||||
|
||||
## Level 2
|
||||
|
||||
C'est reparti pour un tour! Nouvelle exécution du programme en plaçant un point
|
||||
d'arrêt sur `srtcmp@plt` et on arrive jusqu'au niveau 2:
|
||||
C'est reparti pour un tour! Nouvelle exécution du programme avec *gdb* en
|
||||
plaçant un point d'arrêt sur `srtcmp@plt` et on arrive jusqu'au niveau 2:
|
||||
|
||||
```
|
||||
On to level 2! So what do you want?
|
||||
|
@ -202,15 +202,15 @@ Breakpoint 1, 0x08049030 in strcmp@plt ()
|
|||
#2 0x080490cd in main ()
|
||||
```
|
||||
|
||||
Cette fois-ci c'est la fonction `r2()` qui s'occupe du "déchiffrement, voici son
|
||||
code désassemblé :
|
||||
Cette fois-ci c'est la fonction `r2()` qui s'occupe du "déchiffrement", voici
|
||||
son code désassemblé :
|
||||
|
||||
```
|
||||
(gdb) frame 1
|
||||
#1 0x080493ca in r2 ()
|
||||
(gdb) disass
|
||||
Dump of assembler code for function r2:
|
||||
0x080493a0 <+0>: push %ebx
|
||||
0x080493a0 <+0> push %ebx
|
||||
0x080493a1 <+1>: sub $0x14,%esp
|
||||
0x080493a4 <+4>: push $0x804a280
|
||||
0x080493a9 <+9>: call 0x8049060 <wprintf@plt>
|
||||
|
@ -251,7 +251,7 @@ Code de `x1()` qui "chiffre" la saisie utilisateur du troisième mot de passe.
|
|||
C'est le chiffrement inverse de celui vu au niveau 1, ici on ajoute `0x9` à
|
||||
chaque caractère.
|
||||
|
||||
Pour déchiffrer le mote de passe écrit dans le programme, j'ai écris un script
|
||||
Pour déchiffrer le mot de passe écrit dans le programme, j'ai écris un script
|
||||
Python :
|
||||
|
||||
```python
|
||||
|
@ -267,7 +267,7 @@ ce qui nous donne `IWantTea`
|
|||
### Level 3
|
||||
|
||||
Après avoir lancé le programme et atteint la saisie du niveau 3, `Ctrl+c` envoi
|
||||
le signal `SIGINT` au programme, donne la main à l'invite de commande. voici le
|
||||
le signal `SIGINT` au programme, donne la main à l'invite de commande. Voici le
|
||||
résultat de la commande `bt`:
|
||||
|
||||
```
|
||||
|
@ -277,10 +277,9 @@ résultat de la commande `bt`:
|
|||
#7 0x080490d2 in main ()
|
||||
```
|
||||
|
||||
`r()` se se charge de la saisie, mais que fait `wut()`, interessons nous
|
||||
`r()` se se charge de la saisie, mais que fait `wut()`? Intéressons nous
|
||||
à cette fonction d'abord passant dans sa frame puis en la désassemblant:
|
||||
|
||||
|
||||
```
|
||||
(gdb) frame 6
|
||||
#6 0x08049403 in wut ()
|
||||
|
@ -310,7 +309,7 @@ End of assembler dump.
|
|||
```
|
||||
|
||||
Voici deux comparaisons intéressantes. La première s'effectue sur les 4 octets à
|
||||
l'adresse contenur dans `%eax`. La suivante sur le contenu à l'adresse de
|
||||
l'adresse contenue dans `%eax`. La suivante sur le contenu à l'adresse de
|
||||
`%eax + 0x4`.
|
||||
|
||||
Un script Python permet encore une fois de transformer ces deux valeurs en
|
||||
|
@ -339,15 +338,15 @@ print('Level 3 text: {}'.format(finaltext))
|
|||
```
|
||||
|
||||
La seconde série de boucles de ce script sert à remettre les octets dans le bon
|
||||
ordre. En effet les données sont mises sur la pile et chaque élément de 4 octets
|
||||
doit être inversé.
|
||||
ordre. En effet les données sont mises sur la pile donc chaque élément de 4
|
||||
octets doit être inversé.
|
||||
|
||||
Le mot de passe est `EureKa!`
|
||||
|
||||
## Level 4
|
||||
|
||||
comme pour le niveau 3, il faut utiliser la technique du `ctrl+c` pour utiliser
|
||||
`bt`:
|
||||
Comme pour le niveau 3, il faut exécuter notre programme dans gdb, utiliser la
|
||||
technique du `ctrl+c` puis `bt`:
|
||||
|
||||
```
|
||||
...
|
||||
|
@ -356,11 +355,12 @@ comme pour le niveau 3, il faut utiliser la technique du `ctrl+c` pour utiliser
|
|||
#7 0x080490d7 in main ()
|
||||
```
|
||||
|
||||
|
||||
C'est la fonction `aa()` qui appelle `r()` (fonction de saicie), Interessons
|
||||
nous à elle en la désassamblant :
|
||||
C'est la fonction `aa()` qui appelle `r()` (fonction de saisie), intéressons
|
||||
nous à elle en la désassemblant :
|
||||
|
||||
```
|
||||
(gdb) frame 6
|
||||
[...]
|
||||
(gdb) disass
|
||||
Dump of assembler code for function aa:
|
||||
0x080494d0 <+0>: push %ebx
|
||||
|
@ -393,10 +393,9 @@ Dump of assembler code for function aa:
|
|||
End of assembler dump.
|
||||
```
|
||||
|
||||
Cette fonction appelle une autre foncion : `bb()`. C'est elle qui semble se
|
||||
charger de la vérification de la saisie.
|
||||
|
||||
Mais avant ça `aa()` met les élements en place:
|
||||
Cette fonction appelle une autre : `bb()`. C'est elle qui semble se charger de
|
||||
la vérification de la saisie. Avant de l'étudier, voyons comment `aa()` met les
|
||||
éléments en place avant de l'appeler :
|
||||
|
||||
* mets l'adresse vers la zone mémoire contenant la saisie utilisateur dans
|
||||
l'adresse contenue dans `%esp`
|
||||
|
@ -405,17 +404,18 @@ Mais avant ça `aa()` met les élements en place:
|
|||
`%ebx`
|
||||
* `%esp` est incrémenté de 16 (*0x10*).
|
||||
* Ensuite le résultat de `strlen()` est comparé à 4, en cas de non égalité, le
|
||||
procgramme branche sur `f()` qui met fin à l'exécution.. Nous pouvons donc en
|
||||
déduite que notre saisie doit être de 4 cacactères exactement.
|
||||
programme branche sur `f()` qui met fin à l'exécution.. Nous pouvons donc en
|
||||
déduite que notre saisie doit être de 4 caractères exactement.
|
||||
* La pile est ensuite décrémentée de 8
|
||||
* *0x804adf5* est ensuite positionné sur la pile, Il semble que se soit une
|
||||
adresse. le contenu de cette espace mémoire est *0x66737a65*.
|
||||
adresse. Le contenu de cette espace mémoire est *0x66737a65*.
|
||||
* `%ebx` est ensuite poussé sur la pile
|
||||
* `bb()` est appelée, c'est cette fonction qui se chage du 'déchiffrement'
|
||||
* `bb()` est appelée, c'est cette fonction qui se charge du 'déchiffrement'
|
||||
|
||||
### La fonction `bb()`
|
||||
|
||||
voic le code de cette fonction donné par `objdump` avec l'affichage des sauts :
|
||||
Voici le code de cette fonction donné par `objdump` avec l'affichage des sauts :
|
||||
|
||||
```
|
||||
8049470: 56 push %esi
|
||||
8049471: 53 push %ebx
|
||||
|
@ -451,13 +451,13 @@ voic le code de cette fonction donné par `objdump` avec l'affichage des sauts :
|
|||
|
||||
Voici un déroullé des instructions principales de cette fonction :
|
||||
|
||||
* `8049472` : on mets en place le contenu de l'adresse contenant notre série de
|
||||
4 octets mystères *0x66737a65* dans `%ebx`
|
||||
* `8049472` : on mets en place le contenu de l'adresse vers notre série de
|
||||
4 octets mystères (*0x66737a65*) dans `%ebx`
|
||||
* `8049476` : l'adresse vers notre saisie est positionnée dans `%esi`
|
||||
* `804947a` : l'octet de poids faible de `%ebx` est copié dans `%edx`
|
||||
* `804947d` : et logique de `%dl` sur lui même, si le test est vrai alors le
|
||||
programme branche sur la fin "normale" de la fonction. Ceci signifirait que
|
||||
notre chaine mystère est vide (donc pas de mot de passe).
|
||||
programme branche sur la fin "normale" de la fonction. Ceci signifiait que
|
||||
notre chaine mystère est vide (donc pas de mot de passe dans le programme).
|
||||
* `8049481` : l'octet de poids faible de notre saisie `%esi` est positionné
|
||||
dans `%eax`
|
||||
* `8049484` : un `xor` est ensuite réalisé entre *0x12* et `%eax`
|
||||
|
@ -465,11 +465,11 @@ Voici un déroullé des instructions principales de cette fonction :
|
|||
* `8049489` : en cas d'inégalité, la fonction se termine.
|
||||
* `804948b` : *0x1* est écrit dans `%eax`.
|
||||
* `8049490` : Branchement vers l'instruction `80494a6`
|
||||
* `80494a6` : l'octet de poid faible de `(%esi,%eax,1)` correspondant à la
|
||||
* `80494a6` : l'octet de poids faible de `(%esi,%eax,1)` correspondant à la
|
||||
lettre suivante de notre chaine mystère `ecx`
|
||||
* `80494aa` : si l'opération booleene de `%cl` sur lui même est différente de
|
||||
zéro alors le probramme branche sur `8049498`. Ce test permet de savoir si on
|
||||
est en fin de chaine (`\0`) sur notre chaine mystère. sinon le fil de code
|
||||
* `80494aa` : si l'opération booléenne de `%cl` sur lui même est différente de
|
||||
zéro alors le programme branche sur `8049498`. Ce test permet de savoir si on
|
||||
est en fin de chaine (`\0`) sur notre chaine mystère. Sinon le fil de code
|
||||
continue jusqu'à la fin de la fonction.
|
||||
* `8049498` : le programme prend le caractère suivant de notre saisir et le
|
||||
place dans `%edx`
|
||||
|
@ -480,9 +480,9 @@ Voici un déroullé des instructions principales de cette fonction :
|
|||
revenons à l'instruction `80494a6`.
|
||||
|
||||
En clair, notre chaine mystère est bien le **mot de passe "chiffré"**, un simple
|
||||
*xor* avec *0x12* sur cachun des caractères de ce dernier nous permettra de
|
||||
trouver le mot de passe à saisir. On utilise pour celà la propriété suivante du
|
||||
*"ou exclusif"*
|
||||
*xor* avec *0x12* sur chacun des caractères de ce dernier nous permettra de
|
||||
trouver le mot de passe à saisir. On utilise pour cela la propriété suivante du
|
||||
*"ou exclusif"* :
|
||||
|
||||
$$A \oplus B = C \implies C \oplus B = A$$
|
||||
|
||||
|
@ -516,7 +516,7 @@ Ce qui donne:
|
|||
Level 4 text: what
|
||||
```
|
||||
|
||||
Le mot de pase de ce niveau est donc `what`
|
||||
Le mot de passe de ce niveau est donc `what`
|
||||
|
||||
## Niveau 5
|
||||
|
||||
|
@ -581,10 +581,10 @@ niveau précédent, cette fonction:
|
|||
* Boucle sur les caractères contenus dans la chaine saisie par l'utilisateur et
|
||||
réalise un `xor` de celui-ci avec `%ecx`. Le résultat de cette opération est
|
||||
stockée dans `%ecx` (instructions `8049555` à `804956a`).
|
||||
* Cette boucle s'arrete lorsque le caractère fin de chaine (`\0`) est trouvé
|
||||
* Cette boucle s'arrête lorsque le caractère fin de chaine (`\0`) est trouvé
|
||||
(instruction `8049568`)
|
||||
* Compare `%ecx` à `0x43`, s'il y a égalité alors le programme continue, sinon
|
||||
la fonction `f()` est appelée, ammenant la mauvaise fin.
|
||||
la fonction `f()` est appelée, amenant vers la mauvaise fin.
|
||||
|
||||
Cat algorithme de chiffrement est vraiment faible, quelques ligne en Python
|
||||
permettent de générer des mots de passes valides:
|
||||
|
@ -613,3 +613,24 @@ manquant pour arriver à `0x43`:
|
|||
./level5.py Toto
|
||||
here is your password: Totoc
|
||||
```
|
||||
|
||||
Maintenant il est possible de passer le dernier niveau :
|
||||
|
||||
```
|
||||
.hackme
|
||||
[...]
|
||||
Level 5 is onboard! Will you make it?
|
||||
Totoc
|
||||
Yay!
|
||||
|
||||
************************************************
|
||||
* ____ _ _ *
|
||||
* / ___|___ _ __ __ _ _ __ __ _| |_ ___| | *
|
||||
* | | / _ \| '_ \ / _` | '__/ _` | __/ __| | *
|
||||
* | |__| (_) | | | | (_| | | | (_| | |_\__ \_| *
|
||||
* \____\___/|_| |_|\__, |_| \__,_|\__|___(_) *
|
||||
* |___/ *
|
||||
* *
|
||||
* You passed all the levels!! *
|
||||
************************************************
|
||||
```
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue