GNU/Linux >> Znalost Linux >  >> Linux

10 způsobů, jak analyzovat binární soubory na Linuxu

"Na tomto světě je 10 typů lidí:ti, kteří rozumí binárnímu systému, a ti, kteří ne."

Další zdroje pro Linux

  • Cheat pro příkazy Linuxu
  • Cheat sheet pro pokročilé příkazy systému Linux
  • Bezplatný online kurz:Technický přehled RHEL
  • Síťový cheat pro Linux
  • Cheat sheet SELinux
  • Cheat pro běžné příkazy pro Linux
  • Co jsou kontejnery systému Linux?
  • Naše nejnovější články o Linuxu

S binárními soubory pracujeme denně, ale rozumíme jim tak málo. Binárními soubory mám na mysli spustitelné soubory, které denně spouštíte, přímo z nástrojů příkazového řádku až po plnohodnotné aplikace.

Linux poskytuje bohatou sadu nástrojů, díky kterým je analýza binárních souborů hračkou! Ať už je vaše pracovní role jakákoli, pokud pracujete na Linuxu, znalost základů těchto nástrojů vám pomůže lépe porozumět vašemu systému.

V tomto článku pokryjeme některé z nejpopulárnějších těchto linuxových nástrojů a příkazů, z nichž většina bude k dispozici nativně jako součást vaší distribuce Linuxu. Pokud ne, můžete je kdykoli nainstalovat a prozkoumat pomocí správce balíčků. Pamatujte:naučit se používat správný nástroj při správné příležitosti vyžaduje spoustu trpělivosti a praxe.

soubor

Co to dělá:Pomůže určit typ souboru.

Toto bude váš výchozí bod pro binární analýzu. Se soubory pracujeme denně. Ne vše je spustitelný typ; existuje celá řada typů souborů. Než začnete, musíte porozumět typu souboru, který je analyzován. Je to binární soubor, soubor knihovny, textový soubor ASCII, soubor videa, soubor obrázku, PDF, datový soubor atd.?

soubor vám pomůže identifikovat přesný typ souboru, se kterým máte co do činění.

$ soubor /bin/ls
/bin/ls:ELF 64bitový spustitelný LSB, x86-64, verze 1 (SYSV), dynamicky propojený (používá sdílené knihovny), pro GNU/Linux 2.6.32 , BuildID[sha1]=94943a89d17e9d373b2794dcb1f7e38c95b66c86, odstraněno
$
$ soubor /etc/passwd
/etc/passwd:ASCII text
$

ldd

Co to dělá:Tisk závislostí sdílených objektů.

Pokud jste již použili soubor příkazu výše ve spustitelném binárním souboru, nemůžete ve výstupu přehlédnout zprávu „dynamicky propojeno“. Co to znamená?

Při vývoji softwaru se snažíme nevynalézat znovu kolo. Existuje sada běžných úloh, které většina softwarových programů vyžaduje, jako je tisk výstupu nebo čtení ze standardního formátu, otevírání souborů atd. Všechny tyto běžné úlohy jsou abstrahovány v sadě běžných funkcí, které pak může každý použít místo psaní. jejich vlastní varianty. Tyto běžné funkce jsou umístěny v knihovně s názvem libc nebo glibc .

Jak lze zjistit, na kterých knihovnách je spustitelný soubor závislý? To je místo ldd do obrázku vstoupí příkaz. Spuštěním s dynamicky propojeným binárním souborem se zobrazí všechny jeho závislé knihovny a jejich cesty.

$ ldd /bin/ls
        linux-vdso.so.1 =>  (0x00007ffef5ba1000)
        libselinux.so.1 => /lib64/libselinux.so.1 (07fe4a0900)>        libcap.so.2 => /lib64/libcap.so.2 (0x00007fea9f64f000)
        libacl.so.1 => /lib64/libacl.so.1 (0x00007fea9f44600) /lib64/libc.so.6 (0x00007fea9f079000)
        libpcre.so.1 => /lib64/libpcre.so.1 (0x00007fea9ee17000)
  libdl / dl .. 4 .so.2 (0x00007fea9ec13000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fea9fa7b000)
