Identifier le type de processeur à partir du code binaire brut?

19

Pas vraiment lié aux puces, mais j'espère que j'obtiendrai des instructions à suivre à partir d'ici.

J'ai obtenu un morceau de code, mais je ne sais pas à quel processeur il est destiné. Y a-t-il des outils disponibles qui peuvent m'aider à identifier le type de code? Quelles méthodes statistiques peuvent aider? Distribution d'octets? Distribution de paires, etc.? Des chaînes de Markov peut-être?

mentaliste
la source
7
Pourriez-vous nous donner les 200 premiers octets en hexadécimal brut?
pingswept
C'est une question amusante. Quel type d'appareil piratez-vous?
DavidEGrayson
1
vous pouvez essayer de le nourrir avec deux démonteurs différents et voir ce qui se passe.
JustJeff
2
Je nommerai ce code en 100 octets! = P
JustJeff
Grande question. Cela pourrait cependant être mieux adapté à StackOverflow.
sharptooth

Réponses:

16

Essayez de l'exécuter via le fichier GNU. S'il a un en-tête standard, il le ramassera.

Par exemple.

jrt@lin:~/src$ file foo
foo: ELF 32-bit LSB executable, Atmel AVR 8-bit, version 1 (SYSV), statically linked, not stripped
Toby Jaffey
la source
J'ai essayé ça. Le fichier GNU indique qu'il s'agit de "données".
mentaliste
3
Pourriez-vous en publier une partie? Vous avez essayé de chercher ASCII avec des "chaînes"?
Toby Jaffey
9

C'est une question très intéressante. Il existe des millions d'instructions, mais seulement quelques-unes très couramment utilisées.

La première chose que je regarderais est l'origine et l'utilisation prévue. Si vous pensez qu'il a été conçu aux États-Unis, vous viserez principalement les processeurs avec des fiches techniques disponibles en anglais, par exemple. S'il a été conçu en Asie, il existe un certain nombre de processeurs qu'ils utilisent pour les appareils fabriqués en série que les ingénieurs américains voient rarement. Même l'Europe a quelques processeurs plus courants que d'autres.

J'examinerais ensuite la taille et la fonctionnalité du code (en supposant que vous savez ce que fait le code dans une certaine mesure). S'il s'agit de quelques mégaoctets de code, vous pouvez à peu près réduire la plupart des processeurs 8 bits intégrés et commencer à regarder des appareils plus grands avec une mémoire externe. S'il s'agit de quelques kilo-octets ou moins, vous voudrez plutôt vous concentrer sur des appareils plus petits et moins chers. Si la fonctionnalité est simple, il peut même s'agir d'un code pour un processeur quatre bits.

