Journal BinMake : pour construire un fichier binaire décrit en texte

Posté par . Licence CC by-sa
21
12
jan.
2017

BinMake est un logiciel libre permettant de créer des fichiers binaires en décrivant par du texte leur contenu.
Il peut également être inclus dans du code C++ et être utilisé comme un flux.

Le texte décrivant le binaire à générer permet d'indiquer des nombres de bases décimale, hexadécimale, octale et binaire, de fournir du texte brute (sur une ligne). Il permet également de modifier l'endianness.
(Il devrait prochainement proposer des nombres flottants et du texte multi-lignes)

Version programme exécutable

La version exécutable peut lire l'entrée depuis un fichier ou l'entrée standard et générer le binaire dans la sortie standard ou dans un fichier.

La syntaxe est assez simple dont voici un exemple :

# change l'endianness (par défaut little-endian)
big-endian

# créer un nombre (par défaut hexadécimal)
00112233

# créer un nombre dont le type est explicité (%b pour binaire)
%b0100110111100000

# les octets ne sont pas concernés par l'endianness
88 99 aa bb

# change le type de nombre par défaut
decimal

# créer un nombre décimal
0123

# une chaîne de caractères
"ceci n'est pas un texte"

L'exemple donnera le fichier suivant :

$ ./binmake exemple.txt | hexdump -C
00000000  00 11 22 33 4d e0 88 99  aa bb 7b 63 65 63 69 20  |.."3M.....{ceci |
00000010  6e 27 65 73 74 20 70 61  73 20 75 6e 20 74 65 78  |n'est pas un tex|
00000020  74 65                                             |te|
00000022

Version dans un code C++

Son utilisation dans un code C++ est très simple. Il peut être compilé en librairie.
Il s'utilise comme un flux et accepte les E/S standards les flux de fichiers, les chaînes de caractères…
Notez que l'entrée doit forcément être du texte.

Il faut alors inclure le header BinStream.h et instancier la classe BS::BinStream comme dans l'exemple suivant :

#include <iostream>
#include "BinStream.h"

using namespace std;
using namespace BS;

