Automatiquement 'force brute' quelques octets pour récupérer un fichier corrompu

35

Est-ce que quelqu'un connaît un moyen de forcer les valeurs de force à un décalage particulier dans un fichier? C'est 4 octets consécutifs qu'il faudrait forcer brutalement. Je connais le bon SHA-1 du fichier corrompu. Donc, ce que je voudrais faire, c'est comparer le fichier complet SHA-1, chaque fois qu'il change la valeur d'octet.

Je connais les 4 octets exacts qui ont été modifiés, car le fichier m'a été transmis par un expert en récupération de données, à titre de défi de récupération. Pour ceux que cela intéresse, le fichier rar contient 4 octets qui ont été intentionnellement modifiés. On m'a dit les décalages des 4 octets modifiés et du SHA-1 d'origine. La personne a déclaré qu'il était IMPOSSIBLE de récupérer le fichier exact dans l'archive une fois les 4 octets modifiés. Même s'il ne s'agissait que de quelques octets et que vous saviez exactement où se trouvait la corruption. Puisqu'il n'a pas d'enregistrement de récupération. J'essaie de voir s'il est possible de remplir correctement ces 4 octets afin que le fichier soit décompressé sans erreur. La taille du fichier est d'environ 5Mo.

Exemple :

J'ai mis des photos en ligne afin de définir plus clairement ce que je cherche à faire. Je crois que quelqu'un peut les poster ici pour moi avec plus de représentant.

Capture d'écran un

Capture d'écran deux

L'exemple de décalage sur 0x78lequel je me concentre est celui où la première image montre la valeur, car CA je souhaite que le script prenne la valeur de 1, de sorte qu'elle devienne CBcelle illustrée dans la deuxième image. Je veux qu'il continue à augmenter la valeur 1et ensuite à comparer le fichier entier SHA-1 à chaque fois. N'apporter que des modifications à ces 4 octets à l'offset spécifié.

Il va essayer de CAC5C58Acomparer le SHA-1. Si cela ne correspond pas, il essaiera CBC5C58A. Ensuite, une fois que la première valeur aura été atteinte, FFelle ira à 00C6C58Aet ainsi de suite. En gros, j'aimerais qu'il soit possible de 00000000-FFFFFFFFcommencer mais qu'il soit également possible de choisir où vous voulez commencer et finir. Je sais que cela pourrait prendre du temps, mais j'aimerais quand même l'essayer. N'oubliez pas que je connais le décalage exact des octets corrompus. J'ai juste besoin des bonnes valeurs.

Si vous recherchez sur Google: "Comment réparer un fichier corrompu par la force brutale" Il y a une personne qui a écrit un programme Linux. Cependant, cela ne fonctionne que sur les fichiers inclus avec le programme. Je cherche un moyen d'utiliser le même processus avec mon dossier.

Sbt19
la source
3
Bienvenue sur Super User! J'ai modifié votre question pour supprimer la demande de programme, qui serait hors sujet. Pouvez-vous modifier votre question pour inclure (certains des) exemples que vous avez vus? C'est bien que vous ayez fait des recherches, mais nous ayons montré exactement quelles recherches seraient utiles :)
bertieb
20
Puis-je vous demander comment vous vous êtes retrouvé avec ce fichier et comment vous pouvez être sûr que ce sont les 4 seuls octets corrompus?
Edoardo
1
Connaissez-vous le format de fichier? Si vous le faites, vous pourrez peut-être déterminer les valeurs correctes ou limiter les plages plutôt que d'essayer de les forcer brutalement. En général, cependant, je suggérerais que tout fichier corrompu soit vidé pour des raisons de sécurité.
StephenG
11
@eddyce Je suis vraiment intéressé par la deuxième partie de votre question - Pourquoi ces 4 octets?
Craig Otis
2
Par curiosité, comment le fichier a-t-il été corrompu? Et comment savez-vous qu'il s'agissait de ces quatre octets?
JohnEye

Réponses:

27

Voici un petit programme Python qui fait ce que vous semblez décrire.

#!/usr/bin/env python3
from hashlib import sha1

with open('binaryfile', 'rb') as bin:
    binary = bin.read()

