\par YARA je multiplatformní nástroj, který je primárně určený k~identifikaci a~klasifikaci mal-\\waru. Můžeme ho ale využít obecně k~identifikaci textových a~binárních souborů s~určitými specifickými znaky. Těmito znaky může být např. přítomnost sekvence bytů v~souboru, počet výskytů sekvence či charakteristické chování programu~\cite{Alvarez::2022::yara}.
\par Původní motivací tvůrce tohoto nástroje, Victora Alvareze, byla právě automatizace rozpoznávání a~rozdělování vzorků malwaru do tříd podle charakteristických znaků. Ruční metody totiž vyžadovaly memorování velkého počtu názvů těchto tříd a~navíc nebylo snadné sdílet jejich typické znaky s~dalšími odborníky~\cite{Alvarez::2014::yara}.
\par Tento nástroj tedy nejen, že naplnil tyto potřeby tvůrce (a~jistě i~mnoha jiných uživatelů), ale poskytl také cestu, jak popis malwaru formalizovat prostřednictvím stejnojmenného jazyka, který je jím využíván.
\par Pomocí tohoto aplikačně specifického jazyka YARA totiž formulujeme ony charakteristické znaky souborů a~vytváříme tzv. \textit{pravidla}. Program \textit{yara} je nejprve zkompiluje do podoby speciálního bytekódu, což zahrnuje také kontrolu syntaktické a~sémantické správnosti pravidel. Následně zkompilovaná pravidla, která jsou již pro člověka prakticky nečitelná, interpretuje\footnote{Chceme-li pravidla pouze zkompilovat můžeme použít nástroj \textit{yarac} pro příkazový řádek (viz \url{https://yara.readthedocs.io/en/stable/commandline.html})}. To znamená, že provede vyhledávání nad zadaným adresářem, jehož cílem je identifikovat soubory odpovídající pravidlům a~určit, jakým z~nich odpovídají.
\par Kromě programu \textit{yara} pro příkazový řádek, poskytují vývojáři tohoto nástroje také knihovny pro jazyky Python (yara-python) a~C (libyara). Díky tomu můžeme využívat tento nástroj skrze aplikační programové rozhraní těchto knihoven a~snadno jej integrovat do větších projektů vytvářených v~různých programovacích jazycích~\cite{Alvarez::2022::yara}.
\par Gramatika jazyka YARA je dostupná pouze ve formátu pro generátor syntaktických analyzátorů GNU bison, který využívá oficiální distribuce nástroje \textit{yara}. Doposud nebyla zveřejněna žádná jiná formální specifikace gramatiky (neuvažujeme-li dokumentaci, která má spíše neformální charakter). 
\par Při vytváření nástroje pro inkrementální statickou analýzu tohoto jazyka je nezbytné jej dobře znát, aby bylo možné formulovat jeho gramatiku a~na základě ní analyzátor vytvořit. Cílem této kapitoly je proto uvést čtenáře do tohoto jazyka, seznámit jej s~některými jeho zásadními konstrukcemi a~ozřejmit mu jejich sémantiku. Z~tohoto důvodu obsahuje kapitola také několik jednoduchých příkladů obsahujících dané klíčové konstrukce.

\section{Obecný formát zdrojových souborů}
\par Zdrojové soubory v~jazyce YARA obsahují sadu pravidel. Ta mohou být na sobě úplně nezávislá, ale je také možné se v~nich odkazovat na jiná existující pravidla. V~době odkazování musí být dané pravidlo již definované.
\par Kromě pravidel mohou zdrojové soubory obsahovat ještě jednořádkové či víceřádkové komentáře nebo klíčová slova \inlinecode{import} a~\inlinecode{include}, kterými buďto importujeme moduly nebo vkládáme jiné zdrojové soubory v~jazyce YARA. Za těmito klíčovými slovy následuje název modulu, respektive cesta ke zdrojovému souboru.

\subsection{Pravidla v jazyce YARA} \label{sec:rules}
\par Pravidla označujeme klíčovým slovem \inlinecode{rule}, za kterým následuje název pravidla, volitelně značky (tagy) a~nakonec tělo pravidla ve složených závorkách. Značky nám umožňují filtrovat výstup programu \textit{yara}~\cite{Alvarez::2022::yara}.
\par Tělo je rozděleno do několika sekcí, jejichž pořadí nelze zaměnit. Jsou jimi metadata (označována klíčovým slovem \inlinecode{meta}), řetězce (\inlinecode{strings}) a~podmínka (\inlinecode{condition}). Sekce musí být uvedeny právě v~tomto pořadí, případně lze metadata či řetězce vynechat.
\par Příkladem jednoduchého pravidla je:

\medskip

\begin{lstlisting}[language=yara]
rule sample1 : sample {
    meta:
        author = "Vojtech Dvorak"
        desc = "Ukazkove pravidlo"
    strings:
        $s00 = "Welcome"
    condition:
        $s00 // Podminka je splnena, pokud soubor obsahuje retezec $s00
}
\end{lstlisting}

\medskip

\par Pomocí tohoto pravidla můžeme identifikovat všechny soubory v~daném adresáři, které obsahují řetězec \inlinecode{Welcome} na libovolné pozici. Pravidlo také obsahuje metadata tvořená páry \inlinecode{<identifikator> = <hodnota>}, která v~tomto případě obsahují jméno autora a~popis pravidla.
\par Za názvem proměnné je zde uvedena také značka \verb|sample|, jež nám umožňuje odfiltrovat z~výstupu programu \textit{yara} nálezy na základě pravidel, které touto značkou označeny nejsou (při spuštění programu uvedeme parametr \verb|-t sample|).
\par Konvence pro pojmenování pravidel, značek a~položek metadat odpovídají konvencím pro názvy proměnných v~jazyce C. Jedná se o~řetězec složený z~jakýchkoliv alfanumerických znaků nebo podtržítek (\verb|_|) o~maximální délce 128 znaků, přičemž prvním znakem nesmí být číslice. Velikosti písmen jsou přitom rozlišovány a~daný řetězec nesmí kolidovat s~některým z~klíčových slov jazyka YARA~\cite{Alvarez::2022::yara}.


\subsection{Sekce metadat}
\par V~rámci pravidel je možné specifikovat metadata ve~formě \inlinecode{<identifikator> = <hodnota>}. Hodnotou může být textový řetězec, celočíselná nebo pravdivostní hodnota~\cite{Alvarez::2022::yara}.
\par V~sekci s~metadaty (v~pravidlech jako \textit{meta}) je obvykle uchováno jméno autora, stručný popis pravidla nebo specifikace třídy souborů (třídy malwaru), která je pravidlem popsána. Například se může jednat o~úroveň nebezpečnosti dané třídy malwaru.

\subsection{Sekce s řetězci} \label{sec:yara-strings}
\par V~rámci sekce s~řetězci (strings) lze definovat sekvence bytů (řetězce), na které je možné se následně odkazovat v~rámci podmínky pravidla. Definice se skládá z~identifikátoru řetězce a~hodnoty (sekvence bytů). Identifikátor řetězce vždy začíná znakem dolaru a~je libovolnou posloupností alfanumerických znaků a~znaku podtržítka. 
\par Jazyk YARA podporuje tři způsoby jak řetězce specifikovat:

\begin{enumerate}
    \item \textbf{Textové řetězce}\,--\,Sekvenci bytů uvedeme pomocí textu ohraničeného znakem \verb|"|. Textové řetězce mohou navíc obsahovat escape sekvence \verb|\n|, \verb|\r|, \verb|\t| apod.
    
    \item \textbf{Hexadecimální řetězce}\,--\,Hodnotu řetězce zapíšeme pomocí dvojic hexadecimálních číslic, které označují jednotlivé byty řetězce. Od zbytku pravidla oddělujeme tento typ řetězců pomocí složených závorek. \par Součástí může být také operátor \verb|||, pomocí kterého můžeme uvést více alternativ pro určitou část řetězce ohraničenou jednoduchými závorkami. Hexadecimální číslice tvořící byte můžou být nahrazeny znakem otazníku, který označuje, že daný byte, resp. nibble, může být jakýkoliv.
    \par Podobnou funkci mají také tzv. \textit{jumps}. Jedná se o~počet nebo rozsah počtu bytů, jejichž hodnota v~rámci řetězce může být libovolná. Zapisujeme je pomocí hranatých závorek. Pokud chceme například specifikovat řetězec tvořený byty \inlinecode{AA} a~\inlinecode{BB}, přičemž mezi nimi může být dva až pět libovolných bytů, použijeme zápis \inlinecode{{ AA [2-5] BB }}. 
    
    \item \textbf{Regulární výrazy}\,--\,V~dřívějších verzích byly regulární výrazy v~rámci nástroje YARA zpracovávány knihovnami PCRE\footnote{Oficiální webové stránky knihovny PCRE: \url{https://www.pcre.org}} a~RE2\footnote{Oficiální repozitář knihovny RE2: \url{https://github.com/google/re2}}. Od verze 2.0 používá YARA svoje vlastní řešení pro práci s~regulárními výrazy. Dle dokumentace však toto řešení poskytuje až na drobné výjimky stejnou funkcionalitu jako knihovna PCRE. Kompletní přehled funkcionality podporované regulárními výrazy v~jazyce YARA lze najít v~dokumentaci~\cite{Alvarez::2022::yara}. Regulární výrazy ohraničujeme lomítky (\verb|/|). Bezprostředně za ukončující lomítko můžeme přidat také příznaky \verb|i| a~\verb|s|. První označuje, že nezáleží na velikosti písmen a~druhý udává, že metaznak \verb|.| označuje také znak nového řádku. 
\end{enumerate}


\par Za definicí řetězce může následovat také kombinace modifikátorů. Může se jednat například o~modifikátor \verb|base64|, který způsobí, že řetězec bude hledán v~kódování \textit{base64} (budou vyhledávány všechny varianty řetězce v~tomto kódování, viz~\cite{Holmes::2017}). 
\par V~následujícím pravidle jsou uvedeny všechny tři způsoby, jakými lze řetězce specifikovat:

\medskip

\begin{lstlisting}[language=yara]
rule string_rule {
    strings:
        $s00 = "Welcome" nocase     // Textovy retezec
        $r00 = /y+ar{1,10}a/i      // Regularni vyraz
        $h00 = { AA [1-3] BB CC ( DD | 1? ) }   // Hexadecimalni retezec
    condition:
        $s00 and $r00 and $h00
}
\end{lstlisting}

\medskip

\subsection{Podmínka pravidla}
\par Povinnou sekcí pravidla je podmínka (condition). Jedná se o~pravdivostní výraz, jehož evaluací pro daný soubor je získána pravdivostní hodnota, která udává, zda pravidlo soubor popisuje či nikoliv. Kromě odkazování na řetězce a~jiná pravidla nám jazyk YARA poskytuje celou řadu operátorů, které můžeme pro tvorbu podmínek použít. K~dispozici jsou logické, relační, aritmetické a~další operátory. Kompletní jejich seznam se stručným popisem je dostupný v~dokumentaci~\cite{Alvarez::2022::yara}.
\par Pravdivostní hodnota, kterou představuje identifikátor řetězce (např. \verb|$s00|), je rovna hodnotě \verb|true|, pokud se řetězec v~souboru alespoň jednou vyskytuje. V~opačném případě je hodnota tohoto symbolu \verb|false|. Kromě řetězců jako takových, můžeme v~podmínkách použít také odkaz na počet jejich výskytů (zaměníme-li symbol dolaru za znak \verb|#|) nebo index bytu, na kterém n-tý výskyt řetězce začíná (zaměníme-li \verb|$| za \verb|@| a~použijeme hranaté závorky pro odkaz na konkrétní výskyt). 
\par Pravidlo s~podmínkou \textit{\uv{Najdi všechny soubory se třemi výskyty řetězce 'Welcome', přičemž první výskyt tohoto řetězce začíná na bytu s~indexem 2}} bychom tedy zapsali tímto způsobem:

\medskip

\begin{lstlisting}[language=yara]
rule num_and_offset_rule {
    strings:
        $s00 = "Welcome"
    condition:
        #s00 == 3 and @s00[1] == 2
}
\end{lstlisting}

\medskip

\par Zatímco byty v~souborech jsou indexovány od nuly, výskyty řetězců jsou indexovány od~jedničky.
\par Při větším množství řetězců by bylo nepraktické  používat jejich identifikátory ve spojení s~logickými operátory (jako je tomu např. v~pravidle \inlinecode{string_rule} v kapitole \ref{sec:yara-strings}). Situace se ještě zkomplikuje, pokud chceme vytvořit pravidlo kontrolující výskyt např. libovolných dvou z~desíti možných řetězců.
\par Z~tohoto důvodu zavádí YARA operátor \inlinecode{of}, který jako první operand přijímá kvantifikátor, jenž udává, kolik řetězců z~množiny se musí v~souboru vyskytovat. Druhým operandem \inlinecode{of} je množina řetězců. Analogicky lze tento operátor použít i~s~množinou identifikátorů jiných pravidel.
\par YARA rovněž umožňuje iterovat přes výskyty řetězce pomocí operátoru \inlinecode{for...of}. Lze jej využít také pro iterování přes danou množinu čísel. Díky iterátorům lze snadno formulovat např. podmínku \textit{\uv{Najdi všechny soubory, kde všechny výskyty řetězce 'start' začínají nejvýše na bytu s~indexem 1000}}:

\medskip

\begin{lstlisting}[language=yara]
rule iterator_rule {
    strings:
        $s00 = "start"
    condition:
        for all j in (1..#s00) : (@s00[i] <= 1000)
}
\end{lstlisting}

\medskip

\par Ve výše uvedeném případě je využit kvantifikátor \verb|all| označující všechny hodnoty, kterých nabývá proměnná \verb|j| během iterace. Množina čísel je v~tomto případě daná celočíselným intervalem začínajícím číslem jedna a~končícím počtem výskytů řetězce \inlinecode{$s00}. Krajní hodnoty jsou v~intervalu zahrnuty.
\par V~rámci podmínky se lze odkazovat také na symboly z~modulů nebo na externí proměnné, které dodáme programu \textit{yara} při spuštění, čímž je možné pravidla parametrizovat.

\section{Modularita jazyka YARA}
\par Moduly nám umožňují rozšířit funkcionalitu nástroje YARA, přičemž sami jeho tvůrci poskytují uživatelům sadu základních (oficiálních) modulů (PE, ELF, Cuckoo\dots). Uživatelé ale také mohou vytvářet vlastní moduly pomocí rozhraní pro jazyk C~\cite[str.~73]{Alvarez::2022::yara}.
\par Moduly typicky rozšiřují nástroj YARA o~konstanty, vestavěné proměnné, struktury či funkce. Například moduly \textit{ELF} a~\textit{PE}, které jsou specializované pro stejnojmenné formáty spustitelných souborů, obsahují symbol \verb|entry_point| s~hodnotou, jež je rovna virtuální adrese vstupního bodu.
\par Dalším zajímavým modulem je \textit{Cuckoo}. V~případě malwaru může být problematické spoléhat při jeho identifikaci pouze na přítomnost řetězců. Řetězce mohou být v~rámci binárního souboru totiž zakódovány nebo jinak skryty (tzv. obfuskace), aby nebylo snadné malware odhalit. Řešení nám poskytuje tento modul, jenž umožňuje popsat binární soubor rovněž dle jeho chování (behaviorálně). Můžeme také oba přístupy kombinovat~\cite[str.~60]{Alvarez::2022::yara}.
\par Chování souboru je v~tomto případě analyzováno v~izolovaném prostředí vyvíjeného v~rámci open-source projektu \textit{Cuckoo Sandbox} a~pro každou analýzu je vytvořeno prostředí nové. Z~tohoto důvodu není případným malwarem ohrožen hostitelský systém a~jednotlivé běhy behaviorální analýzy se nijak neovlivňují~\cite[str.~16]{Guarnieri::2020::cuckoo}.
\par Při použití tohoto modulu musíme však dodat nástroji YARA behaviorální informace získané z~\textit{Cuckoo Sandbox} reportem ve formátu JSON, který nám toto prostředí vygeneruje. Užitečným modulem může být také \textit{Console}, díky kterému můžeme realizovat ladící a~kontrolní výpisy.

 
\section{YARA ve firmě Avast} \label{sec:yara_at_avast}
\par Nástroj YARA je ve společnosti Avast používán ke svému původnímu účelu, k~identifikaci a~klasifikaci malwaru. Firma používá interní konvence pro pojmenování pravidel, řetězců a~pro informace, jež musí být uvedeny v~metadatech pravidla. Kromě oficiálních modulů a~sandboxu Cuckoo využívá také vlastní interní moduly a~izolovaná prostředí. 
\par Navíc je ve společnosti Avast zavedeno několik rozšíření pro jazyk YARA. Jedná se o~sekci s~proměnnými v~pravidlech (variables) a~přetížení operátoru \verb|of|. Tato rozšíření, která byla představena v~rámci práce Tomáše Kendera~\cite{Kender::2021}, nijak nekolidují s~konstrukcemi originálního jazyka YARA. Tudíž všechna pravidla, jež jsou validní v~oficiálním jazyce YARA, by měla být validní i~v této jeho nadstavbě. Při tvorbě nové verze knihovny pro analýzu tohoto jazyka však musíme s~těmito rozšířeními počítat, aby byla nová verze zpětně kompatibilní se současným řešením. 
\par Pro nedostatek nástrojů pro podporu tvorby pravidel v~integrovaných vývojových prostředích a~textových editorech, byl v~rámci Avastu vytvořen open-source projekt \textit{YARA Language Server} (zkráceně YLS). Jedná se o~aplikaci, která komunikuje s~textovým editorem (s~klientem) prostřednictvím protokolu LSP. Díky tomu poskytuje jednotnou podporu pro více různých textových editorů (VSCode, Vim\dots)~\cite{Kastak::2022::yls}. Protokol LSP byl blíže popsán v~kapitole \ref{sec:static_in_ide}.
\par Jelikož se jedná o~nástroj určený pro analýzu pravidel v~době jejich editace, poskytuje z~hlediska statické analýzy spíše základní funkcionalitu. Ta zahrnuje podporu pro snazší pochopení pravidel (strukturování zdrojového souboru, kontextové popisy symbolů\dots), linting, podporu pro udržování jednotného stylu pravidel a~další užitečné funkce. Díky integraci s~textovými editory a~díky rychlosti analýzy poskytuje uživatelům zpětnou vazbu přímo v~prostředí, kde je kód vytvářen~\cite{Kastak::2022::yls}. Díky těmto vlastnostem YLS umožňuje uživatelům tvořit pravidla efektivněji a~s menším množstvím chyb.
\par Projekt YLS je vyvíjen v~jazyce Python s~využitím knihovny \textit{pygls}, která implementuje LSP a~poskytuje tak rámcové řešení pro tvorbu konkrétních language serverů~\cite{Pygls}. Dále je v~rámci YLS využívána knihovna Yaramod-v3, jejíž zodpovědností je samotná statická analýza zdrojových souborů v~jazyce YARA. Tato knihovna je blíže popsána v~kapitole \ref{sec:yaramodv3}.