0        libattr.so.1 => 070.61x
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fea9e7f2000)
$

ltrace

Co to dělá:Sledování volání knihovny.

Nyní víme, jak najít knihovny, na kterých závisí spustitelný program pomocí ldd příkaz. Knihovna však může obsahovat stovky funkcí. Které z těchto stovek jsou skutečné funkce používané naším binárním systémem?

ltrace zobrazí všechny funkce, které jsou volány za běhu z knihovny. V níže uvedeném příkladu můžete vidět názvy funkcí, které jsou volány, spolu s argumenty předávanými této funkci. Můžete také vidět, co tyto funkce vrátily na pravé straně výstupu.

 $ ltrace ls 
__libc_start_main (0x4028c0, 1, 0x7ffd94023b88, 0x412950
strrch ("ls", '/') =nil
setlocale (lc_all, " ") =" EN_US.UTF-8 "
BindTextDomain (" Coreutils "," / usr / Share / Locale ") =" / usr / Share / Locale "
TextDomain (" Coreutils ") =" Coreutils "
__cxa_Atexit (0x40A930, 0, 0, 0x736c6974756572) =0
ISATTY (1) =1
getenv (" Citing_Style ") =nil
getenv (" sloupce ") =nil
ioctl(1, 21523, 0x7ffd94023a50)                                              >       =0

FCLOSE (0x7ff7baae61C0) =0
+++ ODHED (stav 0) +++
$

Hexdump

Co to dělá:Zobrazuje obsah souboru v ASCII, desítkové, šestnáctkové nebo osmičkové soustavě.

Často se stává, že otevřete soubor pomocí aplikace, která neví, co s tímto souborem dělat. Zkuste otevřít spustitelný soubor nebo video soubor pomocí vim; vše, co uvidíte, jsou bláboly hozené na obrazovce.

Otevření neznámých souborů v Hexdump vám pomůže zjistit, co přesně soubor obsahuje. Pomocí některých voleb příkazového řádku můžete také zobrazit ASCII reprezentaci dat přítomných v souboru. To vám může pomoci zjistit, o jaký druh souboru se jedná.

$ hexdump -C /bin/ls | hlava
00000000  7f 45 4c 46 02 01 01 00  00 00 00 00 00 00 00 00 00  d4 42 40 00 00 00 00 00  |..>......B@.....|
00000020  40 00 00 00 00 00 00 00 @ f0 c3 01 00 00 00 0 0 0 ...............|
00000030  00 00 00 00 40 00 38 00  09 00 40 00 1f 00 1e 00  |[email protected]...@. .....|
00000040  06 00 00 00 05 00 00 00  40 00 00 00 00 00 00 00  |........@.......|
00000050  40 00 40 00 00 00 00 00  40 00 40 00 00 00 00 00 00 00 00 00  |................|
00000070  08 00 00 00 00 00 00 00  03 00 00 00 04 00 00 00  |...... ..........|
00000080  38 02 00 00 00 00 00 00  38 02 40 00 00 00 00 00  |8.......8......@.....|
00000090  38 02 40 00 00 00 00 00  1c 00 00 00 00 00 00 00  |8.@.............|
$

řetězce

Co to dělá:Tisk řetězců tisknutelných znaků v souborech.

Pokud se vám Hexdump zdá trochu přehnaný pro váš případ použití a jednoduše hledáte tisknutelné znaky v binárním souboru, můžete použít řetězce příkaz.

Při vývoji softwaru se k němu přidávají různé textové/ASCII zprávy, jako je tisk informačních zpráv, informace o ladění, zprávy nápovědy, chyby a tak dále. Pokud jsou všechny tyto informace přítomny v binárním formátu, budou vypsány na obrazovku pomocí řetězců .

$ strings /bin/ls 

readelf

Co to dělá:Zobrazuje informace o souborech ELF.

ELF (Executable and Linkable File Format) je dominantním formátem souborů pro spustitelné soubory nebo binární soubory, a to nejen na Linuxu, ale také na různých systémech UNIX. Pokud jste použili nástroje jako file command, který vám sdělí, že soubor je ve formátu ELF, dalším logickým krokem bude použití readelf příkaz a jeho různé možnosti pro další analýzu souboru.

Při používání readelf mít po ruce odkaz na skutečnou specifikaci ELF může být velmi užitečné. Specifikace naleznete zde.

$ readelf -h /bin/ls
ELF Header:
  Magic:  7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Třída:    0 00 00
  Třída:    6         E> Data:2 komplement, malý endan
verze:1 (proud)
OS / ABI:Unix - systém v
ABI verze:0
Typ:Exec (spustitelný soubor)
Stroj:Pokročilá mikro zařízení X86-64
Verze:0x1
Adresa vstupního bodu:0x4042d4
Začátek záhlaví programu:64 (bajty do souboru)
Začátek záhlaví sekce :         115696 (bajtů do souboru)
  Příznaky:                            0x0
  Velikost tohoto záhlaví:                                    64    programu      64 (bytů) 
  Velikost záhlaví sekcí:          64 (bajtů)
  Počet záhlaví sekcí:        31
  Index tabulky řetězců záhlaví sekcí:30
$

objdump

Co to dělá:Zobrazuje informace z objektového souboru.

Binární soubory se vytvářejí, když píšete zdrojový kód, který se kompiluje pomocí nástroje, který se nepřekvapivě nazývá kompilátor. Tento kompilátor generuje instrukce ve strojovém jazyce ekvivalentní zdrojovému kódu, který pak může CPU spustit k provedení dané úlohy. Tento kód strojového jazyka lze interpretovat pomocí mnemotechnických pomůcek nazývaných jazyk symbolických instrukcí. Jazyk symbolických instrukcí je sada instrukcí, které vám pomohou porozumět operacím prováděným programem a nakonec prováděným na CPU.

objdump obslužný program přečte binární nebo spustitelný soubor a vypíše na obrazovku pokyny v jazyce symbolických instrukcí. Znalost sestavení je zásadní pro pochopení výstupu objdump příkaz.

Pamatujte:jazyk symbolických instrukcí je specifický pro architekturu.

$ objdump -d /bin/ls | head

/bin/ls:    formát souboru elf64-x86-64


Demontáž sekce .init:

0000000000402150 <_init @@ základna>:
402150:48 83 EC 08 sub $ 0x8,% rsp
402154:48 8b 05 6d 8E 21 00 mov 0x218E6d (% rip),% rax # 61Afc8 <__ gmon_start __>   40215b:      48 85 c0                test   %rax,%rax
$

strace

Co to dělá:Sledování systémových volání a signálů.

Pokud jste použili ltrace , zmiňovaný dříve, vzpomeňte si na strace být podobný. Jediný rozdíl je v tom, že namísto volání knihovny je to strace utility sleduje systémová volání. Systémová volání jsou způsob, jakým se propojujete s jádrem, abyste mohli pracovat.

Chcete-li uvést příklad, pokud chcete něco vytisknout na obrazovku, použijete printf nebo vloží funkce ze standardní knihovny libc; pod kapotou je však nakonec systémové volání s názvem write budou provedeny tak, aby skutečně něco vytiskly na obrazovku.

$ strace -f /bin/ls
execve("/bin/ls", ["/bin/ls"], [/* 17 vars */]) =0
brk( NULL)                               =0x686000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1"f79) -cld) -1"f/9) =ac. cld. 1 ENOENT (Žádný takový soubor nebo adresář)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) =3
fstat(3, {st_mode=S_IFREG|0644, st_size=40661 , ...}) =0
mmap(NULL, 40661, PROT_READ, MAP_PRIVATE, 3, 0) =0x7f9679560000
zavřít(3)                   <    <    ni> br / 0>< >fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) =0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0 ) =0x7F9679569000
zápis (1, "R2 RH", 7R2 RH
) =7
Zavřít (1) =0
Munmap (0x7F9679569000, 4096) =0
zavřít(2)                                =0
exit_group(0)                           =?
++ + skončilo s 0 +++
$