base = 0x0078
# ... is not valid Python; add more sequences, or take it out (or see below)
for seq in [[0xCA, 0xC5, 0xC5, 0x8A], [0xCB, 0xC5, 0xC5, 0x8A], ...]:
    copy = binary[0:base]
    copy += bytes(seq)
    copy += binary[base+len(seq):]
    if sha1(copy).hexdigest() == '9968733ce3ff0893bbb0a19e75faaf2fb0000e19':
        print('success with bytes {0}'.format(seq))
        break
else:
    print('no success')

ONUSeulement brièvement testé; S'il vous plaît me cingler si vous trouvez des fautes de frappe.

La basespécifie où essayer d'appliquer les quatre octets, et la longue chaîne '996873... est la représentation hexadécimale de la SHA1 attendue. La ligne for seq in... définit les octets à essayer; et bien sûr, remplacez 'binaryfile'par le chemin du fichier que vous voulez tenter de récupérer.

Vous pouvez remplacer la liste littérale [[0xCA, 0xC5,... ]]par quelque chose à boucler sur toutes les valeurs possibles, mais il s'agit simplement d'un espace réservé pour quelque chose de plus utile, car je ne suis pas vraiment sûr de ce que vous voulez exactement.

Quelque chose comme for seq in itertools.product(range(256), repeat=4)):va boucler sur toutes les valeurs possibles de 0 à 2 32 -1. (Vous devrez alors ajouter import itertoolsprès du sommet.) Ou peut-être pourriez-vous simplement ajouter un décalage; mettre à jour le script pour remplacer l'actuel for seq inpar le suivant (où il importfaut encore aller avant le programme principal);

import struct

for n in range(2**32):
    val=(n+0x8AC5C5CA) % 2**32  # notice reverse order
    seq=list(reversed(struct.pack(">I", val)))
    copy = ...

Je renversé l'ordre des octets afin que naturellement par incréments de 0x8AC5C5CA à 0x8AC5C5CB mais l'incrément suivant seront 0x8AC5C5CC etc. La structmagie est de convertir en une séquence d'octets (dû le chercher dans https: // stackoverflow. com / a / 26920983/874188 ). Cela commencera à 0x8AC5C5CA et ira à 0xFFFFFFFF, puis enroulera autour de 0x00000000 et remontera à 0x8AC5C5C9.

Si vous souhaitez examiner plusieurs catégories de candidats dans un ordre particulier, par exemple:

for rge in [(0x8AC5C5CA, 0x8AFFFFFF), (0x00C6C58A, 0x00FFFFFF),
        (0x00000000, 0x00C6C589), (0x01000000, 0x8AC5C5C9)]:
    for val in range(*rge):
        seq=list(reversed(struct.pack(">I", val)))
        copy = ...

mais ensuite, vous devrez vous assurer que les paires (début, fin)rge couvrent tout l'espace entre 0x00000000 et 0xFFFFFFFF si vous voulez vraiment tout examiner. (Et encore une fois, notez que la plage incrémente le dernier octet et que seqles octets de la valeur sont appliqués en sens inverse, conformément à vos exigences.)

Si vous souhaitez utiliser deux baseadresses différentes , vous vous heurtez rapidement aux limites de ce que vous pouvez faire de votre vie avec la force brute; mais vous pouvez, par exemple, scinder le nombre de 4 octets en deux parties de 2 octets et les appliquer à différents décalages.

base1 = 0x1234
base2 = 0x2345

for seq in range(whatever):
    copy = binary[0:base1]
    copy += bytes(seq[0:1])
    copy += binary[base1+2:base1+base2]
    copy += bytes(seq[2:3])
    copy += binary[base2+2:]
triple
la source
Les commentaires ne sont pas pour une discussion prolongée; cette conversation a été déplacée pour discuter .
Compagnon Geek
4

Non, non, encore et encore NON!

Rarement la réponse que vous obtenez n'est pas ce que vous attendez.

Quelques questions pour vous:

  • Est-il possible qu'un expert ignore qu'il est possible de forcer brutalement une chaîne d'octets et d'essayer de manière itérative le SHA-1 jusqu'à ce qu'il converge? Non
  • Est-il possible qu'il l'oublie? Non
  • Est-il possible que vous ne puissiez pas le faire sur un fichier rar? Non
  • Est-ce que l'autre réponse est fausse? absolument NON

Et alors? ... Temps.

Le fait est que vous devez changer si peu d'octets ... seulement 4!

