\par \textit{Yaramod-v3} je open-source knihovna vyvíjená firmou Avast, která poskytuje aplikační programové rozhraní pro syntaktickou a~sémantickou analýzu pravidel v~jazyce YARA, tvorbu nových pravidel a~modifikaci již existujících~\cite{Yaramod}. Ačkoliv je implementována v~jazyce C++, můžeme k~ní přistupovat i~prostřednictvím jazyka Python. To je možné díky využití knihovny \textit{pybind11}~\cite{Pybind}.

\par Knihovna se sestává z~následujících čtyř hlavních částí~\cite[str.~39]{Yaramod}:

\begin{itemize}
    \item Syntaktický a~sémantický analyzátor pravidel v~jazyce YARA (zodpovědnost třídy \verb|ParserDriver|)
    \item Generování nových pravidel (\verb|YaraRuleBuilder|)
    \item Formátování pravidel (\verb|TokenStream|)
    \item Modifikace pravidel (\verb|ModifyingVisitor|)
\end{itemize}

\par Rozhraní této knihovny využívá objektově orientované programování a~návrhové vzory \textit{builder} a~\textit{visitor}. Yaramod-v3 podporuje jak konstrukci \textit{include}, tak import modulů. Symboly obsažené v~modulech jsou popsány prostřednictvím souborů ve formátu JSON. To je důležité zejména pro sémantickou analýzu zdrojových souborů. Uživatelé mohou sami vytvářet soubory s~popisem uživatelsky definovaných modulů, takže se používání nestandardních modulů nijak nevylučuje s~používáním knihovny Yaramod-v3.

\section{Syntaktická a sémantická analýza pravidel}
\par Základní funkcionalitou, kterou knihovna poskytuje, je analýza pravidel ve zdrojovém souboru nebo v~řetězci. Jak již bylo uvedeno výše, o~tento úkol se stará třída \verb|ParserDriver|, která v~jedné ze svých metod obsahuje definici lexémů pro jazyk YARA a~v~jiné zase definici pravidel gramatiky tohoto jazyka. Navíc jsou součástí definice pravidel také sémantické kontroly a~jiné akce, které jsou prováděny po redukci na základě daného pravidla. 
\par Samotná syntaktická analýza je prováděna pomocí LALR(1) (lookahead-LR) syntaktického analyzátoru. Jejím výsledkem je objekt třídy \verb|YaraFile|, který agreguje všechny elementy v~analyzovaném zdrojovém souboru. V~případě, že během analýzy dojde k~chybě, je vyhozena výjimka s~popisným chybovým hlášením. Analýza je však při prvním nálezu syntaktické nebo sémantické chyby ukončena. 

\section{Tvorba nových pravidel}
\par Rozhraní pro tvorbu nových pravidel je implementováno pomocí návrhového vzoru \textit{builder}, který je  řazen mezi tzv. \textit{tvořivé návrhové vzory} (creational design patterns). 
\par Jeho hlavní myšlenkou je oddělit tvorbu komplexního objektu od jeho chování. V~situaci, kdy instance třídy má velké množství atributů, které navíc mohou být dalšími objekty, by tvorba nových instancí vyžadovala volání složitého a~nepřehledného konstruktoru. Situaci bychom se mohli pokusit vyřešit pomocí dědičnosti, nicméně, pokud bychom potřebovali využívat mnoho různých variant tohoto komplexního objektu, potřebovali bychom i~stejně velké množství těchto tříd~\cite{Shvets::2021::builder}.
\par Řešením je právě návrhový vzor \textit{builder}, který instanciaci objektu a~inicializaci jeho atributů deleguje na jiné objekty\,--\,buildery. Pomocí metod těchto objektů tak můžeme snadno inicializovat části komplexního objektu. Jejich voláním určujeme, jak bude onen konkrétní objekt vypadat. Pokud některou z~variant objektu vytváříme opakovaně, můžeme volání metod daného builderu agregovat skrze objekt označovaný jako \textit{director}~\cite[str.~129]{Gamma::1994::design}.
\par Komplexními objekty, jež je zapotřebí instanciovat a~inicializovat, jsou v~případě Yaramodu pravidla v~jazyce YARA. Instance třídy \inlinecode{YaraRuleBuilder} plní funkci objektu typu builder. Voláním metod tohoto objektu inicializujeme jednotlivé části pravidla (tagy, řetězce, podmínku\dots) a~nakonec voláním \inlinecode{get} vytvoříme objekt třídy \inlinecode{Rule}~\cite[str.~17]{Yaramod}.
\par Ačkoliv je způsob tvorby nových pravidel implementačně zajímavý, nejedná se o~statickou analýzu jazyka, a~tudíž se v~této práci toto téma dále nerozvíjí.


