2017-01-20 4 views
-1

En bash je peux fairecommande Java ou sous-routine qui équivalent à bash commande strings

strings someBinaryfile.exe 

pour un .exe (ou .dll, ou .so) et qui permet d'imprimer uniquement la partie lisible par l'homme des binaires . Il existe une bibliothèque similaire dans java. Je sais comment ouvrir un fichier et l'imprimer, mais j'ai juste besoin de la partie lisible par l'homme.

+0

Merci pour le formatage de la question @Inian – RonPringadi

+1

'strings' n'est pas une commande' bash'; C'est un programme autonome que vous pouvez exécuter à partir d'un programme Java tout comme d'un script 'bash'. – chepner

+0

Je comprends @chepner - à part ça, y a-t-il une bibliothèque en java qui serve un but similaire? Par exemple apache commons (bien que je ne puisse pas trouver une fonction similaire dans la bibliothèque apache commons) – RonPringadi

Répondre

2

Je ne suis pas au courant d'une bibliothèque Java préexistante qui réplique complètement la fonctionnalité de strings. Si vous voulez envisager d'appliquer vous-même, nous pouvons lire le Linux man page for strings pour obtenir une meilleure idée des exigences:

Pour chaque fichier donné, les chaînes GNU imprime le caractère imprimables des séquences qui sont au moins 4 caractères (ou le numéro donné avec les options ci-dessous) et sont suivis d'un caractère non imprimable.

Par conséquent, si vous vouliez mettre en œuvre votre propre solution dans le code Java pur, vous pouvez lire chaque octet du fichier, vérifiez si cet octet est imprimable et stocker la séquence de ces octets dans un tampon. Ensuite, une fois que vous rencontrez un caractère non imprimable, imprimez le contenu du tampon si le tampon contient au moins 4 octets. Par exemple:

import java.io.BufferedInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.FileInputStream; 
import java.io.File; 
import java.io.IOException; 

class Strings { 

    private static final int MIN_STRING_LENGTH = 4; 

    public static void main(String[] args) throws IOException { 
     for (String arg : args) { 
      File f = new File(arg); 
      if (!f.exists()) { 
       System.err.printf("error: no such file or directory: %s%n", arg); 
       continue; 
      } 
      if (!f.canRead()) { 
       System.err.printf("error: permission denied: %s%n", arg); 
       continue; 
      } 
      if (f.isDirectory()) { 
       System.err.printf("error: path is directory: %s%n", arg); 
       continue; 
      } 
      try (BufferedInputStream is = new BufferedInputStream(new FileInputStream(f)); 
         ByteArrayOutputStream os = new ByteArrayOutputStream()) { 
       for (int b = is.read(); b != -1; b = is.read()) { 
        if (b >= 0x20 && b < 0x7F) { 
         os.write(b); 
        } else { 
         if (os.size() >= MIN_STRING_LENGTH) { 
          System.out.println(new String(os.toByteArray(), "US-ASCII")); 
         } 
         os.reset(); 
        } 
       } 
       if (os.size() >= MIN_STRING_LENGTH) { 
        System.out.println(new String(os.toByteArray(), "US-ASCII")); 
       } 
      } 
     } 
    } 
} 

qui couvrirait une approximation de base de la fonctionnalité strings, mais il y a plus de détails à considérer:

Par défaut, il affiche seulement les chaînes des sections initialisées et chargées de fichiers d'objets; Pour les autres types de fichiers, il imprime les chaînes de l'ensemble du fichier.

La mise en œuvre de cette partie devient plus compliquée, parce que vous auriez besoin d'analyser et de comprendre les différentes sections du format de fichier binaire, comme ELF ou Windows PE.

Une autre complication est le codage des caractères:

-e encodage --encoding = encodage Sélectionnez le codage de caractères des chaînes qui doivent être trouvées. Les valeurs possibles pour le codage sont: s = caractères à 7 octets (ASCII, ISO 8859, etc., par défaut), S = caractères à 8 octets, b = bigendian à 16 bits, l = 16 bits littleendian, B = bigendian 32 bits, L = littleendian 32 bits. Utile pour trouver des chaînes de caractères larges. (l et b s'appliquent, par exemple, à codages Unicode UTF-16/UCS-2).

La logique simple I décrit ci-dessus suppose caractères d'un octet. Si vous devez identifier des chaînes dans des codages avec des caractères multi-octets, la logique devra alors faire attention à la gestion du tampon, à la vérification de l'imprimabilité et à la vérification de la longueur de la chaîne.

Il existe de nombreux autres arguments que vous pouvez transmettre à strings, tous décrits dans la page man. Si vous avez besoin de reproduire entièrement toutes ces fonctionnalités, cela compliquera encore la logique.

Si vous préférez ne pas implémenter ceci, alors vous pouvez forker et exécuter strings directement via la classe ProcessBuilder et analyser la sortie. Le compromis est qu'il introduit une dépendance externe que votre code doit exécuter sur une plate-forme avec strings installé et encourt une surcharge pour fork et exécuter le processus externe. Ce compromis pourrait ou non être acceptable pour votre application selon les circonstances.

+0

Awesome! Correspondance très étroite avec la commande gnu strings. Merci @ chris-nauroth – RonPringadi