int main()
{
    BinStream bin;
    bin << "'hello world!'"
            << "00112233"
            << "big-endian"
            << "00112233";
    cout << bin;
    return 0;
}
  • # Encodage texte ?

    Posté par . Évalué à 10.

    Je ne vois aucune mention de l'encodage utilisé pour les chaines de caractères, alors que c'est un point crucial pour un outil qui génère du binaire. Il faut différencier l'encodage du fichier source (qui peut être imposé, par exemple UTF-8), et le résultat dans le binaire généré, qui devrait pouvoir être spécifié (sur le modèle de ce qui est fait pour l'endianness).

    • [^] # Re: Encodage texte ?

      Posté par . Évalué à 5.

      C'est juste ! Ceci n'est pas pris en compte et ça devrait l'être. Je compte le prendre en charge plus tard. En fait j'avais surtout besoin des nombres de différents types et de modifier l'endianness dans un même fichier.

    • [^] # Re: Encodage texte ?

      Posté par (page perso) . Évalué à 2.

      ne vois aucune mention de l'encodage utilisé pour les chaines de caractère

      128 caractères sont bien suffisant pour n'importe qui.

  • # et l'inverse ?

    Posté par . Évalué à 6.

    C'est chouette ça. Et est-ce qu'il est prévu de faire un programme qui peut également générer l'inverse, c'est à dire convertir un binaire dans ton format de texte ? Ce qui permettrait notamment de convertir un binaire, de l'analyser, le modifier, puis le reconvertir en binaire par exemple.

    • [^] # Re: et l'inverse ?

      Posté par . Évalué à 4.

      J'y pensais. Il faudrait que je définisse un format textuel décrivant la façon de déchiffrer le binaire.

      • [^] # Re: et l'inverse ?

        Posté par . Évalué à 2.

        À mon avis partir de la syntaxe de scanf est une bonne idée.

        bépo powered

    • [^] # Re: et l'inverse ?

      Posté par . Évalué à 2.

      D'ailleurs je m'étais fait un petit programme en C permettant de modifier des octets dans un binaire comme suit ./setbin.elf source_file dest_file offset value [offset2 value2 [...]]

    • [^] # Re: et l'inverse ?

      Posté par . Évalué à 4.

      L'inverse de cet outil pourrait-être Binwalk (http://binwalk.org/), qui analyse un fichier binaire, et essaye d'en retirer une structure en se basant sur des signatures.

      • [^] # Re: et l'inverse ?

        Posté par . Évalué à 2.

        Ça a l'air en effet très intéressant je note, merci.
        Mais ce n'est pas tout à fait l'inverse étant donné qu'il essaie de reconnaître un format connu.
        Alors qu'ici il s'agit plutôt de formats personnalisés. En tout cas c'est ce qui m'intéresse moi.

    • [^] # Re: et l'inverse ?

      Posté par . Évalué à 2.

      Hachoir, générique avec de nombreux formats reconnus et la possibilité d'en spécifier de nouveaux.

      binwalk, spécialisé dans les firmwares.

      Et dans une moindre mesure radare, spécialisé dans les exécutables.

  • # Re: Journal— BinMake : pour construire un fichier binaire décriten texte

    Posté par (page perso) . Évalué à 9.

    Pourquoi as tu ecrit ce soft ?

  • # Taille des entiers décimaux

    Posté par (page perso) . Évalué à 7.

    Dans ton exemple, tu rentre "0123" mais le résultat est sur un seul octet. Comment fait-on pour encoder 123 (décimal) sur 2 octets ou 4 octets?

    • [^] # Re: Taille des entiers décimaux

      Posté par . Évalué à 3.

      C'est justement une lacune que je dois corriger. Si le nombre est en hexa il prend en compte le nombre de caractères mais pas sur un décimal. Il détermine le nombre de bits en fonction de la valeur ce qui n'est pas bon du tout !
      Je pensais modifier le format en quelque chose du genre 0123[4] pour forcer le nombre d'octets quelque soit le type et la valeur.
      Si tu veux tu peux entrer un ticket (issue).

      • [^] # Re: Taille des entiers décimaux

        Posté par (page perso) . Évalué à 4.

        Je verrais plutôt quelque chose de similaire à ce que vous avez utilisé pour l' endianness.
        C'est à dire une directive pour indiquer la taille minimum de stockage d'une donnée ou/et quelque chose de plus générique comme 8/16/32/64.

        Cela donnerais quelque chose comme les std::setiosflags du C++ pour formater les flux.

        .big-endian
        .decimal,2bytes
        123
        456
        .decimal,4bytes
        5
        -98
        .text,utf8
        "coucou"
        .text,utf8,iso8859-1
        "@èà−Ç"
        

        On pourrait même faire les deux et gérer les crochets pour n'affecter que la donnée en cours, mais ça alourdirait la syntaxe sans apporter grand chose à mon avis.

        D'ailleurs, il faudrait préciser l' endianness affecte aussi les textes, dans les cas où l'encodage prend plus d'un caractère.

        Sinon, bravo, j'adore l'idée.

    • [^] # Re: Taille des entiers décimaux

      Posté par . Évalué à 2.

      Je viens de commiter une version qui permet de spécifier à un nombre (quelque soit son type) par des crochets une taille en octets (2, 4 ou 8). Si pas de crochets l'ancien mécanisme est appliqué.
      Par exemple le nombre décimal 0123[4] produira 4 octets alors que 0123 produira 1 octet.

  • # ASN.1 et PER

    Posté par (page perso) . Évalué à 7.

    Tiens, je pense à un truc: les Grands Anciens de l'Informatique ont inventé ASN.1 et PER, qui permettent de décrire le contenu du message. Il existe des outils qui peuvent non seulement générer les fichiers binaires, mais aussi le code (C, Python, …) pour encoder et décoder un message depuis/vers une structure ou un objet du langage.

    • [^] # Re: ASN.1 et PER

      Posté par . Évalué à 2.

      De ce que je comprends, ASN.1 permet de sérialiser programmatiquement des struct C dans un encodage spécifique pour, par exemple, communiquer sur un protocole réseau.

      Peux tu expliquer comment l'utiliser pour se rapprocher de l'usage proposé par binmake ?

  • # Différence par rapport à xxd ?

    Posté par . Évalué à 1.

    Il me semble que xxd apporte certaines de ces fonctionnalités, est-ce que tu peux nous dire quel était ton besoin ? (bien sûr, le plaisir d'écrire un code nouveau est un besoin certain :-)

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.