\section{Zpřístupnění výsledků analýzy}
\par Výsledky statické analýzy jsou uživateli zpřístupněny prostřednictvím struktury objektů. Jedná se o~model zdrojového kódu, jehož struktura odráží sémantiku zdrojového souboru. Z~tohoto důvodu jsou třídy, které se na tvorbě této reprezentace podílejí, dále označovány také jako \textit{sémantické rozhraní}.
\par Uživatel tedy primárně manipuluje s objekty, které reprezentují celé konstrukce, jež mají v~kontextu jazyka YARA svoji sémantiku. Na druhou stranu, je-li to zapotřebí, uživatel má možnost přistoupit i~k~jednotlivým tokenům tvořícím tyto konstrukce a~určit tak např. jejich pozici v~rámci zdrojového kódu. Jak již bylo uvedeno výše, výsledkem analýzy je objekt třídy \inlinecode{YaraFile}, jenž jako svoje atributy obsahuje seznam pravidel a~konstrukcí \inlinecode{import}. Pokud je použita konstrukce \inlinecode{include}, tyto seznamy obsahují i~elementy, které jsou přítomny ve vložených souborech. 
\par Pravidla obsažená ve zdrojových souborech jsou reprezentována jako objekty třídy \verb|Rule| a~obsahují další seznamy, které odkazují na metadata daného pravidla, značky a~řetězce. Důležitou součástí rozhraní pravidla je také odkaz na stromovou strukturu reprezentující podmínku.
\par Přistupovat k~jednotlivým objektům, které tvoří podmínku lze pomocí návrhového vzoru \textit{visitor}. Jedná se o~\textit{návrhový vzor chování} (behavioral design pattern). Ten je využíván například v~situacích, kdy je zapotřebí provádět nad každým uzlem v~grafu rekurzivně určitou operaci. Uzly přitom mohou být instancemi různých tříd, které mají odlišná rozhraní. Operace pro různé typy uzlů navíc může mít různý průběh.
\par Naivním řešením by bylo tyto operace definovat jako metody ve třídách těchto uzlů. To však vyžaduje zásah do každé třídy, což neprospívá udržovatelnosti kódu, a~navíc je velká šance, že do něj takto zaneseme chyby. Přidání nového druhu operace by vyžadovalo tentýž proces zopakovat~\cite{Shvets::2021::visitor}.
\par Podobně jako u~návrhového vzoru builder, tak i~zde je řešením delegovat provádění operací na speciální objekt\,--\,\textit{visitor}. Tento objekt obsahuje sadu metod, z~nichž je každá určena pro jinou třídu. Tyto metody jsou tak seskupeny pouze v~rámci jedné třídy a~ve třídách uzlů definujeme většinou pouze triviální metodu (např. \inlinecode{accept}), která volá metodu visitoru pro danou třídu~\cite[str.~455]{Gamma::1994::design}.
\par V~knihovně Yaramod je tento návrhový vzor používán pro průchod podmínkami ve zdrojovém souboru. Rozhraní definuje bázovou třídu \verb|ObservingVisitor|, ze které pomocí dědičnosti můžeme vytvořit vlastní visitory, jež budou během průchodu podmínkou provádět libovolné operace~\cite[str.~11]{Yaramod}.
%\par Jak je konkrétně možné použít visitor pro průchod podmínkou pravidla, je demonstrováno na následujícím jednoduchém příkladě:

% \bigskip

% \begin{lstlisting}[language=python]
% import yaramod

% y = yaramod.Yaramod(yaramod.Features.AllCurrent)
% yara_file = y.parse_string(r'''
%     rule sample2 {
%         condition:
%             4 * 2 - 4 * 3 == 4 + 3 * 2 * 4 
% }
% ''')
    
% class AdditionDetector(yaramod.ObservingVisitor):
%     def __init__(self):
%         super().__init__()
%         self.result = false

%     def has_addition(self, yara_file : yaramod.YaraFile):
%         self.result = false
%         for rule in yara_file.rules:
%             self.observe(rule.condition)
%             if self.result:
%                 break

%         return self.result

%     def visit_PlusExpression(self, expr: yaramod.PlusExpression):
%         self.result = true

% is_there_any_addition = AdditionDetector().has_addition(yara_file)
    
% \end{lstlisting}

% \bigskip

% \par Jedná se o~třídu, jež umožňuje detekci použití operátoru \inlinecode{+} v~podmínce některého z~pravidel v~daném zdrojovém souboru. Na řádcích 3\,--\,9 je provedena analýza zdrojového souboru (zde se jedná pouze o~řetězec vložený v~kódu). Na řádcích 11\,--\,26 definujeme vlastní třídu pro průchod stromovou strukturou objektů reprezentující podmínku pravidla, jejímž rodičem je třída \inlinecode{ObservingVisitor}. Přepsáním její metody \inlinecode{visit_PlusExpression} je zajištěno, že nová implementace bude volána nad uzly typu \inlinecode{PlusExpression}, které reprezentují sčítání v~podmínkách pravidla. 
% \par Po zavolání instanciaci třídy \inlinecode{AdditionDetector} a~zavolání metody \inlinecode{has_addition} jsou v~cyklu navštěvována všechna pravidla (ř. 18\,--\,21). Nad podmínkou každého pravidla je volána metoda \inlinecode{observe} rodičovské třídy \inlinecode{ObservingVisitor}, která spustí průchod podmínkou. Pokud dojde k~navštívení objektu typu \inlinecode{PlusExpression}, je nastaven atribut obsahující hodnotu výsledku na \inlinecode{true} (ř. 26), což způsobí ukončení iterace nad pravidly.


\bigskip

\section{Modifikace existujících pravidel}
\par Rozhraní pro modifikace podmínek existujících pravidel využívá opět návrhový vzor visitor a~zvláštní třídu \inlinecode{ModifyingVisitor}~\cite[str.~31]{Yaramod}. Celý proces modifikace podmínek funguje velmi podobně jako při prostém průchodu. Kromě podmínek lze modifikovat i~další komponenty pravidel, jako jsou metadata, řetězce a tagy. V těchto případech je však proces modifikace jednodušší, neboť je prováděn pouze skrze rozhraní příslušných objektů bez využití třídy \inlinecode{ModifyingVisitor}.
\par Stejně jako v~případě rozhraní pro tvorbu nových pravidel, tak ani zde se nejedná o~součást statické analýzy, a~tudíž toto téma nebude dále rozvíjeno.


\section{Aplikace dosavadního řešení}
\par Tato knihovna je užitečná zejména v~projektech, kde je zapotřebí manipulovat s~pravidly automaticky, prostřednictvím programu nebo je staticky analyzovat. Jednou z~aplikací, která tuto knihovnu používá právě pro statickou analýzu a~podporu tvorby pravidel je zmíněný projekt YLS (viz \ref{sec:yara_at_avast}). 
\par Dalším zajímavým projektem je \textit{Arya}\footnote{Oficiální repozitář projektu Arya: \url{https://github.com/claroty/arya}}, který, na základě pravidel v~jazyce YARA, umožňuje vygenerovat pseudomalware, tj. binární soubor, jenž sice odpovídá pravidlům, ale není nijak nebezpečný. Ten může být použit například pro testování v případech, kdy není možné použít reálný malware. 