nm

Co to dělá:Seznam symbolů ze souborů objektů.

Pokud pracujete s binárním souborem, který není odstraněn, nm příkaz vám poskytne cenné informace, které byly vložené do binárního souboru během kompilace. nm vám může pomoci identifikovat proměnné a funkce z binárního kódu. Dokážete si představit, jak užitečné by to bylo, kdybyste neměli přístup ke zdrojovému kódu analyzovaného binárního souboru.

Chcete-li předvést nm , rychle napíšeme malý program a zkompilujeme ho s -g a také uvidíme, že binární soubor není odstraněn pomocí příkazu file.

$ cat hello.c 
#include

int main() {
    printf("Ahoj světe!");
    return 0;
}
$
$ gcc -g ahoj.c -o ahoj
$
$ soubor ahoj
ahoj:spustitelný soubor ELF 64-bit LSB , x86-64, verze 1 (SYSV), dynamicky propojené (používá sdílené knihovny), pro GNU/Linux 2.6.32, BuildID[sha1]=3de46c8efb98bce4ad525d3328121568ba3d8a5d, neodstraněno /
$. br />Ahoj světe!$
$


$ nm ahoj | ocas
000000000000600E20 d __jcr_end__
000000000000600E20 d __jcr_csu_fini
00000000000000400540 t __LIBC_CSU_INIT
000000000000400540>                 U printf@@GLIBC_2.2.5
0000000000400490 t register_tm_clones
0000000000400430 T _start
0000600_0_0_000000_0_0_000000000000000000000000