À ce stade, il vaut la peine d'examiner la structure de la mémoire. Il y aura probablement une section de programme et une section de données au minimum. S'il s'agit d'un fichier binaire (par rapport à un enregistrement hexadécimal d'Intel ou de Motorola), vous avez peu d'informations sur l'emplacement en mémoire de certains blocs de données. Un éditeur hexadécimal peut afficher certains modèles. Si elle vient dans un format d'enregistrement hexadécimal ou s, vous pourriez avoir plus d'informations sur la structure de la mémoire du processeur auquel elle est destinée. Certains processeurs sont réinitialisés à l'emplacement de mémoire de programme 0, certains à l'emplacement de mémoire le plus élevé. Le programme peut inclure des valeurs initiales EEPROM dans un emplacement mémoire séparé. S'il est destiné à un processeur sécurisé (tel qu'utilisé dans le secteur bancaire), il peut même avoir des clés de sécurité pour un emplacement de mémoire impair.

Selon la langue dans laquelle il a été programmé, vous pourriez avoir des indices supplémentaires. S'il a été programmé en C ou dans un langage procédural similaire, les fonctions commenceront presque toujours par une séquence d'instructions pour enregistrer certains registres dans la pile (beaucoup de push) puis juste avant de retourner beaucoup de pops pour retourner les valeurs d'origine de la pile . Si vous pouvez faire une reconnaissance de modèle, vous trouverez un grand nombre de ces séquences tout au long et vous pourrez peut-être déterminer quelles instructions sont les instructions push / pop les plus susceptibles, retourner, etc., ce qui pourrait affiner un peu vos choix.

S'il s'agit d'un appareil intégré avec des interruptions, il peut avoir une table de vecteurs d'interruption, qui ressemblera à un tas de sauts vers différents emplacements de mémoire dans un grand bloc, probablement à un emplacement pratique (adresse de 0x ??? 0 par exemple) . Les tables de sauts sont également utilisées ailleurs pour d'autres choses, mais si vous pouvez localiser une séquence d'instructions qui semblent identiques à l'exception de l'adresse à laquelle vous souhaitez sauter, vous pourrez peut-être déduire à quoi ressemble une instruction de saut, et encore une fois restreindre vos choix vers le bas.

À ce stade, je commencerais par les architectures de processeur les plus courantes et verrais si quelque chose est en corrélation. x86, arm, mips, 8051, avr, pic, powerpc, Z80, 68k, 6502, etc, etc, etc. Il existe des listes de processeurs et de jeux d'instructions courants - au moins dans le monde anglophone - qui pourraient s'avérer utiles.

Je ne connais aucun outil automatisé qui pourrait aider à cela, mais MAME émule un grand nombre d'architectures de processeur, et une méthode possible est d'exécuter le code via un certain nombre de processeurs et de regarder les registres pour voir si quelque chose clique selon ce que vous connaissez le design.

Adam Davis
la source
"Même l'Europe possède quelques processeurs plus courants que d'autres." Vivant en Europe, cela ne m'est jamais venu à l'esprit. Pouvez-vous donner des exemples?
stevenvh
@stevenvh En raison des sociétés Acorn et Sinclair, les systèmes embarqués basés sur 6502 et Z80 étaient très populaires. Et, bien sûr, le processeur ARM a commencé chez Acorn Computers.
Adam Davis
5

Idée: connaissez-vous l' âge du code source, c'est-à-dire vers quelle période / année il a été créé?

S'il était assez vieux, il pourrait vous donner une idée du processeur pour lequel il a été écrit. Vous pouvez prendre l'âge / l'année où il a été écrit et déterminer quel (s) processeur (s) étaient populaires à cette époque, et essayer de charger / exécuter le fichier hexadécimal sur ceux-ci.

À bien y penser, compte tenu de la prolifération massive des processeurs au cours des 20 dernières années, cela pourrait être une technique d'aiguille dans une botte de foin et peu fructueuse.

J. Polfer
la source
4

Il y a de nombreuses lunes, alors qu'il n'y avait pas autant de cœurs de processeurs différents, j'ai identifié le code Z80 à plusieurs reprises grâce à l'analyse de fréquence . Pour le Z80 CDest le code machine pour call subroutineet C9est return from subroutine(je n'oublierai jamais), et ce sont souvent les codes les plus courants. Cela nécessite toutefois que vous connaissiez le jeu d'instructions au niveau du code machine. Avoir de l'expérience dans l'assemblage à la main aide (cela a beaucoup fait, et je peux toujours compter en arrière dans l'hex pour calculer les décalages).

Stevenvh
la source
3

Si le fichier est pour un PIC 12 bits ou 14 bits, chaque paire d'octets sera un mot 12 ou 14 bits, généralement stocké LSB en premier, avec les deux ou quatre bits les plus significatifs effacés.

supercat
la source
1

S'il était compilé à partir d'un langage comme C ou Pascal, il y aurait certaines séquences standard de binaire que vous pourriez rechercher. Avec C par exemple, presque toutes les fonctions commencent par quelque chose qui enregistre le pointeur de pile dans un pointeur "frame" ou "link". Pour un processeur donné, il n'y a généralement que deux façons de procéder. Vous pouvez donc répondre "est ce code pour le processeur X" en recherchant le binaire de X pour ces séquences.

Cela dit, j'ai eu de la chance à différencier les binaires 8088, 6502 et 68000 en utilisant uniquement des histogrammes. Tout processeur donné possède certains opcodes d'instructions légales, et ceux-ci ont tendance à être utilisés un peu plus souvent que la moyenne. Avec un morceau de binaire suffisamment grand, vous pouvez commencer à voir certaines tendances. Cela est rendu difficile, cependant, par le fait que tous les opérandes dans un morceau donné de binaire ont tendance à ne pas être en corrélation avec le type de processeur donné, et cela fait essentiellement du bruit dans vos données d'histogramme. De plus, même deux programmes différents pour le même processeur peuvent avoir des histogrammes sensiblement différents. Pourtant, cela peut vous donner un point de départ.

JustJeff
la source