Qu'est-ce que ça veut dire? 256 4 c'est-à-dire 256x256x256x256 possibilités, un très grand nombre.
Si votre ordinateur était capable de traiter 1 opération par seconde (substitution dans le fichier + sha1) ...
vous devriez attendre plus de 136 ans , ou si vous préférez plus de 49 710 jours.

Vous avez assez de chance, un fichier pré-mis en cache de 5 Mo (déjà chargé dans la mémoire RAM et dans le cache) ne demande qu'environ 0,03 seconde (min 0,025 s) sur un ancien ordinateur. Cela réduit votre temps d'attente à 1242-1492 jours (quelque chose de plus de 3 ans).

Il est vrai, BTW, que statistiquement, vous devriez avoir une réponse positive dans la moitié des cas . Néanmoins, vous devriez attendre jusqu'à ce que vous ayez essayé toutes les possibilités pour être sûr qu'il n'y a qu'une seule substitution qui vous donnera la même somme de contrôle SHA-1 ...

Maintenant que IMPOSSIBLE sonne comme "impossible dans un laps de temps WORTHWHILE ".


La façon de procéder

Une réponse plus appropriée à votre question technique: lorsque vous parlez de force brute, il n’est pas nécessaire que la force aveugle soit nécessaire.

  • Dans une autre réponse, il est simplement indiqué dans un commentaire que vous n'avez pas besoin de calculer la somme de contrôle sha1 de la partie avant la corruption. Vous faites la première fois et vous gagnez du temps pour chaque itération successive (peut-être un facteur 2, cela dépend de la position).

  • Quelque chose qui puisse changer l’effort inutile est d’écrire un code parallèle qui s’exécutera sur le GPU. Si vous avez une bonne carte graphique, vous pouvez avoir environ 1000 cœurs capables de calculer pour vous en parallèle (encore plus mais ils ont une fréquence inférieure au cpu, mais ils sont quand même beaucoup). Si vous êtes en mesure de réduire le temps passé de 1400 à 1,4 jours, vous pourrez peut-être même le faire.

  • Une approche différente peut vous conduire à une solution plus rapide.
    Vous avez dit que c'est un fichier rar. La structure de fichier rar est divisée en blocs. Si vous en tenez compte, vous pouvez voir où se situe la corruption. S'il s'agit de la partie des données, des en-têtes ou des deux. Ensuite, vous pouvez agir en conséquence. Par souci de simplicité, supposons que ce soit sur les données:
    vous pouvez utiliser la force brute de votre offset, vérifiez pour chaque CRC positif de ce bloc s'il est même positif que SHA1 sur l'ensemble du fichier. Encore une fois, vous pouvez créer un code parallèle.

Note finale

S'ils étaient 6 octets au lieu de 4, vous étiez hors du jeu avec la technologie actuelle.

Hastur
la source
Excellente réponse - il ne faudrait pas nécessairement épuiser tout l'espace, car le rar lui-même dans cet exemple ne se décompresserait pas à cause de contrôles internes, même si le sha1 fonctionnait avec un hachage en double. Frapper 4 octets qui ont résolu le problème à tort ET un problème interne serait très très improbable.
Rrauenza
@rrauenza Merci. BTW non seulement (le double contrôle). En effet, le bloc devrait être plus court que la totalité des octets corrompus jusqu'à la fin du fichier, et le CRC devrait être plus léger pour calculer ensuite l'algorithme sha1 ...
Hastur
@ rrauenza Savez-vous comment je m'y prendrais pour obtenir le code parallèle réel sur le GPU? J'ai un bon GPU. Merci.
Sbt19
Non, je ne. Vous pouvez utiliser plusieurs processeurs en partitionnant l’espace de recherche.
Rrauenza
@ Sbt19 Peu importe ce qu'ils vous ont dit, Google n'est pas si effrayant à utiliser ;-). Recherchez (si nvidia) Cuda, brute force, sha1et vous aurez beaucoup d’allusions, par exemple le code source . BTW garder votre haute attention , car la navigation de ce chemin de google, oh mon garçon, peut vous conduire sur l' un des côtés sombres du filet ... :-). (Pas sur github ... dans un autre site que vous pouvez rencontrer avec ce genre de recherches). PS> Il existe de nombreux articles scientifiques sur des sujets connexes, par exemple celui-ci ...
Hastur