gdb

Co to dělá:GNU debugger.

No, ne všechno v binárním systému lze staticky analyzovat. Provedli jsme některé příkazy, které spouštěly binární soubor, například ltracestrace; software se však skládá z různých podmínek, které by mohly vést k provedení různých alternativních cest.

Jediný způsob, jak analyzovat tyto cesty, je za běhu tím, že máte možnost zastavit nebo pozastavit program na libovolném místě a budete schopni analyzovat informace a poté se posunout dále dolů.

To je místo, kde přicházejí debuggery do obrázku a v systému Linux gdb je defacto debugger. Pomůže vám načíst program, nastavit body přerušení na konkrétních místech, analyzovat paměť a registr CPU a dělat mnohem více. Doplňuje ostatní výše uvedené nástroje a umožňuje vám provádět mnohem více analýzy za běhu.

Jedna věc, kterou je třeba si všimnout, je, že jakmile načtete program pomocí gdb , zobrazí se vám vlastní (gdb) výzva. Všechny další příkazy budou spouštěny v tomto gdb příkazového řádku, dokud neukončíte.

Použijeme program „ahoj“, který jsme zkompilovali dříve, a použijeme gdb abyste viděli, jak to funguje.

$ gdb -q ./hello
Čtení symbolů z /home/flash/ahoj...hotovo.
(gdb) break main
Bod 1 na 0x400521:soubor hello.c , řádek 4.
(gdb) info break
Num     Typ           Disp Enb Address            Co
1       bod přerušení     keep y   0x00000000004000521 (hlavní g) 400521 />Spouštěcí program:/home/flash/./hello

Bod 1, hlavní () na hello.c:4
4           printf("Ahoj svět!");
Chybí samostatné informace o ladění, použijte:debuginfo-install glibc-2.17-260.el7_6.6.x86_64
(gdb) bt
#0  main () na hello.c:4
(gdb ) c
Pokračujeme.
Ahoj světe![Inferior 1 (proces 29620) skončil normálně]
(gdb) q
$

Závěr

Jakmile se seznámíte s používáním těchto nativních nástrojů pro binární analýzu Linuxu a pochopíte výstup, který poskytují, můžete přejít na pokročilejší a profesionálnější nástroje pro binární analýzu s otevřeným zdrojovým kódem, jako je radare2.


Linux
  1. Příkazy hledání pro Linux

  2. Příkaz mcopy v Linuxu

  3. Jak porovnám binární soubory v Linuxu?

  1. 5 způsobů, jak použít příkaz move v Linuxu

  2. 3 způsoby, jak zobrazit seznam uživatelů v Linuxu

  3. Soubory protokolu Linux

  1. Linux ls Command - Seznam souborů

  2. Jak rozeznat binární soubory od textových souborů v linuxu

  3. Binární rozdíl/patch pro velké soubory na linuxu?