J'essaie de trouver un moyen efficace de faire le niveau 5 du défi bandit OverTheWire .
Quoi qu'il en soit, j'ai un tas de fichiers, et il n'y en a qu'un qui respecte les critères suivants:
En ce moment, j'utilise la commande find
, et je peux trouver les fichiers correspondant aux 2 derniers critères:
find . -size 1033c ! -executable
Cependant, je ne sais pas comment exclure les fichiers non lisibles par l'homme. Les solutions que j'ai trouvées pour ce défi utilisent le -readable
paramètre de test, mais je ne pense pas que cela fonctionne. -readable
ne regarde que les autorisations des fichiers, et non leur contenu, tandis que la description du défi demande un fichier ASCII ou quelque chose comme ça.
Oui, vous pouvez utiliser find
pour rechercher des fichiers non exécutables de la bonne taille, puis utiliser file
pour rechercher ASCII. Quelque chose comme:
find . -type f -size 1033c ! -executable -exec file {} + | grep ASCII
La question, cependant, n'est pas aussi simple qu'il y paraît. "Lisible par l'homme" est un terme horriblement vague. Vraisemblablement, vous voulez dire du texte. OK, mais quel genre de texte? Caractère latin ASCII uniquement? Unicode complet? Par exemple, considérez ces trois fichiers:
$ cat file1
abcde
$ cat file2
αβγδε
$ cat file3
abcde
αβγδε
$ cat file4
#!/bin/sh
echo foo
Ce sont tous des textes et lisibles par l'homme. Voyons maintenant ce que file
en fait:
$ file *
file1: ASCII text
file2: UTF-8 Unicode text
file3: UTF-8 Unicode text
file4: POSIX Shell script, ASCII text executable
Ainsi, la commande find
ci-dessus ne trouvera que file1
(pour cet exemple, imaginons que ces fichiers contiennent 1033 caractères). Vous pouvez développer le find
pour rechercher la chaîne text
:
find . -type f -size 1033c ! -executable -exec file {} + | grep -w text
Avec le -w
, grep
imprimera uniquement les lignes où text
se trouve en tant que mot autonome. Cela devrait être assez proche de ce que vous voulez, mais je ne peux pas garantir qu'il n'y a pas d'autre type de fichier dont la description pourrait également inclure la chaîne text
.
Tandis que -exec
est principalement utilisé pour faire quelque chose avec les fichiers qui, lorsqu'ils ont été trouvés, peuvent également servir de test. Par conséquent, nous pouvons l'ajouter à vos autres critères:
find . \
-size 1033c \
-not -executable \
-exec sh -c 'file {} | grep "text$"' \;
N'oubliez pas que grep
renvoie une valeur non nulle lorsque le modèle n'a pas été trouvé et sh -c "COMMAND"
renverra le résultat de l'évaluation (tant qu'il est valide). Donc, cela n'imprimera que les fichiers où file <filename>
crache quelque chose qui se termine par text
, par exemple "Texte Unicode UTF-8" ou "Texte ASCII", mais pas "Texte ASCII étendu non ISO, avec séquences d'échappement".
En une seule ligne, cela finit même plus court que de parcourir xargs
:
find . -size 1033c -not -executable -exec sh -c 'file {} | grep "text$"' \;
N'oubliez pas que vous pouvez remplacer sh -c 'file {} | grep "text$"'
avec n'importe quelle commande personnalisée. Si vous souhaitez rechercher quelque chose de très complexe, il peut être préférable de fournir un script Shell et de l'utiliser à la place:
find . -size 1033c -not -executable -exec is_human_readable.sh {} \;
qui, à long terme, est plus facile à entretenir que l'historique de votre Shell:
#!/bin/sh
file "$@" | grep "text$" > /dev/null
find . -size 1033c ! -executable -exec file {} +
Il vous suffit d'utiliser:
find inhere -size 1033c
Il vous donnera le seul fichier contenant le mot de passe.
Exécutez simplement ce qui suit contre le contenu du répertoire:
$ file -- *
-file00: data
-file01: data
-file02: data
-file03: data
-file04: data
-file05: data
-file06: data
-file07: ASCII text
-file08: data
-file09: data
$ cat -- \-file07
<output>
bandit4@bandit:~$ ls
inhere
bandit4@bandit:~$ file inhere/*
inhere/-file00: data
inhere/-file01: data
inhere/-file02: data
inhere/-file03: data
inhere/-file04: data
inhere/-file05: data
inhere/-file06: data
inhere/-file07: ASCII text
inhere/-file08: data
inhere/-file09: data
bandit4@bandit:~$ pwd
/home/bandit4
bandit4@bandit:~$ cat /home/bandit4/inhere/-file07
koReBOKuIDDepwhWk7jZC0RTdopnAYKh
bandit4@bandit:~$
Vous pouvez essayer ceci
find . -size 1033c ! -executable -exec file {} +
Votre défi ne permet pas grep
. Le fichier de mot de passe sera signalé comme "Texte ASCII, avec de très longues lignes"
find . -size 1033c ! -executable|xargs file|grep "ASCII text" |awk -F: '{print $1}'
Veuillez essayer ces commandes combinées. cela fonctionne sur ma station.
find . -type f -size 1033c ! -executable | xargs file | grep text
Fan d'une doublure
Je pense que la manière la plus longue de trouver le mot de passe pour ce niveau de bandit mentionné par la plupart ci-dessus en utilisant find et grep est la commande la plus descriptive.
find . -type f -size 1033c ! -executable -exec file {} + | grep ASCII
Mais, après avoir utilisé la commande 'file' plus, j'ai réalisé qu'il était assez facile de localiser les fichiers lisibles par l'homme (aka ASCII à ce niveau) de cette façon en vérifiant les types de fichiers d'un répertoire entier. Le répertoire inhere contient des fichiers avec le nom '-filexx' ou vérifiez rapidement l'ensemble du répertoire inhere avec file ./*
Voici mon approche.
bandit4@bandit:~/inhere$ file ./*
./-file00: data
./-file01: data
./-file02: data
./-file03: data
./-file04: data
./-file05: data
./-file06: data
./-file07: ASCII text
./-file08: data
./-file09: data
bandit4@bandit:~/inhere$ cat ./-file07
koReBOKuIDDepwhWk7jZC0RTdopnAYKh
find -type f ! -executable -size 1033c
vous obtiendrez le fichier de l'exercice
Pour filtrer les noms de fichiers lisibles par l'homme, vous pouvez utiliser le [:print:]
( imprimable ) classe de caractères nom. Vous trouverez plus d'informations sur ces classes dans le manuel de grep
.
find . -type f -size 1033c -name "[[:print:]]*" ! -executable
Dans un second temps, l'exigence "lisible par l'homme" pourrait faire référence au contenu du fichier, au lieu de son nom. En d'autres termes, vous recherchez des fichiers texte . C'est un peu plus délicat. Comme l'a suggéré @D_Bye dans un commentaire, vous devez ensuite utiliser la commande file
pour déterminer le type de contenu du fichier. Mais ce ne serait pas une bonne idée d'exécuter file
après un pipe, car cela compliquerait la tâche d'afficher le nom du fichier. Voici ce que je suggère:
find . -type f -size 1033c ! -executable -exec sh -c 'file -b $0 | grep -q text' {} \; -print
Voici brièvement comment fonctionne la partie file
-:
-exec
exécute sh -c 'file -b $0 | grep -q text' FILENAME
Pour chaque FILENAME
qui satisfait toutes les conditions précédentes (type, taille, non exécutable).sh
) exécute ce court script: file -b $0 | grep -q text
, En remplaçant $0
Par le nom du fichier.file
détermine le type de contenu de chaque fichier et génère ces informations. L'option -b
Empêche d'imprimer le nom de chaque fichier testé.grep
filtre la sortie provenant du programme file
, recherchant les lignes contenant "texte" . (Voyez par vous-même à quoi ressemble une sortie typique de la commande file
.)grep
ne produit pas le texte filtré, car il a l'option -q
(silencieux) donnée. Ce qu'il fait, c'est simplement changer son état de sortie en 0
(Qui représente "vrai" - le texte filtré a été trouvé) ou 1 (signifiant "erreur" - le texte "texte" n'apparaissait pas dans la sortie de file
).grep
est transmis plus loin par sh
à find
et agit comme le résultat final de l'ensemble du test "-exec sh -c 'file $0 | grep -q text' {} \;
".-print
Est exécutée (c'est-à-dire que le nom du fichier testé est imprimé).