Como encontrar a diferença entre um arquivo de script e um arquivo binário?

11
$ ls -l /usr/bin
total 200732

-rwxr-xr-x 1 root   root     156344 Oct  4  2013 adb
-rwxr-xr-x 1 root   root       6123 Oct  8  2013 add-apt-repository
 list goes long ---------

No acima, adb é um arquivo binário e add-apt-repository é um arquivo de script.Eu recebo essas informações visualizando os arquivos através do nautilus.Mas através da linha de comando, eu não encontrei nenhuma diferença.Eu não sou capaz para prever se um arquivo é um arquivo binário ou um arquivo de script.

Então, como eu diferencio entre script e arquivos binários através da linha de comando?

    
por Avinash Raj 13.04.2014 / 20:02

3 respostas

16

Use apenas file :

$ file /usr/bin/add-apt-repository
/usr/bin/add-apt-repository: Python script, ASCII text executable
$ file /usr/bin/ab
/usr/bin/ab: ELF 64-bit LSB  shared object, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=569314a9c4458e72e4ac66cb043e9a1fdf0b55b7, stripped

Como explicado em man file :

NAME
   file — determine file type

DESCRIPTION
 This manual page documents version 5.14 of the file command.

 file tests each argument in an attempt to classify it.  There are three
 sets of tests, performed in this order: filesystem tests, magic tests,
 and language tests.  The first test that succeeds causes the file type to
 be printed.

 The type printed will usually contain one of the words text (the file
 contains only printing characters and a few common control characters and
 is probably safe to read on an ASCII terminal), executable (the file con‐
 tains the result of compiling a program in a form understandable to some
 UNIX kernel or another), or data meaning anything else (data is usually
 “binary” or non-printable).  Exceptions are well-known file formats (core
 files, tar archives) that are known to contain binary data.  When adding
 local definitions to /etc/magic, make sure to preserve these keywords.
 Users depend on knowing that all the readable files in a directory have
 the word “text” printed.  Don't do as Berkeley did and change “shell
 commands text” to “shell script”.

Você também pode usar um truque para executar isso diretamente no nome do executável em $PATH :

$ file $(type -p add-apt-repository | awk '{print $NF}')
/usr/local/bin/add-apt-repository: Python script, ASCII text executable
$ file $(type -p ab | awk '{print $NF}')
/usr/bin/ab: ELF 64-bit LSB  shared object, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=569314a9c4458e72e4ac66cb043e9a1fdf0b55b7, stripped

Para encontrar o tipo de arquivo de todos os executáveis que podem ser encontrados nos diretórios de seu $PATH , você pode fazer isso:

find $(printf "$PATH" | sed 's/:/ /g') -type f | xargs file

E para executar file em todos os arquivos em um diretório específico ( /usr/bin , por exemplo), faça

file /usr/bin/*
    
por terdon 13.04.2014 / 20:13
5

Na verdade, as diferenças entre elas não são tão boas assim.

Em um sistema Unix ou Linux típico, há menos de cinco executáveis reais. No Ubuntu, estes são /lib/ld-linux.so.2 e /sbin/ldconfig .

Todo o resto marcado como executável é executado através de um interpretador , para o qual dois formatos são suportados:

  1. Os arquivos que começam com #! terão o nome do intérprete entre este e o primeiro caractere de nova linha (isso mesmo, não há exigência de que "scripts" sejam arquivos de texto).
  2. Os arquivos ELF têm um segmento PT_INTERP que fornece o caminho para o interpretador (geralmente /lib/ld-linux.so.2 ).

Quando esse arquivo é executado, o kernel encontra o nome do interpretador e o chama. Isso pode acontecer recursivamente, por exemplo, quando você executa um script de shell:

  1. O kernel abre o script, encontra o #! /bin/sh no começo.
  2. O kernel abre /bin/sh , localiza o segmento PT_INTERP apontando para /lib/ld-linux.so.2 .
  3. O kernel abre /lib/ld-linux.so.2 , descobre que não tem um segmento PT_INTERP , carrega seu segmento de texto e o inicia, passando o identificador aberto para /bin/sh e a linha de comando para sua invocação de script.
  4. ld-linux.so.2 carrega os segmentos de código de /bin/sh , resolve as referências da biblioteca compartilhada e inicia sua função principal
  5. /bin/sh , em seguida, reabre o arquivo de script e começa a interpretá-lo linha por linha.

Do ponto de vista do kernel, a única diferença é que, para o arquivo ELF, o descritor de arquivo aberto é passado em vez do nome do arquivo; isso é principalmente uma otimização. Se o intérprete decide saltar para um segmento de código carregado a partir do arquivo, ou interpretá-lo linha por linha é decidido apenas pelo intérprete, e principalmente baseado na convenção.

    
por Simon Richter 14.04.2014 / 09:22
1
O comando

File é ótimo, mas para uma ferramenta de análise mais profissional, gostaria que você tentasse o pacote TrID , que é uma ferramenta File Identifier.

TrID é um utilitário projetado para identificar tipos de arquivos a partir de suas assinaturas binárias, e é fácil de usar.

Para mais informações e o pacote, visite: Site

    
por nux 14.04.2014 / 11:20