1.2. Yara patched to support unicode paths. Update to 3.8.1

This commit is contained in:
stellarbears
2018-08-24 11:19:21 +03:00
parent cfe0448682
commit d04632b371
125 changed files with 7096 additions and 4690 deletions
Binary file not shown.
Binary file not shown.
-1
View File
@@ -15,7 +15,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
.gitattributes = .gitattributes
.gitignore = .gitignore
README.md = README.md
YaraSharp.1.1.3.nupkg = YaraSharp.1.1.3.nupkg
YaraSharp.png = YaraSharp.png
EndProjectSection
EndProject
+3 -1
View File
@@ -26,10 +26,12 @@ namespace YaraSharp
ErrorUtility::ThrowOnError(yr_scanner_scan_proc(Scanner, PID));
return Matches;
}
List<CMatches^>^ CScanner::ScanFile(String^ Path)
{
ErrorUtility::ThrowOnError(yr_scanner_scan_file(Scanner,
(marshal_as<std::string>(Path)).c_str()));
(marshal_as<std::wstring>(Path)).c_str()));
return Matches;
}
List<CMatches^>^ CScanner::ScanMemory(uint8_t* Buffer, int Length)
BIN
View File
Binary file not shown.
+2 -2
View File
@@ -33,10 +33,10 @@ namespace YaraTest
using (YaraSharp.CContext YSContext = new YaraSharp.CContext())
{
// Compiling rules
using (YaraSharp.CRules YSRules = YSInstance.CompileFromFiles(Directory.GetFiles(Path.Combine(Directory.GetCurrentDirectory(), "..\\..\\signatures"), "*.yar", SearchOption.AllDirectories).ToList(), Externals, out Errors))
using (YaraSharp.CRules YSRules = YSInstance.CompileFromFiles(Directory.GetFiles(@"C:\Users\root\source\repos\aptscan-sources\APTScan\Build\Debug\AnyCPU\signatures\yara", "*.yar", SearchOption.AllDirectories).ToList(), Externals, out Errors))
{
// Some file to test yara rules
string Filename = @"\\?\<filepath>";
string Filename = @"\\?\D:\Test\DWS.pdf";
// Get matches
List<YaraSharp.CMatches> Matches = YSInstance.ScanFile(Filename, YSRules,
Binary file not shown.
+2 -2
View File
@@ -46,9 +46,9 @@
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="YaraSharp, Version=1.0.0.0, Culture=neutral, processorArchitecture=x86">
<Reference Include="YaraSharp, Version=1.1.3.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\Build\Debug\x86\YaraSharp.dll</HintPath>
<HintPath>.\YaraSharp.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
Binary file not shown.
+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata>
<id>YaraSharp</id>
<version>1.2.0</version>
<title>YaraSharp</title>
<authors>stellarbears</authors>
<owners>stellarbears</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<licenseUrl>https://github.com/stellarbear/YaraSharp/blob/master/LICENSE</licenseUrl>
<projectUrl>https://github.com/stellarbear/YaraSharp</projectUrl>
<iconUrl>https://github.com/stellarbear/YaraSharp/blob/master/YaraSharp.png?raw=true</iconUrl>
<description>C# wrapper around the Yara pattern matching library</description>
<summary></summary>
<copyright>stellarbears</copyright>
<tags>yara yara-scanner wrapper-api wrapper-library yara-forensics wrapper libyara async-scanning net csharp</tags>
</metadata>
<files>
<file src="Release\**\YaraSharp.dll" target="build/net" />
<file src="Release\**\YaraSharp.props" target="build/net" />
</files>
</package>
+28
View File
@@ -0,0 +1,28 @@
param (
$SourceDirectory = "$PSScriptRoot/..",
$msbuild = 'msbuild',
$nuget = 'nuget'
)
$projectName = (Split-Path $SourceDirectory -Leaf)
$ErrorActionPreference = 'Stop'
& $msbuild /m "$SourceDirectory/$projectName.sln" /p:Configuration=Release /p:Platform="Any CPU" '/t:Clean;Rebuild'
if (-not $?) {
throw "msbuild returned error code: $LASTEXITCODE"
}
& $msbuild /m "$SourceDirectory/$projectName.sln" /p:Configuration=Release /p:Platform="x86" '/t:Clean;Rebuild'
if (-not $?) {
throw "msbuild returned error code: $LASTEXITCODE"
}
& $msbuild /m "$SourceDirectory/$projectName.sln" /p:Configuration=Release /p:Platform="x64" '/t:Clean;Rebuild'
if (-not $?) {
throw "msbuild returned error code: $LASTEXITCODE"
}
(Get-Content "props").replace('PROJECTNAME', $projectName) | Set-Content "$SourceDirectory/Build/Release/$projectName.props"
& $nuget pack -Exclude **\*.pdb -BasePath "$SourceDirectory/Build" "$PSScriptRoot/$projectName.nuspec"
Write-Host -NoNewLine 'Press any key to continue...';
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown');
+59
View File
@@ -0,0 +1,59 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\Build\Debug\AnyCPU\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\Build\Release\AnyCPU\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\Build\Debug\x64\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>..\Build\Release\x64\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\Build\Debug\x86\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>..\Build\Release\x86\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
+11
View File
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Reference Include="PROJECTNAME" Condition="'$(Platform)' == 'x86'">
<HintPath>$(MSBuildThisFileDirectory)..\net\x86\PROJECTNAME.dll</HintPath>
</Reference>
<Reference Include="PROJECTNAME" Condition="'$(Platform)' == 'x64'">
<HintPath>$(MSBuildThisFileDirectory)..\net\x64\PROJECTNAME.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
+26
View File
@@ -49,6 +49,9 @@ stamp-h1
/yara
/yarac
/libyara/modules/.dirstamp
libyara/proc/.dirstamp
libyara/yara.pc
/tests/.dirstamp
# Linux and Mac files
*.swp
@@ -58,6 +61,21 @@ stamp-h1
test-alignment
test-alignment.log
test-alignment.trs
test-api
test-api.log
test-api.trs
test-atoms
test-atoms.log
test-atoms.trs
test-bitmask
test-bitmask.log
test-bitmask.trs
test-elf
test-elf.log
test-elf.trs
test-exception
test-exception.log
test-exception.trs
test-rules
test-rules.log
test-rules.trs
@@ -68,6 +86,12 @@ test-pe.trs
test-macho
test-macho.log
test-macho.trs
test-math
test-math.log
test-math.trs
test-version
test-version.log
test-version.trs
# Visual Studio files
Release/
@@ -82,3 +106,5 @@ x64/
# NuGet
windows/*/packages/
*.trs
*.log
+10 -13
View File
@@ -63,18 +63,15 @@ after_failure: if [ -e test-suite.log ]; then cat test-suite.log; fi
env:
global:
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
# via the "travis encrypt" command using the project repo's public key
# via the "travis encrypt" command using the project repo's public key
- secure: "JWobvJ94pWt/xVciQURkNFS3I+gyu2IyZPKYEs6HDlHrpHs4BoVDZeRjmgx0s6aDeQjKJHowGDu17IlbnCkKzXrZErEJkA+Oc/d0SwgXKiUU9WYiaGBJjJUoYZw66QIEuGGKkF4uQ7EIcW/vN7wzrCDyAiPeOPUjVP4Tc2XRzmkSfakfmf9cE5nqT84DPUYiRegM7iepMrZi9kEaAoboBuETT+6eUKdERRadM0QNjZmCYMEMjtFj3lE51Ey2stGqZdKJvJN0FUmxGoaXCFFAsNmZPnFeDkqTf0a+MzxG2m4nnIXyNC/nT5XLItKHog4KROHb4tUpCZJ4iJhcw3loWMCtkZqB2fq2PaOkKk2zxPr3HLCn7ltmOzReBEDjEg68UqWydRW5534JGosbcA9IfshS1VqnZLgGwQHieXNeqhJUumt1DpON7AQEiEzbzAk0y2VcPlDPuCt9QS1k+zPMZLzbwgvs1ZOH39oFESW+iEDdzZjbhyC3J6azTHFcnA7r5SsYe1pzcSUaYtS1ehhb0lU/442JSHw2j00Nv9qFycYNvDrRNQNBxLziVustT0WJoVdFlkKy16iu1tUYOVXKgmMfqUDINfU6zRz3DskVuB9MZzq/4cMdK4jMRIDNZWvye1BzM7o/PiJoNaQc/6iav2RD+5YV46bBr60TqnYyjlM="
# Disable Coverity due to a problem with their certificate that makes it fail
# in Travis-CI.
#
#addons:
# coverity_scan:
# project:
# name: "plusvic/yara"
# description: "Build submitted via Travis CI"
# notification_email: plusvic@gmail.com
# build_command_prepend: "./configure; make clean"
# build_command: "make -j 4"
# branch_pattern: master
addons:
coverity_scan:
project:
name: "plusvic/yara"
description: "Build submitted via Travis CI"
notification_email: plusvic@gmail.com
build_command_prepend: "./configure; make clean"
build_command: "make -j 4"
branch_pattern: master
+33 -16
View File
@@ -23,44 +23,61 @@ ACLOCAL_AMFLAGS=-I m4
bin_PROGRAMS = yara yarac
yara_SOURCES = args.c args.h common.h threading.c threading.h yara.c
yara_LDADD = libyara/.libs/libyara.a
yara_LDADD = -Llibyara/.libs -lyara
yarac_SOURCES = args.c args.h common.h yarac.c
yarac_LDADD = libyara/.libs/libyara.a
TESTS = $(check_PROGRAMS)
check_PROGRAMS = test-alignment test-api test-rules test-pe test-elf test-version
# The -fsanitize=address option makes test-exception fail. Include the test
# only if the option is not enabled.
if !ADDRESS_SANITIZER
check_PROGRAMS+=test-exception
endif
yarac_LDADD = -Llibyara/.libs -lyara
test_alignment_SOURCES = tests/test-alignment.c
test_atoms_SOURCES = tests/test-atoms.c tests/util.c libyara/atoms.c
test_atoms_LDADD = libyara/.libs/libyara.a
test_rules_SOURCES = tests/test-rules.c tests/util.c
test_rules_LDADD = libyara/.libs/libyara.a
test_pe_SOURCES = tests/test-pe.c tests/util.c
test_pe_LDADD = libyara/.libs/libyara.a
test_elf_SOURCES = tests/test-elf.c tests/util.c
test_elf_LDADD = libyara/.libs/libyara.a
test_exception_SOURCES = tests/test-exception.c tests/util.c
test_exception_LDADD = libyara/.libs/libyara.a
test_version_SOURCES = tests/test-version.c
test_api_LDADD = libyara/.libs/libyara.a
test_api_SOURCES = tests/test-api.c tests/util.c
test_bitmask_SOURCES = tests/test-bitmask.c
test_bitmask_LDADD = libyara/.libs/libyara.a
test_math_SOURCES = tests/test-math.c tests/util.c
test_math_LDADD = libyara/.libs/libyara.a
TESTS = $(check_PROGRAMS)
TESTS_ENVIRONMENT = TOP_SRCDIR=$(top_srcdir)
check_PROGRAMS = test-alignment \
test-atoms \
test-api \
test-rules \
test-pe \
test-elf \
test-version \
test-bitmask \
test-math
if POSIX
# The -fsanitize=address option makes test-exception fail. Include the test
# only if the option is not enabled.
if !ADDRESS_SANITIZER
check_PROGRAMS+=test-exception
test_exception_SOURCES = tests/test-exception.c tests/util.c
test_exception_LDADD = -Llibyara/.libs -lyara
endif
endif
if MACHO_MODULE
check_PROGRAMS+=test-macho
test_macho_SOURCES = tests/test-macho.c tests/util.c
test_macho_LDADD = libyara/.libs/libyara.a
test_macho_LDADD = -Llibyara/.libs -lyara
endif
if DEX_MODULE
check_PROGRAMS+=test-dex
test_dex_SOURCES = tests/test-dex.c tests/util.c
test_dex_LDADD = libyara/.libs/libyara.a
test_dex_LDADD = -Llibyara/.libs -lyara
endif
# man pages
+9 -1
View File
@@ -13,7 +13,7 @@ malware families (or whatever you want to describe) based on textual or binary
patterns. Each description, a.k.a rule, consists of a set of strings and a
boolean expression which determine its logic. Let's see an example:
```
```yara
rule silent_banker : banker
{
meta:
@@ -41,10 +41,15 @@ YARA is multi-platform, running on Windows, Linux and Mac OS X, and can be used
through its command-line interface or from your own Python scripts with the
yara-python extension.
## Additional resources
If you plan to use YARA to scan compressed files (.zip, .tar, etc) you should
take a look at [yextend](https://github.com/BayshoreNetworks/yextend), a very
helpful extension to YARA developed and open-sourced by Bayshore Networks.
Additionally, the guys from [InQuest](https://inquest.net/) have curated an
awesome list of [YARA-related stuff](https://github.com/InQuest/awesome-yara).
## Who's using YARA
* [ActiveCanopy](https://activecanopy.com/)
@@ -59,6 +64,8 @@ helpful extension to YARA developed and open-sourced by Bayshore Networks.
* [Conix](http://www.conix.fr)
* [CrowdStrike FMS](https://github.com/CrowdStrike/CrowdFMS)
* [Cuckoo Sandbox](https://github.com/cuckoosandbox/cuckoo)
* [Cyber Triage](http://www.cybertriage.com)
* [Digita Security](https://digitasecurity.com/product/uxprotect)
* [ESET](https://www.eset.com)
* [ESTsecurity](https://www.estsecurity.com)
* [Fidelis XPS](http://www.fidelissecurity.com/network-security-appliance/Fidelis-XPS)
@@ -76,6 +83,7 @@ helpful extension to YARA developed and open-sourced by Bayshore Networks.
* [Koodous](https://koodous.com/)
* [Laika BOSS](https://github.com/lmco/laikaboss)
* [Lastline, Inc.](http://www.lastline.com)
* [LimaCharlie](https://limacharlie.io/)
* [McAfee Advanced Threat Defense](http://mcafee.com/atd)
* [Metaflows](http://www.metaflows.com)
* [NBS System](https://www.nbs-system.com/)
+52 -12
View File
@@ -1,24 +1,64 @@
# AppVeyor CI for Windows
version: 3.7.{build}
version: 3.8.1-{build}
pull_requests:
do_not_increment_build_number: true
configuration: Release
environment:
matrix:
- TARGET: vs2015
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
VisualStudioVersion: 14.0
configuration: Release
platform: x86
- TARGET: vs2015
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
VisualStudioVersion: 14.0
configuration: Debug
platform: x86
- TARGET: vs2015
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
VisualStudioVersion: 14.0
platform: x64
configuration: Release
- TARGET: vs2015
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
VisualStudioVersion: 14.0
platform: x64
configuration: Debug
- TARGET: cygwin
platform:
- x64
- x86
for:
-
matrix:
only:
- TARGET: cygwin
before_build:
- ps: nuget restore windows/vs2015/yara.sln
build_script:
- cmd: C:\cygwin64\bin\bash -e -l -c "cd c:/projects/yara && ./build.sh"
build:
project: windows/vs2015/yara.sln
verbosity: minimal
test_script:
- cmd: C:\cygwin64\bin\bash -e -l -c "cd c:/projects/yara && make check"
artifacts:
-
matrix:
only:
- TARGET: vs2015
before_build:
- ps: nuget restore windows/vs2015/yara.sln
build:
project: windows/vs2015/yara.sln
verbosity: minimal
artifacts:
- path: windows\**\*.exe
test: off
test: off
# Uncomment the lines below for enabling Remote Desktop in the Appveyor. This
# allows connecting to the remote machine and debug issues.
# on_finish:
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
+3 -1
View File
@@ -31,6 +31,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string.h>
#include <stdlib.h>
#include <yara.h>
#include "args.h"
#define args_is_long_arg(arg) \
@@ -99,7 +101,7 @@ args_error_type_t args_parse_option(
switch (opt->type)
{
case ARGS_OPT_BOOLEAN:
*(int*) opt->value = 1;
*(bool*) opt->value = true;
break;
case ARGS_OPT_INTEGER:
+20 -14
View File
@@ -31,16 +31,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef COMMON_H
#define COMMON_H
#include <stdbool.h>
#define exit_with_code(code) { result = code; goto _exit; }
int compile_files(
bool compile_files(
YR_COMPILER* compiler,
int argc,
const char** argv)
{
for (int i = 0; i < argc - 1; i++)
{
FILE* rule_file;
const char* ns;
const char* file_name;
char* colon = (char*) strchr(argv[i], ':');
@@ -59,12 +62,15 @@ int compile_files(
ns = NULL;
}
FILE* rule_file = fopen(file_name, "r");
if (strcmp(file_name, "-") == 0)
rule_file = stdin;
else
rule_file = fopen(file_name, "r");
if (rule_file == NULL)
{
fprintf(stderr, "error: could not open file: %s\n", file_name);
return FALSE;
return false;
}
errors = yr_compiler_add_file(compiler, rule_file, ns, file_name);
@@ -72,14 +78,14 @@ int compile_files(
fclose(rule_file);
if (errors > 0)
return FALSE;
return false;
}
return TRUE;
return true;
}
int is_integer(const char *str)
bool is_integer(const char *str)
{
if (*str == '-')
str++;
@@ -87,36 +93,36 @@ int is_integer(const char *str)
while(*str)
{
if (!isdigit(*str))
return FALSE;
return false;
str++;
}
return TRUE;
return true;
}
int is_float(const char *str)
bool is_float(const char *str)
{
int has_dot = FALSE;
bool has_dot = false;
if (*str == '-') // skip the minus sign if present
str++;
if (*str == '.') // float can't start with a dot
return FALSE;
return false;
while(*str)
{
if (*str == '.')
{
if (has_dot) // two dots, not a float
return FALSE;
return false;
has_dot = TRUE;
has_dot = true;
}
else if (!isdigit(*str))
{
return FALSE;
return false;
}
str++;
+11 -11
View File
@@ -1,4 +1,4 @@
AC_INIT([yara], [3.7.0], [vmalvarez@virustotal.com])
AC_INIT([yara], [3.8.1], [vmalvarez@virustotal.com])
AM_SILENT_RULES([yes])
AC_CONFIG_SRCDIR([yara.c])
@@ -26,8 +26,6 @@ AC_PROG_YACC
AC_SYS_LARGEFILE
LT_INIT
AC_PROG_LIBTOOL
AC_CANONICAL_HOST
case $host_alias in
@@ -40,22 +38,25 @@ case $host_os in
# are in /usr/local/opt/openssl/include
CFLAGS="$CFLAGS -DUSE_MACH_PROC -I/usr/local/opt/openssl/include"
LDFLAGS="$LDFLAGS -L/usr/local/opt/openssl/lib"
mach=yes
posix=true
proc_interface=mach
jemalloc_prefix=je_ ;;
mingw*) CFLAGS="$CFLAGS -DUSE_WINDOWS_PROC"
mingw*|cygwin*) CFLAGS="$CFLAGS -DUSE_WINDOWS_PROC"
proc_interface=windows
jemalloc_prefix= ;;
linux*|netbsd*|dragonfly*|kfreebsd*)
CFLAGS="$CFLAGS -DUSE_LINUX_PROC"
posix=true
proc_interface=linux
jemalloc_prefix= ;;
jemalloc_prefix= ;;
freebsd*)
CFLAGS="$CFLAGS -DUSE_FREEBSD_PROC"
posix=true
proc_interface=freebsd
jemalloc_prefix= ;;
openbsd*)
CFLAGS="$CFLAGS -DUSE_OPENBSD_PROC"
posix=true
proc_interface=openbsd
jemalloc_prefix= ;;
*)
@@ -269,13 +270,12 @@ AS_IF([test "x$have_crypto" = "xno"],
PC_REQUIRES_PRIVATE="$PC_REQUIRES_PRIVATE libcrypto"
])
AS_IF([test "x$mach" != "xyes"],
[
AC_CHECK_FUNCS([clock_gettime],,
AC_MSG_ERROR([clock_gettime not supported in your OS.]))
],)
AC_CHECK_HEADERS([stdbool.h])
AC_CHECK_FUNCS([clock_gettime],,)
AM_CONDITIONAL([DEBUG], [test x$debug = xtrue])
AM_CONDITIONAL([POSIX], [test x$posix = xtrue])
AM_CONDITIONAL([PROFILING_ENABLED], [test x$profiling_enabled = xtrue])
AM_CONDITIONAL([OPTIMIZATION], [test x$optimization = xtrue])
AM_CONDITIONAL([ADDRESS_SANITIZER], [test x$address_sanitizer = xtrue])
+207 -24
View File
@@ -37,15 +37,14 @@ sharing a namespace. If the namespace argument is ``NULL`` the rules are put
in the *default* namespace.
The :c:func:`yr_compiler_add_file`, :c:func:`yr_compiler_add_fd`, and
:c:func:`yr_compiler_add_string` functions return
the number of errors found in the source code. If the rules are correct they
will return 0. If any of these functions return an error the compiler can't used
anymore, neither for adding more rules nor getting the compiled rules.
:c:func:`yr_compiler_add_string` functions return the number of errors found in
the source code. If the rules are correct they will return 0. If any of these
functions return an error the compiler can't used anymore, neither for adding
more rules nor getting the compiled rules.
For obtaining detailed error information you must set a callback
function by using :c:func:`yr_compiler_set_callback` before calling
any of the compiling functions. The callback function has the following
prototype:
For obtaining detailed error information you must set a callback function by
using :c:func:`yr_compiler_set_callback` before calling any of the compiling
functions. The callback function has the following prototype:
.. code-block:: c
@@ -67,15 +66,17 @@ you're using :c:func:`yr_compiler_add_string`. The ``user_data`` pointer is the
same you passed to :c:func:`yr_compiler_set_callback`.
By default, for rules containing references to other files
(``include "filename.yara"``), yara will try to find those files on disk.
(``include "filename.yara"``), YARA will try to find those files on disk.
However, if you want to fetch the imported rules from another source (eg: from a
database or remote service), a callback function can be set with
:c:func:`yr_compiler_set_include_callback`.
The callback receives the following parameters:
* ``include_name``: name of the requested file.
* ``calling_rule_filename``: the requesting file name (NULL if not a file).
* ``calling_rule_namespace``: namespace (NULL if undefined).
* ``user_data`` pointer is the same you passed to :c:func:`yr_compiler_set_include_callback`.
It should return the requested file's content as a null-terminated string. The
memory for this string should be allocated by the callback function. Once it is
safe to free the memory used to return the callback's result, the include_free
@@ -113,6 +114,22 @@ multiple times.
Each instance of :c:type:`YR_RULES` must be destroyed with
:c:func:`yr_rules_destroy`.
Defining external variables
===========================
If your rules make use of external variables (like in the example below), you
must define those variables by using any of the ``yr_compiler_define_XXXX_variable``
functions. Variables must be defined before rules are compiled with
``yr_compiler_add_XXXX`` and they must be defined with a type that matches the
context in which the variable is used in the rule, a variable that is used like
`my_var == 5` can't be defined as a string variable.
While defining external variables with ``yr_compiler_define_XXXX_variable`` you
must provide a value for each variable. That value is embedded in the compiled
rules and used whenever the variable appears in a rule. However, you can change
the value associated to an external variable after the rules has been compiled
by using any of the ``yr_rules_define_XXXX_variable`` functions.
Saving and retrieving compiled rules
====================================
@@ -165,8 +182,9 @@ The ``ptr`` argument is a pointer to the buffer where the ``read`` function
should put the read data, or where the ``write`` function will find the data
that needs to be written to the stream. In both cases ``size`` is the size of
each element being read or written and ``count`` the number of elements. The
total size of the data being read or written is ``size`` * ``count``. Both
functions must return the total number of elements read or written.
total size of the data being read or written is ``size`` * ``count``. The
``read`` function must return the number of elements read, the ``write`` function
must return the total size of the data written.
The ``user_data`` pointer is the same you specified in the
:c:type:`YR_STREAM` structure. You can use it to pass arbitrary data to your
@@ -178,10 +196,15 @@ The ``user_data`` pointer is the same you specified in the
Scanning data
=============
Once you have an instance of :c:type:`YR_RULES` you can use it with either
Once you have an instance of :c:type:`YR_RULES` you can use it directly with one
of the ``yr_rules_scan_XXXX`` functions described below, or create a scanner with
:c:func:`yr_scanner_create`. Let's start by discussing the first approach.
The :c:type:`YR_RULES` you got from the compiler can be used with
:c:func:`yr_rules_scan_file`, :c:func:`yr_rules_scan_fd` or
:c:func:`yr_rules_scan_mem`. The results from the scan are returned to your
program via a callback function. The callback has the following prototype:
:c:func:`yr_rules_scan_mem` for scanning a file, a file descriptor and a in-memory
buffer respectively. The results from the scan are returned to your program via
a callback function. The callback has the following prototype:
.. code-block:: c
@@ -255,6 +278,28 @@ single match for the string, even if it appears multiple times in the scanned
data. This flag has the same effect of the ``-f`` command-line option described
in :ref:`command-line`.
Using a scanner
---------------
The ``yr_rules_scan_XXXX`` functions are enough in most cases, but sometimes you
may need a fine-grained control over the scanning. In those cases you can create
a scanner with :c:func:`yr_scanner_create`. A scanner is simply a wrapper around
a :c:type:`YR_RULES` structure that holds additional configuration like external
variables without affecting other users of the :c:type:`YR_RULES` structure.
A scanner is particularly useful when you want to use the same :c:type:`YR_RULES`
with multiple workers (it could be a separate thread, a coroutine, etc) and each
worker needs to set different set of values for external variables. In that
case you can't use ``yr_rules_define_XXXX_variable`` for setting the values of your
external variables, as every worker using the :c:type:`YR_RULES` will be affected
by such changes. However each worker can have its own scanner, where the scanners
share the same :c:type:`YR_RULES`, and use ``yr_scanner_define_XXXX_variable`` for
setting external variables without affecting the rest of the workers.
This is a better solution than having a separate :c:type:`YR_RULES` for each
worker, as :c:type:`YR_RULES` structures have large memory footprint (specially
if you have a lot of rules) while scanners are very lightweight.
API reference
=============
@@ -416,8 +461,11 @@ Functions
.. c:function:: void yr_finalize_thread(void)
.. deprecated:: 3.8.0
Any thread using the library, except the main thread, must call this
function when it finishes using the library.
function when it finishes using the library. Since version 3.8.0 this calling
this function is not required anymore, and it's deprecated.
.. c:function:: int yr_compiler_create(YR_COMPILER** compiler)
@@ -488,19 +536,35 @@ Functions
.. c:function:: int yr_compiler_define_integer_variable(YR_COMPILER* compiler, const char* identifier, int64_t value)
Defines an integer external variable.
Define an integer external variable.
.. c:function:: int yr_compiler_define_float_variable(YR_COMPILER* compiler, const char* identifier, double value)
Defines a float external variable.
Define a float external variable.
.. c:function:: int yr_compiler_define_boolean_variable(YR_COMPILER* compiler, const char* identifier, int value)
Defines a boolean external variable.
Define a boolean external variable.
.. c:function:: int yr_compiler_define_string_variable(YR_COMPILER* compiler, const char* identifier, const char* value)
Defines a string external variable.
Define a string external variable.
.. c:function:: int yr_rules_define_integer_variable(YR_RULES* rules, const char* identifier, int64_t value)
Define an integer external variable.
.. c:function:: int yr_rules_define_boolean_variable(YR_RULES* rules, const char* identifier, int value)
Define a boolean external variable.
.. c:function:: int yr_rules_define_float_variable(YR_RULES* rules, const char* identifier, double value)
Define a float external variable.
.. c:function:: int yr_rules_define_string_variable(YR_RULES* rules, const char* identifier, const char* value)
Define a string external variable.
.. c:function:: void yr_rules_destroy(YR_RULES* rules)
@@ -606,7 +670,6 @@ Functions
as returned by the `open()` function. In Windows ``YR_FILE_DESCRIPTOR`` is a
``HANDLE`` as returned by `CreateFile()`.
Returns one of the following error codes:
:c:macro:`ERROR_SUCCESS`
@@ -709,7 +772,7 @@ Functions
..do something with rule
}
.. c:function:: yr_rule_disable(rule)
.. c:function:: void yr_rule_disable(YR_RULE* rule)
.. versionadded:: 3.7.0
@@ -719,7 +782,7 @@ Functions
true nor false but undefined. For more information about undefined values
see :ref:`undefined-values`.
.. c:function:: yr_rule_enable(rule)
.. c:function:: void yr_rule_enable(YR_RULE* rule)
.. versionadded:: 3.7.0
@@ -727,6 +790,126 @@ Functions
a rule can be enabled again by using this function.
.. c:function:: int yr_scanner_create(YR_RULES* rules, YR_SCANNER **scanner)
.. versionadded:: 3.8.0
Creates a new scanner that can be used for scanning data with the provided
provided rules. `scanner` must be a pointer to a :c:type:`YR_SCANNER`, the
function will set the pointer to the newly allocated scanner. Returns one of
the following error codes:
:c:macro:`ERROR_INSUFFICIENT_MEMORY`
.. c:function:: void yr_scanner_destroy(YR_SCANNER *scanner)
.. versionadded:: 3.8.0
Destroy a scanner. After using a scanner it must be destroyed with this
function.
.. c:function:: void yr_scanner_set_callback(YR_SCANNER *scanner, YR_CALLBACK_FUNC callback, void* user_data)
.. versionadded:: 3.8.0
Set a callback function that will be called for reporting any matches found by
the scanner.
.. c:function:: void yr_scanner_set_timeout(YR_SCANNER* scanner, int timeout)
.. versionadded:: 3.8.0
Set the maximum number of seconds that the scanner will spend in any call to
`yr_scanner_scan_xxx`.
.. c:function:: void yr_scanner_set_flags(YR_SCANNER* scanner, int flags)
.. versionadded:: 3.8.0
Set the flags that will be used by any call to `yr_scanner_scan_xxx`.
.. c:function:: int yr_scanner_define_integer_variable(YR_SCANNER* scanner, const char* identifier, int64_t value)
.. versionadded:: 3.8.0
Define an integer external variable.
.. c:function:: int yr_scanner_define_boolean_variable(YR_SCANNER* scanner, const char* identifier, int value)
.. versionadded:: 3.8.0
Define a boolean external variable.
.. c:function:: int yr_scanner_define_float_variable(YR_SCANNER* scanner, const char* identifier, double value)
.. versionadded:: 3.8.0
Define a float external variable.
.. c:function:: int yr_scanner_define_string_variable(YR_SCANNER* scanner, const char* identifier, const char* value)
.. versionadded:: 3.8.0
Define a string external variable.
.. c:function:: int yr_scanner_scan_mem(YR_SCANNER* scanner, const uint8_t* buffer, size_t buffer_size)
.. versionadded:: 3.8.0
Scan a memory buffer. Returns one of the following error codes:
:c:macro:`ERROR_SUCCESS`
:c:macro:`ERROR_INSUFFICIENT_MEMORY`
:c:macro:`ERROR_TOO_MANY_SCAN_THREADS`
:c:macro:`ERROR_SCAN_TIMEOUT`
:c:macro:`ERROR_CALLBACK_ERROR`
:c:macro:`ERROR_TOO_MANY_MATCHES`
.. c:function:: int yr_scanner_scan_file(YR_SCANNER* scanner, const char* filename)
.. versionadded:: 3.8.0
Scan a file. Returns one of the following error codes:
:c:macro:`ERROR_SUCCESS`
:c:macro:`ERROR_INSUFFICIENT_MEMORY`
:c:macro:`ERROR_TOO_MANY_SCAN_THREADS`
:c:macro:`ERROR_SCAN_TIMEOUT`
:c:macro:`ERROR_CALLBACK_ERROR`
:c:macro:`ERROR_TOO_MANY_MATCHES`
.. c:function:: int yr_scanner_scan_fd(YR_SCANNER* scanner, YR_FILE_DESCRIPTOR fd)
.. versionadded:: 3.8.0
Scan a file descriptor. In POSIX systems ``YR_FILE_DESCRIPTOR`` is an ``int``,
as returned by the `open()` function. In Windows ``YR_FILE_DESCRIPTOR`` is a
``HANDLE`` as returned by `CreateFile()`.
Returns one of the following error codes:
:c:macro:`ERROR_SUCCESS`
:c:macro:`ERROR_INSUFFICIENT_MEMORY`
:c:macro:`ERROR_TOO_MANY_SCAN_THREADS`
:c:macro:`ERROR_SCAN_TIMEOUT`
:c:macro:`ERROR_CALLBACK_ERROR`
:c:macro:`ERROR_TOO_MANY_MATCHES`
Error codes
-----------
@@ -765,7 +948,7 @@ Error codes
.. c:macro:: ERROR_TOO_MANY_SCAN_THREADS
Too many threads trying to use the same :c:type:`YR_RULES` object
simultaneously. The limit is defined by ``MAX_THREADS`` in
simultaneously. The limit is defined by ``YR_MAX_THREADS`` in
*./include/yara/limits.h*
.. c:macro:: ERROR_SCAN_TIMEOUT
@@ -780,5 +963,5 @@ Error codes
Too many matches for some string in your rules. This usually happens when
your rules contains very short or very common strings like ``01 02`` or
``FF FF FF FF``. The limit is defined by ``MAX_STRING_MATCHES`` in
``FF FF FF FF``. The limit is defined by ``YR_MAX_STRING_MATCHES`` in
*./include/yara/limits.h*
+3 -3
View File
@@ -44,16 +44,16 @@ master_doc = 'index'
# General information about the project.
project = u'yara'
copyright = u'2014-2017, VirusTotal'
copyright = u'2014-2018, VirusTotal'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '3.7'
version = '3.8'
# The full version, including alpha/beta/rc tags.
release = '3.7.0'
release = '3.8.1'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
+5 -3
View File
@@ -12,8 +12,8 @@ Compiling and installing YARA
Download the source tarball and get prepared for compiling it::
tar -zxf yara-3.7.0.tar.gz
cd yara-3.7.0
tar -zxf yara-3.8.1.tar.gz
cd yara-3.8.1
./bootstrap.sh
Make sure you have ``automake``, ``libtool``, ``make`` and ``gcc`` installed
@@ -111,7 +111,9 @@ Running YARA for the first time
===============================
Now that you have installed YARA you can write a very simple rule and use the
command-line tool to scan some file::
command-line tool to scan some file:
.. code-block:: sh
echo "rule dummy { condition: true }" > my_first_rule
yara my_first_rule my_first_rule
+3 -1
View File
@@ -8,7 +8,9 @@ Welcome to YARA's documentation!
YARA is a tool aimed at (but not limited to) helping malware researchers to
identify and classify malware samples. With YARA you can create descriptions of malware families (or whatever you want to describe) based on textual or binary patterns. Each description, a.k.a rule, consists of a set of strings and a
boolean expression which determine its logic. Let's see an example::
boolean expression which determine its logic. Let's see an example:
.. code-block:: yara
rule silent_banker : banker
{
+9 -3
View File
@@ -17,7 +17,9 @@ it *contains*, but also on what it *does*.
Suppose that you're interested in executable files sending a HTTP request to
http://someone.doingevil.com. In previous versions of YARA you had to settle
with::
with:
.. code-block:: yara
rule evil_doer
{
@@ -37,7 +39,9 @@ would be completely useless.
But now with the ``cuckoo`` module you can take the behavior report generated
for the executable file by your Cuckoo sandbox, pass it alongside the
executable file to YARA, and write a rule like this::
executable file to YARA, and write a rule like this:
.. code-block:: yara
import "cuckoo"
@@ -48,7 +52,9 @@ executable file to YARA, and write a rule like this::
}
Of course you can mix your behavior-related conditions with good old
string-based conditions::
string-based conditions:
.. code-block:: yara
import "cuckoo"
+3 -1
View File
@@ -8,7 +8,9 @@ dotnet module
.. versionadded:: 3.6.0
The dotnet module allows you to create more fine-grained rules for .NET files by
using attributes and features of the .NET file format. Let's see some examples::
using attributes and features of the .NET file format. Let's see some examples:
.. code-block:: yara
import "dotnet"
+3 -1
View File
@@ -9,7 +9,9 @@ ELF module
The ELF module is very similar to the :ref:`pe-module`, but for ELF files. This
module exposes most of the fields present in an ELF header. Let's see some
examples::
examples:
.. code-block:: yara
import "elf"
+12
View File
@@ -98,3 +98,15 @@ file and create signatures based on those results.
comparisons are inclusive.
*Example: math.in_range(math.deviation(0, filesize, math.MEAN_BYTES), 63.9, 64,1)*
.. c:function:: max(int, int)
.. versionadded:: 3.8.0
Returns the maximum of two unsigned integer values.
.. c:function:: min(int, int)
.. versionadded:: 3.8.0
Returns the minimum of two unsigned integer values.
+326 -20
View File
@@ -8,7 +8,9 @@ PE module
The PE module allows you to create more fine-grained rules for PE files by
using attributes and features of the PE file format. This module exposes most of
the fields present in a PE header and provides functions which can be used to
write more expressive and targeted rules. Let's see some examples::
write more expressive and targeted rules. Let's see some examples:
.. code-block:: yara
import "pe"
@@ -102,37 +104,183 @@ Reference
PE timestamp.
.. c:type:: pointer_to_symbol_table
.. versionadded:: 3.8.0
Value of IMAGE_FILE_HEADER::PointerToSymbolTable. Used when the PE image has
COFF debug info.
.. c:type:: pointer_to_symbol_table
.. versionadded:: 3.8.0
Value of IMAGE_FILE_HEADER::PointerToSymbolTable. Used when the PE image has
COFF debug info.
.. c:type:: number_of_symbols
.. versionadded:: 3.8.0
Value of IMAGE_FILE_HEADER::NumberOfSymbols. Used when the PE image has COFF
debug info.
.. c:type:: size_of_optional_header
.. versionadded:: 3.8.0
Value of IMAGE_FILE_HEADER::SizeOfOptionalHeader. This is real size of the
optional header and reflects differences between 32-bit and 64-bit optional
header and number of data directories.
.. c:type:: opthdr_magic
.. versionadded:: 3.8.0
Value of IMAGE_OPTIONAL_HEADER::Magic.
.. c:type:: size_of_code
.. versionadded:: 3.8.0
Value of IMAGE_OPTIONAL_HEADER::SizeOfCode. This is the sum of raw data
sizes in code sections.
.. c:type:: size_of_initialized_data
.. versionadded:: 3.8.0
Value of IMAGE_OPTIONAL_HEADER::SizeOfInitializedData.
.. c:type:: size_of_uninitialized_data
Value of IMAGE_OPTIONAL_HEADER::SizeOfUninitializedData.
.. c:type:: entry_point
Entry point raw offset or virtual address depending on whether YARA is
scanning a file or process memory respectively. This is equivalent to the
deprecated ``entrypoint`` keyword.
.. c:type:: base_of_code
.. versionadded:: 3.8.0
Value of IMAGE_OPTIONAL_HEADER::BaseOfCode.
.. c:type:: base_of_data
.. versionadded:: 3.8.0
Value of IMAGE_OPTIONAL_HEADER::BaseOfData. This field only exists in 32-bit
PE files.
.. c:type:: image_base
Image base relative virtual address.
.. c:type:: section_alignment
.. versionadded:: 3.8.0
Value of IMAGE_OPTIONAL_HEADER::SectionAlignment. When Windows maps a PE
image to memory, all raw sizes (including size of header) are aligned up to
this value.
.. c:type:: file_alignment
.. versionadded:: 3.8.0
Value of IMAGE_OPTIONAL_HEADER::FileAlignment. All raw data sizes of sections
in the PE image are aligned to this value.
.. c:type:: win32_version_value
.. versionadded:: 3.8.0
Value of IMAGE_OPTIONAL_HEADER::Win32VersionValue.
.. c:type:: size_of_image
.. versionadded:: 3.8.0
Value of IMAGE_OPTIONAL_HEADER::SizeOfImage. This is the total virtual size
of header and all sections.
.. c:type:: size_of_headers
.. versionadded:: 3.8.0
Value of IMAGE_OPTIONAL_HEADER::SizeOfHeaders. This is the raw data size of
the PE headers including DOS header, file header, optional header and all
section headers. When PE is mapped to memory, this value is subject to
aligning up to SectionAlignment.
.. c:type:: characteristics
Bitmap with PE FileHeader characteristics. Individual characteristics
can be inspected by performing a bitwise AND operation with the
Bitmap with PE FileHeader characteristics. Individual characteristics
can be inspected by performing a bitwise AND operation with the
following constants:
.. c:type:: RELOCS_STRIPPED
Relocation info stripped from file.
.. c:type:: EXECUTABLE_IMAGE
File is executable (i.e. no unresolved external references).
.. c:type:: LINE_NUMS_STRIPPED
Line numbers stripped from file.
.. c:type:: LOCAL_SYMS_STRIPPED
Local symbols stripped from file.
.. c:type:: AGGRESIVE_WS_TRIM
Aggressively trim working set
.. c:type:: LARGE_ADDRESS_AWARE
App can handle >2gb addresses
.. c:type:: BYTES_REVERSED_LO
Bytes of machine word are reversed.
.. c:type:: MACHINE_32BIT
32 bit word machine.
.. c:type:: DEBUG_STRIPPED
Debugging info stripped from file in .DBG file
.. c:type:: REMOVABLE_RUN_FROM_SWAP
If Image is on removable media, copy and run from the swap file.
.. c:type:: NET_RUN_FROM_SWAP
If Image is on Net, copy and run from the swap file.
.. c:type:: SYSTEM
System File.
.. c:type:: DLL
File is a DLL.
.. c:type:: UP_SYSTEM_ONLY
File should only be run on a UP machine
.. c:type:: BYTES_REVERSED_HI
Bytes of machine word are reversed.
*Example: pe.characteristics & pe.DLL*
@@ -191,8 +339,8 @@ Reference
.. c:type:: dll_characteristics
Bitmap with PE OptionalHeader DllCharacteristics. Do not confuse these
flags with the PE FileHeader Characteristics. Individual
characteristics can be inspected by performing a bitwise AND
flags with the PE FileHeader Characteristics. Individual
characteristics can be inspected by performing a bitwise AND
operation with the following constants:
.. c:type:: DYNAMIC_BASE
@@ -207,7 +355,7 @@ Reference
.. c:type:: NO_ISOLATION
.. c:type:: NO_SEH
The file does not contain structured exception handlers, this must be
The file does not contain structured exception handlers, this must be
set to use SafeSEH
.. c:type:: NO_BIND
@@ -219,6 +367,123 @@ Reference
Marks the file as terminal server compatible
.. c:type:: size_of_stack_reserve
.. versionadded:: 3.8.0
Value of IMAGE_OPTIONAL_HEADER::SizeOfStackReserve. This is the default
amount of virtual memory that will be reserved for stack.
.. c:type:: size_of_stack_commit
.. versionadded:: 3.8.0
Value of IMAGE_OPTIONAL_HEADER::SizeOfStackCommit. This is the default
amount of virtual memory that will be allocated for stack.
.. c:type:: size_of_heap_reserve
.. versionadded:: 3.8.0
Value of IMAGE_OPTIONAL_HEADER::SizeOfHeapReserve. This is the default
amount of virtual memory that will be reserved for main process heap.
.. c:type:: size_of_heap_commit
.. versionadded:: 3.8.0
Value of IMAGE_OPTIONAL_HEADER::SizeOfHeapCommit. This is the default
amount of virtual memory that will be allocated for main process heap.
.. c:type:: loader_flags
.. versionadded:: 3.8.0
Value of IMAGE_OPTIONAL_HEADER::LoaderFlags.
.. c:type:: number_of_rva_and_sizes
Value of IMAGE_OPTIONAL_HEADER::NumberOfRvaAndSizes. This is the number of
items in the IMAGE_OPTIONAL_HEADER::DataDirectory array.
.. c:type:: data_directories
.. versionadded:: 3.8.0
A zero-based array of data directories. Each data directory contains virtual
address and length of the appropriate data directory. Each data directory
has the following entries:
.. c:member:: virtual_address
Relative virtual address (RVA) of the PE data directory. If this is zero,
then the data directory is missing.
Note that for digital signature, this is the file offset, not RVA.
.. c:member:: size
Size of the PE data directory, in bytes.
The index for the data directory entry can be one of the following values:
.. c:type:: IMAGE_DIRECTORY_ENTRY_EXPORT
Data directory for exported functions.
.. c:type:: IMAGE_DIRECTORY_ENTRY_IMPORT
Data directory for import directory.
.. c:type:: IMAGE_DIRECTORY_ENTRY_RESOURCE
Data directory for resource section.
.. c:type:: IMAGE_DIRECTORY_ENTRY_EXCEPTION
Data directory for exception information.
.. c:type:: IMAGE_DIRECTORY_ENTRY_SECURITY
This is the raw file offset and length of the image digital signature.
If the image has no embedded digital signature, this directory will contain zeros.
.. c:type:: IMAGE_DIRECTORY_ENTRY_BASERELOC
Data directory for image relocation table.
.. c:type:: IMAGE_DIRECTORY_ENTRY_DEBUG
Data directory for debug information.
.. c:type:: IMAGE_DIRECTORY_ENTRY_TLS
Data directory for image thread local storage.
.. c:type:: IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
Data directory for image load configuration.
.. c:type:: IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
Data directory for image bound import table.
.. c:type:: IMAGE_DIRECTORY_ENTRY_IAT
Data directory for image Import Address Table.
.. c:type:: IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
Data directory for Delayed Import Table. Structure of the delayed import table
is linker-dependent. Microsoft version of delayed imports is described
in the souces "delayimp.h" and "delayimp.cpp", which can be found
in MS Visual Studio 2008 CRT sources.
.. c:type:: IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
Data directory for .NET headers.
*Example: pe.data_directories[pe.IMAGE_DIRECTORY_ENTRY_EXPORT].virtual_address != 0*
.. c:type:: number_of_sections
Number of sections in the PE.
@@ -255,6 +520,30 @@ Reference
Section raw size.
.. c:member:: pointer_to_relocations
.. versionadded:: 3.8.0
Value of IMAGE_SECTION_HEADER::PointerToRelocations.
.. c:member:: pointer_to_line_numbers
.. versionadded:: 3.8.0
Value of IMAGE_SECTION_HEADER::PointerToLinenumbers.
.. c:member:: number_of_relocations
.. versionadded:: 3.8.0
Value of IMAGE_SECTION_HEADER::NumberOfRelocations.
.. c:member:: number_of_line_numbers
.. versionadded:: 3.8.0
Value of IMAGE_SECTION_HEADER::NumberOfLineNumbers.
*Example: pe.sections[0].name == ".text"*
Individual section characteristics can be inspected using a bitwise AND
@@ -419,6 +708,12 @@ Reference
A zero-based array of signature objects, one for each authenticode
signature in the PE file. Usually PE files have a single signature.
.. c:member:: thumbprint
.. versionadded:: 3.8.0
A string containing the thumbprint of the signature.
.. c:member:: issuer
A string containing information about the issuer. These are some
@@ -495,7 +790,7 @@ Reference
.. c:function:: version(version, [toolid])
.. versionadded:: 3.5.0
.. versionadded:: 3.5.0
Function returning true if the PE has the specified *version* in the PE's rich
signature. Provide the optional *toolid* argument to only match when both match
@@ -507,7 +802,7 @@ Reference
.. c:function:: toolid(toolid, [version])
.. versionadded:: 3.5.0
.. versionadded:: 3.5.0
Function returning true if the PE has the specified *id* in the PE's rich
signature. Provide the optional *version* argument to only match when both
@@ -579,6 +874,17 @@ Reference
*Example: pe.imports("WS2_32.DLL", 3)*
.. c:function:: imports(dll_regexp, function_regexp)
.. versionadded:: 3.8.0
Function returning true if the PE imports a function name matching
*function_regexp* from a DLL matching *dll_regexp*. *dll_regexp* is case
sensitive unless you use the "/i" modifier in the regexp, as shown in the
example below.
*Example: pe.imports(/kernel32\.dll/i, /(Read|Write)ProcessMemory/)*
.. c:function:: locale(locale_identifier)
.. versionadded:: 3.2.0
@@ -607,26 +913,26 @@ Reference
Function returning the import hash or imphash for the PE. The imphash is
a MD5 hash of the PE's import table after some normalization. The imphash
for a PE can be also computed with `pefile <http://code.google.com/p/pefile/>`_ and you can find more information in
`Mandiant's blog <https://www.mandiant.com/blog/tracking-malware-import-hashing/>`_.
for a PE can be also computed with `pefile <http://code.google.com/p/pefile/>`_
and you can find more information in `Mandiant's blog <https://www.mandiant.com/blog/tracking-malware-import-hashing/>`_.
*Example: pe.imphash() == "b8bb385806b89680e13fc0cf24f4431e"*
.. c:function:: section_index(name)
Function returning the index into the sections array for the section that has
*name*. *name* is case sensitive.
Function returning the index into the sections array for the section that has
*name*. *name* is case sensitive.
*Example: pe.section_index(".TEXT")*
*Example: pe.section_index(".TEXT")*
.. c:function:: section_index(addr)
.. versionadded:: 3.3.0
.. versionadded:: 3.3.0
Function returning the index into the sections array for the section that has
*addr*. *addr* can be an offset into the file or a memory address.
Function returning the index into the sections array for the section that has
*addr*. *addr* can be an offset into the file or a memory address.
*Example: pe.section_index(pe.entry_point)*
*Example: pe.section_index(pe.entry_point)*
.. c:function:: is_dll()
@@ -654,8 +960,8 @@ Reference
.. c:function:: rva_to_offset(addr)
.. versionadded:: 3.6.0
.. versionadded:: 3.6.0
Function returning the file offset for RVA *addr*.
Function returning the file offset for RVA *addr*.
*Example: pe.rva_to_offset(pe.entry_point)*
*Example: pe.rva_to_offset(pe.entry_point)*
+3 -1
View File
@@ -230,7 +230,9 @@ included. Just go to the source tree root directory and type as always::
sudo make install
Now you should be able to create a rule like this::
Now you should be able to create a rule like this:
.. code-block:: yara
import "demo"
+162 -56
View File
@@ -4,7 +4,9 @@ Writing YARA rules
YARA rules are easy to write and understand, and they have a syntax that
resembles the C language. Here is the simplest rule that you can write for
YARA, which does absolutely nothing::
YARA, which does absolutely nothing:
.. code-block:: yara
rule dummy
{
@@ -73,7 +75,9 @@ section is where the strings that will be part of the rule are defined. Each
string has an identifier consisting of a $ character followed by a sequence of
alphanumeric characters and underscores, these identifiers can be used in the
condition section to refer to the corresponding string. Strings can be defined
in text or hexadecimal form, as shown in the following example::
in text or hexadecimal form, as shown in the following example:
.. code-block:: yara
rule ExampleRule
{
@@ -101,7 +105,9 @@ Comments
========
You can add comments to your YARA rules just as if it was a C source file, both
single-line and multi-line C-style comments are supported. ::
single-line and multi-line C-style comments are supported.
.. code-block:: yara
/*
This is a multi-line comment ...
@@ -130,7 +136,9 @@ Hexadecimal strings allow three special constructions that make them more
flexible: wild-cards, jumps, and alternatives. Wild-cards are just placeholders
that you can put into the string indicating that some bytes are unknown and they
should match anything. The placeholder character is the question mark (?). Here
you have an example of a hexadecimal string with wild-cards::
you have an example of a hexadecimal string with wild-cards:
.. code-block:: yara
rule WildcardExample
{
@@ -147,7 +155,9 @@ define just one nibble of the byte and leave the other unknown.
Wild-cards are useful when defining strings whose content can vary but you know
the length of the variable chunks, however, this is not always the case. In some
circumstances you may need to define strings with chunks of variable content and
length. In those situations you can use jumps instead of wild-cards::
length. In those situations you can use jumps instead of wild-cards:
.. code-block:: yara
rule JumpExample
{
@@ -200,7 +210,9 @@ The first one means ``[10-infinite]``, the second one means ``[0-infinite]``.
There are also situations in which you may want to provide different
alternatives for a given fragment of your hex string. In those situations you
can use a syntax which resembles a regular expression::
can use a syntax which resembles a regular expression:
.. code-block:: yara
rule AlternativesExample1
{
@@ -215,7 +227,9 @@ This rule will match any file containing ``F42362B445`` or ``F4235645``.
But more than two alternatives can be also expressed. In fact, there are no
limits to the amount of alternative sequences you can provide, and neither to
their lengths. ::
their lengths.
.. code-block:: yara
rule AlternativesExample2
{
@@ -232,7 +246,9 @@ allowed as part of alternative sequences.
Text strings
------------
As shown in previous sections, text strings are generally defined like this::
As shown in previous sections, text strings are generally defined like this:
.. code-block:: yara
rule TextExample
{
@@ -270,7 +286,9 @@ Case-insensitive strings
Text strings in YARA are case-sensitive by default, however you can turn your
string into case-insensitive mode by appending the modifier nocase at the end
of the string definition, in the same line::
of the string definition, in the same line:
.. code-block:: yara
rule CaseInsensitiveTextExample
{
@@ -294,7 +312,9 @@ per character, something typical in many executable binaries.
In the above figure, the string "Borland" appears encoded as two bytes per
character, therefore the following rule will match::
character, therefore the following rule will match:
.. code-block:: yara
rule WideCharTextExample1
{
@@ -309,7 +329,9 @@ However, keep in mind that this modifier just interleaves the ASCII codes of
the characters in the string with zeroes, it does not support truly UTF-16
strings containing non-English characters. If you want to search for strings
in both ASCII and wide form, you can use the ``ascii`` modifier in conjunction
with ``wide`` , no matter the order in which they appear. ::
with ``wide`` , no matter the order in which they appear.
.. code-block:: yara
rule WideCharTextExample2
{
@@ -331,7 +353,9 @@ The ``xor`` modifier can be used to search for strings with a single byte xor
applied to them.
The following rule will search for every single byte xor applied to the string
"This program cannot"::
"This program cannot":
.. code-block:: yara
rule XorExample1
{
@@ -342,7 +366,9 @@ The following rule will search for every single byte xor applied to the string
$xor_string
}
The above rule is logically equivalent to::
The above rule is logically equivalent to:
.. code-block:: yara
rule XorExample2
{
@@ -358,7 +384,9 @@ The above rule is logically equivalent to::
You can also combine the ``xor`` modifier with ``wide``, ``ascii`` and
``nocase`` modifiers. For example, to search for the ``wide`` and ``ascii``
versions of a string after every single byte xor has been applied you would
use::
use:
.. code-block:: yara
rule XorExample3
{
@@ -371,7 +399,9 @@ use::
The ``xor`` modifier is applied after every other modifier. This means that
using the ``xor`` and ``wide`` together results in the xor applying to the
interleaved zero bytes. For example, the following two rules are logically
equivalent::
equivalent:
.. code-block:: yara
rule XorExample3
{
@@ -406,7 +436,9 @@ Regular expressions
Regular expressions are one of the most powerful features of YARA. They are
defined in the same way as text strings, but enclosed in forward slashes instead
of double-quotes, like in the Perl programming language. ::
of double-quotes, like in the Perl programming language.
.. code-block:: yara
rule RegExpExample1
{
@@ -542,13 +574,15 @@ Conditions
Conditions are nothing more than Boolean expressions as those that can be found
in all programming languages, for example in an *if* statement. They can contain
the typical Boolean operators ``and``, ``or``, and ``not``, and relational operators
>=, <=, <, >, == and !=. Also, the arithmetic operators (\+, \-, \*, \\, \%)
and bitwise operators (\&, \|, <<, >>, \~, \^) can be used on numerical
``>=``, ``<=``, ``<``, ``>``, ``==`` and ``!=``. Also, the arithmetic operators (``+``, ``-``, ``*``, ``\``, ``%``)
and bitwise operators (``&``, ``|``, ``<<``, ``>>``, ``~``, ``^``) can be used on numerical
expressions.
String identifiers can be also used within a condition, acting as Boolean
variables whose value depends on the presence or not of the associated string
in the file. ::
in the file.
.. code-block:: yara
rule Example
{
@@ -569,7 +603,9 @@ Sometimes we need to know not only if a certain string is present or not,
but how many times the string appears in the file or process memory. The number
of occurrences of each string is represented by a variable whose name is the
string identifier but with a # character in place of the $ character.
For example::
For example:
.. code-block:: yara
rule CountExample
{
@@ -595,7 +631,9 @@ are willing to know if the associated string is anywhere within the file or
process memory, but sometimes we need to know if the string is at some specific
offset on the file or at some virtual address within the process address space.
In such situations the operator ``at`` is what we need. This operator is used as
shown in the following example::
shown in the following example:
.. code-block:: yara
rule AtExample
{
@@ -617,7 +655,9 @@ operator ``at`` over the ``and``.
While the ``at`` operator allows to search for a string at some fixed offset in
the file or virtual address in a process memory space, the ``in`` operator
allows to search for the string within a range of offsets or addresses. ::
allows to search for the string within a range of offsets or addresses.
.. code-block:: yara
rule InExample
{
@@ -661,7 +701,9 @@ String identifiers are not the only variables that can appear in a condition
(in fact, rules can be defined without any string definition as will be shown
below), there are other special variables that can be used as well. One of
these special variables is ``filesize``, which holds, as its name indicates,
the size of the file being scanned. The size is expressed in bytes. ::
the size of the file being scanned. The size is expressed in bytes.
.. code-block:: yara
rule FileSizeExample
{
@@ -687,7 +729,9 @@ this variable holds the raw offset of the executables entry point in case we
are scanning a file. If we are scanning a running process, the entrypoint will
hold the virtual address of the main executables entry point. A typical use of
this variable is to look for some pattern at the entry point to detect packers
or simple file infectors. ::
or simple file infectors.
.. code-block:: yara
rule EntryPointExample1
{
@@ -747,7 +791,9 @@ Both 16 and 32 bit integers are considered to be little-endian. If you
want to read a big-endian integer use the corresponding function ending
in ``be``. The <offset or virtual address> parameter can be any expression returning
an unsigned integer, including the return value of one the ``uintXX`` functions
itself. As an example let's see a rule to distinguish PE files::
itself. As an example let's see a rule to distinguish PE files:
.. code-block:: yara
rule IsPE
{
@@ -765,7 +811,9 @@ Sets of strings
There are circumstances in which it is necessary to express that the file should
contain a certain number strings from a given set. None of the strings in the
set are required to be present, but at least some of them should be. In these
situations the ``of`` operator can be used. ::
situations the ``of`` operator can be used.
.. code-block:: yara
rule OfExample1
{
@@ -784,7 +832,9 @@ using this operator, the number before the ``of`` keyword must be less than or
equal to the number of strings in the set.
The elements of the set can be explicitly enumerated like in the previous
example, or can be specified by using wild cards. For example::
example, or can be specified by using wild cards. For example:
.. code-block:: yara
rule OfExample2
{
@@ -811,7 +861,9 @@ example, or can be specified by using wild cards. For example::
}
You can even use ``($*)`` to refer to all the strings in your rule, or write
the equivalent keyword ``them`` for more legibility. ::
the equivalent keyword ``them`` for more legibility.
.. code-block:: yara
rule OfExample4
{
@@ -826,7 +878,9 @@ the equivalent keyword ``them`` for more legibility. ::
In all the examples above, the number of strings have been specified by a
numeric constant, but any expression returning a numeric value can be used.
The keywords ``any`` and ``all`` can be used as well. ::
The keywords ``any`` and ``all`` can be used as well.
.. code-block:: yara
all of them // all strings in the rule
any of them // any string in the rule
@@ -838,7 +892,9 @@ Applying the same condition to many strings
-------------------------------------------
There is another operator very similar to ``of`` but even more powerful, the
``for..of`` operator. The syntax is::
``for..of`` operator. The syntax is:
.. code-block:: yara
for expression of string_set : ( boolean_expression )
@@ -852,7 +908,9 @@ True.
Of course, ``boolean_expression`` can be any boolean expression accepted in
the condition section of a rule, except for one important detail: here you
can (and should) use a dollar sign ($) as a place-holder for the string being
evaluated. Take a look at the following expression::
evaluated. Take a look at the following expression:
.. code-block:: yara
for any of ($a,$b,$c) : ( $ at entrypoint )
@@ -861,13 +919,17 @@ it will be $a, and then $b, and then $c in the three successive evaluations
of the expression.
Maybe you already realised that the ``of`` operator is an special case of
``for..of``. The following expressions are the same::
``for..of``. The following expressions are the same:
.. code-block:: yara
any of ($a,$b,$c)
for any of ($a,$b,$c) : ( $ )
You can also employ the symbols # and @ to make reference to the number of
occurrences and the first offset of each string respectively. ::
occurrences and the first offset of each string respectively.
.. code-block:: yara
for all of them : ( # > 3 )
for all of ($a*) : ( @ > @b )
@@ -880,7 +942,9 @@ identifier assigned to each string of the rule is usually superfluous. As
we are not referencing any string individually we do not need to provide
a unique identifier for each of them. In those situations you can declare
anonymous strings with identifiers consisting only of the $ character, as in
the following example::
the following example:
.. code-block:: yara
rule AnonymousStrings
{
@@ -902,7 +966,9 @@ using the syntax: @a[i], where i is an index indicating which occurrence
of the string $a you are referring to. (@a[1], @a[2],...).
Sometimes you will need to iterate over some of these offsets and guarantee
they satisfy a given condition. For example::
they satisfy a given condition. For example:
.. code-block:: yara
rule Occurrences
{
@@ -917,13 +983,17 @@ they satisfy a given condition. For example::
The previous rule says that the first three occurrences of $b should be 10
bytes away from the first three occurrences of $a.
The same condition could be written also as::
The same condition could be written also as:
.. code-block:: yara
for all i in (1..3) : ( @a[i] + 10 == @b[i] )
Notice that were using a range (1..3) instead of enumerating the index
values (1,2,3). Of course, were not forced to use constants to specify range
boundaries, we can use expressions as well like in the following example::
boundaries, we can use expressions as well like in the following example:
.. code-block:: yara
for all i in (1..#a) : ( @a[i] < 100 )
@@ -933,12 +1003,16 @@ occurrence of $a should be within the first 100 bytes of the file.
In case you want to express that only some occurrences of the string
should satisfy your condition, the same logic seen in the ``for..of`` operator
applies here::
applies here:
.. code-block:: yara
for any i in (1..#a) : ( @a[i] < 100 )
for 2 i in (1..#a) : ( @a[i] < 100 )
In summary, the syntax of this operator is::
In summary, the syntax of this operator is:
.. code-block:: yara
for expression identifier in indexes : ( boolean_expression )
@@ -950,7 +1024,9 @@ Referencing other rules
When writing the condition for a rule you can also make reference to a
previously defined rule in a manner that resembles a function invocation of
traditional programming languages. In this way you can create rules that
depend on others. Let's see an example::
depend on others. Let's see an example:
.. code-block:: yara
rule Rule1
{
@@ -988,7 +1064,9 @@ Global rules give you the possibility of imposing restrictions in all your
rules at once. For example, suppose that you want all your rules ignoring
those files that exceed a certain size limit, you could go rule by rule making
the required modifications to their conditions, or just write a global rule
like this one::
like this one:
.. code-block:: yara
global rule SizeLimit
{
@@ -1010,7 +1088,9 @@ offered by YARA of referencing one rule from another (see
:ref:`referencing-rules`) they become useful. Private rules can serve as
building blocks for other rules, and at the same time prevent cluttering
YARA's output with irrelevant information. To delcare a rule as private
just add the keyword ``private`` before the rule declaration. ::
just add the keyword ``private`` before the rule declaration.
.. code-block:: yara
private rule PrivateRuleExample
{
@@ -1026,7 +1106,9 @@ Rule tags
Another useful feature of YARA is the possibility of adding tags to rules.
Those tags can be used later to filter YARA's output and show only the rules
that you are interested in. You can add as many tags as you want to a rule,
they are declared after the rule identifier as shown below::
they are declared after the rule identifier as shown below:
.. code-block:: yara
rule TagsExample1 : Foo Bar Baz
{
@@ -1053,7 +1135,9 @@ Metadata
Besides the string definition and condition sections, rules can also have a
metadata section where you can put additional information about your rule.
The metadata section is defined with the keyword ``meta`` and contains
identifier/value pairs like in the following example::
identifier/value pairs like in the following example:
.. code-block:: yara
rule MetadataExample
{
@@ -1089,15 +1173,18 @@ third-parties or even yourself as described in :ref:`writing-modules`.
The first step to using a module is importing it with the ``import`` statement.
These statements must be placed outside any rule definition and followed by
the module name enclosed in double-quotes. Like this::
the module name enclosed in double-quotes. Like this:
.. code-block:: yara
import "pe"
import "cuckoo"
After importing the module you can make use of its features, always using
``<module name>.`` as a prefix to any variable or function exported by the
module. For example::
module. For example:
.. code-block:: yara
pe.entry_point == 0x1000
cuckoo.http_request(/someregexp/)
@@ -1110,7 +1197,9 @@ Undefined values
Modules often leave variables in an undefined state, for example when the
variable doesn't make sense in the current context (think of ``pe.entry_point``
while scanning a non-PE file). YARA handles undefined values in way that allows
the rule to keep its meaningfulness. Take a look at this rule::
the rule to keep its meaningfulness. Take a look at this rule:
.. code-block:: yara
import "pe"
@@ -1126,7 +1215,9 @@ the rule to keep its meaningfulness. Take a look at this rule::
If the scanned file is not a PE you wouldn't expect this rule to match the file,
even if it contains the string, because **both** conditions (the presence of
the string and the right value for the entry point) must be satisfied. However,
if the condition is changed to::
if the condition is changed to:
.. code-block:: yara
$a or pe.entry_point == 0x1000
@@ -1141,7 +1232,9 @@ External variables
==================
External variables allow you to define rules which depends on values provided
from the outside. For example you can write the following rule::
from the outside. For example you can write the following rule:
.. code-block:: yara
rule ExternalVariableExample1
{
@@ -1155,7 +1248,9 @@ run-time (see ``-d`` option of command-line tool, and ``externals`` parameter of
of types: integer, string or boolean; their type depends on the value assigned
to them. An integer variable can substitute any integer constant in the
condition and boolean variables can occupy the place of boolean expressions.
For example::
For example:
.. code-block:: yara
rule ExternalVariableExample2
{
@@ -1166,8 +1261,9 @@ For example::
External variables of type string can be used with the operators: ``contains``
and ``matches``. The ``contains`` operator returns true if the string contains
the specified substring. The ``matches`` operator returns true if the string
matches the given regular expression. ::
matches the given regular expression.
.. code-block:: yara
rule ExternalVariableExample3
{
@@ -1187,7 +1283,9 @@ to be case insensitive you can use ``/[a-z]+/i``. Notice the ``i`` following the
regular expression in a Perl-like manner. You can also use the ``s`` modifier
for single-line mode, in this mode the dot matches all characters including
line breaks. Of course both modifiers can be used simultaneously, like in the
following example::
following example:
.. code-block:: yara
rule ExternalVariableExample5
{
@@ -1209,24 +1307,32 @@ YARA provides the ``include`` directive. This directive works in a similar way
to the *#include* pre-processor directive in C programs, which inserts the
content of the specified source file into the current file during compilation.
The following example will include the content of *other.yar* into the current
file::
file:
.. code-block:: yara
include "other.yar"
The base path when searching for a file in an ``include`` directive will be the
directory where the current file resides. For this reason, the file *other.yar*
in the previous example should be located in the same directory of the current
file. However, you can also specify relative paths like these::
file. However, you can also specify relative paths like these:
.. code-block:: yara
include "./includes/other.yar"
include "../includes/other.yar"
Or use absolute paths::
Or use absolute paths:
.. code-block:: yara
include "/home/plusvic/yara/includes/other.yar"
In Windows, both forward and back slashes are accepted, but dont forget to
write the drive letter::
write the drive letter:
.. code-block:: yara
include "c:/yara/includes/other.yar"
include "c:\\yara\\includes\\other.yar"
+41 -12
View File
@@ -78,9 +78,11 @@ If includes are used, a python callback can be set to define a custom source for
the imported files (by default they are read from disk). This callback function
is set through the ``include_callback`` optional parameter.
It receives the following parameters:
*``requested_filename``: file requested with 'include'
*``filename``: file containing the 'include' directive if applicable, else None
*``namespace``: namespace
* ``requested_filename``: file requested with 'include'
* ``filename``: file containing the 'include' directive if applicable, else None
* ``namespace``: namespace
And returns the requested rules sources as a single string.
.. code-block:: python
@@ -240,11 +242,10 @@ The *matches* field indicates if the rule matches the data or not. The
(<offset>, <string identifier>, <string data>)
The ``match`` method returns a list of instances of the class ``Match``.
The ``match`` method returns a list of instances of the class :py:class:`yara.Match`.
Instances of this class have the same attributes as the dictionary passed to the
callback function.
You can also specify a module callback function when invoking the ``match``
method. The provided function will be called for every imported module that
scanned a file. Your callback function should expect a single parameter of
@@ -336,22 +337,22 @@ Reference
Provide either *stack_size* or *max_strings_per_rule*. These kwargs take
unsigned integer values as input and will assign the provided value to the
yr_set_configuration(...) variables YR_CONFIG_STACK_SIZE and
YR_CONFIG_MAX_STRINGS_PER_RULE, respectively.
yr_set_configuration(...) variables ``YR_CONFIG_STACK_SIZE`` and
``YR_CONFIG_MAX_STRINGS_PER_RULE``, respectively.
:param int stack_size: Stack size to use for YR_CONFIG_STACK_SIZE
:param int stack_size: Stack size to use for ``YR_CONFIG_STACK_SIZE``
:param int max_strings_per_rule: Maximum number of strings to allow per
yara rule. Will be mapped to YR_CONFIG_MAX_STRINGS_PER_RULE.
yara rule. Will be mapped to ``YR_CONFIG_MAX_STRINGS_PER_RULE``.
:return: None
:rtype: **NoneType**
:raises: **YaraError**: If an error occurred.
.. py:class:: Rules
Instances of this class are returned by :py:func:`yara.compile` and
represents a set of compiled rules.
Instances of this class are returned by :py:func:`yara.compile` and represents
a set of compiled rules.
.. py:method:: match(filepath, pid, data, externals=None, callback=None, fast=False, timeout=None, modules_data=None, modules_callback=None)
.. py:method:: match(filepath, pid, data, externals=None, callback=None, fast=False, timeout=None, modules_data=None, modules_callback=None, which_callbacks=CALLBACK_ALL)
Scan a file, process memory or data string.
@@ -371,6 +372,9 @@ Reference
are module names and values are *bytes* objects containing the additional
data.
:param function modules_callback: Callback function invoked for each module.
:param int which_callbacks: An integer that indicates in which cases the
callback function must be called. Possible values are ``yara.CALLBACK_ALL``,
``yara.CALLBACK_MATCHES`` and ``yara.CALLBACK_NON_MATCHES``.
:raises YaraTimeoutError: If the timeout was reached.
:raises YaraError: If an error occurred during the scan.
@@ -383,3 +387,28 @@ Reference
:param str filepath: Path to the file.
:param file-object file: A file object supporting the ``write`` method.
:raises: **YaraError**: If an error occurred while saving the file.
.. py:class:: Match
Objects returned by :py:func:`yara.match`, representing a match.
.. py:attribute:: rule
Name of the matching rule.
.. py:attribute:: namespace
Namespace associated to the matching rule.
.. py:attribute:: tags
Array of strings containig the tags associated to the matching rule.
.. py:attribute:: meta
Dictionary containing metadata associated to the matching rule.
.. py:attribute:: strings
List of tuples containing information about the matching strings. Each
tuple has the form: `(<offset>, <string identifier>, <string data>)`.
+3 -1
View File
@@ -69,6 +69,7 @@ yarainclude_HEADERS = \
include/yara/ahocorasick.h \
include/yara/arena.h \
include/yara/atoms.h \
include/yara/bitmask.h \
include/yara/compiler.h \
include/yara/error.h \
include/yara/exec.h \
@@ -112,7 +113,7 @@ noinst_HEADERS = \
lib_LTLIBRARIES = libyara.la
libyara_la_LDFLAGS = -version-number 3:7:0
libyara_la_LDFLAGS = -version-number 3:8:1
BUILT_SOURCES = \
lexer.c \
@@ -128,6 +129,7 @@ libyara_la_SOURCES = \
ahocorasick.c \
arena.c \
atoms.c \
bitmask.c \
compiler.c \
endian.c \
exec.c \
+93 -86
View File
@@ -141,7 +141,7 @@ static YR_AC_STATE* _yr_ac_queue_pop(
// QUEUE* queue - The queue
//
// Returns:
// TRUE if queue is empty, FALSE otherwise.
// true if queue is empty, false otherwise.
//
static int _yr_ac_queue_is_empty(
@@ -270,7 +270,6 @@ static int _yr_ac_create_failure_links(
root_state->failure = root_state;
// Push root's children and set their failure link to root.
state = root_state->first_child;
while (state != NULL)
@@ -365,7 +364,7 @@ static int _yr_ac_create_failure_links(
// accepted in s1 too.
//
static int _yr_ac_transitions_subset(
static bool _yr_ac_transitions_subset(
YR_AC_STATE* s1,
YR_AC_STATE* s2)
{
@@ -386,12 +385,12 @@ static int _yr_ac_transitions_subset(
while (state != NULL)
{
if (!(set[state->input / 8] & 1 << state->input % 8))
return FALSE;
return false;
state = state->siblings;
}
return TRUE;
return true;
}
@@ -407,7 +406,6 @@ static int _yr_ac_optimize_failure_links(
QUEUE queue = { NULL, NULL};
// Push root's children.
YR_AC_STATE* root_state = automaton->root;
YR_AC_STATE* state = root_state->first_child;
@@ -444,11 +442,10 @@ static int _yr_ac_optimize_failure_links(
//
// _yr_ac_find_suitable_transition_table_slot
//
// Find a place within the transition table where the transitions for the given
// state can be put. The function first searches for an unused slot to put the
// failure link, then it checks if the slots corresponding to the state
// transitions (wich are at offsets 1 to 256 relative to the failure link ) are
// available too.
// Find a place within the automaton's transition table where the transitions
// for the given state can be put. The function first create a bitmask for the
// state's transition table, then searches for an offset within the automaton's
// bitmask where the state's bitmask can be put without bit collisions.
//
static int _yr_ac_find_suitable_transition_table_slot(
@@ -456,77 +453,69 @@ static int _yr_ac_find_suitable_transition_table_slot(
YR_AC_STATE* state,
uint32_t* slot)
{
YR_AC_STATE* child_state;
// The state's transition table has 257 entries, 1 for the failure link and
// 256 for each possible input byte, so the state's bitmask has 257 bits.
YR_BITMASK state_bitmask[YR_BITMASK_SIZE(257)];
uint32_t i = automaton->t_table_unused_candidate;
YR_AC_STATE* child_state = state->first_child;
int first_unused = TRUE;
int found = FALSE;
// Start with all bits set to zero.
yr_bitmask_clear_all(state_bitmask);
while (!found)
// The first slot in the transition table is for the state's failure link,
// so the first bit in the bitmask must be set to one.
yr_bitmask_set(state_bitmask, 0);
while (child_state != NULL)
{
// Check if there is enough room in the table to hold 257 items
// (1 failure link + 256 transitions) starting at offset i. If there's
// no room double the table size.
yr_bitmask_set(state_bitmask, child_state->input + 1);
child_state = child_state->siblings;
}
if (automaton->tables_size - i < 257)
{
*slot = yr_bitmask_find_non_colliding_offset(
automaton->bitmask,
state_bitmask,
automaton->tables_size,
257,
&automaton->t_table_unused_candidate);
// Make sure that we are not going beyond the maximum size of the transition
// table, starting at the slot found there must be at least 257 other slots
// for accommodating the state's transition table.
assert(*slot + 257 < YR_AC_MAX_TRANSITION_TABLE_SIZE);
if (*slot > automaton->tables_size - 257)
{
size_t t_bytes_size = automaton->tables_size *
sizeof(YR_AC_TRANSITION);
size_t m_bytes_size = automaton->tables_size *
sizeof(YR_AC_MATCH_TABLE_ENTRY);
size_t b_bytes_size = YR_BITMASK_SIZE(automaton->tables_size) *
sizeof(YR_BITMASK);
automaton->t_table = (YR_AC_TRANSITION_TABLE) yr_realloc(
automaton->t_table, t_bytes_size * 2);
automaton->m_table = (YR_AC_MATCH_TABLE) yr_realloc(
automaton->m_table, m_bytes_size * 2);
if (automaton->t_table == NULL || automaton->m_table == NULL)
automaton->bitmask = (YR_BITMASK*) yr_realloc(
automaton->bitmask, b_bytes_size * 2);
if (automaton->t_table == NULL ||
automaton->m_table == NULL ||
automaton->bitmask == NULL)
{
return ERROR_INSUFFICIENT_MEMORY;
}
memset((uint8_t*) automaton->t_table + t_bytes_size, 0, t_bytes_size);
memset((uint8_t*) automaton->m_table + m_bytes_size, 0, m_bytes_size);
memset((uint8_t*) automaton->bitmask + b_bytes_size, 0, b_bytes_size);
automaton->tables_size *= 2;
}
if (YR_AC_UNUSED_TRANSITION_SLOT(automaton->t_table[i]))
{
// A unused slot in the table has been found and could be a potential
// candidate. Let's check if table slots for the transitions are
// unused too.
found = TRUE;
child_state = state->first_child;
while (child_state != NULL)
{
if (YR_AC_USED_TRANSITION_SLOT(
automaton->t_table[child_state->input + i + 1]))
{
found = FALSE;
break;
}
child_state = child_state->siblings;
}
// If this is the first unused entry we found, use it as the first
// candidate in the next call to this function.
if (first_unused)
{
automaton->t_table_unused_candidate = found ? i + 1 : i;
first_unused = FALSE;
}
if (found)
*slot = i;
}
i++;
}
return ERROR_SUCCESS;
@@ -536,15 +525,15 @@ static int _yr_ac_find_suitable_transition_table_slot(
// _yr_ac_build_transition_table
//
// Builds the transition table for the automaton. The transition table (T) is a
// large array of 64-bits integers. Each state in the automaton is represented
// by an offset S within the array. The integer stored in T[S] is the failure
// link for state S, it contains the offset for the next state when no valid
// large array of 32-bits integers. Each state in the automaton is represented
// by an index S within the array. The integer stored in T[S] is the failure
// link for state S, it contains the index of the next state when no valid
// transition exists for the next input byte.
//
// At position T[S+1+B] (where B is a byte) we can find the transition (if any)
// that must be followed from state S if the next input is B. The value in
// T[S+1+B] contains the offset for next state or 0. The 0 means that no
// valid transition exists from state S when next input is B, and the failure
// T[S+1+B] contains the index for next state or zero. A zero value means that
// no valid transition exists from state S when next input is B, and the failure
// link must be used instead.
//
// The transition table for state S starts at T[S] and spans the next 257
@@ -554,7 +543,7 @@ static int _yr_ac_find_suitable_transition_table_slot(
// collide. For example, instead of having this transition table with state S1
// and S2 separated by a large number of slots:
//
// S1 S2
// S1 S2
// +------+------+------+------+-- ~ --+------+------+------+-- ~ --+
// | FLS1 | X | - | - | - | Y | FLS2 | Z | - |
// +------+------+------+------+-- ~ --+------+------+------+-- ~ --+
@@ -569,7 +558,7 @@ static int _yr_ac_find_suitable_transition_table_slot(
//
// And how do we know that transition Z belongs to state S2 and not S1? Or that
// transition Y belongs to S1 and not S2? Because each slot of the array not
// only contains the offset for the state where the transition points to, it
// only contains the index for the state where the transition points to, it
// also contains the offset of the transition relative to its owner state. So,
// the value for the owner offset would be 1 for transitions X, because X
// belongs to state S1 and it's located 1 position away from S1. The same occurs
@@ -578,6 +567,16 @@ static int _yr_ac_find_suitable_transition_table_slot(
// the transition at T[S1+1+2] which is Z. But we know that transition Z is not
// a valid transition for state S1 because the owner offset for Z is 1 not 3.
//
// Each 32-bit slot in the transition table has 23 bits for storing the index
// of the target state and 9 bits for storing the offset of the slot relative
// to its own state. The offset can be any value from 0 to 256, both inclusive,
// hence 9 bits are required for it. The layout for the slot goes like:
//
// 32 23 0
// +-----------------------+---------+
// | Target state's index | Offset |
// +-----------------------+---------+
//
// A more detailed description can be found in: http://goo.gl/lE6zG
@@ -594,29 +593,31 @@ static int _yr_ac_build_transition_table(
automaton->tables_size = 1024;
automaton->t_table = (YR_AC_TRANSITION_TABLE) yr_malloc(
automaton->tables_size * sizeof(YR_AC_TRANSITION));
automaton->t_table = (YR_AC_TRANSITION_TABLE) yr_calloc(
automaton->tables_size, sizeof(YR_AC_TRANSITION));
automaton->m_table = (YR_AC_MATCH_TABLE) yr_malloc(
automaton->tables_size * sizeof(YR_AC_MATCH_TABLE_ENTRY));
automaton->m_table = (YR_AC_MATCH_TABLE) yr_calloc(
automaton->tables_size, sizeof(YR_AC_MATCH_TABLE_ENTRY));
if (automaton->t_table == NULL || automaton->m_table == NULL)
automaton->bitmask = (YR_BITMASK*) yr_calloc(
YR_BITMASK_SIZE(automaton->tables_size), sizeof(YR_BITMASK));
if (automaton->t_table == NULL ||
automaton->m_table == NULL ||
automaton->bitmask == NULL)
{
yr_free(automaton->t_table);
yr_free(automaton->m_table);
yr_free(automaton->bitmask);
return ERROR_INSUFFICIENT_MEMORY;
}
memset(automaton->t_table, 0,
automaton->tables_size * sizeof(YR_AC_TRANSITION));
memset(automaton->m_table, 0,
automaton->tables_size * sizeof(YR_AC_MATCH_TABLE_ENTRY));
automaton->t_table[0] = YR_AC_MAKE_TRANSITION(0, 0, YR_AC_USED_FLAG);
automaton->t_table[0] = YR_AC_MAKE_TRANSITION(0, 0);
automaton->m_table[0].match = root_state->matches;
yr_bitmask_set(automaton->bitmask, 0);
// Index 0 is for root node. Unused indexes start at 1.
automaton->t_table_unused_candidate = 1;
@@ -626,7 +627,9 @@ static int _yr_ac_build_transition_table(
{
child_state->t_table_slot = child_state->input + 1;
automaton->t_table[child_state->input + 1] = YR_AC_MAKE_TRANSITION(
0, child_state->input + 1, YR_AC_USED_FLAG);
0, child_state->input + 1);
yr_bitmask_set(automaton->bitmask, child_state->input + 1);
FAIL_ON_ERROR(_yr_ac_queue_push(&queue, child_state));
child_state = child_state->siblings;
@@ -637,16 +640,16 @@ static int _yr_ac_build_transition_table(
state = _yr_ac_queue_pop(&queue);
FAIL_ON_ERROR(_yr_ac_find_suitable_transition_table_slot(
automaton,
state,
&slot));
automaton, state, &slot));
automaton->t_table[state->t_table_slot] |= ((uint64_t) slot << 32);
automaton->t_table[state->t_table_slot] |= (slot << YR_AC_SLOT_OFFSET_BITS);
state->t_table_slot = slot;
automaton->t_table[slot] = YR_AC_MAKE_TRANSITION(
state->failure->t_table_slot, 0, YR_AC_USED_FLAG);
state->failure->t_table_slot, 0);
yr_bitmask_set(automaton->bitmask, slot);
automaton->m_table[slot].match = state->matches;
@@ -658,7 +661,9 @@ static int _yr_ac_build_transition_table(
{
child_state->t_table_slot = slot + child_state->input + 1;
automaton->t_table[child_state->t_table_slot] = YR_AC_MAKE_TRANSITION(
0, child_state->input + 1, YR_AC_USED_FLAG);
0, child_state->input + 1);
yr_bitmask_set(automaton->bitmask, child_state->t_table_slot);
FAIL_ON_ERROR(_yr_ac_queue_push(&queue, child_state));
@@ -678,7 +683,7 @@ static int _yr_ac_build_transition_table(
//
static void _yr_ac_print_automaton_state(
YR_AC_STATE* state)
YR_AC_STATE* state)
{
int i;
int child_count;
@@ -788,6 +793,7 @@ int yr_ac_automaton_create(
new_automaton->root = root_state;
new_automaton->m_table = NULL;
new_automaton->t_table = NULL;
new_automaton->bitmask = NULL;
new_automaton->tables_size = 0;
*automaton = new_automaton;
@@ -809,6 +815,7 @@ int yr_ac_automaton_destroy(
yr_free(automaton->t_table);
yr_free(automaton->m_table);
yr_free(automaton->bitmask);
yr_free(automaton);
return ERROR_SUCCESS;
+28 -9
View File
@@ -928,6 +928,7 @@ int yr_arena_load_stream(
uint32_t reloc_offset;
uint8_t** reloc_address;
uint8_t* reloc_target;
uint32_t max_reloc_offset;
int result;
@@ -973,9 +974,11 @@ int yr_arena_load_stream(
return ERROR_CORRUPT_FILE;
}
max_reloc_offset = header.size - sizeof(uint8_t*);
while (reloc_offset != 0xFFFFFFFF)
{
if (reloc_offset > header.size - sizeof(uint8_t*))
if (reloc_offset > max_reloc_offset)
{
yr_arena_destroy(new_arena);
return ERROR_CORRUPT_FILE;
@@ -986,10 +989,19 @@ int yr_arena_load_stream(
reloc_address = (uint8_t**) (page->address + reloc_offset);
reloc_target = *reloc_address;
if (reloc_target != (uint8_t*) (size_t) 0xFFFABADA)
*reloc_address += (size_t) page->address;
else
if (reloc_target == (uint8_t*) (size_t) 0xFFFABADA)
{
*reloc_address = 0;
}
else if (reloc_target < (uint8_t*) (size_t) max_reloc_offset)
{
*reloc_address += (size_t) page->address;
}
else
{
yr_arena_destroy(new_arena);
return ERROR_CORRUPT_FILE;
}
if (yr_stream_read(&reloc_offset, sizeof(reloc_offset), 1, stream) != 1)
{
@@ -1079,8 +1091,11 @@ int yr_arena_save_stream(
header.size = (int32_t) page->size;
header.version = ARENA_FILE_VERSION;
yr_stream_write(&header, sizeof(header), 1, stream);
yr_stream_write(page->address, header.size, 1, stream);
if (yr_stream_write(&header, sizeof(header), 1, stream) != 1)
return ERROR_WRITING_FILE;
if (yr_stream_write(page->address, header.size, 1, stream) != 1)
return ERROR_WRITING_FILE;
file_hash = yr_hash(0, &header, sizeof(header));
file_hash = yr_hash(file_hash, page->address, page->used);
@@ -1090,7 +1105,8 @@ int yr_arena_save_stream(
// Convert offsets back to pointers.
while (reloc != NULL)
{
yr_stream_write(&reloc->offset, sizeof(reloc->offset), 1, stream);
if (yr_stream_write(&reloc->offset, sizeof(reloc->offset), 1, stream) != 1)
return ERROR_WRITING_FILE;
reloc_address = (uint8_t**) (page->address + reloc->offset);
reloc_target = *reloc_address;
@@ -1103,8 +1119,11 @@ int yr_arena_save_stream(
reloc = reloc->next;
}
yr_stream_write(&end_marker, sizeof(end_marker), 1, stream);
yr_stream_write(&file_hash, sizeof(file_hash), 1, stream);
if (yr_stream_write(&end_marker, sizeof(end_marker), 1, stream) != 1)
return ERROR_WRITING_FILE;
if (yr_stream_write(&file_hash, sizeof(file_hash), 1, stream) != 1)
return ERROR_WRITING_FILE;
return ERROR_SUCCESS;
}
+183 -95
View File
@@ -1,5 +1,5 @@
/*
Copyright (c) 2013. The YARA Authors. All Rights Reserved.
Copyright (c) 2013-2018. The YARA Authors. All Rights Reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
@@ -89,10 +89,6 @@ will end up using the "Look" atom alone, but in /a(bcd|efg)h/ atoms "bcd" and
#include <yara/types.h>
#define YR_MAX_ATOM_QUALITY 100000
#define YR_MIN_ATOM_QUALITY -100000
#define append_current_leaf_to_node(node) \
if (atom_tree->current_leaf != NULL) \
{ \
@@ -102,7 +98,7 @@ will end up using the "Look" atom alone, but in /a(bcd|efg)h/ atoms "bcd" and
//
// _yr_atoms_quality
// yr_atoms_heuristic_quality
//
// Returns a numeric value indicating the quality of an atom. The quality
// depends on some characteristics of the atom, including its length, number
@@ -112,21 +108,23 @@ will end up using the "Look" atom alone, but in /a(bcd|efg)h/ atoms "bcd" and
// because the same byte is repeated. Atom 01 02 03 04 is an optimal one.
//
// Args:
// uint8_t* atom - Pointer to the atom's bytes.
// int atom_length - Atom's length.
// YR_ATOMS_CONFIG* config - Pointer to YR_ATOMS_CONFIG struct.
// uint8_t* atom - Pointer to the atom's bytes.
// int atom_length - Atom's length.
//
// Returns:
// An integer indicating the atom's quality
//
static int _yr_atoms_quality(
int yr_atoms_heuristic_quality(
YR_ATOMS_CONFIG* config,
uint8_t* atom,
int atom_length)
{
int penalty = 0;
int unique_bytes = 0;
int is_unique;
int i, j;
bool is_unique;
for (i = 0; i < atom_length; i++)
{
@@ -149,12 +147,12 @@ static int _yr_atoms_quality(
}
}
is_unique = TRUE;
is_unique = true;
for (j = i + 1; j < atom_length; j++)
if (atom[i] == atom[j])
{
is_unique = FALSE;
is_unique = false;
break;
}
@@ -162,9 +160,90 @@ static int _yr_atoms_quality(
unique_bytes += 1;
}
return atom_length + unique_bytes - penalty;
// yr_max(atom_length + unique_bytes - penalty, 0) is within the range
// [0 - 2 * YR_MAX_ATOM_LENGTH], which means that the function returns a value
// in [YR_MAX_ATOM_QUALITY - 2 * YR_MAX_ATOM_LENGTH, YR_MAX_ATOM_QUALITY]
return YR_MAX_ATOM_QUALITY - 2 * YR_MAX_ATOM_LENGTH +
yr_max(atom_length + unique_bytes - penalty, 0);
}
//
// yr_atoms_table_quality
//
// Returns a numeric value indicating the quality of an atom. The quality is
// based in the atom quality table passed in "config". Very common atoms
// (i.e: those with greater quality) have lower quality than those that are
// uncommon. See the comment for yr_compiler_set_atom_quality_table for
// details about the quality table's format.
//
// Args:
// YR_ATOMS_CONFIG* config - Pointer to YR_ATOMS_CONFIG struct.
// uint8_t* atom - Pointer to the atom's bytes.
// int atom_length - Atom's length.
//
// Returns:
// An integer indicating the atom's quality
//
int yr_atoms_table_quality(
YR_ATOMS_CONFIG* config,
uint8_t* atom,
int atom_length)
{
YR_ATOM_QUALITY_TABLE_ENTRY* table = config->quality_table;
int begin = 0;
int end = config->quality_table_entries;
while (end > begin)
{
int middle = begin + (end - begin) / 2;
int c = memcmp(table[middle].atom, atom, atom_length);
if (c < 0)
{
begin = middle + 1;
}
else if (c > 0)
{
end = middle;
}
else
{
int i = middle + 1;
int quality = table[middle].quality;
int min_quality = quality;
if (atom_length == YR_MAX_ATOM_LENGTH)
return table[middle].quality;
while (i < end && memcmp(table[i].atom, atom, atom_length) == 0)
{
if (min_quality > table[i].quality)
min_quality = table[i].quality;
i++;
}
i = middle - 1;
while (i >= begin && memcmp(table[i].atom, atom, atom_length) == 0)
{
if (min_quality > table[i].quality)
min_quality = table[i].quality;
i--;
}
return min_quality >> (YR_MAX_ATOM_LENGTH - atom_length);
}
}
return YR_MAX_ATOM_QUALITY;
}
//
// yr_atoms_min_quality
//
@@ -172,6 +251,7 @@ static int _yr_atoms_quality(
//
int yr_atoms_min_quality(
YR_ATOMS_CONFIG* config,
YR_ATOM_LIST_ITEM* atom_list)
{
YR_ATOM_LIST_ITEM* atom;
@@ -186,7 +266,7 @@ int yr_atoms_min_quality(
while (atom != NULL)
{
quality = _yr_atoms_quality(atom->atom, atom->atom_length);
quality = config->get_atom_quality(config, atom->atom, atom->atom_length);
if (quality < min_quality)
min_quality = quality;
@@ -346,6 +426,7 @@ static YR_ATOM_LIST_ITEM* _yr_atoms_list_concat(
//
static int _yr_atoms_choose(
YR_ATOMS_CONFIG* config,
ATOM_TREE_NODE* node,
YR_ATOM_LIST_ITEM** chosen_atoms,
int* atoms_quality)
@@ -379,7 +460,8 @@ static int _yr_atoms_choose(
item->next = NULL;
*chosen_atoms = item;
*atoms_quality = _yr_atoms_quality(node->atom, node->atom_length);
*atoms_quality = config->get_atom_quality(
config, node->atom, node->atom_length);
break;
case ATOM_TREE_OR:
@@ -388,7 +470,7 @@ static int _yr_atoms_choose(
while (child != NULL)
{
FAIL_ON_ERROR(_yr_atoms_choose(child, &item, &quality));
FAIL_ON_ERROR(_yr_atoms_choose(config, child, &item, &quality));
if (quality > max_quality)
{
@@ -401,6 +483,9 @@ static int _yr_atoms_choose(
yr_atoms_list_destroy(item);
}
if (max_quality == YR_MAX_ATOM_QUALITY)
break;
child = child->next_sibling;
}
@@ -413,7 +498,7 @@ static int _yr_atoms_choose(
while (child != NULL)
{
FAIL_ON_ERROR(_yr_atoms_choose(child, &item, &quality));
FAIL_ON_ERROR(_yr_atoms_choose(config, child, &item, &quality));
if (quality < min_quality)
min_quality = quality;
@@ -504,14 +589,14 @@ static uint8_t* _yr_atoms_case_combinations(
}
// Size of buffer used in _yr_atoms_case_insensitive for storing the all
// the possible combinations for an atom. Each atom has up to MAX_ATOM_LENGTH
// the possible combinations for an atom. Each atom has up to YR_MAX_ATOM_LENGTH
// characters and each character has two possible values (upper and lower case).
// That means 2 ^ MAX_ATOM_LENGTH combinations for an atom, where each atom
// occupies MAX_ATOM_LENGTH + 1 bytes (the atom itself +1 byte for its length)
// That means 2 ^ YR_MAX_ATOM_LENGTH combinations for an atom, where each atom
// occupies YR_MAX_ATOM_LENGTH + 1 bytes (the atom itself +1 byte for its length)
// One extra bytes is allocated for the zero value indicating the end.
#define CASE_COMBINATIONS_BUFFER_SIZE \
(1 << MAX_ATOM_LENGTH) * (MAX_ATOM_LENGTH + 1) + 1
(1 << YR_MAX_ATOM_LENGTH) * (YR_MAX_ATOM_LENGTH + 1) + 1
//
// _yr_atoms_case_insensitive
@@ -607,7 +692,7 @@ static int _yr_atoms_xor(
for (i = 0; i < atom->atom_length; i++)
new_atom->atom[i] = atom->atom[i] ^ j;
new_atom->atom_length = yr_min(atom->atom_length, MAX_ATOM_LENGTH);
new_atom->atom_length = yr_min(atom->atom_length, YR_MAX_ATOM_LENGTH);
new_atom->forward_code = atom->forward_code;
new_atom->backward_code = atom->backward_code;
new_atom->backtrack = atom->backtrack;
@@ -647,18 +732,18 @@ static int _yr_atoms_wide(
if (new_atom == NULL)
return ERROR_INSUFFICIENT_MEMORY;
for (i = 0; i < MAX_ATOM_LENGTH; i++)
for (i = 0; i < YR_MAX_ATOM_LENGTH; i++)
new_atom->atom[i] = 0;
for (i = 0; i < atom->atom_length; i++)
{
if (i * 2 < MAX_ATOM_LENGTH)
if (i * 2 < YR_MAX_ATOM_LENGTH)
new_atom->atom[i * 2] = atom->atom[i];
else
break;
}
new_atom->atom_length = yr_min(atom->atom_length * 2, MAX_ATOM_LENGTH);
new_atom->atom_length = yr_min(atom->atom_length * 2, YR_MAX_ATOM_LENGTH);
new_atom->forward_code = atom->forward_code;
new_atom->backward_code = atom->backward_code;
new_atom->backtrack = atom->backtrack * 2;
@@ -681,9 +766,10 @@ static int _yr_atoms_wide(
//
static ATOM_TREE_NODE* _yr_atoms_extract_from_re_node(
RE_NODE* re_node,
ATOM_TREE* atom_tree,
ATOM_TREE_NODE* current_node)
YR_ATOMS_CONFIG* config,
RE_NODE* re_node,
ATOM_TREE* atom_tree,
ATOM_TREE_NODE* current_node)
{
ATOM_TREE_NODE* left_node;
ATOM_TREE_NODE* right_node;
@@ -695,7 +781,7 @@ static ATOM_TREE_NODE* _yr_atoms_extract_from_re_node(
int new_quality;
int i;
uint8_t new_atom[MAX_ATOM_LENGTH];
uint8_t new_atom[YR_MAX_ATOM_LENGTH];
switch(re_node->type)
{
@@ -717,7 +803,7 @@ static ATOM_TREE_NODE* _yr_atoms_extract_from_re_node(
current_leaf = atom_tree->current_leaf;
if (current_leaf->atom_length < MAX_ATOM_LENGTH)
if (current_leaf->atom_length < YR_MAX_ATOM_LENGTH)
{
current_leaf->atom[current_leaf->atom_length] =
(uint8_t) re_node->value;
@@ -726,35 +812,36 @@ static ATOM_TREE_NODE* _yr_atoms_extract_from_re_node(
}
else
{
for (i = 1; i < MAX_ATOM_LENGTH; i++)
current_leaf->recent_nodes[i - 1] = current_leaf->recent_nodes[i];
quality = config->get_atom_quality(
config, current_leaf->atom, YR_MAX_ATOM_LENGTH);
current_leaf->recent_nodes[MAX_ATOM_LENGTH - 1] = re_node;
for (i = 0; i < MAX_ATOM_LENGTH; i++)
new_atom[i] = (uint8_t) current_leaf->recent_nodes[i]->value;
quality = _yr_atoms_quality(
current_leaf->atom,
MAX_ATOM_LENGTH);
new_quality = _yr_atoms_quality(
new_atom,
MAX_ATOM_LENGTH);
if (new_quality > quality)
if (quality < YR_MAX_ATOM_QUALITY)
{
for (i = 0; i < MAX_ATOM_LENGTH; i++)
current_leaf->atom[i] = new_atom[i];
for (i = 1; i < YR_MAX_ATOM_LENGTH; i++)
current_leaf->recent_nodes[i - 1] = current_leaf->recent_nodes[i];
current_leaf->forward_code = \
current_leaf->recent_nodes[0]->forward_code;
current_leaf->recent_nodes[YR_MAX_ATOM_LENGTH - 1] = re_node;
current_leaf->backward_code = \
current_leaf->recent_nodes[0]->backward_code;
for (i = 0; i < YR_MAX_ATOM_LENGTH; i++)
new_atom[i] = (uint8_t) current_leaf->recent_nodes[i]->value;
assert(current_leaf->forward_code != NULL);
assert(current_leaf->backward_code != NULL);
new_quality = config->get_atom_quality(
config, new_atom, YR_MAX_ATOM_LENGTH);
if (new_quality > quality)
{
for (i = 0; i < YR_MAX_ATOM_LENGTH; i++)
current_leaf->atom[i] = new_atom[i];
current_leaf->forward_code = \
current_leaf->recent_nodes[0]->forward_code;
current_leaf->backward_code = \
current_leaf->recent_nodes[0]->backward_code;
assert(current_leaf->forward_code != NULL);
assert(current_leaf->backward_code != NULL);
}
}
}
@@ -763,13 +850,13 @@ static ATOM_TREE_NODE* _yr_atoms_extract_from_re_node(
case RE_NODE_CONCAT:
current_node = _yr_atoms_extract_from_re_node(
re_node->left, atom_tree, current_node);
config, re_node->left, atom_tree, current_node);
if (current_node == NULL)
return NULL;
current_node = _yr_atoms_extract_from_re_node(
re_node->right, atom_tree, current_node);
config, re_node->right, atom_tree, current_node);
return current_node;
@@ -783,7 +870,7 @@ static ATOM_TREE_NODE* _yr_atoms_extract_from_re_node(
return NULL;
left_node = _yr_atoms_extract_from_re_node(
re_node->left, atom_tree, left_node);
config, re_node->left, atom_tree, left_node);
if (left_node == NULL)
return NULL;
@@ -809,7 +896,7 @@ static ATOM_TREE_NODE* _yr_atoms_extract_from_re_node(
return NULL;
right_node = _yr_atoms_extract_from_re_node(
re_node->right, atom_tree, right_node);
config, re_node->right, atom_tree, right_node);
if (right_node == NULL)
return NULL;
@@ -849,14 +936,14 @@ static ATOM_TREE_NODE* _yr_atoms_extract_from_re_node(
append_current_leaf_to_node(current_node);
// In a regexp like /a{10,20}/ the optimal atom is 'aaaa' (assuming that
// MAX_ATOM_LENGTH = 4) because the 'a' character must appear at least
// YR_MAX_ATOM_LENGTH = 4) because the 'a' character must appear at least
// 10 times in the matching string. Each call in the loop will append
// one 'a' to the atom, so MAX_ATOM_LENGTH iterations are enough.
// one 'a' to the atom, so YR_MAX_ATOM_LENGTH iterations are enough.
for (i = 0; i < yr_min(re_node->start, MAX_ATOM_LENGTH); i++)
for (i = 0; i < yr_min(re_node->start, YR_MAX_ATOM_LENGTH); i++)
{
current_node = _yr_atoms_extract_from_re_node(
re_node->left, atom_tree, current_node);
config, re_node->left, atom_tree, current_node);
if (current_node == NULL)
return NULL;
@@ -870,7 +957,7 @@ static ATOM_TREE_NODE* _yr_atoms_extract_from_re_node(
case RE_NODE_PLUS:
current_node = _yr_atoms_extract_from_re_node(
re_node->left, atom_tree, current_node);
config, re_node->left, atom_tree, current_node);
if (current_node == NULL)
return NULL;
@@ -899,7 +986,7 @@ static ATOM_TREE_NODE* _yr_atoms_extract_from_re_node(
return current_node;
default:
assert(FALSE);
assert(false);
}
return NULL;
@@ -1074,6 +1161,7 @@ int yr_atoms_extract_triplets(
//
int yr_atoms_extract_from_re(
YR_ATOMS_CONFIG* config,
RE_AST* re_ast,
int flags,
YR_ATOM_LIST_ITEM** atoms)
@@ -1100,7 +1188,7 @@ int yr_atoms_extract_from_re(
atom_tree->current_leaf = NULL;
atom_tree->root_node = _yr_atoms_extract_from_re_node(
re_ast->root_node, atom_tree, atom_tree->root_node);
config, re_ast->root_node, atom_tree, atom_tree->root_node);
if (atom_tree->root_node == NULL)
{
@@ -1129,34 +1217,29 @@ int yr_atoms_extract_from_re(
{
// Choose the atoms that will be used.
FAIL_ON_ERROR_WITH_CLEANUP(
_yr_atoms_choose(atom_tree->root_node, atoms, &min_atom_quality),
_yr_atoms_choose(
config, atom_tree->root_node, atoms, &min_atom_quality),
_yr_atoms_tree_destroy(atom_tree));
}
_yr_atoms_tree_destroy(atom_tree);
if (min_atom_quality <= 2)
FAIL_ON_ERROR_WITH_CLEANUP(
yr_atoms_extract_triplets(re_ast->root_node, &triplet_atoms),
{
yr_atoms_list_destroy(*atoms);
yr_atoms_list_destroy(triplet_atoms);
*atoms = NULL;
});
if (min_atom_quality < (yr_atoms_min_quality(config, triplet_atoms) >> 1))
{
// Chosen atoms contain low quality ones, let's try infering some higher
// quality atoms.
FAIL_ON_ERROR_WITH_CLEANUP(
yr_atoms_extract_triplets(re_ast->root_node, &triplet_atoms),
{
yr_atoms_list_destroy(*atoms);
yr_atoms_list_destroy(triplet_atoms);
*atoms = NULL;
});
if (min_atom_quality < yr_atoms_min_quality(triplet_atoms))
{
yr_atoms_list_destroy(*atoms);
*atoms = triplet_atoms;
}
else
{
yr_atoms_list_destroy(triplet_atoms);
}
yr_atoms_list_destroy(*atoms);
*atoms = triplet_atoms;
}
else
{
yr_atoms_list_destroy(triplet_atoms);
}
if (flags & STRING_GFLAGS_WIDE)
@@ -1220,6 +1303,7 @@ int yr_atoms_extract_from_re(
//
int yr_atoms_extract_from_string(
YR_ATOMS_CONFIG* config,
uint8_t* string,
int32_t string_length,
int flags,
@@ -1243,26 +1327,30 @@ int yr_atoms_extract_from_string(
item->next = NULL;
item->backtrack = 0;
length = yr_min(string_length, MAX_ATOM_LENGTH);
length = yr_min(string_length, YR_MAX_ATOM_LENGTH);
for (i = 0; i < length; i++)
item->atom[i] = string[i];
item->atom_length = i;
max_quality = _yr_atoms_quality(string, length);
max_quality = config->get_atom_quality(config, string, length);
for (i = MAX_ATOM_LENGTH; i < string_length; i++)
for (i = YR_MAX_ATOM_LENGTH;
i < string_length && max_quality < YR_MAX_ATOM_QUALITY;
i++)
{
int quality = _yr_atoms_quality(
string + i - MAX_ATOM_LENGTH + 1, MAX_ATOM_LENGTH);
int quality = config->get_atom_quality(
config,
string + i - YR_MAX_ATOM_LENGTH + 1,
YR_MAX_ATOM_LENGTH);
if (quality > max_quality)
{
for (j = 0; j < MAX_ATOM_LENGTH; j++)
item->atom[j] = string[i + j - MAX_ATOM_LENGTH + 1];
for (j = 0; j < YR_MAX_ATOM_LENGTH; j++)
item->atom[j] = string[i + j - YR_MAX_ATOM_LENGTH + 1];
item->backtrack = i - MAX_ATOM_LENGTH + 1;
item->backtrack = i - YR_MAX_ATOM_LENGTH + 1;
max_quality = quality;
}
}
+113
View File
@@ -0,0 +1,113 @@
/*
Copyright (c) 2018. The YARA Authors. All Rights Reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <yara/utils.h>
#include <yara/bitmask.h>
//
// yr_bitmask_find_non_colliding_offset
//
// Finds the smaller offset within bitmask A where bitmask B can be accommodated
// without bit collisions. A collision occurs when bots bitmasks have a bit set
// to 1 at the same offset. This function assumes that the first bit in B is 1
// and do optimizations that rely on that.
//
// The function also receives a pointer to an uint64_t where the function stores
// a value that is used for speeding-up subsequent searches over the same
// bitmask A. When called for the first time with some bitmask A, the pointer
// must point to zero-initialized uint64_t. In the next call the function uses
// the previously stored value for skiping over a portion of the A bitmask and
// updates the value.
//
// Args:
// YR_BITMASK* a - Bitmask A
// YR_BITMASK* b - Bitmask B
// uint64_t len_a - Length of bitmask A in bits
// uint64_t len_b - Length of bitmask B in bits
// uint64_t* hint - Address of an uint64_t where the function writes a
// value that can be used as a hint.
// Returns:
// The smaller offset within bitmask A where bitmask B can be put.
//
uint32_t yr_bitmask_find_non_colliding_offset(
YR_BITMASK* a,
YR_BITMASK* b,
uint32_t len_a,
uint32_t len_b,
uint32_t* off_a)
{
uint32_t i, j, k;
// Ensure that the first bit of bitmask B is set, as this function does some
// optimizations that rely on that.
assert(yr_bitmask_isset(b, 0));
// Skip all slots that are filled with 1s. It's safe to do that because the
// first bit of B is 1, so we won't be able to accommodate B at any offset
// within such slots.
for (i = *off_a / YR_BITMASK_SLOT_BITS;
i <= len_a / YR_BITMASK_SLOT_BITS && a[i] == -1L;
i++);
*off_a = i;
for (; i <= len_a / YR_BITMASK_SLOT_BITS; i++)
{
// The slot is filled with 1s, we can safely skip it.
if (a[i] == -1L)
continue;
for (j = 0; j <= yr_min(len_a, YR_BITMASK_SLOT_BITS - 1); j++)
{
bool found = true;
for (k = 0; k <= len_b / YR_BITMASK_SLOT_BITS; k++)
{
YR_BITMASK m = b[k] << j;
if (j > 0 && k > 0)
m |= b[k - 1] >> (YR_BITMASK_SLOT_BITS - j);
if ((i + k <= len_a / YR_BITMASK_SLOT_BITS) && (m & a[i + k]) != 0)
{
found = false;
break ;
}
}
if (found)
return i * YR_BITMASK_SLOT_BITS + j;
}
}
return len_a;
}
+264 -202
View File
@@ -1,5 +1,5 @@
/*
Copyright (c) 2013. The YARA Authors. All Rights Reserved.
Copyright (c) 2013-2018. The YARA Authors. All Rights Reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
@@ -171,7 +171,6 @@ YR_API int yr_compiler_create(
new_compiler->last_error = ERROR_SUCCESS;
new_compiler->last_error_line = 0;
new_compiler->current_line = 0;
new_compiler->last_result = ERROR_SUCCESS;
new_compiler->file_name_stack_ptr = 0;
new_compiler->fixup_stack_head = NULL;
new_compiler->loop_depth = 0;
@@ -179,6 +178,9 @@ YR_API int yr_compiler_create(
new_compiler->compiled_rules_arena = NULL;
new_compiler->namespaces_count = 0;
new_compiler->current_rule = NULL;
new_compiler->atoms_config.get_atom_quality = yr_atoms_heuristic_quality;
new_compiler->atoms_config.quality_warning_threshold = \
YR_ATOM_QUALITY_WARNING_THRESHOLD;
result = yr_hash_table_create(10007, &new_compiler->rules_table);
@@ -276,6 +278,9 @@ YR_API void yr_compiler_destroy(
compiler->objects_table,
(YR_HASH_TABLE_FREE_VALUE_FUNC) yr_object_destroy);
if (compiler-> atoms_config.free_quality_table)
yr_free(compiler->atoms_config.quality_table);
for (i = 0; i < compiler->file_name_stack_ptr; i++)
yr_free(compiler->file_name_stack[i]);
@@ -324,6 +329,103 @@ YR_API void yr_compiler_set_re_ast_callback(
}
//
// yr_compiler_set_atom_quality_table
//
// This function allows to specify an atom quality table to be used by the
// compiler for choosing the best atoms from regular expressions and strings.
// When a quality table is set, the compiler uses yr_atoms_table_quality
// instead of yr_atoms_heuristic_quality for computing atom quality. The table
// has an arbitary number of entries, each composed of YR_MAX_ATOM_LENGTH + 1
// bytes. The first YR_MAX_ATOM_LENGTH bytes from each entry are the atom's
// ones, and the remaining byte is a value in the range 0-255 determining the
// atom's quality. Entries must be lexicografically sorted by atom in ascending
// order.
//
// [ atom (YR_MAX_ATOM_LENGTH bytes) ] [ quality (1 byte) ]
//
// [ 00 00 .. 00 00 ] [ 00 ]
// [ 00 00 .. 00 01 ] [ 45 ]
// [ 00 00 .. 00 02 ] [ 13 ]
// ...
// [ FF FF .. FF FF ] [ 03 ]
//
// The "table" argument must point to a buffer containing the quality in
// the format explained above, and "entries" must contain the number of entries
// in the table. The table can not be freed while the compiler is in use, the
// caller is responsible for freeing the table.
//
// The "warning_threshold" argument must be a number between 0 and 255, if some
// atom choosen for a string have a quality below the specified threshold a
// warning like "<string> is slowing down scanning" is shown.
YR_API void yr_compiler_set_atom_quality_table(
YR_COMPILER* compiler,
const void* table,
int entries,
unsigned char warning_threshold)
{
compiler->atoms_config.free_quality_table = false;
compiler->atoms_config.quality_warning_threshold = warning_threshold;
compiler->atoms_config.get_atom_quality = yr_atoms_table_quality;
compiler->atoms_config.quality_table_entries = entries;
compiler->atoms_config.quality_table = \
(YR_ATOM_QUALITY_TABLE_ENTRY*) table;
}
//
// yr_compiler_set_atom_quality_table
//
// Load an atom quality table from a file. The file's content must have the
// format explained in the decription for yr_compiler_set_atom_quality_table.
//
YR_API int yr_compiler_load_atom_quality_table(
YR_COMPILER* compiler,
const char* filename,
unsigned char warning_threshold)
{
long file_size;
int entries;
void* table;
FILE* fh = fopen(filename, "rb");
if (fh == NULL)
return ERROR_COULD_NOT_OPEN_FILE;
fseek(fh, 0L, SEEK_END);
file_size = ftell(fh);
fseek(fh, 0L, SEEK_SET);
table = yr_malloc(file_size);
if (table == NULL)
{
fclose(fh);
return ERROR_INSUFFICIENT_MEMORY;
}
entries = (int) file_size / sizeof(YR_ATOM_QUALITY_TABLE_ENTRY);
if (fread(table, sizeof(YR_ATOM_QUALITY_TABLE_ENTRY), entries, fh) != entries)
{
fclose(fh);
yr_free(table);
return ERROR_COULD_NOT_READ_FILE;
}
fclose(fh);
yr_compiler_set_atom_quality_table(
compiler, table, entries, warning_threshold);
compiler->atoms_config.free_quality_table = true;
return ERROR_SUCCESS;
}
int _yr_compiler_push_file_name(
YR_COMPILER* compiler,
const char* file_name)
@@ -334,29 +436,21 @@ int _yr_compiler_push_file_name(
for (i = 0; i < compiler->file_name_stack_ptr; i++)
{
if (strcmp(file_name, compiler->file_name_stack[i]) == 0)
{
compiler->last_result = ERROR_INCLUDES_CIRCULAR_REFERENCE;
return ERROR_INCLUDES_CIRCULAR_REFERENCE;
}
}
if (compiler->file_name_stack_ptr < MAX_INCLUDE_DEPTH)
{
str = yr_strdup(file_name);
if (str == NULL)
return ERROR_INSUFFICIENT_MEMORY;
compiler->file_name_stack[compiler->file_name_stack_ptr] = str;
compiler->file_name_stack_ptr++;
return ERROR_SUCCESS;
}
else
{
compiler->last_result = ERROR_INCLUDE_DEPTH_EXCEEDED;
if (compiler->file_name_stack_ptr == YR_MAX_INCLUDE_DEPTH)
return ERROR_INCLUDE_DEPTH_EXCEEDED;
}
str = yr_strdup(file_name);
if (str == NULL)
return ERROR_INSUFFICIENT_MEMORY;
compiler->file_name_stack[compiler->file_name_stack_ptr] = str;
compiler->file_name_stack_ptr++;
return ERROR_SUCCESS;
}
@@ -395,16 +489,16 @@ static int _yr_compiler_set_namespace(
char* ns_name;
int result;
int i;
int found;
bool found;
ns = (YR_NAMESPACE*) yr_arena_base_address(compiler->namespaces_arena);
found = FALSE;
found = false;
for (i = 0; i < compiler->namespaces_count; i++)
{
if (strcmp(ns->name, namespace_) == 0)
{
found = TRUE;
found = true;
break;
}
@@ -434,7 +528,7 @@ static int _yr_compiler_set_namespace(
ns->name = ns_name;
for (i = 0; i < MAX_THREADS; i++)
for (i = 0; i < YR_MAX_THREADS; i++)
ns->t_flags[i] = 0;
compiler->namespaces_count++;
@@ -451,6 +545,8 @@ YR_API int yr_compiler_add_file(
const char* namespace_,
const char* file_name)
{
int result;
// Don't allow yr_compiler_add_file() after
// yr_compiler_get_rules() has been called.
@@ -461,24 +557,23 @@ YR_API int yr_compiler_add_file(
assert(compiler->errors == 0);
if (file_name != NULL)
_yr_compiler_push_file_name(compiler, file_name);
if (namespace_ != NULL)
compiler->last_result = _yr_compiler_set_namespace(compiler, namespace_);
compiler->last_error = _yr_compiler_set_namespace(compiler, namespace_);
else
compiler->last_result = _yr_compiler_set_namespace(compiler, "default");
compiler->last_error = _yr_compiler_set_namespace(compiler, "default");
if (compiler->last_result == ERROR_SUCCESS)
{
return yr_lex_parse_rules_file(rules_file, compiler);
}
else
{
compiler->errors++;
return compiler->errors;
}
if (compiler->last_error == ERROR_SUCCESS && file_name != NULL)
compiler->last_error = _yr_compiler_push_file_name(compiler, file_name);
if (compiler->last_error != ERROR_SUCCESS)
return ++compiler->errors;
result = yr_lex_parse_rules_file(rules_file, compiler);
if (file_name != NULL)
_yr_compiler_pop_file_name(compiler);
return result;
}
@@ -488,6 +583,8 @@ YR_API int yr_compiler_add_fd(
const char* namespace_,
const char* file_name)
{
int result;
// Don't allow yr_compiler_add_fd() after
// yr_compiler_get_rules() has been called.
@@ -496,25 +593,25 @@ YR_API int yr_compiler_add_fd(
// Don't allow calls to yr_compiler_add_fd() if a previous call to
// yr_compiler_add_XXXX failed.
assert(compiler->last_error == ERROR_SUCCESS);
if (file_name != NULL)
_yr_compiler_push_file_name(compiler, file_name);
assert(compiler->errors == 0);
if (namespace_ != NULL)
compiler->last_result = _yr_compiler_set_namespace(compiler, namespace_);
compiler->last_error = _yr_compiler_set_namespace(compiler, namespace_);
else
compiler->last_result = _yr_compiler_set_namespace(compiler, "default");
compiler->last_error = _yr_compiler_set_namespace(compiler, "default");
if (compiler->last_result == ERROR_SUCCESS)
{
return yr_lex_parse_rules_fd(rules_fd, compiler);
}
else
{
compiler->errors++;
return compiler->errors;
}
if (compiler->last_error == ERROR_SUCCESS && file_name != NULL)
compiler->last_error = _yr_compiler_push_file_name(compiler, file_name);
if (compiler->last_error != ERROR_SUCCESS)
return ++compiler->errors;
result = yr_lex_parse_rules_fd(rules_fd, compiler);
if (file_name != NULL)
_yr_compiler_pop_file_name(compiler);
return result;
}
@@ -531,27 +628,22 @@ YR_API int yr_compiler_add_string(
// Don't allow calls to yr_compiler_add_string() if a previous call to
// yr_compiler_add_XXXX failed.
assert(compiler->last_error == ERROR_SUCCESS);
assert(compiler->errors == 0);
if (namespace_ != NULL)
compiler->last_result = _yr_compiler_set_namespace(compiler, namespace_);
compiler->last_error = _yr_compiler_set_namespace(compiler, namespace_);
else
compiler->last_result = _yr_compiler_set_namespace(compiler, "default");
compiler->last_error = _yr_compiler_set_namespace(compiler, "default");
if (compiler->last_result == ERROR_SUCCESS)
{
return yr_lex_parse_rules_string(rules_string, compiler);
}
else
{
compiler->errors++;
return compiler->errors;
}
if (compiler->last_error != ERROR_SUCCESS)
return ++compiler->errors;
return yr_lex_parse_rules_string(rules_string, compiler);
}
static int _yr_compiler_compile_rules(
YR_COMPILER* compiler)
YR_COMPILER* compiler)
{
YARA_RULES_FILE_HEADER* rules_file_header = NULL;
YR_ARENA* arena = NULL;
@@ -606,8 +698,8 @@ static int _yr_compiler_compile_rules(
offsetof(YARA_RULES_FILE_HEADER, rules_list_head),
offsetof(YARA_RULES_FILE_HEADER, externals_list_head),
offsetof(YARA_RULES_FILE_HEADER, code_start),
offsetof(YARA_RULES_FILE_HEADER, match_table),
offsetof(YARA_RULES_FILE_HEADER, transition_table),
offsetof(YARA_RULES_FILE_HEADER, ac_match_table),
offsetof(YARA_RULES_FILE_HEADER, ac_transition_table),
EOL);
if (result == ERROR_SUCCESS)
@@ -621,8 +713,9 @@ static int _yr_compiler_compile_rules(
rules_file_header->code_start = (uint8_t*) yr_arena_base_address(
compiler->code_arena);
rules_file_header->match_table = tables.matches;
rules_file_header->transition_table = tables.transitions;
rules_file_header->ac_match_table = tables.matches;
rules_file_header->ac_transition_table = tables.transitions;
rules_file_header->ac_tables_size = compiler->automaton->tables_size;
}
if (result == ERROR_SUCCESS)
@@ -729,7 +822,7 @@ YR_API int yr_compiler_get_rules(
// Don't allow calls to yr_compiler_get_rules() if a previous call to
// yr_compiler_add_XXXX failed.
assert(compiler->last_error == ERROR_SUCCESS);
assert(compiler->errors == 0);
*rules = NULL;
@@ -750,8 +843,9 @@ YR_API int yr_compiler_get_rules(
yara_rules->externals_list_head = rules_file_header->externals_list_head;
yara_rules->rules_list_head = rules_file_header->rules_list_head;
yara_rules->match_table = rules_file_header->match_table;
yara_rules->transition_table = rules_file_header->transition_table;
yara_rules->ac_match_table = rules_file_header->ac_match_table;
yara_rules->ac_transition_table = rules_file_header->ac_transition_table;
yara_rules->ac_tables_size = rules_file_header->ac_tables_size;
yara_rules->code_start = rules_file_header->code_start;
yara_rules->time_cost = 0;
@@ -768,44 +862,84 @@ YR_API int yr_compiler_get_rules(
return ERROR_SUCCESS;
}
int _yr_compiler_define_variable(
YR_COMPILER* compiler,
YR_EXTERNAL_VARIABLE* external)
{
YR_EXTERNAL_VARIABLE* ext;
YR_OBJECT* object;
char* id;
object = (YR_OBJECT*) yr_hash_table_lookup(
compiler->objects_table,
external->identifier,
NULL);
if (object != NULL)
return ERROR_DUPLICATED_EXTERNAL_VARIABLE;
FAIL_ON_ERROR(yr_arena_write_string(
compiler->sz_arena,
external->identifier,
&id));
FAIL_ON_ERROR(yr_arena_allocate_struct(
compiler->externals_arena,
sizeof(YR_EXTERNAL_VARIABLE),
(void**) &ext,
offsetof(YR_EXTERNAL_VARIABLE, identifier),
EOL));
ext->identifier = id;
ext->type = external->type;
ext->value = external->value;
if (external->type == EXTERNAL_VARIABLE_TYPE_STRING)
{
char* val;
FAIL_ON_ERROR(yr_arena_write_string(
compiler->sz_arena,
external->value.s,
&val));
ext->value.s = val;
FAIL_ON_ERROR(yr_arena_make_ptr_relocatable(
compiler->externals_arena,
ext,
offsetof(YR_EXTERNAL_VARIABLE, value.s),
EOL));
}
FAIL_ON_ERROR(yr_object_from_external_variable(
external,
&object));
FAIL_ON_ERROR(yr_hash_table_add(
compiler->objects_table,
external->identifier,
NULL,
(void*) object));
return ERROR_SUCCESS;
}
YR_API int yr_compiler_define_integer_variable(
YR_COMPILER* compiler,
const char* identifier,
int64_t value)
{
YR_EXTERNAL_VARIABLE* external;
YR_OBJECT* object;
YR_EXTERNAL_VARIABLE external;
char* id;
external.type = EXTERNAL_VARIABLE_TYPE_INTEGER;
external.identifier = identifier;
external.value.i = value;
compiler->last_result = ERROR_SUCCESS;
FAIL_ON_COMPILER_ERROR(yr_arena_write_string(
compiler->sz_arena,
identifier,
&id));
FAIL_ON_COMPILER_ERROR(yr_arena_allocate_struct(
compiler->externals_arena,
sizeof(YR_EXTERNAL_VARIABLE),
(void**) &external,
offsetof(YR_EXTERNAL_VARIABLE, identifier),
EOL));
external->type = EXTERNAL_VARIABLE_TYPE_INTEGER;
external->identifier = id;
external->value.i = value;
FAIL_ON_COMPILER_ERROR(yr_object_from_external_variable(
external,
&object));
FAIL_ON_COMPILER_ERROR(yr_hash_table_add(
compiler->objects_table,
external->identifier,
NULL,
(void*) object));
FAIL_ON_ERROR(_yr_compiler_define_variable(
compiler, &external));
return ERROR_SUCCESS;
}
@@ -816,38 +950,14 @@ YR_API int yr_compiler_define_boolean_variable(
const char* identifier,
int value)
{
YR_EXTERNAL_VARIABLE* external;
YR_OBJECT* object;
YR_EXTERNAL_VARIABLE external;
char* id;
external.type = EXTERNAL_VARIABLE_TYPE_BOOLEAN;
external.identifier = identifier;
external.value.i = value;
compiler->last_result = ERROR_SUCCESS;
FAIL_ON_COMPILER_ERROR(yr_arena_write_string(
compiler->sz_arena,
identifier,
&id));
FAIL_ON_COMPILER_ERROR(yr_arena_allocate_struct(
compiler->externals_arena,
sizeof(YR_EXTERNAL_VARIABLE),
(void**) &external,
offsetof(YR_EXTERNAL_VARIABLE, identifier),
EOL));
external->type = EXTERNAL_VARIABLE_TYPE_BOOLEAN;
external->identifier = id;
external->value.i = value;
FAIL_ON_COMPILER_ERROR(yr_object_from_external_variable(
external,
&object));
FAIL_ON_COMPILER_ERROR(yr_hash_table_add(
compiler->objects_table,
external->identifier,
NULL,
(void*) object));
FAIL_ON_ERROR(_yr_compiler_define_variable(
compiler, &external));
return ERROR_SUCCESS;
}
@@ -858,38 +968,14 @@ YR_API int yr_compiler_define_float_variable(
const char* identifier,
double value)
{
YR_EXTERNAL_VARIABLE* external;
YR_OBJECT* object;
YR_EXTERNAL_VARIABLE external;
char* id;
external.type = EXTERNAL_VARIABLE_TYPE_FLOAT;
external.identifier = identifier;
external.value.f = value;
compiler->last_result = ERROR_SUCCESS;
FAIL_ON_COMPILER_ERROR(yr_arena_write_string(
compiler->sz_arena,
identifier,
&id));
FAIL_ON_COMPILER_ERROR(yr_arena_allocate_struct(
compiler->externals_arena,
sizeof(YR_EXTERNAL_VARIABLE),
(void**) &external,
offsetof(YR_EXTERNAL_VARIABLE, identifier),
EOL));
external->type = EXTERNAL_VARIABLE_TYPE_FLOAT;
external->identifier = id;
external->value.f = value;
FAIL_ON_COMPILER_ERROR(yr_object_from_external_variable(
external,
&object));
FAIL_ON_COMPILER_ERROR(yr_hash_table_add(
compiler->objects_table,
external->identifier,
NULL,
(void*) object));
FAIL_ON_ERROR(_yr_compiler_define_variable(
compiler, &external));
return ERROR_SUCCESS;
}
@@ -900,47 +986,16 @@ YR_API int yr_compiler_define_string_variable(
const char* identifier,
const char* value)
{
YR_OBJECT* object;
YR_EXTERNAL_VARIABLE* external;
YR_EXTERNAL_VARIABLE external;
char* id = NULL;
char* val = NULL;
external.type = EXTERNAL_VARIABLE_TYPE_STRING;
external.identifier = identifier;
external.value.s = (char*) value;
compiler->last_result = ERROR_SUCCESS;
FAIL_ON_ERROR(_yr_compiler_define_variable(
compiler, &external));
FAIL_ON_COMPILER_ERROR(yr_arena_write_string(
compiler->sz_arena,
identifier,
&id));
FAIL_ON_COMPILER_ERROR(yr_arena_write_string(
compiler->sz_arena,
value,
&val));
FAIL_ON_COMPILER_ERROR(yr_arena_allocate_struct(
compiler->externals_arena,
sizeof(YR_EXTERNAL_VARIABLE),
(void**) &external,
offsetof(YR_EXTERNAL_VARIABLE, identifier),
offsetof(YR_EXTERNAL_VARIABLE, value.s),
EOL));
external->type = EXTERNAL_VARIABLE_TYPE_STRING;
external->identifier = id;
external->value.s = val;
FAIL_ON_COMPILER_ERROR(yr_object_from_external_variable(
external,
&object));
FAIL_ON_COMPILER_ERROR(yr_hash_table_add(
compiler->objects_table,
external->identifier,
NULL,
(void*) object));
return compiler->last_result;
return ERROR_SUCCESS;
}
@@ -1156,6 +1211,13 @@ YR_API char* yr_compiler_get_error_message(
buffer_size,
"integer overflow in \"%s\"",
compiler->last_error_extra_info);
break;
case ERROR_COULD_NOT_READ_FILE:
snprintf(
buffer,
buffer_size,
"could not read file");
break;
}
return buffer;
+3 -5
View File
@@ -37,7 +37,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <windows.h>
#include <setjmp.h>
jmp_buf *exc_jmp_buf[MAX_THREADS];
jmp_buf *exc_jmp_buf[YR_MAX_THREADS];
static LONG CALLBACK exception_handler(
PEXCEPTION_POINTERS ExceptionInfo)
@@ -105,7 +105,7 @@ static LONG CALLBACK exception_handler(
#include <setjmp.h>
#include <signal.h>
sigjmp_buf *exc_jmp_buf[MAX_THREADS];
sigjmp_buf *exc_jmp_buf[YR_MAX_THREADS];
static void exception_handler(int sig) {
if (sig == SIGBUS || sig == SIGSEGV)
@@ -113,9 +113,7 @@ static void exception_handler(int sig) {
int tidx = yr_get_tidx();
if (tidx != -1 && exc_jmp_buf[tidx] != NULL)
siglongjmp(*exc_jmp_buf[tidx], 1);
assert(FALSE); // We should not reach this point.
siglongjmp(*exc_jmp_buf[tidx], 1);
}
}
+124 -22
View File
@@ -32,7 +32,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string.h>
#include <assert.h>
#include <math.h>
#include <float.h>
#include <yara/globals.h>
#include <yara/arena.h>
#include <yara/endian.h>
#include <yara/exec.h>
@@ -50,7 +52,26 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <yara.h>
#define MEM_SIZE MAX_LOOP_NESTING * LOOP_LOCAL_VARS
// Turn on paranoid mode by default if not defined otherwise. In paranoid
// mode additional checks are performed in order to mitigate the effects of
// malicious tampering with compiled rules. Such checks are not necessary
// when you can ensure that the compiled rules are executed exactly as they
// were generated by YARA, without any further modification. Check issue #891
// (https://github.com/VirusTotal/yara/issues/891) for more context.
//
// Paranoid mode does not guarantee that it's safe to load compiled rules from
// third parties, it only prevents severe security issues. Maliciously crafted
// compiled rules can still crash YARA. Loading third-party compiled rules is
// *highly* undiscouraged. If you need to distribute YARA rules in compiled
// form you should encapsulate them in some digitally-signed package that
// ensure that they haven't been modified by someone else.
#if !defined(PARANOID_EXEC)
#define PARANOID_EXEC 1
#endif
#define MEM_SIZE YR_MAX_LOOP_NESTING * LOOP_LOCAL_VARS
#define push(x) \
@@ -61,7 +82,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
else \
{ \
result = ERROR_EXEC_STACK_OVERFLOW; \
stop = TRUE; \
stop = true; \
break; \
} \
@@ -78,6 +99,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
break; \
}
#define ensure_within_mem(x) \
if (x < 0 || x >= MEM_SIZE) \
{ \
stop = true; \
result = ERROR_INTERNAL_FATAL_ERROR; \
break; \
}
#define check_object_canary(o) \
if (o->canary != yr_canary) \
{ \
stop = true; \
result = ERROR_INTERNAL_FATAL_ERROR; \
break; \
}
#define little_endian_uint8_t(x) (x)
#define little_endian_int8_t(x) (x)
@@ -159,7 +195,7 @@ int yr_execute_code(
const uint8_t* ip = context->rules->code_start;
YR_VALUE args[MAX_FUNCTION_ARGS];
YR_VALUE args[YR_MAX_FUNCTION_ARGS];
YR_VALUE *stack;
YR_VALUE r1;
YR_VALUE r2;
@@ -187,11 +223,12 @@ int yr_execute_code(
int found;
int count;
int result = ERROR_SUCCESS;
int stop = FALSE;
int cycle = 0;
int tidx = context->tidx;
int stack_size;
bool stop = false;
uint8_t opcode;
yr_get_configuration(YR_CONFIG_STACK_SIZE, (void*) &stack_size);
@@ -221,7 +258,7 @@ int yr_execute_code(
case OP_HALT:
assert(sp == 0); // When HALT is reached the stack should be empty.
stop = TRUE;
stop = true;
break;
case OP_PUSH:
@@ -237,12 +274,18 @@ int yr_execute_code(
case OP_CLEAR_M:
r1.i = *(uint64_t*)(ip);
ip += sizeof(uint64_t);
#if PARANOID_EXEC
ensure_within_mem(r1.i);
#endif
mem[r1.i] = 0;
break;
case OP_ADD_M:
r1.i = *(uint64_t*)(ip);
ip += sizeof(uint64_t);
#if PARANOID_EXEC
ensure_within_mem(r1.i);
#endif
pop(r2);
if (!is_undef(r2))
mem[r1.i] += r2.i;
@@ -251,12 +294,18 @@ int yr_execute_code(
case OP_INCR_M:
r1.i = *(uint64_t*)(ip);
ip += sizeof(uint64_t);
#if PARANOID_EXEC
ensure_within_mem(r1.i);
#endif
mem[r1.i]++;
break;
case OP_PUSH_M:
r1.i = *(uint64_t*)(ip);
ip += sizeof(uint64_t);
#if PARANOID_EXEC
ensure_within_mem(r1.i);
#endif
r1.i = mem[r1.i];
push(r1);
break;
@@ -264,6 +313,9 @@ int yr_execute_code(
case OP_POP_M:
r1.i = *(uint64_t*)(ip);
ip += sizeof(uint64_t);
#if PARANOID_EXEC
ensure_within_mem(r1.i);
#endif
pop(r2);
mem[r1.i] = r2.i;
break;
@@ -271,6 +323,9 @@ int yr_execute_code(
case OP_SWAPUNDEF:
r1.i = *(uint64_t*)(ip);
ip += sizeof(uint64_t);
#if PARANOID_EXEC
ensure_within_mem(r1.i);
#endif
pop(r2);
if (is_undef(r2))
@@ -463,7 +518,11 @@ int yr_execute_code(
#ifdef PROFILING_ENABLED
elapsed_time = yr_stopwatch_elapsed_us(&context->stopwatch);
rule->time_cost += (elapsed_time - start_time);
#ifdef _WIN32
InterlockedAdd64(&rule->time_cost, elapsed_time - start_time);
#else
__sync_fetch_and_add(&rule->time_cost, elapsed_time - start_time);
#endif
start_time = elapsed_time;
#endif
@@ -500,6 +559,10 @@ int yr_execute_code(
pop(r1);
ensure_defined(r1);
#if PARANOID_EXEC
check_object_canary(r1.o);
#endif
switch(r1.o->type)
{
case OBJECT_TYPE_INTEGER:
@@ -521,7 +584,7 @@ int yr_execute_code(
break;
default:
assert(FALSE);
assert(false);
}
push(r1);
@@ -533,8 +596,13 @@ int yr_execute_code(
ensure_defined(r1);
ensure_defined(r2);
assert(r2.o->type == OBJECT_TYPE_ARRAY);
#if PARANOID_EXEC
check_object_canary(r2.o);
#endif
r1.o = yr_object_array_get_item(r2.o, 0, (int) r1.i);
if (r1.o == NULL)
@@ -549,8 +617,13 @@ int yr_execute_code(
ensure_defined(r1);
ensure_defined(r2);
assert(r2.o->type == OBJECT_TYPE_DICTIONARY);
#if PARANOID_EXEC
check_object_canary(r2.o);
#endif
r1.o = yr_object_dict_get_item(
r2.o, 0, r1.ss->c_string);
@@ -567,6 +640,15 @@ int yr_execute_code(
i = (int) strlen(args_fmt);
count = 0;
#if PARANOID_EXEC
if (i > YR_MAX_FUNCTION_ARGS)
{
stop = true;
result = ERROR_INTERNAL_FATAL_ERROR;
break;
}
#endif
// pop arguments from stack and copy them to args array
while (i > 0)
@@ -583,6 +665,10 @@ int yr_execute_code(
pop(r2);
ensure_defined(r2);
#if PARANOID_EXEC
check_object_canary(r2.o);
#endif
if (count > 0)
{
// if there are undefined args, result for function call
@@ -596,7 +682,7 @@ int yr_execute_code(
function = object_as_function(r2.o);
result = ERROR_INTERNAL_FATAL_ERROR;
for (i = 0; i < MAX_OVERLOADED_FUNCTIONS; i++)
for (i = 0; i < YR_MAX_OVERLOADED_FUNCTIONS; i++)
{
if (function->prototypes[i].arguments_fmt == NULL)
break;
@@ -608,10 +694,10 @@ int yr_execute_code(
}
}
// if i == MAX_OVERLOADED_FUNCTIONS at this point no matching
// if i == YR_MAX_OVERLOADED_FUNCTIONS at this point no matching
// prototype was found, but this shouldn't happen.
assert(i < MAX_OVERLOADED_FUNCTIONS);
assert(i < YR_MAX_OVERLOADED_FUNCTIONS);
// make a copy of the returned object and push the copy into the stack
// function->return_obj can't be pushed because it can change in
@@ -648,13 +734,13 @@ int yr_execute_code(
}
match = r2.s->matches[tidx].head;
r3.i = FALSE;
r3.i = false;
while (match != NULL)
{
if (r1.i == match->base + match->offset)
{
r3.i = TRUE;
r3.i = true;
break;
}
@@ -676,14 +762,14 @@ int yr_execute_code(
ensure_defined(r2);
match = r3.s->matches[tidx].head;
r3.i = FALSE;
r3.i = false;
while (match != NULL && !r3.i)
{
if (match->base + match->offset >= r1.i &&
match->base + match->offset <= r2.i)
{
r3.i = TRUE;
r3.i = true;
}
if (match->base + match->offset > r2.i)
@@ -869,7 +955,7 @@ int yr_execute_code(
result = yr_modules_load((char*) r1.p, context);
if (result != ERROR_SUCCESS)
stop = TRUE;
stop = true;
break;
@@ -883,7 +969,7 @@ int yr_execute_code(
if (r1.ss->length == 0)
{
r1.i = FALSE;
r1.i = false;
push(r1);
break;
}
@@ -900,16 +986,28 @@ int yr_execute_code(
&found);
if (result != ERROR_SUCCESS)
stop = TRUE;
stop = true;
r1.i = found >= 0;
push(r1);
break;
case OP_INT_TO_DBL:
r1.i = *(uint64_t*)(ip);
ip += sizeof(uint64_t);
#if PARANOID_EXEC
if (r1.i > sp || sp - r1.i >= stack_size)
{
stop = true;
result = ERROR_INTERNAL_FATAL_ERROR;
break;
}
#endif
r2 = stack[sp - r1.i];
if (is_undef(r2))
stack[sp - r1.i].i = UNDEFINED;
else
@@ -1064,7 +1162,7 @@ int yr_execute_code(
pop(r1);
ensure_defined(r2);
ensure_defined(r1);
r1.i = r1.d == r2.d;
r1.i = fabs(r1.d - r2.d) < DBL_EPSILON;
push(r1);
break;
@@ -1073,7 +1171,7 @@ int yr_execute_code(
pop(r1);
ensure_defined(r2);
ensure_defined(r1);
r1.i = r1.d != r2.d;
r1.i = fabs(r1.d - r2.d) >= DBL_EPSILON;
push(r1);
break;
@@ -1160,7 +1258,7 @@ int yr_execute_code(
default:
// Unknown instruction, this shouldn't happen.
assert(FALSE);
assert(false);
}
// Check for timeout every 10 instruction cycles. If timeout == 0 it means
@@ -1174,10 +1272,14 @@ int yr_execute_code(
{
#ifdef PROFILING_ENABLED
assert(current_rule != NULL);
current_rule->time_cost += elapsed_time - start_time;
#ifdef _WIN32
InterlockedAdd64(&rule->time_cost, elapsed_time - start_time);
#else
__sync_fetch_and_add(&rule->time_cost, elapsed_time - start_time);
#endif
#endif
result = ERROR_SCAN_TIMEOUT;
stop = TRUE;
stop = true;
}
cycle = 0;
+4 -4
View File
@@ -59,7 +59,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
YR_API int yr_filemap_map(
const char* file_path,
const wchar_t* file_path,
YR_MAPPED_FILE* pmapped_file)
{
return yr_filemap_map_ex(file_path, 0, 0, pmapped_file);
@@ -261,7 +261,7 @@ YR_API int yr_filemap_map_fd(
#if defined(_WIN32) || defined(__CYGWIN__)
YR_API int yr_filemap_map_ex(
const char* file_path,
const wchar_t* file_path,
off_t offset,
size_t size,
YR_MAPPED_FILE* pmapped_file)
@@ -272,7 +272,7 @@ YR_API int yr_filemap_map_ex(
if (file_path == NULL)
return ERROR_INVALID_ARGUMENT;
fd = CreateFileA(
fd = CreateFileW(
file_path,
GENERIC_READ,
FILE_SHARE_READ,
@@ -295,7 +295,7 @@ YR_API int yr_filemap_map_ex(
#else // POSIX
YR_API int yr_filemap_map_ex(
const char* file_path,
const wchar_t* file_path,
off_t offset,
size_t size,
YR_MAPPED_FILE* pmapped_file)
+1069 -1087
View File
File diff suppressed because it is too large Load Diff
+108 -104
View File
@@ -1,8 +1,8 @@
/* A Bison parser, made by GNU Bison 3.0.4.18-9674. */
/* A Bison parser, made by GNU Bison 3.0.5. */
/* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
Copyright (C) 1984, 1989-1990, 2000-2015, 2018 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -45,116 +45,120 @@ extern int yara_yydebug;
# define YYTOKENTYPE
enum yytokentype
{
_DOT_DOT_ = 258,
_RULE_ = 259,
_PRIVATE_ = 260,
_GLOBAL_ = 261,
_META_ = 262,
_STRINGS_ = 263,
_CONDITION_ = 264,
_IDENTIFIER_ = 265,
_STRING_IDENTIFIER_ = 266,
_STRING_COUNT_ = 267,
_STRING_OFFSET_ = 268,
_STRING_LENGTH_ = 269,
_STRING_IDENTIFIER_WITH_WILDCARD_ = 270,
_NUMBER_ = 271,
_DOUBLE_ = 272,
_INTEGER_FUNCTION_ = 273,
_TEXT_STRING_ = 274,
_HEX_STRING_ = 275,
_REGEXP_ = 276,
_ASCII_ = 277,
_WIDE_ = 278,
_XOR_ = 279,
_NOCASE_ = 280,
_FULLWORD_ = 281,
_AT_ = 282,
_FILESIZE_ = 283,
_ENTRYPOINT_ = 284,
_ALL_ = 285,
_ANY_ = 286,
_IN_ = 287,
_OF_ = 288,
_FOR_ = 289,
_THEM_ = 290,
_MATCHES_ = 291,
_CONTAINS_ = 292,
_IMPORT_ = 293,
_TRUE_ = 294,
_FALSE_ = 295,
_OR_ = 296,
_AND_ = 297,
_EQ_ = 298,
_NEQ_ = 299,
_LT_ = 300,
_LE_ = 301,
_GT_ = 302,
_GE_ = 303,
_SHIFT_LEFT_ = 304,
_SHIFT_RIGHT_ = 305,
_NOT_ = 306,
UNARY_MINUS = 307
_END_OF_FILE_ = 0,
_END_OF_INCLUDED_FILE_ = 258,
_DOT_DOT_ = 259,
_RULE_ = 260,
_PRIVATE_ = 261,
_GLOBAL_ = 262,
_META_ = 263,
_STRINGS_ = 264,
_CONDITION_ = 265,
_IDENTIFIER_ = 266,
_STRING_IDENTIFIER_ = 267,
_STRING_COUNT_ = 268,
_STRING_OFFSET_ = 269,
_STRING_LENGTH_ = 270,
_STRING_IDENTIFIER_WITH_WILDCARD_ = 271,
_NUMBER_ = 272,
_DOUBLE_ = 273,
_INTEGER_FUNCTION_ = 274,
_TEXT_STRING_ = 275,
_HEX_STRING_ = 276,
_REGEXP_ = 277,
_ASCII_ = 278,
_WIDE_ = 279,
_XOR_ = 280,
_NOCASE_ = 281,
_FULLWORD_ = 282,
_AT_ = 283,
_FILESIZE_ = 284,
_ENTRYPOINT_ = 285,
_ALL_ = 286,
_ANY_ = 287,
_IN_ = 288,
_OF_ = 289,
_FOR_ = 290,
_THEM_ = 291,
_MATCHES_ = 292,
_CONTAINS_ = 293,
_IMPORT_ = 294,
_TRUE_ = 295,
_FALSE_ = 296,
_OR_ = 297,
_AND_ = 298,
_NOT_ = 299,
_EQ_ = 300,
_NEQ_ = 301,
_LT_ = 302,
_LE_ = 303,
_GT_ = 304,
_GE_ = 305,
_SHIFT_LEFT_ = 306,
_SHIFT_RIGHT_ = 307,
UNARY_MINUS = 308
};
#endif
/* Tokens. */
#define _DOT_DOT_ 258
#define _RULE_ 259
#define _PRIVATE_ 260
#define _GLOBAL_ 261
#define _META_ 262
#define _STRINGS_ 263
#define _CONDITION_ 264
#define _IDENTIFIER_ 265
#define _STRING_IDENTIFIER_ 266
#define _STRING_COUNT_ 267
#define _STRING_OFFSET_ 268
#define _STRING_LENGTH_ 269
#define _STRING_IDENTIFIER_WITH_WILDCARD_ 270
#define _NUMBER_ 271
#define _DOUBLE_ 272
#define _INTEGER_FUNCTION_ 273
#define _TEXT_STRING_ 274
#define _HEX_STRING_ 275
#define _REGEXP_ 276
#define _ASCII_ 277
#define _WIDE_ 278
#define _XOR_ 279
#define _NOCASE_ 280
#define _FULLWORD_ 281
#define _AT_ 282
#define _FILESIZE_ 283
#define _ENTRYPOINT_ 284
#define _ALL_ 285
#define _ANY_ 286
#define _IN_ 287
#define _OF_ 288
#define _FOR_ 289
#define _THEM_ 290
#define _MATCHES_ 291
#define _CONTAINS_ 292
#define _IMPORT_ 293
#define _TRUE_ 294
#define _FALSE_ 295
#define _OR_ 296
#define _AND_ 297
#define _EQ_ 298
#define _NEQ_ 299
#define _LT_ 300
#define _LE_ 301
#define _GT_ 302
#define _GE_ 303
#define _SHIFT_LEFT_ 304
#define _SHIFT_RIGHT_ 305
#define _NOT_ 306
#define UNARY_MINUS 307
#define _END_OF_FILE_ 0
#define _END_OF_INCLUDED_FILE_ 258
#define _DOT_DOT_ 259
#define _RULE_ 260
#define _PRIVATE_ 261
#define _GLOBAL_ 262
#define _META_ 263
#define _STRINGS_ 264
#define _CONDITION_ 265
#define _IDENTIFIER_ 266
#define _STRING_IDENTIFIER_ 267
#define _STRING_COUNT_ 268
#define _STRING_OFFSET_ 269
#define _STRING_LENGTH_ 270
#define _STRING_IDENTIFIER_WITH_WILDCARD_ 271
#define _NUMBER_ 272
#define _DOUBLE_ 273
#define _INTEGER_FUNCTION_ 274
#define _TEXT_STRING_ 275
#define _HEX_STRING_ 276
#define _REGEXP_ 277
#define _ASCII_ 278
#define _WIDE_ 279
#define _XOR_ 280
#define _NOCASE_ 281
#define _FULLWORD_ 282
#define _AT_ 283
#define _FILESIZE_ 284
#define _ENTRYPOINT_ 285
#define _ALL_ 286
#define _ANY_ 287
#define _IN_ 288
#define _OF_ 289
#define _FOR_ 290
#define _THEM_ 291
#define _MATCHES_ 292
#define _CONTAINS_ 293
#define _IMPORT_ 294
#define _TRUE_ 295
#define _FALSE_ 296
#define _OR_ 297
#define _AND_ 298
#define _NOT_ 299
#define _EQ_ 300
#define _NEQ_ 301
#define _LT_ 302
#define _LE_ 303
#define _GT_ 304
#define _GE_ 305
#define _SHIFT_LEFT_ 306
#define _SHIFT_RIGHT_ 307
#define UNARY_MINUS 308
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
union YYSTYPE
{
#line 216 "grammar.y" /* yacc.c:1915 */
#line 237 "grammar.y" /* yacc.c:1916 */
EXPRESSION expression;
SIZED_STRING* sized_string;
@@ -165,7 +169,7 @@ union YYSTYPE
YR_META* meta;
YR_RULE* rule;
#line 169 "grammar.h" /* yacc.c:1915 */
#line 173 "grammar.h" /* yacc.c:1916 */
};
typedef union YYSTYPE YYSTYPE;
File diff suppressed because it is too large Load Diff
+5 -3
View File
@@ -30,6 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assert.h>
#include <string.h>
#include <yara/utils.h>
#include <yara/integers.h>
#include <yara/hash.h>
#include <yara/mem.h>
@@ -97,7 +98,8 @@ uint32_t yr_hash(
uint32_t result = seed;
size_t i;
assert(len > 0);
if (len == 0)
return result;
for (i = len - 1; i > 0; i--)
{
@@ -251,7 +253,7 @@ YR_API void* yr_hash_table_lookup_raw_key(
size_t key_length,
const char* ns)
{
return _yr_hash_table_lookup(table, key, key_length, ns, FALSE);
return _yr_hash_table_lookup(table, key, key_length, ns, false);
}
@@ -261,7 +263,7 @@ YR_API void* yr_hash_table_remove_raw_key(
size_t key_length,
const char* ns)
{
return _yr_hash_table_lookup(table, key, key_length, ns, TRUE);
return _yr_hash_table_lookup(table, key, key_length, ns, true);
}
+65 -64
View File
@@ -1,8 +1,8 @@
/* A Bison parser, made by GNU Bison 3.0.4. */
/* A Bison parser, made by GNU Bison 3.0.5. */
/* Bison implementation for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
Copyright (C) 1984, 1989-1990, 2000-2015, 2018 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -44,7 +44,7 @@
#define YYBISON 1
/* Bison version. */
#define YYBISON_VERSION "3.0.4"
#define YYBISON_VERSION "3.0.5"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -104,7 +104,7 @@
#define fail_if(x, error) \
if (x) \
{ \
lex_env->last_error_code = error; \
lex_env->last_error = error; \
YYABORT; \
} \
@@ -960,6 +960,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
case N: \
yyformat = S; \
break
default: /* Avoid compiler warnings. */
YYCASE_(0, YY_("syntax error"));
YYCASE_(1, YY_("syntax error, unexpected %s"));
YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
@@ -1025,45 +1026,45 @@ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, void *yyscanner, H
switch (yytype)
{
case 16: /* tokens */
#line 102 "hex_grammar.y" /* yacc.c:1257 */
#line 102 "hex_grammar.y" /* yacc.c:1258 */
{ yr_re_node_destroy(((*yyvaluep).re_node)); ((*yyvaluep).re_node) = NULL; }
#line 1031 "hex_grammar.c" /* yacc.c:1257 */
#line 1032 "hex_grammar.c" /* yacc.c:1258 */
break;
case 17: /* token_sequence */
#line 103 "hex_grammar.y" /* yacc.c:1257 */
#line 103 "hex_grammar.y" /* yacc.c:1258 */
{ yr_re_node_destroy(((*yyvaluep).re_node)); ((*yyvaluep).re_node) = NULL; }
#line 1037 "hex_grammar.c" /* yacc.c:1257 */
#line 1038 "hex_grammar.c" /* yacc.c:1258 */
break;
case 18: /* token_or_range */
#line 104 "hex_grammar.y" /* yacc.c:1257 */
#line 104 "hex_grammar.y" /* yacc.c:1258 */
{ yr_re_node_destroy(((*yyvaluep).re_node)); ((*yyvaluep).re_node) = NULL; }
#line 1043 "hex_grammar.c" /* yacc.c:1257 */
#line 1044 "hex_grammar.c" /* yacc.c:1258 */
break;
case 19: /* token */
#line 105 "hex_grammar.y" /* yacc.c:1257 */
#line 105 "hex_grammar.y" /* yacc.c:1258 */
{ yr_re_node_destroy(((*yyvaluep).re_node)); ((*yyvaluep).re_node) = NULL; }
#line 1049 "hex_grammar.c" /* yacc.c:1257 */
#line 1050 "hex_grammar.c" /* yacc.c:1258 */
break;
case 21: /* range */
#line 108 "hex_grammar.y" /* yacc.c:1257 */
#line 108 "hex_grammar.y" /* yacc.c:1258 */
{ yr_re_node_destroy(((*yyvaluep).re_node)); ((*yyvaluep).re_node) = NULL; }
#line 1055 "hex_grammar.c" /* yacc.c:1257 */
#line 1056 "hex_grammar.c" /* yacc.c:1258 */
break;
case 22: /* alternatives */
#line 107 "hex_grammar.y" /* yacc.c:1257 */
#line 107 "hex_grammar.y" /* yacc.c:1258 */
{ yr_re_node_destroy(((*yyvaluep).re_node)); ((*yyvaluep).re_node) = NULL; }
#line 1061 "hex_grammar.c" /* yacc.c:1257 */
#line 1062 "hex_grammar.c" /* yacc.c:1258 */
break;
case 23: /* byte */
#line 106 "hex_grammar.y" /* yacc.c:1257 */
#line 106 "hex_grammar.y" /* yacc.c:1258 */
{ yr_re_node_destroy(((*yyvaluep).re_node)); ((*yyvaluep).re_node) = NULL; }
#line 1067 "hex_grammar.c" /* yacc.c:1257 */
#line 1068 "hex_grammar.c" /* yacc.c:1258 */
break;
@@ -1329,24 +1330,24 @@ yyreduce:
switch (yyn)
{
case 2:
#line 114 "hex_grammar.y" /* yacc.c:1661 */
#line 114 "hex_grammar.y" /* yacc.c:1663 */
{
RE_AST* re_ast = yyget_extra(yyscanner);
re_ast->root_node = (yyvsp[-1].re_node);
}
#line 1338 "hex_grammar.c" /* yacc.c:1661 */
#line 1339 "hex_grammar.c" /* yacc.c:1663 */
break;
case 3:
#line 123 "hex_grammar.y" /* yacc.c:1661 */
#line 123 "hex_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = (yyvsp[0].re_node);
}
#line 1346 "hex_grammar.c" /* yacc.c:1661 */
#line 1347 "hex_grammar.c" /* yacc.c:1663 */
break;
case 4:
#line 127 "hex_grammar.y" /* yacc.c:1661 */
#line 127 "hex_grammar.y" /* yacc.c:1663 */
{
fail_if_too_many_ast_levels({
yr_re_node_destroy((yyvsp[-1].re_node));
@@ -1360,11 +1361,11 @@ yyreduce:
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
}
#line 1364 "hex_grammar.c" /* yacc.c:1661 */
#line 1365 "hex_grammar.c" /* yacc.c:1663 */
break;
case 5:
#line 141 "hex_grammar.y" /* yacc.c:1661 */
#line 141 "hex_grammar.y" /* yacc.c:1663 */
{
RE_NODE* new_concat;
RE_NODE* leftmost_concat = NULL;
@@ -1428,19 +1429,19 @@ yyreduce:
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
}
#line 1432 "hex_grammar.c" /* yacc.c:1661 */
#line 1433 "hex_grammar.c" /* yacc.c:1663 */
break;
case 6:
#line 209 "hex_grammar.y" /* yacc.c:1661 */
#line 209 "hex_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = (yyvsp[0].re_node);
}
#line 1440 "hex_grammar.c" /* yacc.c:1661 */
#line 1441 "hex_grammar.c" /* yacc.c:1663 */
break;
case 7:
#line 213 "hex_grammar.y" /* yacc.c:1661 */
#line 213 "hex_grammar.y" /* yacc.c:1663 */
{
fail_if_too_many_ast_levels({
yr_re_node_destroy((yyvsp[-1].re_node));
@@ -1454,53 +1455,53 @@ yyreduce:
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
}
#line 1458 "hex_grammar.c" /* yacc.c:1661 */
#line 1459 "hex_grammar.c" /* yacc.c:1663 */
break;
case 8:
#line 231 "hex_grammar.y" /* yacc.c:1661 */
#line 231 "hex_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = (yyvsp[0].re_node);
}
#line 1466 "hex_grammar.c" /* yacc.c:1661 */
#line 1467 "hex_grammar.c" /* yacc.c:1663 */
break;
case 9:
#line 235 "hex_grammar.y" /* yacc.c:1661 */
#line 235 "hex_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = (yyvsp[0].re_node);
(yyval.re_node)->greedy = FALSE;
(yyval.re_node)->greedy = false;
}
#line 1475 "hex_grammar.c" /* yacc.c:1661 */
#line 1476 "hex_grammar.c" /* yacc.c:1663 */
break;
case 10:
#line 244 "hex_grammar.y" /* yacc.c:1661 */
#line 244 "hex_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = (yyvsp[0].re_node);
}
#line 1483 "hex_grammar.c" /* yacc.c:1661 */
#line 1484 "hex_grammar.c" /* yacc.c:1663 */
break;
case 11:
#line 248 "hex_grammar.y" /* yacc.c:1661 */
#line 248 "hex_grammar.y" /* yacc.c:1663 */
{
lex_env->inside_or++;
}
#line 1491 "hex_grammar.c" /* yacc.c:1661 */
#line 1492 "hex_grammar.c" /* yacc.c:1663 */
break;
case 12:
#line 252 "hex_grammar.y" /* yacc.c:1661 */
#line 252 "hex_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = (yyvsp[-1].re_node);
lex_env->inside_or--;
}
#line 1500 "hex_grammar.c" /* yacc.c:1661 */
#line 1501 "hex_grammar.c" /* yacc.c:1663 */
break;
case 13:
#line 261 "hex_grammar.y" /* yacc.c:1661 */
#line 261 "hex_grammar.y" /* yacc.c:1663 */
{
if ((yyvsp[-1].integer) <= 0)
{
@@ -1508,10 +1509,10 @@ yyreduce:
YYABORT;
}
if (lex_env->inside_or && (yyvsp[-1].integer) > STRING_CHAINING_THRESHOLD)
if (lex_env->inside_or && (yyvsp[-1].integer) > YR_STRING_CHAINING_THRESHOLD)
{
yyerror(yyscanner, lex_env, "jumps over "
STR(STRING_CHAINING_THRESHOLD)
STR(YR_STRING_CHAINING_THRESHOLD)
" now allowed inside alternation (|)");
YYABORT;
}
@@ -1523,18 +1524,18 @@ yyreduce:
(yyval.re_node)->start = (int) (yyvsp[-1].integer);
(yyval.re_node)->end = (int) (yyvsp[-1].integer);
}
#line 1527 "hex_grammar.c" /* yacc.c:1661 */
#line 1528 "hex_grammar.c" /* yacc.c:1663 */
break;
case 14:
#line 284 "hex_grammar.y" /* yacc.c:1661 */
#line 284 "hex_grammar.y" /* yacc.c:1663 */
{
if (lex_env->inside_or &&
((yyvsp[-3].integer) > STRING_CHAINING_THRESHOLD ||
(yyvsp[-1].integer) > STRING_CHAINING_THRESHOLD) )
((yyvsp[-3].integer) > YR_STRING_CHAINING_THRESHOLD ||
(yyvsp[-1].integer) > YR_STRING_CHAINING_THRESHOLD) )
{
yyerror(yyscanner, lex_env, "jumps over "
STR(STRING_CHAINING_THRESHOLD)
STR(YR_STRING_CHAINING_THRESHOLD)
" now allowed inside alternation (|)");
YYABORT;
@@ -1559,11 +1560,11 @@ yyreduce:
(yyval.re_node)->start = (int) (yyvsp[-3].integer);
(yyval.re_node)->end = (int) (yyvsp[-1].integer);
}
#line 1563 "hex_grammar.c" /* yacc.c:1661 */
#line 1564 "hex_grammar.c" /* yacc.c:1663 */
break;
case 15:
#line 316 "hex_grammar.y" /* yacc.c:1661 */
#line 316 "hex_grammar.y" /* yacc.c:1663 */
{
if (lex_env->inside_or)
{
@@ -1585,11 +1586,11 @@ yyreduce:
(yyval.re_node)->start = (int) (yyvsp[-2].integer);
(yyval.re_node)->end = INT_MAX;
}
#line 1589 "hex_grammar.c" /* yacc.c:1661 */
#line 1590 "hex_grammar.c" /* yacc.c:1663 */
break;
case 16:
#line 338 "hex_grammar.y" /* yacc.c:1661 */
#line 338 "hex_grammar.y" /* yacc.c:1663 */
{
if (lex_env->inside_or)
{
@@ -1605,19 +1606,19 @@ yyreduce:
(yyval.re_node)->start = 0;
(yyval.re_node)->end = INT_MAX;
}
#line 1609 "hex_grammar.c" /* yacc.c:1661 */
#line 1610 "hex_grammar.c" /* yacc.c:1663 */
break;
case 17:
#line 358 "hex_grammar.y" /* yacc.c:1661 */
#line 358 "hex_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = (yyvsp[0].re_node);
}
#line 1617 "hex_grammar.c" /* yacc.c:1661 */
#line 1618 "hex_grammar.c" /* yacc.c:1663 */
break;
case 18:
#line 362 "hex_grammar.y" /* yacc.c:1661 */
#line 362 "hex_grammar.y" /* yacc.c:1663 */
{
mark_as_not_fast_regexp();
@@ -1633,11 +1634,11 @@ yyreduce:
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
}
#line 1637 "hex_grammar.c" /* yacc.c:1661 */
#line 1638 "hex_grammar.c" /* yacc.c:1663 */
break;
case 19:
#line 381 "hex_grammar.y" /* yacc.c:1661 */
#line 381 "hex_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = yr_re_node_create(RE_NODE_LITERAL, NULL, NULL);
@@ -1645,11 +1646,11 @@ yyreduce:
(yyval.re_node)->value = (int) (yyvsp[0].integer);
}
#line 1649 "hex_grammar.c" /* yacc.c:1661 */
#line 1650 "hex_grammar.c" /* yacc.c:1663 */
break;
case 20:
#line 389 "hex_grammar.y" /* yacc.c:1661 */
#line 389 "hex_grammar.y" /* yacc.c:1663 */
{
uint8_t mask = (uint8_t) ((yyvsp[0].integer) >> 8);
@@ -1669,11 +1670,11 @@ yyreduce:
(yyval.re_node)->mask = mask;
}
}
#line 1673 "hex_grammar.c" /* yacc.c:1661 */
#line 1674 "hex_grammar.c" /* yacc.c:1663 */
break;
#line 1677 "hex_grammar.c" /* yacc.c:1661 */
#line 1678 "hex_grammar.c" /* yacc.c:1663 */
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
@@ -1901,4 +1902,4 @@ yyreturn:
#endif
return yyresult;
}
#line 410 "hex_grammar.y" /* yacc.c:1906 */
#line 410 "hex_grammar.y" /* yacc.c:1907 */
+4 -4
View File
@@ -1,8 +1,8 @@
/* A Bison parser, made by GNU Bison 3.0.4. */
/* A Bison parser, made by GNU Bison 3.0.5. */
/* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
Copyright (C) 1984, 1989-1990, 2000-2015, 2018 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -60,12 +60,12 @@ extern int hex_yydebug;
union YYSTYPE
{
#line 86 "hex_grammar.y" /* yacc.c:1915 */
#line 86 "hex_grammar.y" /* yacc.c:1916 */
int64_t integer;
RE_NODE *re_node;
#line 69 "hex_grammar.h" /* yacc.c:1915 */
#line 69 "hex_grammar.h" /* yacc.c:1916 */
};
typedef union YYSTYPE YYSTYPE;
+7 -7
View File
@@ -62,7 +62,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define fail_if(x, error) \
if (x) \
{ \
lex_env->last_error_code = error; \
lex_env->last_error = error; \
YYABORT; \
} \
@@ -234,7 +234,7 @@ token_or_range
| range
{
$$ = $1;
$$->greedy = FALSE;
$$->greedy = false;
}
;
@@ -265,10 +265,10 @@ range
YYABORT;
}
if (lex_env->inside_or && $2 > STRING_CHAINING_THRESHOLD)
if (lex_env->inside_or && $2 > YR_STRING_CHAINING_THRESHOLD)
{
yyerror(yyscanner, lex_env, "jumps over "
STR(STRING_CHAINING_THRESHOLD)
STR(YR_STRING_CHAINING_THRESHOLD)
" now allowed inside alternation (|)");
YYABORT;
}
@@ -283,11 +283,11 @@ range
| '[' _NUMBER_ '-' _NUMBER_ ']'
{
if (lex_env->inside_or &&
($2 > STRING_CHAINING_THRESHOLD ||
$4 > STRING_CHAINING_THRESHOLD) )
($2 > YR_STRING_CHAINING_THRESHOLD ||
$4 > YR_STRING_CHAINING_THRESHOLD) )
{
yyerror(yyscanner, lex_env, "jumps over "
STR(STRING_CHAINING_THRESHOLD)
STR(YR_STRING_CHAINING_THRESHOLD)
" now allowed inside alternation (|)");
YYABORT;
+23 -23
View File
@@ -256,7 +256,7 @@
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
* if you want the limit (max/min) macros for int types.
* if you want the limit (max/min) macros for int types.
*/
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS 1
@@ -273,7 +273,7 @@ typedef uint32_t flex_uint32_t;
typedef signed char flex_int8_t;
typedef short int flex_int16_t;
typedef int flex_int32_t;
typedef unsigned char flex_uint8_t;
typedef unsigned char flex_uint8_t;
typedef unsigned short int flex_uint16_t;
typedef unsigned int flex_uint32_t;
@@ -397,7 +397,7 @@ typedef size_t yy_size_t;
#define EOB_ACT_CONTINUE_SCAN 0
#define EOB_ACT_END_OF_FILE 1
#define EOB_ACT_LAST_MATCH 2
/* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
* access to the local variable yy_act. Since yyless() is a macro, it would break
* existing scanners that call yyless() from OUTSIDE yylex.
@@ -419,7 +419,7 @@ typedef size_t yy_size_t;
if ( *p == '\n' )\
--yylineno;\
}while(0)
/* Return all but the first "n" matched characters back to the input stream. */
#define yyless(n) \
do \
@@ -816,7 +816,7 @@ static int yy_init_globals ( yyscan_t yyscanner );
/* This must go here because YYSTYPE and YYLTYPE are included
* from bison output in section 1.*/
# define yylval yyg->yylval_r
int yylex_init (yyscan_t* scanner);
int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner);
@@ -871,7 +871,7 @@ extern int yywrap ( yyscan_t yyscanner );
#endif
#ifndef YY_NO_UNPUT
#endif
#ifndef yytext_ptr
@@ -1082,7 +1082,7 @@ yy_find_action:
int yyl;
for ( yyl = 0; yyl < yyleng; ++yyl )
if ( yytext[yyl] == '\n' )
do{ yylineno++;
yycolumn=0;
}while(0)
@@ -1643,7 +1643,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
yyg->yy_hold_char = *++yyg->yy_c_buf_p;
if ( c == '\n' )
do{ yylineno++;
yycolumn=0;
}while(0)
@@ -1726,7 +1726,7 @@ static void yy_load_buffer_state (yyscan_t yyscanner)
YY_BUFFER_STATE yy_create_buffer (FILE * file, int size , yyscan_t yyscanner)
{
YY_BUFFER_STATE b;
b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner );
if ( ! b )
YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
@@ -1792,7 +1792,7 @@ static void yy_load_buffer_state (yyscan_t yyscanner)
}
b->yy_is_interactive = 0;
errno = oerrno;
}
@@ -1934,7 +1934,7 @@ static void yyensure_buffer_stack (yyscan_t yyscanner)
YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
{
YY_BUFFER_STATE b;
if ( size < 2 ||
base[size-2] != YY_END_OF_BUFFER_CHAR ||
base[size-1] != YY_END_OF_BUFFER_CHAR )
@@ -1970,7 +1970,7 @@ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscann
*/
YY_BUFFER_STATE yy_scan_string (const char * yystr , yyscan_t yyscanner)
{
return yy_scan_bytes( yystr, (int) strlen(yystr) , yyscanner);
}
@@ -1987,7 +1987,7 @@ YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len , yyscan
char *buf;
yy_size_t n;
int i;
/* Get memory for full buffer, including space for trailing EOB's. */
n = (yy_size_t) (_yybytes_len + 2);
buf = (char *) yyalloc( n , yyscanner );
@@ -2060,7 +2060,7 @@ int yyget_lineno (yyscan_t yyscanner)
if (! YY_CURRENT_BUFFER)
return 0;
return yylineno;
}
@@ -2073,7 +2073,7 @@ int yyget_column (yyscan_t yyscanner)
if (! YY_CURRENT_BUFFER)
return 0;
return yycolumn;
}
@@ -2135,7 +2135,7 @@ void yyset_lineno (int _line_number , yyscan_t yyscanner)
/* lineno is only valid if an input buffer exists. */
if (! YY_CURRENT_BUFFER )
YY_FATAL_ERROR( "yyset_lineno called with no buffer" );
yylineno = _line_number;
}
@@ -2150,7 +2150,7 @@ void yyset_column (int _column_no , yyscan_t yyscanner)
/* column is only valid if an input buffer exists. */
if (! YY_CURRENT_BUFFER )
YY_FATAL_ERROR( "yyset_column called with no buffer" );
yycolumn = _column_no;
}
@@ -2397,14 +2397,14 @@ void yyerror(
HEX_LEX_ENVIRONMENT* lex_env,
const char *error_message)
{
// if lex_env->last_error_code was set to some error code before
// if lex_env->last_error was set to some error code before
// don't overwrite it, we are interested in the first error, not in
// subsequent errors like "syntax error, unexpected $end" caused by
// early parser termination.
if (lex_env->last_error_code == ERROR_SUCCESS)
if (lex_env->last_error == ERROR_SUCCESS)
{
lex_env->last_error_code = ERROR_INVALID_HEX_STRING;
lex_env->last_error = ERROR_INVALID_HEX_STRING;
strlcpy(
lex_env->last_error_message,
@@ -2423,7 +2423,7 @@ int yr_parse_hex_string(
jmp_buf recovery_state;
HEX_LEX_ENVIRONMENT lex_env;
lex_env.last_error_code = ERROR_SUCCESS;
lex_env.last_error = ERROR_SUCCESS;
lex_env.inside_or = 0;
yr_thread_storage_set_value(&yr_recovery_state_key, &recovery_state);
@@ -2454,10 +2454,10 @@ int yr_parse_hex_string(
yyparse(yyscanner, &lex_env);
yylex_destroy(yyscanner);
if (lex_env.last_error_code != ERROR_SUCCESS)
if (lex_env.last_error != ERROR_SUCCESS)
{
strlcpy(error->message, lex_env.last_error_message, sizeof(error->message));
return lex_env.last_error_code;
return lex_env.last_error;
}
return ERROR_SUCCESS;
+6 -6
View File
@@ -185,14 +185,14 @@ void yyerror(
HEX_LEX_ENVIRONMENT* lex_env,
const char *error_message)
{
// if lex_env->last_error_code was set to some error code before
// if lex_env->last_error was set to some error code before
// don't overwrite it, we are interested in the first error, not in
// subsequent errors like "syntax error, unexpected $end" caused by
// early parser termination.
if (lex_env->last_error_code == ERROR_SUCCESS)
if (lex_env->last_error == ERROR_SUCCESS)
{
lex_env->last_error_code = ERROR_INVALID_HEX_STRING;
lex_env->last_error = ERROR_INVALID_HEX_STRING;
strlcpy(
lex_env->last_error_message,
@@ -211,7 +211,7 @@ int yr_parse_hex_string(
jmp_buf recovery_state;
HEX_LEX_ENVIRONMENT lex_env;
lex_env.last_error_code = ERROR_SUCCESS;
lex_env.last_error = ERROR_SUCCESS;
lex_env.inside_or = 0;
yr_thread_storage_set_value(&yr_recovery_state_key, &recovery_state);
@@ -242,10 +242,10 @@ int yr_parse_hex_string(
yyparse(yyscanner, &lex_env);
yylex_destroy(yyscanner);
if (lex_env.last_error_code != ERROR_SUCCESS)
if (lex_env.last_error != ERROR_SUCCESS)
{
strlcpy(error->message, lex_env.last_error_message, sizeof(error->message));
return lex_env.last_error_code;
return lex_env.last_error;
}
return ERROR_SUCCESS;
+12 -9
View File
@@ -34,18 +34,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <yara/atoms.h>
#include <yara/types.h>
// Number of bits dedicated to store the offset of the slot relative to its
// own state.
#define YR_AC_SLOT_OFFSET_BITS 9
#define YR_AC_ROOT_STATE 0
#define YR_AC_NEXT_STATE(t) (t >> 32)
#define YR_AC_INVALID_TRANSITION(t, c) (((t) & 0xFFFF) != c)
// Max number of slots in the transition table. This is the maximum number of
// slots that can be addressed with 23-bit indexes.
#define YR_AC_MAX_TRANSITION_TABLE_SIZE 0x800000
#define YR_AC_MAKE_TRANSITION(state, code, flags) \
((uint64_t)((((uint64_t) state) << 32) | ((flags) << 16) | (code)))
#define YR_AC_ROOT_STATE 0
#define YR_AC_NEXT_STATE(t) (t >> YR_AC_SLOT_OFFSET_BITS)
#define YR_AC_INVALID_TRANSITION(t, c) (((t) & 0x1FF) != c)
#define YR_AC_USED_FLAG 0x1
#define YR_AC_USED_TRANSITION_SLOT(x) ((x) & (YR_AC_USED_FLAG << 16))
#define YR_AC_UNUSED_TRANSITION_SLOT(x) (!YR_AC_USED_TRANSITION_SLOT(x))
#define YR_AC_MAKE_TRANSITION(state, code) \
((YR_AC_TRANSITION) \
((((YR_AC_TRANSITION) state) << YR_AC_SLOT_OFFSET_BITS) | (code)))
int yr_ac_automaton_create(
+1 -1
View File
@@ -47,7 +47,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// address within the relocated arena.
#define ARENA_FLAGS_RELOCATABLE 2
#define ARENA_FILE_VERSION ((17 << 16) | MAX_THREADS)
#define ARENA_FILE_VERSION ((19 << 16) | YR_MAX_THREADS)
#define EOL ((size_t) -1)
+70 -15
View File
@@ -38,61 +38,116 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define ATOM_TREE_OR 3
typedef struct _ATOM_TREE_NODE
typedef struct ATOM_TREE_NODE ATOM_TREE_NODE;
typedef struct ATOM_TREE ATOM_TREE;
typedef struct YR_ATOM_LIST_ITEM YR_ATOM_LIST_ITEM;
typedef struct YR_ATOM_QUALITY_TABLE_ENTRY YR_ATOM_QUALITY_TABLE_ENTRY;
typedef struct YR_ATOMS_CONFIG YR_ATOMS_CONFIG;
struct ATOM_TREE_NODE
{
uint8_t type;
uint8_t atom_length;
uint8_t atom[MAX_ATOM_LENGTH];
uint8_t atom[YR_MAX_ATOM_LENGTH];
uint8_t* forward_code;
uint8_t* backward_code;
RE_NODE* recent_nodes[MAX_ATOM_LENGTH];
RE_NODE* recent_nodes[YR_MAX_ATOM_LENGTH];
struct _ATOM_TREE_NODE* children_head;
struct _ATOM_TREE_NODE* children_tail;
struct _ATOM_TREE_NODE* next_sibling;
} ATOM_TREE_NODE;
ATOM_TREE_NODE* children_head;
ATOM_TREE_NODE* children_tail;
ATOM_TREE_NODE* next_sibling;
};
typedef struct _ATOM_TREE
struct ATOM_TREE
{
ATOM_TREE_NODE* current_leaf;
ATOM_TREE_NODE* root_node;
} ATOM_TREE;
};
typedef struct _YR_ATOM_LIST_ITEM
struct YR_ATOM_LIST_ITEM
{
uint8_t atom_length;
uint8_t atom[MAX_ATOM_LENGTH];
uint8_t atom[YR_MAX_ATOM_LENGTH];
uint16_t backtrack;
uint8_t* forward_code;
uint8_t* backward_code;
struct _YR_ATOM_LIST_ITEM* next;
YR_ATOM_LIST_ITEM* next;
};
} YR_ATOM_LIST_ITEM;
#pragma pack(push)
#pragma pack(1)
struct YR_ATOM_QUALITY_TABLE_ENTRY
{
const uint8_t atom[YR_MAX_ATOM_LENGTH];
const uint8_t quality;
};
#pragma pack(pop)
typedef int (*YR_ATOMS_QUALITY_FUNC)(
YR_ATOMS_CONFIG* config,
uint8_t* atom,
int atom_length);
struct YR_ATOMS_CONFIG
{
YR_ATOMS_QUALITY_FUNC get_atom_quality;
YR_ATOM_QUALITY_TABLE_ENTRY* quality_table;
int quality_warning_threshold;
int quality_table_entries;
bool free_quality_table;
};
int yr_atoms_extract_from_re(
YR_ATOMS_CONFIG* config,
RE_AST* re_ast,
int flags,
YR_ATOM_LIST_ITEM** atoms);
int yr_atoms_extract_from_string(
YR_ATOMS_CONFIG* config,
uint8_t* string,
int string_length,
int flags,
YR_ATOM_LIST_ITEM** atoms);
int yr_atoms_extract_triplets(
RE_NODE* re_node,
YR_ATOM_LIST_ITEM** atoms);
int yr_atoms_heuristic_quality(
YR_ATOMS_CONFIG* config,
uint8_t* atom,
int atom_length);
int yr_atoms_table_quality(
YR_ATOMS_CONFIG* config,
uint8_t* atom,
int atom_length);
int yr_atoms_min_quality(
YR_ATOMS_CONFIG* config,
YR_ATOM_LIST_ITEM* atom_list);
@@ -0,0 +1,80 @@
/*
Copyright (c) 2018. The YARA Authors. All Rights Reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef YR_BITMASK_H
#define YR_BITMASK_H
#include <yara/integers.h>
#define YR_BITMASK unsigned long
#define YR_BITMASK_SLOT_BITS (sizeof(YR_BITMASK) * 8)
#define YR_BITMASK_SIZE(n) (((n) / (YR_BITMASK_SLOT_BITS)) + 1)
#define yr_bitmask_set(bm, i) \
do { \
(bm)[(i) / YR_BITMASK_SLOT_BITS] |= 1UL << ((i) % YR_BITMASK_SLOT_BITS); \
} while(0)
#define yr_bitmask_clear(bm, i) \
do { \
(bm)[(i) / YR_BITMASK_SLOT_BITS] &= ~(1UL << ((i) % YR_BITMASK_SLOT_BITS)); \
} while(0)
#define yr_bitmask_clear_all(bm) \
memset(bm, 0, sizeof(bm))
#define yr_bitmask_isset(bm, i) \
( \
(bm)[(i) / YR_BITMASK_SLOT_BITS] & (1UL << ((i) % YR_BITMASK_SLOT_BITS)) \
)
#define yr_bitmask_print(bm) \
{ \
int i; \
for (i = 0; i < sizeof(bm) / sizeof(bm[0]); i++) { \
printf("%016lX\n", bm[i]); \
} \
}
uint32_t yr_bitmask_find_non_colliding_offset(
YR_BITMASK* a,
YR_BITMASK* b,
uint32_t len_a,
uint32_t len_b,
uint32_t* off_a);
#endif
+23 -11
View File
@@ -85,7 +85,6 @@ typedef struct _YR_COMPILER
int current_line;
int last_error;
int last_error_line;
int last_result;
jmp_buf error_recovery;
@@ -112,17 +111,17 @@ typedef struct _YR_COMPILER
int namespaces_count;
uint8_t* loop_address[MAX_LOOP_NESTING];
char* loop_identifier[MAX_LOOP_NESTING];
uint8_t* loop_address[YR_MAX_LOOP_NESTING];
char* loop_identifier[YR_MAX_LOOP_NESTING];
int loop_depth;
int loop_for_of_mem_offset;
char* file_name_stack[MAX_INCLUDE_DEPTH];
char* file_name_stack[YR_MAX_INCLUDE_DEPTH];
int file_name_stack_ptr;
char last_error_extra_info[MAX_COMPILER_ERROR_EXTRA_INFO];
char last_error_extra_info[YR_MAX_COMPILER_ERROR_EXTRA_INFO];
char lex_buf[LEX_BUF_SIZE];
char lex_buf[YR_LEX_BUF_SIZE];
char* lex_buf_ptr;
unsigned short lex_buf_len;
@@ -131,11 +130,11 @@ typedef struct _YR_COMPILER
void* incl_clbk_user_data;
void* re_ast_clbk_user_data;
YR_COMPILER_CALLBACK_FUNC callback;
YR_COMPILER_INCLUDE_CALLBACK_FUNC include_callback;
YR_COMPILER_INCLUDE_FREE_FUNC include_free;
YR_COMPILER_RE_AST_CALLBACK_FUNC re_ast_callback;
YR_COMPILER_CALLBACK_FUNC callback;
YR_COMPILER_INCLUDE_CALLBACK_FUNC include_callback;
YR_COMPILER_INCLUDE_FREE_FUNC include_free;
YR_COMPILER_RE_AST_CALLBACK_FUNC re_ast_callback;
YR_ATOMS_CONFIG atoms_config;
} YR_COMPILER;
@@ -198,6 +197,19 @@ YR_API void yr_compiler_set_re_ast_callback(
void* user_data);
YR_API void yr_compiler_set_atom_quality_table(
YR_COMPILER* compiler,
const void* table,
int entries,
unsigned char warning_threshold);
YR_API int yr_compiler_load_atom_quality_table(
YR_COMPILER* compiler,
const char* filename,
unsigned char warning_threshold);
YR_API int yr_compiler_add_file(
YR_COMPILER* compiler,
FILE* rules_file,
+7 -4
View File
@@ -97,7 +97,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define ERROR_INTEGER_OVERFLOW 52
#define ERROR_CALLBACK_REQUIRED 53
#define ERROR_INVALID_OPERAND 54
#define ERROR_COULD_NOT_READ_FILE 55
#define ERROR_DUPLICATED_EXTERNAL_VARIABLE 56
#define ERROR_INVALID_MODULE_DATA 57
#define ERROR_WRITING_FILE 58
#define FAIL_ON_ERROR(x) { \
int result = (x); \
@@ -114,9 +117,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
}
#define FAIL_ON_COMPILER_ERROR(x) { \
compiler->last_result = (x); \
if (compiler->last_result != ERROR_SUCCESS) \
return compiler->last_result; \
compiler->last_error = (x); \
if (compiler->last_error != ERROR_SUCCESS) \
return compiler->last_error; \
}
+2 -2
View File
@@ -62,7 +62,7 @@ typedef struct _YR_MAPPED_FILE
YR_API int yr_filemap_map(
const char* file_path,
const wchar_t* file_path,
YR_MAPPED_FILE* pmapped_file);
@@ -74,7 +74,7 @@ YR_API int yr_filemap_map_fd(
YR_API int yr_filemap_map_ex(
const char* file_path,
const wchar_t* file_path,
off_t offset,
size_t size,
YR_MAPPED_FILE* pmapped_file);
@@ -32,9 +32,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <yara/threading.h>
// Pre-computed tables for quickly converting a character to lowercase or to
// its alternative case (uppercase if it is a lowercase and vice versa). This
// tables are initialized by yr_initialize.
extern char yr_lowercase[256];
extern char yr_altercase[256];
// Canary value used for preventing hand-crafted objects from being embedded
// in compiled rules and used to exploit YARA. The canary value is initialized
// to a random value by yr_initialize and is subsequently set to all objects
// created by yr_object_create. The canary is verified when objects are used
// by yr_execute_code.
extern int yr_canary;
extern YR_THREAD_STORAGE_KEY yr_tidx_key;
extern YR_THREAD_STORAGE_KEY yr_recovery_state_key;
+1 -1
View File
@@ -66,7 +66,7 @@ typedef void* yyscan_t;
typedef struct _HEX_LEX_ENVIRONMENT
{
int inside_or;
int last_error_code;
int last_error;
char last_error_message[256];
} HEX_LEX_ENVIRONMENT;
+1 -1
View File
@@ -127,7 +127,7 @@ void yyerror(
void yywarning(
yyscan_t yyscanner,
const char *message_fmt,
...);
...) YR_PRINTF_LIKE(2, 3);
void yyfatal(
yyscan_t yyscanner,
+2 -2
View File
@@ -33,8 +33,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <yara/utils.h>
#define YR_MAJOR_VERSION 3
#define YR_MINOR_VERSION 7
#define YR_MICRO_VERSION 0
#define YR_MINOR_VERSION 8
#define YR_MICRO_VERSION 1
#define version_str(s) _version_str(s)
#define _version_str(s) #s
+52 -32
View File
@@ -36,111 +36,131 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "utils.h"
// Maximum lenght of file paths. This is the only limit that doesn't have the
// YR_ prefix. The intention is using the default MAX_PATH if defined.
#ifndef MAX_PATH
#define MAX_PATH 1024
#endif
// Maximum number of threads that can use a YR_RULES structure simultaneously.
// Increasing this number also increase memory usage as each YR_STRING structure
// has an array with MAX_THREADS entries for storing pointers to YR_MATCH
// has an array with YR_MAX_THREADS entries for storing pointers to YR_MATCH
// structures.
#ifndef MAX_THREADS
#define MAX_THREADS 32
#ifndef YR_MAX_THREADS
#define YR_MAX_THREADS 32
#endif
// Capacity of the buffer used for storing compiler error messages. Messages
// will be truncated at this size.
#ifndef MAX_COMPILER_ERROR_EXTRA_INFO
#define MAX_COMPILER_ERROR_EXTRA_INFO 256
#ifndef YR_MAX_COMPILER_ERROR_EXTRA_INFO
#define YR_MAX_COMPILER_ERROR_EXTRA_INFO 256
#endif
// Maximum size for the substring (atoms) extracted from strings and regular
// expressions and put into the Aho-Corasick automaton. The maximum allows size
// for this constant is 255.
#ifndef MAX_ATOM_LENGTH
#define MAX_ATOM_LENGTH 4
#ifndef YR_MAX_ATOM_LENGTH
#define YR_MAX_ATOM_LENGTH 4
#endif
#ifndef YR_MAX_ATOM_QUALITY
#define YR_MAX_ATOM_QUALITY 255
#endif
#ifndef YR_MIN_ATOM_QUALITY
#define YR_MIN_ATOM_QUALITY 0
#endif
// If the minimum atom quality for a string or regexp is below this constant,
// a warning like "<string> is slowing down the scan" is shown. This used only
// with heuristic atom quality, when using an atom quality table the user must
// specify the threshold when calling yr_compiler_set_atom_quality_table
#ifndef YR_ATOM_QUALITY_WARNING_THRESHOLD
#define YR_ATOM_QUALITY_WARNING_THRESHOLD \
(YR_MAX_ATOM_QUALITY - 2 * YR_MAX_ATOM_LENGTH + 3)
#endif
// Maximum number of nested "for" loops in rule. Rules ith nested loops
// exceeding this number will be rejected by the compiler.
#ifndef MAX_LOOP_NESTING
#define MAX_LOOP_NESTING 4
#ifndef YR_MAX_LOOP_NESTING
#define YR_MAX_LOOP_NESTING 4
#endif
#ifndef MAX_ARENA_PAGES
#define MAX_ARENA_PAGES 32
#ifndef YR_MAX_ARENA_PAGES
#define YR_MAX_ARENA_PAGES 32
#endif
// Maximum number of nested included files.
#ifndef MAX_INCLUDE_DEPTH
#define MAX_INCLUDE_DEPTH 16
#ifndef YR_MAX_INCLUDE_DEPTH
#define YR_MAX_INCLUDE_DEPTH 16
#endif
// Maximum number of matches allowed for a string. If more matches are found
// the scan will fail with ERROR_TOO_MANY_MATCHES.
#ifndef MAX_STRING_MATCHES
#define MAX_STRING_MATCHES 1000000
#ifndef YR_MAX_STRING_MATCHES
#define YR_MAX_STRING_MATCHES 1000000
#endif
// Maximum number of argument that a function in a YARA module can have.
#ifndef MAX_FUNCTION_ARGS
#define MAX_FUNCTION_ARGS 128
#ifndef YR_MAX_FUNCTION_ARGS
#define YR_MAX_FUNCTION_ARGS 128
#endif
// How many overloaded functions can share the same name in a YARA module.
#ifndef MAX_OVERLOADED_FUNCTIONS
#define MAX_OVERLOADED_FUNCTIONS 10
#ifndef YR_MAX_OVERLOADED_FUNCTIONS
#define YR_MAX_OVERLOADED_FUNCTIONS 10
#endif
// Size of the stack used by yr_re_fast_exec.
#ifndef MAX_FAST_RE_STACK
#define MAX_FAST_RE_STACK 300
#ifndef YR_MAX_FAST_RE_STACK
#define YR_MAX_FAST_RE_STACK 300
#endif
// Regular expressions like /foo.{x,y}bar/ are split in two separate ones /foo/
// and /bar/ if x is larger than STRING_CHAINING_THRESHOLD. This also applies to
// and /bar/ if x is larger than YR_STRING_CHAINING_THRESHOLD. This also applies to
// hex strings like { 01 02 03 [x-y] 004 05 06 }.
#ifndef STRING_CHAINING_THRESHOLD
#define STRING_CHAINING_THRESHOLD 200
#ifndef YR_STRING_CHAINING_THRESHOLD
#define YR_STRING_CHAINING_THRESHOLD 200
#endif
// Size of the buffer used by the lexer for storing strings like include file
// paths and regular expressions.
#ifndef LEX_BUF_SIZE
#define LEX_BUF_SIZE 8192
#ifndef YR_LEX_BUF_SIZE
#define YR_LEX_BUF_SIZE 8192
#endif
// Maximum allowed split ID, also limiting the number of split instructions
// allowed in a regular expression. This number can't be increased
// over 255 without changing RE_SPLIT_ID_TYPE.
#ifndef RE_MAX_SPLIT_ID
#define RE_MAX_SPLIT_ID 128
#define RE_MAX_SPLIT_ID 128
#endif
// Maximum stack size for regexp evaluation
#ifndef RE_MAX_STACK
#define RE_MAX_STACK 1024
#define RE_MAX_STACK 1024
#endif
// Maximum code size for a compiled regexp
#ifndef RE_MAX_CODE_SIZE
#define RE_MAX_CODE_SIZE 32768
#define RE_MAX_CODE_SIZE 32768
#endif
// Maximum input size scanned by yr_re_exec
#ifndef RE_SCAN_LIMIT
#define RE_SCAN_LIMIT 4096
#define RE_SCAN_LIMIT 4096
#endif
// Maximum number of fibers
#ifndef RE_MAX_FIBERS
#define RE_MAX_FIBERS 1024
#define RE_MAX_FIBERS 1024
#endif
// Maximum number of levels in regexp's AST
#ifndef RE_MAX_AST_LEVELS
#define RE_MAX_AST_LEVELS 5000
#define RE_MAX_AST_LEVELS 5000
#endif
#endif
+22 -22
View File
@@ -290,7 +290,7 @@ typedef struct {
uint32_t ncmds;
uint32_t sizeofcmds;
uint32_t flags;
} mach_header_32_t;
} yr_mach_header_32_t;
typedef struct {
@@ -302,13 +302,13 @@ typedef struct {
uint32_t sizeofcmds;
uint32_t flags;
uint32_t reserved;
} mach_header_64_t;
} yr_mach_header_64_t;
typedef struct {
uint32_t cmd;
uint32_t cmdsize;
} load_command_t;
} yr_load_command_t;
typedef struct {
@@ -323,7 +323,7 @@ typedef struct {
uint32_t initprot;
uint32_t nsects;
uint32_t flags;
} segment_command_32_t;
} yr_segment_command_32_t;
typedef struct {
@@ -338,7 +338,7 @@ typedef struct {
uint32_t initprot;
uint32_t nsects;
uint32_t flags;
} segment_command_64_t;
} yr_segment_command_64_t;
typedef struct {
@@ -353,7 +353,7 @@ typedef struct {
uint32_t flags;
uint32_t reserved1;
uint32_t reserved2;
} section_32_t;
} yr_section_32_t;
typedef struct {
@@ -369,14 +369,14 @@ typedef struct {
uint32_t reserved1;
uint32_t reserved2;
uint32_t reserved3;
} section_64_t;
} yr_section_64_t;
typedef struct {
uint32_t cmd;
uint32_t cmdsize;
uint8_t uuid[16];
} uuid_command_t;
} yr_uuid_command_t;
typedef struct {
@@ -384,7 +384,7 @@ typedef struct {
uint32_t cmdsize;
uint64_t entryoff;
uint64_t stacksize;
} entry_point_command_t;
} yr_entry_point_command_t;
typedef struct {
@@ -393,7 +393,7 @@ typedef struct {
uint32_t flavor;
uint32_t count;
// cpu_thread_state
} thread_command_t;
} yr_thread_command_t;
typedef struct {
@@ -413,7 +413,7 @@ typedef struct {
uint32_t es;
uint32_t fs;
uint32_t gs;
} x86_thread_state_t;
} yr_x86_thread_state_t;
typedef struct {
@@ -422,7 +422,7 @@ typedef struct {
uint32_t lr;
uint32_t pc;
uint32_t cpsr;
} arm_thread_state_t;
} yr_arm_thread_state_t;
typedef struct {
@@ -435,7 +435,7 @@ typedef struct {
uint32_t ctr;
uint32_t mq;
uint32_t vrsavead;
} ppc_thread_state_t;
} yr_ppc_thread_state_t;
typedef struct {
@@ -458,7 +458,7 @@ typedef struct {
uint32_t o5;
uint32_t o6;
uint32_t o7;
} sparc_thread_state_t;
} yr_sparc_thread_state_t;
typedef struct {
@@ -467,7 +467,7 @@ typedef struct {
uint16_t pad;
uint16_t sr;
uint32_t pc;
} m68k_thread_state_t;
} yr_m68k_thread_state_t;
typedef struct {
@@ -505,7 +505,7 @@ typedef struct {
uint32_t xip;
uint32_t xip_in_bd;
uint32_t nip;
} m88k_thread_state_t;
} yr_m88k_thread_state_t;
typedef struct {
@@ -530,7 +530,7 @@ typedef struct {
uint64_t cs;
uint64_t fs;
uint64_t gs;
} x86_thread_state64_t;
} yr_x86_thread_state64_t;
typedef struct {
@@ -540,7 +540,7 @@ typedef struct {
uint64_t sp;
uint64_t pc;
uint64_t cpsr;
} arm_thread_state64_t;
} yr_arm_thread_state64_t;
typedef struct {
@@ -552,13 +552,13 @@ typedef struct {
uint64_t lr;
uint64_t ctr;
uint32_t vrsave;
} ppc_thread_state64_t;
} yr_ppc_thread_state64_t;
typedef struct {
uint32_t magic;
uint32_t nfat_arch;
} fat_header_t;
} yr_fat_header_t;
typedef struct {
@@ -567,7 +567,7 @@ typedef struct {
uint32_t offset;
uint32_t size;
uint32_t align;
} fat_arch_32_t;
} yr_fat_arch_32_t;
typedef struct {
@@ -577,7 +577,7 @@ typedef struct {
uint64_t size;
uint32_t align;
uint32_t reserved;
} fat_arch_64_t;
} yr_fat_arch_64_t;
#pragma pack(pop)
+9 -9
View File
@@ -47,7 +47,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif
#include <yara/utils.h>
#include <yara/types.h>
#include <yara/sizedstr.h>
@@ -101,38 +101,38 @@ YR_OBJECT* yr_object_lookup(
YR_OBJECT* root,
int flags,
const char* pattern,
...);
...) YR_PRINTF_LIKE(3, 4);
int yr_object_has_undefined_value(
bool yr_object_has_undefined_value(
YR_OBJECT* object,
const char* field,
...);
...) YR_PRINTF_LIKE(2, 3);
int64_t yr_object_get_integer(
YR_OBJECT* object,
const char* field,
...);
...) YR_PRINTF_LIKE(2, 3);
SIZED_STRING* yr_object_get_string(
YR_OBJECT* object,
const char* field,
...);
...) YR_PRINTF_LIKE(2, 3);
int yr_object_set_integer(
int64_t value,
YR_OBJECT* object,
const char* field,
...);
...) YR_PRINTF_LIKE(3, 4);
int yr_object_set_float(
double value,
YR_OBJECT* object,
const char* field,
...);
...) YR_PRINTF_LIKE(3, 4);
int yr_object_set_string(
@@ -140,7 +140,7 @@ int yr_object_set_string(
size_t len,
YR_OBJECT* object,
const char* field,
...);
...) YR_PRINTF_LIKE(4, 5);
YR_OBJECT* yr_object_array_get_item(
+13 -9
View File
@@ -70,9 +70,10 @@ int yr_parser_check_types(
const char* actual_args_fmt);
YR_STRING* yr_parser_lookup_string(
yyscan_t yyscanner,
const char* identifier);
int yr_parser_lookup_string(
yyscan_t yyscanner,
const char* identifier,
YR_STRING** string);
int yr_parser_lookup_loop_variable(
@@ -80,10 +81,11 @@ int yr_parser_lookup_loop_variable(
const char* identifier);
YR_RULE* yr_parser_reduce_rule_declaration_phase_1(
int yr_parser_reduce_rule_declaration_phase_1(
yyscan_t yyscanner,
int32_t flags,
const char* identifier);
const char* identifier,
YR_RULE** rule);
int yr_parser_reduce_rule_declaration_phase_2(
@@ -91,19 +93,21 @@ int yr_parser_reduce_rule_declaration_phase_2(
YR_RULE* rule);
YR_STRING* yr_parser_reduce_string_declaration(
int yr_parser_reduce_string_declaration(
yyscan_t yyscanner,
int32_t flags,
const char* identifier,
SIZED_STRING* str);
SIZED_STRING* str,
YR_STRING** string);
YR_META* yr_parser_reduce_meta_declaration(
int yr_parser_reduce_meta_declaration(
yyscan_t yyscanner,
int32_t type,
const char* identifier,
const char* string,
int64_t integer);
int64_t integer,
YR_META** meta);
int yr_parser_reduce_string_identifier(
+19 -5
View File
@@ -27,7 +27,7 @@ typedef struct _IMPORTED_DLL
{
char *name;
struct _IMPORT_EXPORT_FUNCTION *functions;
struct _IMPORT_FUNCTION *functions;
struct _IMPORTED_DLL *next;
} IMPORTED_DLL, *PIMPORTED_DLL;
@@ -41,15 +41,29 @@ typedef struct _IMPORTED_DLL
// exports.
//
typedef struct _IMPORT_EXPORT_FUNCTION
typedef struct _IMPORT_FUNCTION
{
char *name;
uint8_t has_ordinal;
uint16_t ordinal;
struct _IMPORT_EXPORT_FUNCTION *next;
struct _IMPORT_FUNCTION *next;
} IMPORT_EXPORT_FUNCTION, *PIMPORT_EXPORT_FUNCTION;
} IMPORT_FUNCTION, *PIMPORT_FUNCTION;
typedef struct _EXPORT_FUNCTION
{
char *name;
uint16_t ordinal;
} EXPORT_FUNCTION, *PEXPORT_FUNCTION;
typedef struct _EXPORT_FUNCTIONS
{
uint32_t number_of_exports;
EXPORT_FUNCTION* functions;
} EXPORT_FUNCTIONS, *PEXPORT_FUNCTIONS;
typedef struct _PE
@@ -64,7 +78,7 @@ typedef struct _PE
YR_OBJECT* object;
IMPORTED_DLL* imported_dlls;
IMPORT_EXPORT_FUNCTION* exported_functions;
EXPORT_FUNCTIONS* exported_functions;
uint32_t resources;
+1
View File
@@ -32,6 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <ctype.h>
#include <yara/utils.h>
#include <yara/types.h>
#include <yara/arena.h>
#include <yara/sizedstr.h>
+1 -1
View File
@@ -65,7 +65,7 @@ typedef void* yyscan_t;
typedef struct _RE_LEX_ENVIRONMENT
{
RE_CLASS re_class;
int last_error_code;
int last_error;
char last_error_message[256];
} RE_LEX_ENVIRONMENT;
+6 -1
View File
@@ -81,7 +81,7 @@ YR_API int yr_rules_scan_mem(
YR_API int yr_rules_scan_file(
YR_RULES* rules,
const char* filename,
const wchar_t* filename,
int flags,
YR_CALLBACK_FUNC callback,
void* user_data,
@@ -158,6 +158,11 @@ YR_API void yr_rules_print_profiling_info(
YR_RULES* rules);
YR_API int yr_rules_get_stats(
YR_RULES* rules,
YR_RULES_STATS *stats);
YR_API void yr_rule_disable(
YR_RULE* rule);
+1 -1
View File
@@ -99,7 +99,7 @@ YR_API int yr_scanner_scan_mem(
YR_API int yr_scanner_scan_file(
YR_SCANNER* scanner,
const char* filename);
const wchar_t* filename);
YR_API int yr_scanner_scan_fd(
+12 -3
View File
@@ -55,7 +55,7 @@ typedef struct _YR_STOPWATCH
} YR_STOPWATCH;
#else
#elif defined(HAVE_CLOCK_GETTIME)
typedef struct _YR_STOPWATCH
{
@@ -63,6 +63,16 @@ typedef struct _YR_STOPWATCH
} YR_STOPWATCH;
#else
#include <sys/time.h>
typedef struct _YR_STOPWATCH
{
struct timeval tv_start;
} YR_STOPWATCH;
#endif
@@ -71,8 +81,7 @@ void yr_stopwatch_start(
YR_STOPWATCH* stopwatch);
// yr_stopwatch_elapsed_us returns the number of microseconds elapsed
// since the last call to yr_stopwatch_start or since the last time that
// yr_stopwatch_elapsed_us was called with restart set to TRUE.
// since the last call to yr_stopwatch_start.
uint64_t yr_stopwatch_elapsed_us(
YR_STOPWATCH* stopwatch);
@@ -32,6 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <yara/integers.h>
+68 -22
View File
@@ -30,8 +30,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef YR_TYPES_H
#define YR_TYPES_H
#include <yara/arena.h>
#include <yara/bitmask.h>
#include <yara/limits.h>
#include <yara/hash.h>
#include <yara/utils.h>
@@ -167,7 +167,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define META_TYPE_BOOLEAN 3
#define META_IS_NULL(x) \
((x) != NULL ? (x)->type == META_TYPE_NULL : TRUE)
((x) != NULL ? (x)->type == META_TYPE_NULL : true)
#define EXTERNAL_VARIABLE_TYPE_NULL 0
@@ -178,7 +178,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define EXTERNAL_VARIABLE_TYPE_MALLOC_STRING 5
#define EXTERNAL_VARIABLE_IS_NULL(x) \
((x) != NULL ? (x)->type == EXTERNAL_VARIABLE_TYPE_NULL : TRUE)
((x) != NULL ? (x)->type == EXTERNAL_VARIABLE_TYPE_NULL : true)
typedef struct RE RE;
@@ -202,6 +202,7 @@ typedef struct YR_MATCHES YR_MATCHES;
typedef struct YR_STRING YR_STRING;
typedef struct YR_RULE YR_RULE;
typedef struct YR_RULES YR_RULES;
typedef struct YR_RULES_STATS YR_RULES_STATS;
typedef struct YR_EXTERNAL_VARIABLE YR_EXTERNAL_VARIABLE;
typedef struct YR_MATCH YR_MATCH;
typedef struct YR_SCAN_CONTEXT YR_SCAN_CONTEXT;
@@ -231,7 +232,7 @@ typedef struct YR_MEMORY_BLOCK_ITERATOR YR_MEMORY_BLOCK_ITERATOR;
struct YR_NAMESPACE
{
int32_t t_flags[MAX_THREADS]; // Thread-specific flags
int32_t t_flags[YR_MAX_THREADS]; // Thread-specific flags
DECLARE_REFERENCE(char*, name);
};
@@ -270,18 +271,18 @@ struct YR_STRING
int64_t fixed_offset;
YR_MATCHES matches[MAX_THREADS];
YR_MATCHES unconfirmed_matches[MAX_THREADS];
YR_MATCHES matches[YR_MAX_THREADS];
YR_MATCHES unconfirmed_matches[YR_MAX_THREADS];
// Used only when PROFILING_ENABLED is defined
uint64_t time_cost;
volatile int64_t time_cost;
};
struct YR_RULE
{
int32_t g_flags; // Global flags
int32_t t_flags[MAX_THREADS]; // Thread-specific flags
int32_t g_flags; // Global flags
int32_t t_flags[YR_MAX_THREADS]; // Thread-specific flags
DECLARE_REFERENCE(const char*, identifier);
DECLARE_REFERENCE(const char*, tags);
@@ -290,7 +291,7 @@ struct YR_RULE
DECLARE_REFERENCE(YR_NAMESPACE*, ns);
// Used only when PROFILING_ENABLED is defined
uint64_t time_cost;
volatile int64_t time_cost;
};
@@ -304,7 +305,7 @@ struct YR_EXTERNAL_VARIABLE
char* s;
} value;
DECLARE_REFERENCE(char*, identifier);
DECLARE_REFERENCE(const char*, identifier);
};
@@ -325,7 +326,7 @@ struct YR_AC_MATCH_TABLE_ENTRY
};
typedef uint64_t YR_AC_TRANSITION;
typedef uint32_t YR_AC_TRANSITION;
typedef YR_AC_TRANSITION* YR_AC_TRANSITION_TABLE;
typedef YR_AC_MATCH_TABLE_ENTRY* YR_AC_MATCH_TABLE;
@@ -342,8 +343,12 @@ typedef struct YARA_RULES_FILE_HEADER
DECLARE_REFERENCE(YR_RULE*, rules_list_head);
DECLARE_REFERENCE(YR_EXTERNAL_VARIABLE*, externals_list_head);
DECLARE_REFERENCE(const uint8_t*, code_start);
DECLARE_REFERENCE(YR_AC_MATCH_TABLE, match_table);
DECLARE_REFERENCE(YR_AC_TRANSITION_TABLE, transition_table);
DECLARE_REFERENCE(YR_AC_MATCH_TABLE, ac_match_table);
DECLARE_REFERENCE(YR_AC_TRANSITION_TABLE, ac_transition_table);
// Size of ac_match_table and ac_transition_table in number of items (both
// tables have the same number of items)
uint32_t ac_tables_size;
} YARA_RULES_FILE_HEADER;
@@ -497,10 +502,14 @@ struct YR_AC_AUTOMATON
{
// Both m_table and t_table have the same number of elements, which is
// stored in tables_size.
uint32_t tables_size;
uint32_t t_table_unused_candidate;
// Bitmask where each bit indicates if the corresponding slot in m_table
// and t_table is already in use.
YR_BITMASK* bitmask;
YR_AC_TRANSITION_TABLE t_table;
YR_AC_MATCH_TABLE m_table;
YR_AC_STATE* root;
@@ -509,21 +518,57 @@ struct YR_AC_AUTOMATON
struct YR_RULES
{
unsigned char tidx_mask[YR_BITARRAY_NCHARS(MAX_THREADS)];
unsigned char tidx_mask[YR_BITARRAY_NCHARS(YR_MAX_THREADS)];
const uint8_t* code_start;
YR_MUTEX mutex;
YR_ARENA* arena;
YR_RULE* rules_list_head;
YR_EXTERNAL_VARIABLE* externals_list_head;
YR_AC_TRANSITION_TABLE transition_table;
YR_AC_MATCH_TABLE match_table;
YR_AC_TRANSITION_TABLE ac_transition_table;
YR_AC_MATCH_TABLE ac_match_table;
// Used only when PROFILING_ENABLED is defined
// Size of ac_match_table and ac_transition_table in number of items (both
// tables have the same numbe of items).
uint32_t ac_tables_size;
// Used only when PROFILING_ENABLED is defined.
uint64_t time_cost;
};
struct YR_RULES_STATS
{
// Total number of rules
uint32_t rules;
// Total number of strings across all rules.
uint32_t strings;
// Total number of Aho-Corasick matches. Each node in the Aho-Corasick
// automaton has a list of YR_AC_MATCH structures (match list) pointing to
// strings that are potential matches. This field holds the total number of
// those structures across all nodes in the automaton.
uint32_t ac_matches;
// Length of the match list for the root node in the Aho-Corasick automaton.
uint32_t ac_root_match_list_length;
// Average number of matches per match list.
float ac_average_match_list_length;
// Top 10 longest match lists.
uint32_t top_ac_match_list_lengths[100];
// Percentiles of match lists' lengths. If the i-th value in the array is N
// then i percent of the match lists have N or less items.
uint32_t ac_match_list_length_pctls[101];
// Size of Aho-Corasick transition & match tables.
uint32_t ac_tables_size;
};
typedef const uint8_t* (*YR_MEMORY_BLOCK_FETCH_DATA_FUNC)(
YR_MEMORY_BLOCK* self);
@@ -570,9 +615,9 @@ struct YR_SCAN_CONTEXT
int flags;
// Thread index for the thread using this scan context. The number of threads
// that can use a YR_RULES object simultaneusly is limited by the MAX_THREADS
// that can use a YR_RULES object simultaneusly is limited by the YR_MAX_THREADS
// constant. Each thread using a YR_RULES get assigned a unique thread index
// in the range [0, MAX_THREADS)
// in the range [0, YR_MAX_THREADS)
int tidx;
// Scan timeout in nanoseconds.
@@ -626,6 +671,7 @@ union YR_VALUE
#define OBJECT_COMMON_FIELDS \
int canary; \
int8_t type; \
const char* identifier; \
YR_OBJECT* parent; \
@@ -677,7 +723,7 @@ struct YR_OBJECT_FUNCTION
{
const char* arguments_fmt;
YR_MODULE_FUNC code;
} prototypes[MAX_OVERLOADED_FUNCTIONS];
} prototypes[YR_MAX_OVERLOADED_FUNCTIONS];
};
+45 -25
View File
@@ -32,23 +32,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define YR_UTILS_H
#include <limits.h>
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#include <yara/strutils.h>
#ifndef NULL
#define NULL 0
#endif
#if _WIN32 || __CYGWIN__
#define PRIu64 "I64d"
#if defined(HAVE_STDBOOL_H)
#include <stdbool.h>
#else
#include <inttypes.h>
#ifndef __cplusplus
#define bool int
#define true 1
#define false 0
#endif /* __cplusplus */
#endif
#ifdef __cplusplus
@@ -57,21 +54,38 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define EXTERNC
#endif
#if defined(__GNUC__)
#define YR_API EXTERNC __attribute__((visibility("default")))
#elif defined(_MSC_VER)
#define YR_API EXTERNC __declspec(dllexport)
#if defined(_WIN32) || defined(__CYGWIN__)
#ifdef YR_BUILDING_DLL
#ifdef __GNUC__
#define YR_API EXTERNC __attribute_((dllexport))
#define YR_DEPRECATED_API EXTERNC __attribute__((deprecated))
#else
#define YR_API EXTERNC __declspec(dllexport)
#define YR_DEPRECATED_API EXTERNC __declspec(deprecated)
#endif
#elif defined(YR_IMPORTING_DLL)
#ifdef __GNUC__
#define YR_API EXTERNC __attribute__((dllimport))
#define YR_DEPRECATED_API EXTERNC __attribute__((deprecated))
#else
#define YR_API EXTERNC __declspec(dllimport)
#define YR_DEPRECATED_API EXTERNC __declspec(deprecated)
#endif
#else
#define YR_API EXTERNC
#define YR_DEPRECATED_API EXTERNC
#endif
#else
#define YR_API EXTERNC
#if __GNUC__ >= 4
#define YR_API EXTERNC __attribute__((visibility ("default")))
#define YR_DEPRECATED_API YR_API __attribute__((deprecated))
#else
#define YR_API EXTERNC
#define YR_DEPRECATED_API EXTERNC
#endif
#endif
#if defined(__GNUC__)
#define YR_DEPRECATED_API EXTERNC __attribute__((deprecated))
#elif defined(_MSC_VER)
#define YR_DEPRECATED_API EXTERNC __declspec(deprecated)
#else
#define YR_DEPRECATED_API EXTERNC
#endif
#if defined(__GNUC__)
#define YR_ALIGN(n) __attribute__((aligned(n)))
@@ -81,8 +95,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define YR_ALIGN(n)
#endif
#define yr_min(x, y) ((x < y) ? (x) : (y))
#define yr_max(x, y) ((x > y) ? (x) : (y))
#if defined(__GNUC__)
#define YR_PRINTF_LIKE(x, y) __attribute__((format(printf, x, y)))
#else
#define YR_PRINTF_LIKE(x, y)
#endif
#define yr_min(x, y) (((x) < (y)) ? (x) : (y))
#define yr_max(x, y) (((x) > (y)) ? (x) : (y))
#define yr_swap(x, y, T) do { T temp = x; x = y; y = temp; } while (0)
File diff suppressed because it is too large Load Diff
+67 -56
View File
@@ -53,23 +53,28 @@ with noyywrap then we can remove this pragma.
#if defined(_WIN32) || defined(__CYGWIN__)
#include <windows.h>
#define strtoll _strtoi64
#else
#include <sys/stat.h>
#include <unistd.h>
#endif
#if defined(_WIN32)
#define strtoll _strtoi64
#endif
#include <yara/integers.h>
#include <yara/lexer.h>
#include <yara/sizedstr.h>
#include <yara/error.h>
#include <yara/mem.h>
#include <yara/utils.h>
#include <yara/strutils.h>
#include "grammar.h"
#define error(error_code) \
{ \
compiler->last_result = error_code; \
compiler->last_error = error_code; \
yyerror(yyscanner, compiler, NULL); \
yyterminate(); \
}
@@ -90,7 +95,7 @@ with noyywrap then we can remove this pragma.
#define yytext_to_buffer \
{ \
char *yptr = yytext; \
lex_check_space_ok(yptr, yyextra->lex_buf_len, LEX_BUF_SIZE); \
lex_check_space_ok(yptr, yyextra->lex_buf_len, YR_LEX_BUF_SIZE); \
while(*yptr) \
{ \
*yyextra->lex_buf_ptr++ = *yptr++; \
@@ -116,11 +121,11 @@ with noyywrap then we can remove this pragma.
#define snprintf _snprintf
#endif
static int is_absolute_path(
static bool is_absolute_path(
char* path)
{
if (path == NULL)
return FALSE;
return false;
#if defined(_WIN32) || defined(__CYGWIN__)
return strlen(path) > 2 &&
@@ -343,15 +348,12 @@ include[ \t]+\" {
<<EOF>> {
YR_COMPILER* compiler = yyget_extra(yyscanner);
_yr_compiler_pop_file_name(compiler);
yypop_buffer_state(yyscanner);
if (!YY_CURRENT_BUFFER)
{
yyterminate();
}
return _END_OF_INCLUDED_FILE_;
}
@@ -575,7 +577,7 @@ u?int(8|16|32)(be)? {
<str>\\t {
lex_check_space_ok("\t", yyextra->lex_buf_len, LEX_BUF_SIZE);
lex_check_space_ok("\t", yyextra->lex_buf_len, YR_LEX_BUF_SIZE);
*yyextra->lex_buf_ptr++ = '\t';
yyextra->lex_buf_len++;
}
@@ -583,7 +585,7 @@ u?int(8|16|32)(be)? {
<str>\\n {
lex_check_space_ok("\n", yyextra->lex_buf_len, LEX_BUF_SIZE);
lex_check_space_ok("\n", yyextra->lex_buf_len, YR_LEX_BUF_SIZE);
*yyextra->lex_buf_ptr++ = '\n';
yyextra->lex_buf_len++;
}
@@ -591,7 +593,7 @@ u?int(8|16|32)(be)? {
<str>\\\" {
lex_check_space_ok("\"", yyextra->lex_buf_len, LEX_BUF_SIZE);
lex_check_space_ok("\"", yyextra->lex_buf_len, YR_LEX_BUF_SIZE);
*yyextra->lex_buf_ptr++ = '\"';
yyextra->lex_buf_len++;
}
@@ -599,7 +601,7 @@ u?int(8|16|32)(be)? {
<str>\\\\ {
lex_check_space_ok("\\", yyextra->lex_buf_len, LEX_BUF_SIZE);
lex_check_space_ok("\\", yyextra->lex_buf_len, YR_LEX_BUF_SIZE);
*yyextra->lex_buf_ptr++ = '\\';
yyextra->lex_buf_len++;
}
@@ -610,7 +612,7 @@ u?int(8|16|32)(be)? {
int result;
sscanf( yytext + 2, "%x", &result );
lex_check_space_ok("X", yyextra->lex_buf_len, LEX_BUF_SIZE);
lex_check_space_ok("X", yyextra->lex_buf_len, YR_LEX_BUF_SIZE);
*yyextra->lex_buf_ptr++ = result;
yyextra->lex_buf_len++;
}
@@ -657,7 +659,7 @@ u?int(8|16|32)(be)? {
<regexp>\\\/ {
lex_check_space_ok("/", yyextra->lex_buf_len, LEX_BUF_SIZE);
lex_check_space_ok("/", yyextra->lex_buf_len, YR_LEX_BUF_SIZE);
*yyextra->lex_buf_ptr++ = '/';
yyextra->lex_buf_len++ ;
}
@@ -665,7 +667,7 @@ u?int(8|16|32)(be)? {
<regexp>\\. {
lex_check_space_ok("\\.", yyextra->lex_buf_len, LEX_BUF_SIZE);
lex_check_space_ok("\\.", yyextra->lex_buf_len, YR_LEX_BUF_SIZE);
if (yytext[1] == 0)
syntax_error("malformed regular expression");
@@ -788,7 +790,7 @@ void yyerror(
/*
if error_message != NULL the error comes from yyparse internal code
else the error comes from my code and the error code is set in
compiler->last_result
compiler->last_error
*/
compiler->errors++;
@@ -824,24 +826,17 @@ void yyerror(
compiler->user_data);
}
}
else
else if (compiler->callback != NULL)
{
compiler->last_error = compiler->last_result;
yr_compiler_get_error_message(compiler, message, sizeof(message));
if (compiler->callback != NULL)
{
yr_compiler_get_error_message(compiler, message, sizeof(message));
compiler->callback(
YARA_ERROR_LEVEL_ERROR,
file_name,
compiler->last_error_line,
message,
compiler->user_data);
}
compiler->callback(
YARA_ERROR_LEVEL_ERROR,
file_name,
compiler->last_error_line,
message,
compiler->user_data);
}
compiler->last_result = ERROR_SUCCESS;
}
@@ -903,13 +898,48 @@ int yr_lex_parse_rules_fd(
YR_COMPILER* compiler)
{
yyscan_t yyscanner;
char buf[1024];
size_t file_size;
void* buffer;
compiler->errors = 0;
if (setjmp(compiler->error_recovery) != 0)
return compiler->errors;
#if defined(_WIN32) || defined(__CYGWIN__)
file_size = (size_t) GetFileSize(rules_fd, NULL);
#else
struct stat fs;
if (fstat(rules_fd, &fs) != 0)
{
compiler->errors = 1;
compiler->last_error = ERROR_COULD_NOT_READ_FILE;
return compiler->errors;
}
file_size = (size_t) fs.st_size;
#endif
buffer = yr_malloc(file_size);
if (buffer == NULL)
{
compiler->errors = 1;
compiler->last_error = ERROR_INSUFFICIENT_MEMORY;
return compiler->errors;
}
#if defined(_WIN32) || defined(__CYGWIN__)
if (!ReadFile(rules_fd, buffer, file_size, NULL, NULL))
#else
if (read(rules_fd, buffer, file_size) != file_size)
#endif
{
yr_free(buffer);
compiler->errors = 1;
compiler->last_error = ERROR_COULD_NOT_READ_FILE;
return compiler->errors;
}
yylex_init(&yyscanner);
#if YYDEBUG
@@ -917,30 +947,11 @@ int yr_lex_parse_rules_fd(
#endif
yyset_extra(compiler, yyscanner);
while (1)
{
#if defined(_WIN32) || defined(__CYGWIN__)
DWORD len;
if (!ReadFile(rules_fd, buf, sizeof(buf), &len, NULL))
break;
#else
int len = (int) read(rules_fd, buf, sizeof(buf));
if (len < 0)
{
if (errno == EINTR)
continue;
else
break;
}
#endif
if (len == 0)
break;
yy_scan_bytes(buf, len, yyscanner);
}
yy_scan_bytes((const char*) buffer, file_size, yyscanner);
yyparse(yyscanner, compiler);
yylex_destroy(yyscanner);
yr_free(buffer);
return compiler->errors;
}
+10 -1
View File
@@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdio.h>
#include <ctype.h>
#include <yara/globals.h>
#include <yara/error.h>
#include <yara/re.h>
#include <yara/modules.h>
@@ -69,6 +70,10 @@ static struct yr_config_var
} yr_cfgs[YR_CONFIG_LAST];
// Global variables. See globals.h for their descriptions.
int yr_canary;
char yr_lowercase[256];
char yr_altercase[256];
@@ -122,6 +127,10 @@ YR_API int yr_initialize(void)
if (init_count > 1)
return ERROR_SUCCESS;
srand((unsigned) time(NULL));
yr_canary = rand();
for (i = 0; i < 256; i++)
{
if (i >= 'a' && i <= 'z')
@@ -151,7 +160,7 @@ YR_API int yr_initialize(void)
#elif defined(HAVE_WINCRYPT_H)
if (!CryptAcquireContext(&yr_cryptprov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
if (!CryptAcquireContext(&yr_cryptprov, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
return ERROR_INTERNAL_FATAL_ERROR;
}
+1 -1
View File
@@ -315,7 +315,7 @@ int module_load(
&json_error);
if (json == NULL)
return ERROR_INVALID_FILE;
return ERROR_INVALID_MODULE_DATA;
module_object->data = (void*) json;
+136 -115
View File
@@ -295,7 +295,7 @@ void dex_parse_header(
"header.magic");
set_integer(
dex_header->checksum,
yr_le32toh(dex_header->checksum),
module_object,
"header.checksum");
@@ -305,45 +305,45 @@ void dex_parse_header(
module_object,
"header.signature");
set_integer(dex_header->file_size, module_object,
set_integer(yr_le32toh(dex_header->file_size), module_object,
"header.file_size");
set_integer(dex_header->header_size, module_object,
set_integer(yr_le32toh(dex_header->header_size), module_object,
"header.header_size");
set_integer(dex_header->endian_tag, module_object,
set_integer(yr_le32toh(dex_header->endian_tag), module_object,
"header.endian_tag");
set_integer(dex_header->link_size, module_object,
set_integer(yr_le32toh(dex_header->link_size), module_object,
"header.link_size");
set_integer(dex_header->link_offset, module_object,
set_integer(yr_le32toh(dex_header->link_offset), module_object,
"header.link_offset");
set_integer(dex_header->map_offset, module_object,
set_integer(yr_le32toh(dex_header->map_offset), module_object,
"header.map_offset");
set_integer(dex_header->string_ids_size, module_object,
set_integer(yr_le32toh(dex_header->string_ids_size), module_object,
"header.string_ids_size");
set_integer(dex_header->string_ids_offset, module_object,
set_integer(yr_le32toh(dex_header->string_ids_offset), module_object,
"header.string_ids_offset");
set_integer(dex_header->type_ids_size, module_object,
set_integer(yr_le32toh(dex_header->type_ids_size), module_object,
"header.type_ids_size");
set_integer(dex_header->type_ids_offset, module_object,
set_integer(yr_le32toh(dex_header->type_ids_offset), module_object,
"header.type_ids_offset");
set_integer(dex_header->proto_ids_size, module_object,
set_integer(yr_le32toh(dex_header->proto_ids_size), module_object,
"header.proto_ids_size");
set_integer(dex_header->proto_ids_offset, module_object,
set_integer(yr_le32toh(dex_header->proto_ids_offset), module_object,
"header.proto_ids_offset");
set_integer(dex_header->field_ids_size, module_object,
set_integer(yr_le32toh(dex_header->field_ids_size), module_object,
"header.field_ids_size");
set_integer(dex_header->field_ids_offset, module_object,
set_integer(yr_le32toh(dex_header->field_ids_offset), module_object,
"header.field_ids_offset");
set_integer(dex_header->method_ids_size, module_object,
set_integer(yr_le32toh(dex_header->method_ids_size), module_object,
"header.method_ids_size");
set_integer(dex_header->method_ids_offset, module_object,
set_integer(yr_le32toh(dex_header->method_ids_offset), module_object,
"header.method_ids_offset");
set_integer(dex_header->class_defs_size, module_object,
set_integer(yr_le32toh(dex_header->class_defs_size), module_object,
"header.class_defs_size");
set_integer(dex_header->class_defs_offset, module_object,
set_integer(yr_le32toh(dex_header->class_defs_offset), module_object,
"header.class_defs_offset");
set_integer(dex_header->data_size, module_object,
set_integer(yr_le32toh(dex_header->data_size), module_object,
"header.data_size");
set_integer(dex_header->data_offset, module_object,
set_integer(yr_le32toh(dex_header->data_offset), module_object,
"header.data_offset");
}
@@ -405,7 +405,7 @@ uint32_t load_encoded_field(
encoded_field.access_flags);
#endif
uint32_t name_idx = get_integer(
int name_idx = (int) get_integer(
dex->object, "field_ids[%i].name_idx", *previous_field_idx);
#ifdef DEBUG_DEX_MODULE
@@ -431,10 +431,10 @@ uint32_t load_encoded_field(
index_encoded_field);
}
uint32_t class_idx = get_integer(
int class_idx = (int) get_integer(
dex->object, "field_ids[%i].class_idx", *previous_field_idx);
uint32_t descriptor_idx = get_integer(
int descriptor_idx = (int) get_integer(
dex->object, "type_ids[%i].descriptor_idx", class_idx);
SIZED_STRING* class_name = get_string(
@@ -457,10 +457,10 @@ uint32_t load_encoded_field(
index_encoded_field);
}
uint32_t type_idx = get_integer(dex->object,
int type_idx = (int) get_integer(dex->object,
"field_ids[%i].type_idx", *previous_field_idx);
uint32_t shorty_idx = get_integer(dex->object,
int shorty_idx = (int) get_integer(dex->object,
"type_ids[%i].descriptor_idx", type_idx);
SIZED_STRING* proto_name = get_string(dex->object,
@@ -553,7 +553,7 @@ uint32_t load_encoded_method(
encoded_method.code_off);
#endif
uint32_t name_idx = get_integer(
int name_idx = (int) get_integer(
dex->object, "method_ids[%i].name_idx", *previous_method_idx);
#ifdef DEBUG_DEX_MODULE
@@ -579,10 +579,10 @@ uint32_t load_encoded_method(
index_encoded_method);
}
uint32_t class_idx = get_integer(
int class_idx = (int) get_integer(
dex->object, "method_ids[%i].class_idx", *previous_method_idx);
uint32_t descriptor_idx = get_integer(
int descriptor_idx = (int) get_integer(
dex->object, "type_ids[%i].descriptor_idx", class_idx);
SIZED_STRING* class_name = get_string(
@@ -605,10 +605,10 @@ uint32_t load_encoded_method(
index_encoded_method);
}
uint32_t proto_idx = get_integer(
int proto_idx = (int) get_integer(
dex->object, "method_ids[%i].proto_idx", *previous_method_idx);
uint32_t shorty_idx = get_integer(
int shorty_idx = (int) get_integer(
dex->object, "proto_ids[%i].shorty_idx", proto_idx);
SIZED_STRING* proto_name = get_string(
@@ -673,7 +673,7 @@ uint32_t load_encoded_method(
void dex_parse(
DEX* dex,
size_t base_address)
uint64_t base_address)
{
dex_header_t* dex_header;
@@ -691,8 +691,9 @@ void dex_parse(
dex_header = dex->header;
if (!fits_in_dex(dex, dex->data + dex_header->string_ids_offset,
dex_header->string_ids_size * sizeof(string_id_item_t)))
if (!fits_in_dex(
dex, dex->data + yr_le32toh(dex_header->string_ids_offset),
yr_le32toh(dex_header->string_ids_size) * sizeof(string_id_item_t)))
return;
#ifdef DEBUG_DEX_MODULE
@@ -700,50 +701,54 @@ void dex_parse(
#endif
// Get information about the String ID section
for (i = 0; i < dex_header->string_ids_size; i++)
for (i = 0; i < yr_le32toh(dex_header->string_ids_size); i++)
{
string_id_item_t* string_id_item = (string_id_item_t*) (
dex->data +
dex_header->string_ids_offset +
yr_le32toh(dex_header->string_ids_offset) +
i * sizeof(string_id_item_t));
#ifdef DEBUG_DEX_MODULE
printf("[DEX] STRING ID item data_offset:0x%x\n",
string_id_item->string_data_offset);
yr_le32toh(string_id_item->string_data_offset));
#endif
if (!fits_in_dex(dex, dex->data + string_id_item->string_data_offset,
sizeof(uint32_t)))
if (!fits_in_dex(
dex, dex->data + yr_le32toh(string_id_item->string_data_offset),
sizeof(uint32_t)))
continue;
uint32_t value = (uint32_t)read_uleb128(
(dex->data + string_id_item->string_data_offset), &uleb128_size);
uint32_t value = (uint32_t) read_uleb128(
(dex->data + yr_le32toh(string_id_item->string_data_offset)),
&uleb128_size);
#ifdef DEBUG_DEX_MODULE
printf("[DEX] STRING ID item size:0x%x\n", value);
#endif
if (!fits_in_dex(dex, dex->data + string_id_item->string_data_offset,
value))
if (!fits_in_dex(
dex, dex->data + yr_le32toh(string_id_item->string_data_offset),
value))
continue;
set_integer(
string_id_item->string_data_offset, dex->object,
yr_le32toh(string_id_item->string_data_offset), dex->object,
"string_ids[%i].offset", i);
set_integer(string_id_item->string_data_offset, dex->object,
set_integer(yr_le32toh(string_id_item->string_data_offset), dex->object,
"string_ids[%i].size", value);
set_sized_string(
(const char*)((dex->data + string_id_item->string_data_offset + 1)),
(const char*) ((dex->data + yr_le32toh(string_id_item->string_data_offset) + 1)),
value,
dex->object,
"string_ids[%i].value",
i);
}
if (!fits_in_dex(dex, dex->data + dex_header->type_ids_offset,
dex_header->type_ids_size * sizeof(type_id_item_t)))
if (!fits_in_dex(
dex, dex->data + yr_le32toh(dex_header->type_ids_offset),
yr_le32toh(dex_header->type_ids_size) * sizeof(type_id_item_t)))
return;
#ifdef DEBUG_DEX_MODULE
@@ -751,20 +756,23 @@ void dex_parse(
#endif
// Get information about the Type ID section
for (i = 0; i < dex_header->type_ids_size; i++)
for (i = 0; i < yr_le32toh(dex_header->type_ids_size); i++)
{
type_id_item_t* type_id_item = (type_id_item_t*) (
dex->data + dex_header->type_ids_offset + i * sizeof(type_id_item_t));
dex->data +
yr_le32toh(dex_header->type_ids_offset) +
i * sizeof(type_id_item_t));
set_integer(
type_id_item->descriptor_idx,
yr_le32toh(type_id_item->descriptor_idx),
dex->object,
"type_ids[%i].descriptor_idx",
i);
}
if (!fits_in_dex(dex, dex->data + dex_header->proto_ids_offset,
dex_header->proto_ids_size * sizeof(proto_id_item_t)))
if (!fits_in_dex(
dex, dex->data + yr_le32toh(dex_header->proto_ids_offset),
yr_le32toh(dex_header->proto_ids_size) * sizeof(proto_id_item_t)))
return;
#ifdef DEBUG_DEX_MODULE
@@ -772,21 +780,24 @@ void dex_parse(
#endif
// Get information about the Proto ID section
for (i = 0; i < dex_header->proto_ids_size; i++)
for (i = 0; i < yr_le32toh(dex_header->proto_ids_size); i++)
{
proto_id_item_t* proto_id_item = (proto_id_item_t*) (
dex->data + dex_header->proto_ids_offset + i * sizeof(proto_id_item_t));
dex->data +
yr_le32toh(dex_header->proto_ids_offset) +
i * sizeof(proto_id_item_t));
set_integer(proto_id_item->shorty_idx, dex->object,
set_integer(yr_le32toh(proto_id_item->shorty_idx), dex->object,
"proto_ids[%i].shorty_idx", i);
set_integer(proto_id_item->return_type_idx, dex->object,
set_integer(yr_le32toh(proto_id_item->return_type_idx), dex->object,
"proto_ids[%i].return_type_idx", i);
set_integer(proto_id_item->parameters_offset, dex->object,
set_integer(yr_le32toh(proto_id_item->parameters_offset), dex->object,
"proto_ids[%i].parameters_offset", i);
}
if (!fits_in_dex(dex, dex->data + dex_header->field_ids_offset,
dex_header->field_ids_size * sizeof(field_id_item_t)))
if (!fits_in_dex(
dex, dex->data + yr_le32toh(dex_header->field_ids_offset),
yr_le32toh(dex_header->field_ids_size) * sizeof(field_id_item_t)))
return;
#ifdef DEBUG_DEX_MODULE
@@ -794,21 +805,24 @@ void dex_parse(
#endif
// Get information about the Field ID section
for (i = 0; i < dex_header->field_ids_size; i++)
for (i = 0; i < yr_le32toh(dex_header->field_ids_size); i++)
{
field_id_item_t* field_id_item = (field_id_item_t*) (
dex->data + dex_header->field_ids_offset + i * sizeof(field_id_item_t));
dex->data +
yr_le32toh(dex_header->field_ids_offset) +
i * sizeof(field_id_item_t));
set_integer(field_id_item->class_idx, dex->object,
set_integer(yr_le16toh(field_id_item->class_idx), dex->object,
"field_ids[%i].class_idx", i);
set_integer(field_id_item->type_idx, dex->object,
set_integer(yr_le16toh(field_id_item->type_idx), dex->object,
"field_ids[%i].type_idx", i);
set_integer(field_id_item->name_idx, dex->object,
set_integer(yr_le32toh(field_id_item->name_idx), dex->object,
"field_ids[%i].name_idx", i);
}
if (!fits_in_dex(dex, dex->data + dex_header->method_ids_offset,
dex_header->method_ids_size * sizeof(method_id_item_t)))
if (!fits_in_dex(
dex, dex->data + yr_le32toh(dex_header->method_ids_offset),
yr_le32toh(dex_header->method_ids_size) * sizeof(method_id_item_t)))
return;
#ifdef DEBUG_DEX_MODULE
@@ -816,18 +830,18 @@ void dex_parse(
#endif
// Get information about the Method ID section
for (i = 0; i < dex_header->method_ids_size; i++)
for (i = 0; i < yr_le32toh(dex_header->method_ids_size); i++)
{
method_id_item_t* method_id_item = (method_id_item_t*) (
dex->data +
dex_header->method_ids_offset +
yr_le32toh(dex_header->method_ids_offset) +
i * sizeof(method_id_item_t));
set_integer(method_id_item->class_idx, dex->object,
set_integer(yr_le16toh(method_id_item->class_idx), dex->object,
"method_ids[%i].class_idx", i);
set_integer(method_id_item->proto_idx, dex->object,
set_integer(yr_le16toh(method_id_item->proto_idx), dex->object,
"method_ids[%i].proto_idx", i);
set_integer(method_id_item->name_idx, dex->object,
set_integer(yr_le32toh(method_id_item->name_idx), dex->object,
"method_ids[%i].name_idx", i);
}
@@ -836,38 +850,41 @@ void dex_parse(
#endif
// Get information about the Map List ID section
if (dex_header->map_offset != 0 &&
fits_in_dex(dex, dex->data + dex_header->map_offset, sizeof(uint32_t)))
if (yr_le32toh(dex_header->map_offset) != 0 &&
fits_in_dex(dex, dex->data + yr_le32toh(dex_header->map_offset), sizeof(uint32_t)))
{
uint32_t* map_list_size = (uint32_t *) (dex->data + dex_header->map_offset);
uint32_t* map_list_size = (uint32_t *) (
dex->data + yr_le32toh(dex_header->map_offset));
set_integer(*map_list_size, dex->object, "map_list.size");
set_integer(yr_le32toh(*map_list_size), dex->object, "map_list.size");
if (!fits_in_dex(dex, dex->data + dex_header->map_offset,
sizeof(uint32_t) + *map_list_size * sizeof(map_item_t)))
if (!fits_in_dex(
dex, dex->data + yr_le32toh(dex_header->map_offset),
sizeof(uint32_t) + yr_le32toh(*map_list_size) * sizeof(map_item_t)))
return;
for (i = 0; i < *map_list_size; i++)
for (i = 0; i < yr_le32toh(*map_list_size); i++)
{
map_item_t* map_item = (map_item_t*) (
dex->data +
dex_header->map_offset +
yr_le32toh(dex_header->map_offset) +
sizeof(uint32_t) +
i * sizeof(map_item_t));
set_integer(map_item->type, dex->object,
set_integer(yr_le16toh(map_item->type), dex->object,
"map_list.map_item[%i].type", i);
set_integer(map_item->unused, dex->object,
set_integer(yr_le16toh(map_item->unused), dex->object,
"map_list.map_item[%i].unused", i);
set_integer(map_item->size, dex->object,
set_integer(yr_le32toh(map_item->size), dex->object,
"map_list.map_item[%i].size", i);
set_integer(map_item->offset, dex->object,
set_integer(yr_le32toh(map_item->offset), dex->object,
"map_list.map_item[%i].offset", i);
}
}
if (!fits_in_dex(dex, dex->data + dex_header->class_defs_offset,
dex_header->class_defs_size * sizeof(class_id_item_t)))
if (!fits_in_dex(
dex, dex->data + yr_le32toh(dex_header->class_defs_offset),
yr_le32toh(dex_header->class_defs_size) * sizeof(class_id_item_t)))
return;
#ifdef DEBUG_DEX_MODULE
@@ -875,11 +892,11 @@ void dex_parse(
#endif
// Get information about the Class ID section
for (i = 0; i < dex_header->class_defs_size; i++)
for (i = 0; i < yr_le32toh(dex_header->class_defs_size); i++)
{
class_id_item_t* class_id_item = (class_id_item_t*) (
dex->data +
dex_header->class_defs_offset +
yr_le32toh(dex_header->class_defs_offset) +
i * sizeof(class_id_item_t));
#ifdef DEBUG_DEX_MODULE
@@ -887,57 +904,58 @@ void dex_parse(
"super_class_idx:0x%x interfaces_off:0x%x source_file_idx:0x%x "\
"annotations_offset:0x%x class_data_offset:0x%x "\
"static_values_offset:0x%x\n",
class_id_item->class_idx,
class_id_item->access_flags,
class_id_item->super_class_idx,
class_id_item->interfaces_off,
class_id_item->source_file_idx,
class_id_item->annotations_offset,
class_id_item->class_data_offset,
class_id_item->static_values_offset);
yr_le32toh(class_id_item->class_idx),
yr_le32toh(class_id_item->access_flags),
yr_le32toh(class_id_item->super_class_idx),
yr_le32toh(class_id_item->interfaces_off),
yr_le32toh(class_id_item->source_file_idx),
yr_le32toh(class_id_item->annotations_offset),
yr_le32toh(class_id_item->class_data_offset),
yr_le32toh(class_id_item->static_values_offset));
#endif
set_integer(class_id_item->class_idx, dex->object,
set_integer(yr_le32toh(class_id_item->class_idx), dex->object,
"class_defs[%i].class_idx", i);
set_integer(class_id_item->access_flags, dex->object,
set_integer(yr_le32toh(class_id_item->access_flags), dex->object,
"class_defs[%i].access_flags", i);
set_integer(class_id_item->super_class_idx, dex->object,
set_integer(yr_le32toh(class_id_item->super_class_idx), dex->object,
"class_defs[%i].super_class_idx", i);
set_integer(class_id_item->interfaces_off, dex->object,
set_integer(yr_le32toh(class_id_item->interfaces_off), dex->object,
"class_defs[%i].interfaces_off", i);
set_integer(class_id_item->source_file_idx, dex->object,
set_integer(yr_le32toh(class_id_item->source_file_idx), dex->object,
"class_defs[%i].source_file_idx", i);
set_integer(class_id_item->annotations_offset, dex->object,
set_integer(yr_le32toh(class_id_item->annotations_offset), dex->object,
"class_defs[%i].annotations_offset", i);
set_integer(class_id_item->class_data_offset, dex->object,
set_integer(yr_le32toh(class_id_item->class_data_offset), dex->object,
"class_defs[%i].class_data_off", i);
set_integer(class_id_item->static_values_offset, dex->object,
set_integer(yr_le32toh(class_id_item->static_values_offset), dex->object,
"class_defs[%i].static_values_offset", i);
if (class_id_item->class_data_offset != 0)
if (yr_le32toh(class_id_item->class_data_offset) != 0)
{
class_data_item_t class_data_item;
if (!fits_in_dex(dex, dex->data + class_id_item->class_data_offset,
4 * sizeof(uint32_t)))
if (!fits_in_dex(
dex, dex->data + yr_le32toh(class_id_item->class_data_offset),
4 * sizeof(uint32_t)))
return;
uleb128_size = 0;
class_data_item.static_fields_size = (uint32_t) read_uleb128(
(dex->data + class_id_item->class_data_offset),
(dex->data + yr_le32toh(class_id_item->class_data_offset)),
&uleb128_size);
class_data_item.instance_fields_size = (uint32_t) read_uleb128(
(dex->data + class_id_item->class_data_offset + uleb128_size),
(dex->data + yr_le32toh(class_id_item->class_data_offset) + uleb128_size),
&uleb128_size);
class_data_item.direct_methods_size = (uint32_t) read_uleb128(
(dex->data + class_id_item->class_data_offset + uleb128_size),
(dex->data + yr_le32toh(class_id_item->class_data_offset) + uleb128_size),
&uleb128_size);
class_data_item.virtual_methods_size = (uint32_t) read_uleb128(
(dex->data + class_id_item->class_data_offset + uleb128_size),
(dex->data + yr_le32toh(class_id_item->class_data_offset) + uleb128_size),
&uleb128_size);
set_integer(
@@ -965,7 +983,7 @@ void dex_parse(
{
uleb128_size += load_encoded_field(
dex,
class_id_item->class_data_offset + uleb128_size,
yr_le32toh(class_id_item->class_data_offset) + uleb128_size,
&previous_field_idx,
index_encoded_field,
1,0);
@@ -978,11 +996,12 @@ void dex_parse(
#endif
previous_field_idx = 0;
for (j = 0; j < class_data_item.instance_fields_size; j++)
{
uleb128_size += load_encoded_field(
dex,
class_id_item->class_data_offset + uleb128_size,
yr_le32toh(class_id_item->class_data_offset) + uleb128_size,
&previous_field_idx,
index_encoded_field,
0, 1);
@@ -995,11 +1014,12 @@ void dex_parse(
#endif
uint32_t previous_method_idx = 0;
for (j = 0; j < class_data_item.direct_methods_size; j++)
{
uleb128_size += load_encoded_method(
dex,
class_id_item->class_data_offset + uleb128_size,
yr_le32toh(class_id_item->class_data_offset) + uleb128_size,
&previous_method_idx,
index_encoded_method,
1, 0);
@@ -1012,11 +1032,12 @@ void dex_parse(
#endif
previous_method_idx = 0;
for (j = 0; j < class_data_item.virtual_methods_size; j++)
{
uleb128_size += load_encoded_method(
dex,
class_id_item->class_data_offset + uleb128_size,
yr_le32toh(class_id_item->class_data_offset) + uleb128_size,
&previous_method_idx,
index_encoded_method,
0, 1);
+2 -1
View File
@@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <yara/endian.h>
#include <yara/modules.h>
#include <yara/mem.h>
#include <yara/utils.h>
#define MODULE_NAME elf
@@ -63,7 +64,7 @@ int get_elf_class_data(
}
}
static int is_valid_ptr(
static bool is_valid_ptr(
const void* base,
size_t size,
const void* ptr,
+8 -8
View File
@@ -180,7 +180,7 @@ define_function(data_md5)
char digest_ascii[YR_MD5_LEN * 2 + 1];
char* cached_ascii_digest;
int past_first_block = FALSE;
bool past_first_block = false;
YR_SCAN_CONTEXT* context = scan_context();
YR_MEMORY_BLOCK* block = first_memory_block(context);
@@ -224,7 +224,7 @@ define_function(data_md5)
yr_md5_update(&md5_context, block_data + data_offset, data_len);
}
past_first_block = TRUE;
past_first_block = true;
}
else if (past_first_block)
{
@@ -263,7 +263,7 @@ define_function(data_sha1)
char digest_ascii[YR_SHA1_LEN * 2 + 1];
char* cached_ascii_digest;
int past_first_block = FALSE;
int past_first_block = false;
int64_t arg_offset = integer_argument(1); // offset where to start
int64_t arg_length = integer_argument(2); // length of bytes we want hash on
@@ -306,7 +306,7 @@ define_function(data_sha1)
yr_sha1_update(&sha_context, block_data + data_offset, data_len);
}
past_first_block = TRUE;
past_first_block = true;
}
else if (past_first_block)
{
@@ -345,7 +345,7 @@ define_function(data_sha256)
char digest_ascii[YR_SHA256_LEN * 2 + 1];
char* cached_ascii_digest;
int past_first_block = FALSE;
int past_first_block = false;
int64_t arg_offset = integer_argument(1); // offset where to start
int64_t arg_length = integer_argument(2); // length of bytes we want hash on
@@ -387,7 +387,7 @@ define_function(data_sha256)
yr_sha256_update(&sha256_context, block_data + data_offset, data_len);
}
past_first_block = TRUE;
past_first_block = true;
}
else if (past_first_block)
{
@@ -428,7 +428,7 @@ define_function(data_checksum32)
YR_MEMORY_BLOCK_ITERATOR* iterator = context->iterator;
uint32_t checksum = 0;
int past_first_block = FALSE;
int past_first_block = false;
if (offset < 0 || length < 0 || offset < block->base)
return_integer(UNDEFINED);
@@ -454,7 +454,7 @@ define_function(data_checksum32)
checksum += *(block_data + data_offset + i);
}
past_first_block = TRUE;
past_first_block = true;
}
else if (past_first_block)
{
+37 -37
View File
@@ -91,13 +91,13 @@ int macho_fat_is_32(
// Convert virtual address to file offset. Segments have to be already loaded.
int macho_rva_to_offset(
bool macho_rva_to_offset(
uint64_t address,
uint64_t* result,
YR_OBJECT* object)
{
uint64_t segment_count = get_integer(object, "number_of_segments");
for (uint64_t i = 0; i < segment_count; i++)
for (int i = 0; i < segment_count; i++)
{
uint64_t start = get_integer(object, "segments[%i].vmaddr", i);
uint64_t end = start + get_integer(object, "segments[%i].vmsize", i);
@@ -106,10 +106,10 @@ int macho_rva_to_offset(
{
uint64_t fileoff = get_integer(object, "segments[%i].fileoff", i);
*result = fileoff + (address - start);
return TRUE;
return true;
}
}
return FALSE;
return false;
}
@@ -121,7 +121,7 @@ int macho_offset_to_rva(
YR_OBJECT* object)
{
uint64_t segment_count = get_integer(object, "number_of_segments");
for (uint64_t i = 0; i < segment_count; i++)
for (int i = 0; i < segment_count; i++)
{
uint64_t start = get_integer(object, "segments[%i].fileoff", i);
uint64_t end = start + get_integer(object, "segments[%i].filesize", i);
@@ -130,10 +130,10 @@ int macho_offset_to_rva(
{
uint64_t vmaddr = get_integer(object, "segments[%i].vmaddr", i);
*result = vmaddr + (offset - start);
return TRUE;
return true;
}
}
return FALSE;
return false;
}
@@ -145,62 +145,62 @@ void macho_handle_unixthread_##bo( \
YR_OBJECT* object, \
YR_SCAN_CONTEXT* context) \
{ \
command = (void*)((uint8_t*)command + sizeof(thread_command_t)); \
command = (void*)((uint8_t*)command + sizeof(yr_thread_command_t)); \
uint64_t address = 0; \
\
switch (get_integer(object, "cputype")) \
{ \
case CPU_TYPE_MC680X0: \
{ \
m68k_thread_state_t* m68k_state = (m68k_thread_state_t*)command; \
yr_m68k_thread_state_t* m68k_state = (yr_m68k_thread_state_t*)command; \
address = yr_##bo##32toh(m68k_state->pc); \
break; \
} \
case CPU_TYPE_MC88000: \
{ \
m88k_thread_state_t* m88k_state = (m88k_thread_state_t*)command; \
yr_m88k_thread_state_t* m88k_state = (yr_m88k_thread_state_t*)command; \
address = yr_##bo##32toh(m88k_state->xip); \
break; \
} \
case CPU_TYPE_SPARC: \
{ \
sparc_thread_state_t* sparc_state = (sparc_thread_state_t*)command; \
yr_sparc_thread_state_t* sparc_state = (yr_sparc_thread_state_t*)command;\
address = yr_##bo##32toh(sparc_state->pc); \
break; \
} \
case CPU_TYPE_POWERPC: \
{ \
ppc_thread_state_t* ppc_state = (ppc_thread_state_t*)command; \
yr_ppc_thread_state_t* ppc_state = (yr_ppc_thread_state_t*)command; \
address = yr_##bo##32toh(ppc_state->srr0); \
break; \
} \
case CPU_TYPE_X86: \
{ \
x86_thread_state_t* x86_state = (x86_thread_state_t*)command; \
yr_x86_thread_state_t* x86_state = (yr_x86_thread_state_t*)command; \
address = yr_##bo##32toh(x86_state->eip); \
break; \
} \
case CPU_TYPE_ARM: \
{ \
arm_thread_state_t* arm_state = (arm_thread_state_t*)command; \
yr_arm_thread_state_t* arm_state = (yr_arm_thread_state_t*)command; \
address = yr_##bo##32toh(arm_state->pc); \
break; \
} \
case CPU_TYPE_X86_64: \
{ \
x86_thread_state64_t* x64_state = (x86_thread_state64_t*)command; \
yr_x86_thread_state64_t* x64_state = (yr_x86_thread_state64_t*)command; \
address = yr_##bo##64toh(x64_state->rip); \
break; \
} \
case CPU_TYPE_ARM64: \
{ \
arm_thread_state64_t* arm64_state = (arm_thread_state64_t*)command; \
yr_arm_thread_state64_t* arm64_state = (yr_arm_thread_state64_t*)command;\
address = yr_##bo##64toh(arm64_state->pc); \
break; \
} \
case CPU_TYPE_POWERPC64: \
{ \
ppc_thread_state64_t* ppc64_state = (ppc_thread_state64_t*)command; \
yr_ppc_thread_state64_t* ppc64_state = (yr_ppc_thread_state64_t*)command;\
address = yr_##bo##64toh(ppc64_state->srr0); \
break; \
} \
@@ -235,7 +235,7 @@ void macho_handle_main_##bo( \
YR_OBJECT* object, \
YR_SCAN_CONTEXT* context) \
{ \
entry_point_command_t* ep_command = (entry_point_command_t*)command; \
yr_entry_point_command_t* ep_command = (yr_entry_point_command_t*)command; \
\
uint64_t offset = yr_##bo##64toh(ep_command->entryoff); \
if (context->flags & SCAN_FLAGS_PROCESS_MEMORY) \
@@ -262,10 +262,10 @@ MACHO_HANDLE_MAIN(be)
#define MACHO_HANDLE_SEGMENT(bits,bo) \
void macho_handle_segment_##bits##_##bo( \
const uint8_t* command, \
const uint64_t i, \
const unsigned i, \
YR_OBJECT* object) \
{ \
segment_command_##bits##_t* sg = (segment_command_##bits##_t*)command; \
yr_segment_command_##bits##_t* sg = (yr_segment_command_##bits##_t*)command; \
uint64_t command_size = yr_##bo##bits##toh(sg->cmdsize); \
\
set_sized_string(sg->segname, strnlen(sg->segname, 16), \
@@ -288,14 +288,14 @@ void macho_handle_segment_##bits##_##bo( \
set_integer(yr_##bo##32toh(sg->flags), \
object, "segments[%i].flags", i); \
\
uint64_t parsed_size = sizeof(segment_command_##bits##_t); \
uint64_t parsed_size = sizeof(yr_segment_command_##bits##_t); \
for (unsigned j = 0; j < yr_##bo##32toh(sg->nsects); ++j) \
{ \
parsed_size += sizeof(section_##bits##_t); \
parsed_size += sizeof(yr_section_##bits##_t); \
if (command_size < parsed_size) \
break; \
\
section_##bits##_t* sec = ((section_##bits##_t*)(sg + 1)) + j; \
yr_section_##bits##_t* sec = ((yr_section_##bits##_t*)(sg + 1)) + j; \
set_sized_string(sec->segname, strnlen(sec->segname, 16), \
object, "segments[%i].sections[%i].segname", i, j); \
set_sized_string(sec->sectname, strnlen(sec->sectname, 16), \
@@ -321,7 +321,7 @@ void macho_handle_segment_##bits##_##bo( \
object, "segments[%i].sections[%i].reserved2", i, j); \
if (bits == 64) \
{ \
section_64_t* sec_64 = (section_64_t*)sec; \
yr_section_64_t* sec_64 = (yr_section_64_t*)sec; \
set_integer(yr_##bo##32toh(sec_64->reserved3), \
object, "segments[%i].sections[%i].reserved3", i, j); \
} \
@@ -343,10 +343,10 @@ void macho_parse_file_##bits##_##bo( \
YR_OBJECT* object, \
YR_SCAN_CONTEXT* context) \
{ \
if (size < sizeof(mach_header_##bits##_t)) \
if (size < sizeof(yr_mach_header_##bits##_t)) \
return; \
\
mach_header_##bits##_t* header = (mach_header_##bits##_t*)data; \
yr_mach_header_##bits##_t* header = (yr_mach_header_##bits##_t*)data; \
set_integer(yr_##bo##32toh(header->magic), object, "magic"); \
set_integer(yr_##bo##32toh(header->cputype), object, "cputype"); \
set_integer(yr_##bo##32toh(header->cpusubtype), object, "cpusubtype"); \
@@ -356,17 +356,17 @@ void macho_parse_file_##bits##_##bo( \
set_integer(yr_##bo##32toh(header->flags), object, "flags"); \
if (bits == 64) \
{ \
mach_header_64_t* header_64 = (mach_header_64_t*)data; \
yr_mach_header_64_t* header_64 = (yr_mach_header_64_t*)data; \
set_integer(yr_##bo##32toh(header_64->reserved), object, "reserved"); \
} \
\
uint64_t seg_count = 0; \
uint64_t parsed_size = sizeof(mach_header_##bits##_t); \
uint64_t parsed_size = sizeof(yr_mach_header_##bits##_t); \
\
uint8_t *command = (uint8_t*)(header + 1); \
for (unsigned i = 0; i < yr_##bo##32toh(header->ncmds); i++) \
{ \
load_command_t* command_struct = (load_command_t*)command; \
yr_load_command_t* command_struct = (yr_load_command_t*)command; \
uint64_t command_size = yr_##bo##32toh(command_struct->cmdsize); \
\
if (size < parsed_size + command_size) \
@@ -447,21 +447,21 @@ void macho_parse_fat_file_##bits( \
YR_OBJECT* object, \
YR_SCAN_CONTEXT* context) \
{ \
if (size < sizeof(fat_header_t)) \
if (size < sizeof(yr_fat_header_t)) \
return; \
\
/* All data in Mach-O fat binary headers are in big-endian byte order. */ \
\
const fat_header_t* header = (fat_header_t*)data; \
const yr_fat_header_t* header = (yr_fat_header_t*)data; \
set_integer(yr_be32toh(header->magic), object, "fat_magic"); \
\
uint32_t count = yr_be32toh(header->nfat_arch); \
set_integer(count, object, "nfat_arch"); \
\
if (size < sizeof(fat_header_t) + count * sizeof(fat_arch_##bits##_t)) \
if (size < sizeof(yr_fat_header_t) + count * sizeof(yr_fat_arch_##bits##_t)) \
return; \
\
fat_arch_##bits##_t* archs = (fat_arch_##bits##_t*)(header + 1); \
yr_fat_arch_##bits##_t* archs = (yr_fat_arch_##bits##_t*)(header + 1); \
for (uint32_t i = 0; i < count; i++) \
{ \
set_integer(yr_be32toh(archs[i].cputype), \
@@ -722,7 +722,7 @@ define_function(file_index_type)
if (is_undefined(module, "nfat_arch"))
return_integer(UNDEFINED);
for (uint64_t i = 0; i < nfat; i++)
for (int i = 0; i < nfat; i++)
{
int64_t type = get_integer(module, "file[%i].cputype", i);
if (type == type_arg)
@@ -746,7 +746,7 @@ define_function(file_index_subtype)
if (is_undefined(module, "nfat_arch"))
return_integer(UNDEFINED);
for (uint64_t i = 0; i < nfat; i++)
for (int i = 0; i < nfat; i++)
{
int64_t type = get_integer(module, "file[%i].cputype", i);
int64_t subtype = get_integer(module, "file[%i].cpusubtype", i);
@@ -771,7 +771,7 @@ define_function(ep_for_arch_type)
if (is_undefined(module, "nfat_arch"))
return_integer(UNDEFINED);
for (uint64_t i = 0; i < nfat; i++)
for (int i = 0; i < nfat; i++)
{
int64_t type = get_integer(module, "fat_arch[%i].cputype", i);
if (type == type_arg)
@@ -797,7 +797,7 @@ define_function(ep_for_arch_subtype)
if (is_undefined(module, "nfat_arch"))
return_integer(UNDEFINED);
for (uint64_t i = 0; i < nfat; i++)
for (int i = 0; i < nfat; i++)
{
int64_t type = get_integer(module, "fat_arch[%i].cputype", i);
int64_t subtype = get_integer(module, "fat_arch[%i].cpusubtype", i);
+5 -5
View File
@@ -38,10 +38,10 @@ The original idea and inspiration for this module comes from Armin Buescher.
#define MODULE_NAME magic
magic_t magic_cookie[MAX_THREADS];
magic_t magic_cookie[YR_MAX_THREADS];
const char* cached_types[MAX_THREADS];
const char* cached_mime_types[MAX_THREADS];
const char* cached_types[YR_MAX_THREADS];
const char* cached_mime_types[YR_MAX_THREADS];
define_function(magic_mime_type)
@@ -122,7 +122,7 @@ int module_initialize(
{
int i;
for (i = 0; i < MAX_THREADS; i++)
for (i = 0; i < YR_MAX_THREADS; i++)
magic_cookie[i] = NULL;
return ERROR_SUCCESS;
@@ -134,7 +134,7 @@ int module_finalize(
{
int i;
for (i = 0; i < MAX_THREADS; i++)
for (i = 0; i < YR_MAX_THREADS; i++)
if (magic_cookie[i] != NULL)
magic_close(magic_cookie[i]);
+36 -10
View File
@@ -29,6 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <math.h>
#include <yara/utils.h>
#include <yara/modules.h>
#include <yara/mem.h>
@@ -80,7 +81,7 @@ define_function(string_entropy)
define_function(data_entropy)
{
int past_first_block = FALSE;
bool past_first_block = false;
double entropy = 0.0;
size_t total_len = 0;
@@ -130,7 +131,7 @@ define_function(data_entropy)
data[c] += 1;
}
past_first_block = TRUE;
past_first_block = true;
}
else if (past_first_block)
{
@@ -186,7 +187,7 @@ define_function(string_deviation)
define_function(data_deviation)
{
int past_first_block = FALSE;
int past_first_block = false;
int64_t offset = integer_argument(1);
int64_t length = integer_argument(2);
@@ -228,7 +229,7 @@ define_function(data_deviation)
for (i = 0; i < data_len; i++)
sum += fabs(((double)* (block_data + data_offset + i)) - mean);
past_first_block = TRUE;
past_first_block = true;
}
else if (past_first_block)
{
@@ -267,7 +268,7 @@ define_function(string_mean)
define_function(data_mean)
{
int past_first_block = FALSE;
int past_first_block = false;
double sum = 0.0;
int64_t offset = integer_argument(1);
@@ -304,7 +305,7 @@ define_function(data_mean)
for (i = 0; i < data_len; i++)
sum += (double)* (block_data + data_offset + i);
past_first_block = TRUE;
past_first_block = true;
}
else if (past_first_block)
{
@@ -329,7 +330,7 @@ define_function(data_mean)
define_function(data_serial_correlation)
{
int past_first_block = FALSE;
int past_first_block = false;
size_t total_len = 0;
size_t i;
@@ -378,7 +379,7 @@ define_function(data_serial_correlation)
scclast = sccun;
}
past_first_block = TRUE;
past_first_block = true;
}
else if (past_first_block)
{
@@ -449,7 +450,7 @@ define_function(string_serial_correlation)
define_function(data_monte_carlo_pi)
{
int past_first_block = FALSE;
int past_first_block = false;
int mcount = 0;
int inmont = 0;
@@ -510,7 +511,7 @@ define_function(data_monte_carlo_pi)
}
}
past_first_block = TRUE;
past_first_block = true;
}
else if (past_first_block)
{
@@ -591,6 +592,29 @@ define_function(in_range)
}
// Undefine existing "min" and "max" macros in order to avoid conflicts with
// function names.
#undef min
#undef max
define_function(min)
{
uint64_t i = integer_argument(1);
uint64_t j = integer_argument(2);
return_integer(i < j ? i : j);
}
define_function(max)
{
uint64_t i = integer_argument(1);
uint64_t j = integer_argument(2);
return_integer(i > j ? i : j);
}
begin_declarations;
declare_float("MEAN_BYTES");
@@ -605,6 +629,8 @@ begin_declarations;
declare_function("monte_carlo_pi", "s", "f", string_monte_carlo_pi);
declare_function("entropy", "ii", "f", data_entropy);
declare_function("entropy", "s", "f", string_entropy);
declare_function("min", "ii", "i", min);
declare_function("max", "ii", "i", max);
end_declarations;
+437 -125
View File
@@ -50,6 +50,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <yara/modules.h>
#include <yara/mem.h>
#include <yara/strutils.h>
#include <yara/utils.h>
#include <yara/pe_utils.h>
@@ -677,15 +679,14 @@ int pe_collect_resources(
}
IMPORT_EXPORT_FUNCTION* pe_parse_import_descriptor(
IMPORT_FUNCTION* pe_parse_import_descriptor(
PE* pe,
PIMAGE_IMPORT_DESCRIPTOR import_descriptor,
char* dll_name)
char* dll_name,
int* num_function_imports)
{
IMPORT_EXPORT_FUNCTION* head = NULL;
IMPORT_EXPORT_FUNCTION* tail = NULL;
int num_functions = 0;
IMPORT_FUNCTION* head = NULL;
IMPORT_FUNCTION* tail = NULL;
int64_t offset = pe_rva_to_offset(
pe, yr_le32toh(import_descriptor->OriginalFirstThunk));
@@ -705,7 +706,7 @@ IMPORT_EXPORT_FUNCTION* pe_parse_import_descriptor(
while (struct_fits_in_pe(pe, thunks64, IMAGE_THUNK_DATA64) &&
yr_le64toh(thunks64->u1.Ordinal) != 0 &&
num_functions < MAX_PE_IMPORTS)
*num_function_imports < MAX_PE_IMPORTS)
{
char* name = NULL;
uint16_t ordinal = 0;
@@ -740,8 +741,8 @@ IMPORT_EXPORT_FUNCTION* pe_parse_import_descriptor(
if (name != NULL || has_ordinal == 1)
{
IMPORT_EXPORT_FUNCTION* imported_func = (IMPORT_EXPORT_FUNCTION*)
yr_calloc(1, sizeof(IMPORT_EXPORT_FUNCTION));
IMPORT_FUNCTION* imported_func = (IMPORT_FUNCTION*)
yr_calloc(1, sizeof(IMPORT_FUNCTION));
if (imported_func == NULL)
{
@@ -763,7 +764,7 @@ IMPORT_EXPORT_FUNCTION* pe_parse_import_descriptor(
tail = imported_func;
}
num_functions++;
(*num_function_imports)++;
thunks64++;
}
}
@@ -772,7 +773,7 @@ IMPORT_EXPORT_FUNCTION* pe_parse_import_descriptor(
PIMAGE_THUNK_DATA32 thunks32 = (PIMAGE_THUNK_DATA32)(pe->data + offset);
while (struct_fits_in_pe(pe, thunks32, IMAGE_THUNK_DATA32) &&
yr_le32toh(thunks32->u1.Ordinal) != 0 && num_functions < MAX_PE_IMPORTS)
yr_le32toh(thunks32->u1.Ordinal) != 0 && *num_function_imports < MAX_PE_IMPORTS)
{
char* name = NULL;
uint16_t ordinal = 0;
@@ -807,8 +808,8 @@ IMPORT_EXPORT_FUNCTION* pe_parse_import_descriptor(
if (name != NULL || has_ordinal == 1)
{
IMPORT_EXPORT_FUNCTION* imported_func = (IMPORT_EXPORT_FUNCTION*)
yr_calloc(1, sizeof(IMPORT_EXPORT_FUNCTION));
IMPORT_FUNCTION* imported_func = (IMPORT_FUNCTION*)
yr_calloc(1, sizeof(IMPORT_FUNCTION));
if (imported_func == NULL)
{
@@ -830,7 +831,7 @@ IMPORT_EXPORT_FUNCTION* pe_parse_import_descriptor(
tail = imported_func;
}
num_functions++;
(*num_function_imports)++;
thunks32++;
}
}
@@ -857,7 +858,7 @@ int pe_valid_dll_name(
}
else
{
return FALSE;
return false;
}
}
@@ -875,14 +876,19 @@ IMPORTED_DLL* pe_parse_imports(
PE* pe)
{
int64_t offset;
int num_imports = 0;
int num_imports = 0; // Number of imported DLLs
int num_function_imports = 0; // Total number of functions imported
IMPORTED_DLL* head = NULL;
IMPORTED_DLL* tail = NULL;
PIMAGE_IMPORT_DESCRIPTOR imports;
PIMAGE_DATA_DIRECTORY directory;
PIMAGE_DATA_DIRECTORY directory = pe_get_directory_entry(
/* default to 0 imports until we know there are any */
set_integer(0, pe->object, "number_of_imports");
directory = pe_get_directory_entry(
pe, IMAGE_DIRECTORY_ENTRY_IMPORT);
if (directory == NULL)
@@ -911,14 +917,17 @@ IMPORTED_DLL* pe_parse_imports(
char* dll_name = (char *) (pe->data + offset);
if (!pe_valid_dll_name(dll_name, pe->data_size - (size_t) offset))
break;
{
imports++;
continue;
}
imported_dll = (IMPORTED_DLL*) yr_calloc(1, sizeof(IMPORTED_DLL));
if (imported_dll != NULL)
{
IMPORT_EXPORT_FUNCTION* functions = pe_parse_import_descriptor(
pe, imports, dll_name);
IMPORT_FUNCTION* functions = pe_parse_import_descriptor(
pe, imports, dll_name, &num_function_imports);
if (functions != NULL)
{
@@ -954,29 +963,30 @@ IMPORTED_DLL* pe_parse_imports(
// "exports" function for comparison.
//
IMPORT_EXPORT_FUNCTION* pe_parse_exports(
EXPORT_FUNCTIONS* pe_parse_exports(
PE* pe)
{
IMPORT_EXPORT_FUNCTION* head = NULL;
IMPORT_EXPORT_FUNCTION* tail = NULL;
PIMAGE_DATA_DIRECTORY directory;
PIMAGE_EXPORT_DIRECTORY exports;
EXPORT_FUNCTIONS* exported_functions;
DWORD* names;
WORD* ordinals;
int64_t offset;
uint32_t i;
uint32_t number_of_names;
uint16_t ordinal;
int64_t offset;
size_t remaining;
int num_exports = 0;
DWORD* names = NULL;
WORD* ordinals = NULL;
// If not a PE file, return UNDEFINED
if (pe == NULL)
return NULL;
/* default to 0 exports until we know there are any */
set_integer(0, pe->object, "number_of_exports");
directory = pe_get_directory_entry(
pe, IMAGE_DIRECTORY_ENTRY_EXPORT);
@@ -996,33 +1006,63 @@ IMPORT_EXPORT_FUNCTION* pe_parse_exports(
if (!struct_fits_in_pe(pe, exports, IMAGE_EXPORT_DIRECTORY))
return NULL;
offset = pe_rva_to_offset(pe, yr_le32toh(exports->AddressOfNames));
if (offset < 0)
return NULL;
if (yr_le32toh(exports->NumberOfFunctions) > MAX_PE_EXPORTS ||
yr_le32toh(exports->NumberOfFunctions) * sizeof(DWORD) > pe->data_size - offset)
return NULL;
names = (DWORD*)(pe->data + offset);
if (yr_le32toh(exports->NumberOfNames) > 0)
{
offset = pe_rva_to_offset(pe, yr_le32toh(exports->AddressOfNames));
offset = pe_rva_to_offset(pe, yr_le32toh(exports->AddressOfNameOrdinals));
if (offset < 0)
return NULL;
if (offset < 0)
if (yr_le32toh(exports->NumberOfNames) * sizeof(DWORD) > pe->data_size - offset)
return NULL;
names = (DWORD*)(pe->data + offset);
offset = pe_rva_to_offset(pe, yr_le32toh(exports->AddressOfNameOrdinals));
if (offset < 0)
return NULL;
ordinals = (WORD*)(pe->data + offset);
}
exported_functions = (EXPORT_FUNCTIONS*) yr_malloc(sizeof(EXPORT_FUNCTIONS));
if (exported_functions == NULL)
return NULL;
ordinals = (WORD*)(pe->data + offset);
exported_functions->number_of_exports = yr_le32toh(
exports->NumberOfFunctions);
// Walk the number of functions, not the number of names as each exported
// symbol has an ordinal value, but names are optional.
exported_functions->functions = (EXPORT_FUNCTION*) yr_malloc(
exported_functions->number_of_exports * sizeof(EXPORT_FUNCTION));
for (i = 0; i < yr_le32toh(exports->NumberOfFunctions); i++)
if (exported_functions->functions == NULL)
{
IMPORT_EXPORT_FUNCTION* exported_func;
uint16_t ordinal = 0;
char* name;
yr_free(exported_functions);
return NULL;
}
// At first, iterate through Functions array and create representation for
// each exported function. Ordinal is just array index that starts from 1
for (i = 0; i < exported_functions->number_of_exports; i++)
{
exported_functions->functions[i].name = NULL;
exported_functions->functions[i].ordinal = i + 1;
}
// Now, we can iterate through Names and NameOrdinals arrays to obtain
// function names. Not all functions have names.
number_of_names = yr_min(
yr_le32toh(exports->NumberOfNames),
exported_functions->number_of_exports);
for (i = 0; i < number_of_names; i++)
{
if (available_space(pe, names + i) < sizeof(DWORD) ||
available_space(pe, ordinals + i) < sizeof(WORD))
{
@@ -1034,40 +1074,27 @@ IMPORT_EXPORT_FUNCTION* pe_parse_exports(
if (offset < 0)
continue;
remaining = pe->data_size - (size_t) offset;
name = yr_strndup((char*) (pe->data + offset), remaining);
// Get the corresponding ordinal. Note that we are not subtracting the
// ordinal base here as we don't intend to index into the export address
// table.
// Even though it is called ordinal, it is just index to Functions array
// If it was ordinal it would start from 1 but it starts from 0
ordinal = yr_le16toh(ordinals[i]);
// Now add it to the list...
exported_func = (IMPORT_EXPORT_FUNCTION*)
yr_calloc(1, sizeof(IMPORT_EXPORT_FUNCTION));
if (exported_func == NULL)
{
yr_free(name);
if (ordinal >= exported_functions->number_of_exports)
continue;
remaining = pe->data_size - (size_t) offset;
if (exported_functions->functions[ordinal].name == NULL)
{
exported_functions->functions[ordinal].name = yr_strndup(
(char*) (pe->data + offset), remaining);
}
exported_func->name = name;
exported_func->ordinal = ordinal;
exported_func->next = NULL;
if (head == NULL)
head = exported_func;
if (tail != NULL)
tail->next = exported_func;
tail = exported_func;
num_exports++;
}
set_integer(num_exports, pe->object, "number_of_exports");
return head;
set_integer(
exported_functions->number_of_exports,
pe->object, "number_of_exports");
return exported_functions;
}
@@ -1174,11 +1201,25 @@ void pe_parse_certificates(
const char* sig_alg;
char buffer[256];
int bytes;
const EVP_MD* sha1_digest = EVP_sha1();
unsigned char thumbprint[YR_SHA1_LEN];
char thumbprint_ascii[YR_SHA1_LEN * 2 + 1];
ASN1_INTEGER* serial;
X509* cert = sk_X509_value(certs, i);
X509_digest(cert, sha1_digest, thumbprint, NULL);
for (i = 0; i < YR_SHA1_LEN; i++)
sprintf(thumbprint_ascii + (i * 2), "%02x", thumbprint[i]);
set_string(
(char*) thumbprint_ascii,
pe->object,
"signatures[%i].thumbprint",
counter);
X509_NAME_oneline(
X509_get_issuer_name(cert), buffer, sizeof(buffer));
@@ -1314,13 +1355,19 @@ void pe_parse_header(
int flags)
{
PIMAGE_SECTION_HEADER section;
PIMAGE_DATA_DIRECTORY data_dir;
char section_name[IMAGE_SIZEOF_SHORT_NAME + 1];
int i, scount;
int i, scount, ddcount;
uint64_t highest_sec_siz = 0;
uint64_t highest_sec_ofs = 0;
uint64_t section_end;
uint64_t last_section_end;
set_integer(1, pe->object, "is_pe");
set_integer(
yr_le16toh(pe->header->FileHeader.Machine),
pe->object, "machine");
@@ -1333,6 +1380,18 @@ void pe_parse_header(
yr_le32toh(pe->header->FileHeader.TimeDateStamp),
pe->object, "timestamp");
set_integer(
yr_le32toh(pe->header->FileHeader.PointerToSymbolTable),
pe->object, "pointer_to_symbol_table");
set_integer(
yr_le32toh(pe->header->FileHeader.NumberOfSymbols),
pe->object, "number_of_symbols");
set_integer(
yr_le32toh(pe->header->FileHeader.SizeOfOptionalHeader),
pe->object, "size_of_optional_header");
set_integer(
yr_le16toh(pe->header->FileHeader.Characteristics),
pe->object, "characteristics");
@@ -1350,11 +1409,13 @@ void pe_parse_header(
pe->object, "image_base");
set_integer(
IS_64BITS_PE(pe) ?
yr_le64toh(OptionalHeader(pe, NumberOfRvaAndSizes)) :
yr_le32toh(OptionalHeader(pe, NumberOfRvaAndSizes)),
pe->object, "number_of_rva_and_sizes");
set_integer(
yr_le32toh(OptionalHeader(pe, Magic)),
pe->object, "opthdr_magic");
set_integer(
OptionalHeader(pe, MajorLinkerVersion),
pe->object, "linker_version.major");
@@ -1363,6 +1424,37 @@ void pe_parse_header(
OptionalHeader(pe, MinorLinkerVersion),
pe->object, "linker_version.minor");
set_integer(
yr_le32toh(OptionalHeader(pe, SizeOfCode)),
pe->object, "size_of_code");
set_integer(
yr_le32toh(OptionalHeader(pe, SizeOfInitializedData)),
pe->object, "size_of_initialized_data");
set_integer(
yr_le32toh(OptionalHeader(pe, SizeOfUninitializedData)),
pe->object, "size_of_uninitialized_data");
set_integer(
yr_le32toh(OptionalHeader(pe, BaseOfCode)),
pe->object, "base_of_code");
if (!IS_64BITS_PE(pe))
{
set_integer(
yr_le32toh(pe->header->OptionalHeader.BaseOfData),
pe->object, "base_of_data");
}
set_integer(
yr_le32toh(OptionalHeader(pe, SectionAlignment)),
pe->object, "section_alignment");
set_integer(
yr_le32toh(OptionalHeader(pe, FileAlignment)),
pe->object, "file_alignment");
set_integer(
yr_le16toh(OptionalHeader(pe, MajorOperatingSystemVersion)),
pe->object, "os_version.major");
@@ -1387,6 +1479,18 @@ void pe_parse_header(
yr_le16toh(OptionalHeader(pe, MinorSubsystemVersion)),
pe->object, "subsystem_version.minor");
set_integer(
yr_le32toh(OptionalHeader(pe, Win32VersionValue)),
pe->object, "win32_version_value");
set_integer(
yr_le32toh(OptionalHeader(pe, SizeOfImage)),
pe->object, "size_of_image");
set_integer(
yr_le32toh(OptionalHeader(pe, SizeOfHeaders)),
pe->object, "size_of_headers");
set_integer(
yr_le32toh(OptionalHeader(pe, CheckSum)),
pe->object, "checksum");
@@ -1399,6 +1503,54 @@ void pe_parse_header(
OptionalHeader(pe, DllCharacteristics),
pe->object, "dll_characteristics");
set_integer(
IS_64BITS_PE(pe) ?
yr_le64toh(OptionalHeader(pe, SizeOfStackReserve)) :
yr_le32toh(OptionalHeader(pe, SizeOfStackReserve)),
pe->object, "size_of_stack_reserve");
set_integer(
IS_64BITS_PE(pe) ?
yr_le64toh(OptionalHeader(pe, SizeOfStackCommit)) :
yr_le32toh(OptionalHeader(pe, SizeOfStackCommit)),
pe->object, "size_of_stack_commit");
set_integer(
IS_64BITS_PE(pe) ?
yr_le64toh(OptionalHeader(pe, SizeOfHeapReserve)) :
yr_le32toh(OptionalHeader(pe, SizeOfHeapReserve)),
pe->object, "size_of_heap_reserve");
set_integer(
IS_64BITS_PE(pe) ?
yr_le64toh(OptionalHeader(pe, SizeOfHeapCommit)) :
yr_le32toh(OptionalHeader(pe, SizeOfHeapCommit)),
pe->object, "size_of_heap_commit");
set_integer(
yr_le32toh(OptionalHeader(pe, LoaderFlags)),
pe->object, "loader_flags");
data_dir = IS_64BITS_PE(pe) ? pe->header64->OptionalHeader.DataDirectory : pe->header->OptionalHeader.DataDirectory;
ddcount = yr_le16toh(OptionalHeader(pe, NumberOfRvaAndSizes));
ddcount = yr_min(ddcount, IMAGE_NUMBEROF_DIRECTORY_ENTRIES);
for (i = 0; i < ddcount; i++)
{
if (!struct_fits_in_pe(pe, data_dir, IMAGE_DATA_DIRECTORY))
break;
set_integer(
yr_le32toh(data_dir->VirtualAddress),
pe->object, "data_directories[%i].virtual_address", i);
set_integer(
yr_le32toh(data_dir->Size),
pe->object, "data_directories[%i].size", i);
data_dir++;
}
pe_iterate_resources(
pe,
(RESOURCE_CALLBACK_FUNC) pe_collect_resources,
@@ -1443,9 +1595,31 @@ void pe_parse_header(
yr_le32toh(section->Misc.VirtualSize),
pe->object, "sections[%i].virtual_size", i);
set_integer(
yr_le32toh(section->PointerToRelocations),
pe->object, "sections[%i].pointer_to_relocations", i);
set_integer(
yr_le32toh(section->PointerToLinenumbers),
pe->object, "sections[%i].pointer_to_line_numbers", i);
set_integer(
yr_le32toh(section->NumberOfRelocations),
pe->object, "sections[%i].number_of_relocations", i);
set_integer(
yr_le32toh(section->NumberOfLinenumbers),
pe->object, "sections[%i].number_of_line_numbers", i);
// This will catch the section with the highest raw offset to help checking
// if overlay data is present
if (yr_le32toh(section->PointerToRawData) > highest_sec_ofs)
// if overlay data is present. If two sections have the same raw pointer
// but different raw sizes the largest one is used. An example of this case
// is file: cf62bf1815a93e68e6c5189f689286b66c4088b9507cf3ecf835e4ac3f9ededa
section_end = yr_le32toh(section->PointerToRawData) +
yr_le32toh(section->SizeOfRawData);
if (section_end > highest_sec_ofs + highest_sec_siz)
{
highest_sec_ofs = yr_le32toh(section->PointerToRawData);
highest_sec_siz = yr_le32toh(section->SizeOfRawData);
@@ -1498,7 +1672,7 @@ define_function(section_index_addr)
YR_OBJECT* module = module();
YR_SCAN_CONTEXT* context = scan_context();
int64_t i;
int i;
int64_t offset;
int64_t size;
@@ -1536,7 +1710,7 @@ define_function(section_index_name)
char* name = string_argument(1);
int64_t n = get_integer(module, "number_of_sections");
int64_t i;
int i;
if (is_undefined(module, "number_of_sections"))
return_integer(UNDEFINED);
@@ -1560,21 +1734,23 @@ define_function(exports)
YR_OBJECT* module = module();
PE* pe = (PE*) module->data;
IMPORT_EXPORT_FUNCTION* exported_func;
int i;
// If not a PE, return UNDEFINED.
if (pe == NULL)
return_integer(UNDEFINED);
exported_func = pe->exported_functions;
// If PE, but not exported functions, return false.
if (pe->exported_functions == NULL)
return_integer(0);
while (exported_func != NULL)
for (i = 0; i < pe->exported_functions->number_of_exports; i++)
{
if (strcasecmp(exported_func->name, function_name->c_string) == 0)
if (pe->exported_functions->functions[i].name &&
strcasecmp(pe->exported_functions->functions[i].name, function_name->c_string) == 0)
{
return_integer(1);
exported_func = exported_func->next;
}
}
return_integer(0);
@@ -1588,19 +1764,23 @@ define_function(exports_regexp)
YR_OBJECT* module = module();
PE* pe = (PE*) module->data;
IMPORT_EXPORT_FUNCTION* exported_func;
int i;
if (!pe)
// If not a PE, return UNDEFINED.
if (pe == NULL)
return_integer(UNDEFINED);
exported_func = pe->exported_functions;
// If PE, but not exported functions, return false.
if (pe->exported_functions == NULL)
return_integer(0);
while (exported_func != NULL)
for (i = 0; i < pe->exported_functions->number_of_exports; i++)
{
if (yr_re_match(scan_context(), regex, exported_func->name) != -1)
if (pe->exported_functions->functions[i].name &&
yr_re_match(scan_context(), regex, pe->exported_functions->functions[i].name) != -1)
{
return_integer(1);
exported_func = exported_func->next;
}
}
return_integer(0);
@@ -1614,20 +1794,20 @@ define_function(exports_ordinal)
YR_OBJECT* module = module();
PE* pe = (PE*) module->data;
IMPORT_EXPORT_FUNCTION* exported_func;
if (!pe)
// If not a PE, return UNDEFINED.
if (pe == NULL)
return_integer(UNDEFINED);
exported_func = pe->exported_functions;
// If PE, but not exported functions, return false.
if (pe->exported_functions == NULL)
return_integer(0);
while (exported_func != NULL)
{
if (exported_func->ordinal == ordinal)
return_integer(1);
if (ordinal == 0 || ordinal > pe->exported_functions->number_of_exports)
return_integer(0);
exported_func = exported_func->next;
}
// Just in case, this should always be true
if (pe->exported_functions->functions[ordinal - 1].ordinal == ordinal)
return_integer(1);
return_integer(0);
}
@@ -1653,7 +1833,7 @@ define_function(imphash)
unsigned char digest[YR_MD5_LEN];
char digest_ascii[YR_MD5_LEN * 2 + 1];
size_t i;
int first = TRUE;
bool first = true;
PE* pe = (PE*) module->data;
@@ -1668,7 +1848,7 @@ define_function(imphash)
while (dll)
{
IMPORT_EXPORT_FUNCTION* func;
IMPORT_FUNCTION* func;
size_t dll_name_len;
char* dll_name;
@@ -1724,7 +1904,7 @@ define_function(imphash)
yr_free(final_name);
func = func->next;
first = FALSE;
first = false;
}
yr_free(dll_name);
@@ -1768,7 +1948,7 @@ define_function(imports)
{
if (strcasecmp(imported_dll->name, dll_name) == 0)
{
IMPORT_EXPORT_FUNCTION* imported_func = imported_dll->functions;
IMPORT_FUNCTION* imported_func = imported_dll->functions;
while (imported_func != NULL)
{
@@ -1805,7 +1985,7 @@ define_function(imports_ordinal)
{
if (strcasecmp(imported_dll->name, dll_name) == 0)
{
IMPORT_EXPORT_FUNCTION* imported_func = imported_dll->functions;
IMPORT_FUNCTION* imported_func = imported_dll->functions;
while (imported_func != NULL)
{
@@ -1822,6 +2002,38 @@ define_function(imports_ordinal)
return_integer(0);
}
define_function(imports_regex)
{
YR_OBJECT* module = module();
PE* pe = (PE*)module->data;
IMPORTED_DLL* imported_dll;
if (!pe)
return_integer(UNDEFINED);
imported_dll = pe->imported_dlls;
while (imported_dll != NULL)
{
if (yr_re_match(scan_context(), regexp_argument(1), imported_dll->name) > 0)
{
IMPORT_FUNCTION* imported_func = imported_dll->functions;
while (imported_func != NULL)
{
if (yr_re_match(scan_context(), regexp_argument(2), imported_func->name) > 0)
return_integer(1);
imported_func = imported_func->next;
}
}
imported_dll = imported_dll->next;
}
return_integer(0);
}
define_function(imports_dll)
{
char* dll_name = string_argument(1);
@@ -1855,7 +2067,7 @@ define_function(locale)
PE* pe = (PE*) module->data;
uint64_t locale = integer_argument(1);
int64_t n, i;
int n, i;
if (is_undefined(module, "number_of_resources"))
return_integer(UNDEFINED);
@@ -1885,7 +2097,7 @@ define_function(language)
PE* pe = (PE*) module->data;
uint64_t language = integer_argument(1);
int64_t n, i;
int n, i;
if (is_undefined(module, "number_of_resources"))
return_integer(UNDEFINED);
@@ -1953,7 +2165,7 @@ static uint64_t rich_internal(
{
int64_t rich_length;
int64_t rich_count;
int64_t i;
int i;
PRICH_SIGNATURE clear_rich_signature;
SIZED_STRING* rich_string;
@@ -1970,7 +2182,7 @@ static uint64_t rich_internal(
return UNDEFINED;
if (version == UNDEFINED && toolid == UNDEFINED)
return FALSE;
return false;
clear_rich_signature = (PRICH_SIGNATURE) rich_string->c_string;
@@ -1990,23 +2202,23 @@ static uint64_t rich_internal(
{
// check version and toolid
if (match_version && match_toolid)
return TRUE;
return true;
}
else if (version != UNDEFINED)
{
// check only version
if (match_version)
return TRUE;
return true;
}
else if (toolid != UNDEFINED)
{
// check only toolid
if (match_toolid)
return TRUE;
return true;
}
}
return FALSE;
return false;
}
@@ -2170,6 +2382,22 @@ begin_declarations;
declare_integer("UP_SYSTEM_ONLY");
declare_integer("BYTES_REVERSED_HI");
declare_integer("IMAGE_DIRECTORY_ENTRY_EXPORT");
declare_integer("IMAGE_DIRECTORY_ENTRY_IMPORT");
declare_integer("IMAGE_DIRECTORY_ENTRY_RESOURCE");
declare_integer("IMAGE_DIRECTORY_ENTRY_EXCEPTION");
declare_integer("IMAGE_DIRECTORY_ENTRY_SECURITY");
declare_integer("IMAGE_DIRECTORY_ENTRY_BASERELOC");
declare_integer("IMAGE_DIRECTORY_ENTRY_DEBUG");
declare_integer("IMAGE_DIRECTORY_ENTRY_ARCHITECTURE");
declare_integer("IMAGE_DIRECTORY_ENTRY_GLOBALPTR");
declare_integer("IMAGE_DIRECTORY_ENTRY_TLS");
declare_integer("IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG");
declare_integer("IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT");
declare_integer("IMAGE_DIRECTORY_ENTRY_IAT");
declare_integer("IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT");
declare_integer("IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR");
declare_integer("SECTION_CNT_CODE");
declare_integer("SECTION_CNT_INITIALIZED_DATA");
declare_integer("SECTION_CNT_UNINITIALIZED_DATA");
@@ -2206,9 +2434,14 @@ begin_declarations;
declare_integer("RESOURCE_TYPE_HTML");
declare_integer("RESOURCE_TYPE_MANIFEST");
declare_integer("is_pe");
declare_integer("machine");
declare_integer("number_of_sections");
declare_integer("timestamp");
declare_integer("pointer_to_symbol_table");
declare_integer("number_of_symbols");
declare_integer("size_of_optional_header");
declare_integer("characteristics");
declare_integer("entry_point");
@@ -2217,6 +2450,15 @@ begin_declarations;
declare_string_dictionary("version_info");
declare_integer("opthdr_magic");
declare_integer("size_of_code");
declare_integer("size_of_initialized_data");
declare_integer("size_of_uninitialized_data");
declare_integer("base_of_code");
declare_integer("base_of_data");
declare_integer("section_alignment");
declare_integer("file_alignment");
begin_struct("linker_version");
declare_integer("major");
declare_integer("minor");
@@ -2237,11 +2479,25 @@ begin_declarations;
declare_integer("minor");
end_struct("subsystem_version");
declare_integer("win32_version_value");
declare_integer("size_of_image");
declare_integer("size_of_headers");
declare_integer("checksum");
declare_function("calculate_checksum", "", "i", calculate_checksum);
declare_integer("subsystem");
declare_integer("dll_characteristics");
declare_integer("size_of_stack_reserve");
declare_integer("size_of_stack_commit");
declare_integer("size_of_heap_reserve");
declare_integer("size_of_heap_commit");
declare_integer("loader_flags");
begin_struct_array("data_directories");
declare_integer("virtual_address");
declare_integer("size");
end_struct_array("data_directories");
begin_struct_array("sections");
declare_string("name");
@@ -2250,6 +2506,10 @@ begin_declarations;
declare_integer("virtual_size");
declare_integer("raw_data_offset");
declare_integer("raw_data_size");
declare_integer("pointer_to_relocations");
declare_integer("pointer_to_line_numbers");
declare_integer("number_of_relocations");
declare_integer("number_of_line_numbers");
end_struct_array("sections");
begin_struct("overlay");
@@ -2283,6 +2543,7 @@ begin_declarations;
declare_function("imports", "ss", "i", imports);
declare_function("imports", "si", "i", imports_ordinal);
declare_function("imports", "s", "i", imports_dll);
declare_function("imports", "rr", "i", imports_regex);
declare_function("locale", "i", "i", locale);
declare_function("language", "i", "i", language);
declare_function("is_dll", "", "i", is_dll);
@@ -2314,6 +2575,7 @@ begin_declarations;
#if defined(HAVE_LIBCRYPTO)
begin_struct_array("signatures");
declare_string("thumbprint");
declare_string("issuer");
declare_string("subject");
declare_integer("version");
@@ -2537,6 +2799,52 @@ int module_load(
IMAGE_FILE_BYTES_REVERSED_HI, module_object,
"BYTES_REVERSED_HI");
set_integer(
IMAGE_DIRECTORY_ENTRY_EXPORT, module_object,
"IMAGE_DIRECTORY_ENTRY_EXPORT");
set_integer(
IMAGE_DIRECTORY_ENTRY_IMPORT, module_object,
"IMAGE_DIRECTORY_ENTRY_IMPORT");
set_integer(
IMAGE_DIRECTORY_ENTRY_RESOURCE, module_object,
"IMAGE_DIRECTORY_ENTRY_RESOURCE");
set_integer(
IMAGE_DIRECTORY_ENTRY_EXCEPTION, module_object,
"IMAGE_DIRECTORY_ENTRY_EXCEPTION");
set_integer(
IMAGE_DIRECTORY_ENTRY_SECURITY, module_object,
"IMAGE_DIRECTORY_ENTRY_SECURITY");
set_integer(
IMAGE_DIRECTORY_ENTRY_BASERELOC, module_object,
"IMAGE_DIRECTORY_ENTRY_BASERELOC");
set_integer(
IMAGE_DIRECTORY_ENTRY_DEBUG, module_object,
"IMAGE_DIRECTORY_ENTRY_DEBUG");
set_integer(
IMAGE_DIRECTORY_ENTRY_ARCHITECTURE, module_object,
"IMAGE_DIRECTORY_ENTRY_ARCHITECTURE");
set_integer(
IMAGE_DIRECTORY_ENTRY_GLOBALPTR, module_object,
"IMAGE_DIRECTORY_ENTRY_GLOBALPTR");
set_integer(
IMAGE_DIRECTORY_ENTRY_TLS, module_object,
"IMAGE_DIRECTORY_ENTRY_TLS");
set_integer(
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, module_object,
"IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG");
set_integer(
IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT, module_object,
"IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT");
set_integer(
IMAGE_DIRECTORY_ENTRY_IAT, module_object,
"IMAGE_DIRECTORY_ENTRY_IAT");
set_integer(
IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT, module_object,
"IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT");
set_integer(
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, module_object,
"IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR");
set_integer(
IMAGE_SCN_CNT_CODE, module_object,
"SECTION_CNT_CODE");
@@ -2640,6 +2948,7 @@ int module_load(
set_integer(
RESOURCE_TYPE_MANIFEST, module_object,
"RESOURCE_TYPE_MANIFEST");
set_integer(0, module_object, "is_pe");
foreach_memory_block(iterator, block)
{
@@ -2694,8 +3003,9 @@ int module_unload(
{
IMPORTED_DLL* dll = NULL;
IMPORTED_DLL* next_dll = NULL;
IMPORT_EXPORT_FUNCTION* func = NULL;
IMPORT_EXPORT_FUNCTION* next_func = NULL;
IMPORT_FUNCTION* func = NULL;
IMPORT_FUNCTION* next_func = NULL;
int i = 0;
PE* pe = (PE *) module_object->data;
@@ -2726,14 +3036,16 @@ int module_unload(
dll = next_dll;
}
func = pe->exported_functions;
while (func)
if (pe->exported_functions)
{
yr_free(func->name);
next_func = func->next;
yr_free(func);
func = next_func;
for (i = 0; i < pe->exported_functions->number_of_exports; i++)
{
if (pe->exported_functions->functions[i].name)
yr_free(pe->exported_functions->functions[i].name);
}
yr_free(pe->exported_functions->functions);
yr_free(pe->exported_functions);
}
yr_free(pe);
+1 -1
View File
@@ -263,7 +263,7 @@ int64_t pe_rva_to_offset(
#include <time.h>
static int is_leap(
static bool is_leap(
unsigned int year)
{
year += 1900;
+1 -1
View File
@@ -213,7 +213,7 @@ int module_unload(
{
// Fail if module_unload is called twice with the same module_object
if (module_object->data == (void*) 0xFABADA)
assert(FALSE);
assert(false);
module_object->data = (void*) 0xFABADA;
return ERROR_SUCCESS;
+11 -10
View File
@@ -36,7 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string.h>
#include <math.h>
#include <yara/globals.h>
#include <yara/mem.h>
#include <yara/error.h>
#include <yara/object.h>
@@ -80,7 +80,7 @@ int yr_object_create(
object_size = sizeof(YR_OBJECT_FUNCTION);
break;
default:
assert(FALSE);
assert(false);
}
obj = (YR_OBJECT*) yr_malloc(object_size);
@@ -88,6 +88,7 @@ int yr_object_create(
if (obj == NULL)
return ERROR_INSUFFICIENT_MEMORY;
obj->canary = yr_canary;
obj->type = type;
obj->identifier = yr_strdup(identifier);
obj->parent = parent;
@@ -117,7 +118,7 @@ int yr_object_create(
break;
case OBJECT_TYPE_FUNCTION:
object_as_function(obj)->return_obj = NULL;
for (i = 0; i < MAX_OVERLOADED_FUNCTIONS; i++)
for (i = 0; i < YR_MAX_OVERLOADED_FUNCTIONS; i++)
{
object_as_function(obj)->prototypes[i].arguments_fmt = NULL;
object_as_function(obj)->prototypes[i].code = NULL;
@@ -237,7 +238,7 @@ int yr_object_function_create(
f = object_as_function(o);
}
for (i = 0; i < MAX_OVERLOADED_FUNCTIONS; i++)
for (i = 0; i < YR_MAX_OVERLOADED_FUNCTIONS; i++)
{
if (f->prototypes[i].arguments_fmt == NULL)
{
@@ -280,7 +281,7 @@ int yr_object_from_external_variable(
break;
default:
assert(FALSE);
assert(false);
}
result = yr_object_create(
@@ -589,7 +590,7 @@ int yr_object_copy(
&object_as_function(copy)->return_obj),
yr_object_destroy(copy));
for (i = 0; i < MAX_OVERLOADED_FUNCTIONS; i++)
for (i = 0; i < YR_MAX_OVERLOADED_FUNCTIONS; i++)
object_as_function(copy)->prototypes[i] = \
object_as_function(object)->prototypes[i];
@@ -636,7 +637,7 @@ int yr_object_copy(
break;
default:
assert(FALSE);
assert(false);
}
@@ -858,7 +859,7 @@ int yr_object_dict_set_item(
}
int yr_object_has_undefined_value(
bool yr_object_has_undefined_value(
YR_OBJECT* object,
const char* field,
...)
@@ -876,7 +877,7 @@ int yr_object_has_undefined_value(
va_end(args);
if (field_obj == NULL)
return TRUE;
return true;
switch(field_obj->type)
{
@@ -888,7 +889,7 @@ int yr_object_has_undefined_value(
return field_obj->value.i == UNDEFINED;
}
return FALSE;
return false;
}
+202 -232
View File
@@ -205,10 +205,10 @@ int yr_parser_emit_pushes_for_strings(
if (matching == 0)
{
yr_compiler_set_error_extra_info(compiler, identifier);
compiler->last_result = ERROR_UNDEFINED_STRING;
return ERROR_UNDEFINED_STRING;
}
return compiler->last_result;
return ERROR_SUCCESS;
}
@@ -219,57 +219,54 @@ int yr_parser_check_types(
{
int i;
for (i = 0; i < MAX_OVERLOADED_FUNCTIONS; i++)
for (i = 0; i < YR_MAX_OVERLOADED_FUNCTIONS; i++)
{
if (function->prototypes[i].arguments_fmt == NULL)
break;
if (strcmp(function->prototypes[i].arguments_fmt, actual_args_fmt) == 0)
{
compiler->last_result = ERROR_SUCCESS;
return compiler->last_result;
}
return ERROR_SUCCESS;
}
yr_compiler_set_error_extra_info(compiler, function->identifier);
compiler->last_result = ERROR_WRONG_ARGUMENTS;
return compiler->last_result;
return ERROR_WRONG_ARGUMENTS;
}
YR_STRING* yr_parser_lookup_string(
int yr_parser_lookup_string(
yyscan_t yyscanner,
const char* identifier)
const char* identifier,
YR_STRING** string)
{
YR_STRING* string;
YR_COMPILER* compiler = yyget_extra(yyscanner);
string = compiler->current_rule->strings;
*string = compiler->current_rule->strings;
while(!STRING_IS_NULL(string))
while(!STRING_IS_NULL(*string))
{
// If some string $a gets fragmented into multiple chained
// strings, all those fragments have the same $a identifier
// but we are interested in the heading fragment, which is
// that with chained_to == NULL
if (strcmp(string->identifier, identifier) == 0 &&
string->chained_to == NULL)
if (strcmp((*string)->identifier, identifier) == 0 &&
(*string)->chained_to == NULL)
{
return string;
return ERROR_SUCCESS;
}
string = (YR_STRING*) yr_arena_next_address(
*string = (YR_STRING*) yr_arena_next_address(
compiler->strings_arena,
string,
*string,
sizeof(YR_STRING));
}
yr_compiler_set_error_extra_info(compiler, identifier);
compiler->last_result = ERROR_UNDEFINED_STRING;
return NULL;
*string = NULL;
return ERROR_UNDEFINED_STRING;
}
@@ -305,7 +302,7 @@ static int _yr_parser_write_string(
int result;
int max_string_len;
int free_literal = FALSE;
bool free_literal = false;
*string = NULL;
@@ -338,7 +335,7 @@ static int _yr_parser_write_string(
if (literal_string != NULL)
{
flags |= STRING_GFLAGS_LITERAL;
free_literal = TRUE;
free_literal = true;
}
else
{
@@ -384,6 +381,7 @@ static int _yr_parser_write_string(
if (result == ERROR_SUCCESS)
{
result = yr_atoms_extract_from_string(
&compiler->atoms_config,
(uint8_t*) literal_string->c_string,
(int32_t) literal_string->length,
flags,
@@ -393,14 +391,15 @@ static int _yr_parser_write_string(
else
{
// Emit forwards code
result = yr_re_ast_emit_code(re_ast, compiler->re_code_arena, FALSE);
result = yr_re_ast_emit_code(re_ast, compiler->re_code_arena, false);
// Emit backwards code
if (result == ERROR_SUCCESS)
result = yr_re_ast_emit_code(re_ast, compiler->re_code_arena, TRUE);
result = yr_re_ast_emit_code(re_ast, compiler->re_code_arena, true);
if (result == ERROR_SUCCESS)
result = yr_atoms_extract_from_re(re_ast, flags, &atom_list);
result = yr_atoms_extract_from_re(
&compiler->atoms_config, re_ast, flags, &atom_list);
}
if (result == ERROR_SUCCESS)
@@ -413,7 +412,8 @@ static int _yr_parser_write_string(
compiler->matches_arena);
}
*min_atom_quality = yr_atoms_min_quality(atom_list);
*min_atom_quality = yr_atoms_min_quality(
&compiler->atoms_config, atom_list);
if (flags & STRING_GFLAGS_LITERAL)
{
@@ -422,7 +422,7 @@ static int _yr_parser_write_string(
else
max_string_len = (*string)->length;
if (max_string_len <= MAX_ATOM_LENGTH)
if (max_string_len <= YR_MAX_ATOM_LENGTH)
(*string)->g_flags |= STRING_GFLAGS_FITS_IN_ATOM;
}
@@ -440,11 +440,12 @@ static int _yr_parser_write_string(
#include <yara/integers.h>
YR_STRING* yr_parser_reduce_string_declaration(
int yr_parser_reduce_string_declaration(
yyscan_t yyscanner,
int32_t string_flags,
const char* identifier,
SIZED_STRING* str)
SIZED_STRING* str,
YR_STRING** string)
{
int min_atom_quality;
int min_atom_quality_aux;
@@ -455,7 +456,6 @@ YR_STRING* yr_parser_reduce_string_declaration(
char message[512];
YR_COMPILER* compiler = yyget_extra(yyscanner);
YR_STRING* string = NULL;
YR_STRING* aux_string;
YR_STRING* prev_string;
@@ -464,17 +464,19 @@ YR_STRING* yr_parser_reduce_string_declaration(
RE_ERROR re_error;
int result = ERROR_SUCCESS;
// Determine if a string with the same identifier was already defined
// by searching for the identifier in string_table.
string = (YR_STRING*) yr_hash_table_lookup(
*string = (YR_STRING*) yr_hash_table_lookup(
compiler->strings_table,
identifier,
NULL);
if (string != NULL)
if (*string != NULL)
{
compiler->last_result = ERROR_DUPLICATED_STRING_IDENTIFIER;
result = ERROR_DUPLICATED_STRING_IDENTIFIER;
yr_compiler_set_error_extra_info(compiler, identifier);
goto _exit;
}
@@ -483,7 +485,7 @@ YR_STRING* yr_parser_reduce_string_declaration(
if (str->length == 0)
{
compiler->last_result = ERROR_EMPTY_STRING;
result = ERROR_EMPTY_STRING;
yr_compiler_set_error_extra_info(compiler, identifier);
goto _exit;
}
@@ -526,13 +528,11 @@ YR_STRING* yr_parser_reduce_string_declaration(
string_flags & STRING_GFLAGS_REGEXP)
{
if (string_flags & STRING_GFLAGS_HEXADECIMAL)
compiler->last_result = yr_re_parse_hex(
str->c_string, &re_ast, &re_error);
result = yr_re_parse_hex(str->c_string, &re_ast, &re_error);
else
compiler->last_result = yr_re_parse(
str->c_string, &re_ast, &re_error);
result = yr_re_parse(str->c_string, &re_ast, &re_error);
if (compiler->last_result != ERROR_SUCCESS)
if (result != ERROR_SUCCESS)
{
snprintf(
message,
@@ -561,7 +561,7 @@ YR_STRING* yr_parser_reduce_string_declaration(
if ((re_ast->flags & RE_FLAGS_GREEDY) &&
(re_ast->flags & RE_FLAGS_UNGREEDY))
{
compiler->last_result = ERROR_INVALID_REGULAR_EXPRESSION;
result = ERROR_INVALID_REGULAR_EXPRESSION;
yr_compiler_set_error_extra_info(compiler,
"greedy and ungreedy quantifiers can't be mixed in a regular "
@@ -577,7 +577,7 @@ YR_STRING* yr_parser_reduce_string_declaration(
{
yywarning(
yyscanner,
"%s contains .* or .+, consider using .{N} or .{1-N} with a reasonable value for N",
"%s contains .* or .+, consider using .{N} or .{1,N} with a reasonable value for N",
identifier);
}
@@ -590,35 +590,35 @@ YR_STRING* yr_parser_reduce_string_declaration(
compiler->re_ast_clbk_user_data);
}
compiler->last_result = yr_re_ast_split_at_chaining_point(
result = yr_re_ast_split_at_chaining_point(
re_ast, &re_ast, &remainder_re_ast, &min_gap, &max_gap);
if (compiler->last_result != ERROR_SUCCESS)
if (result != ERROR_SUCCESS)
goto _exit;
compiler->last_result = _yr_parser_write_string(
result = _yr_parser_write_string(
identifier,
string_flags,
compiler,
NULL,
re_ast,
&string,
string,
&min_atom_quality);
if (compiler->last_result != ERROR_SUCCESS)
if (result != ERROR_SUCCESS)
goto _exit;
if (remainder_re_ast != NULL)
{
string->g_flags |= STRING_GFLAGS_CHAIN_TAIL | STRING_GFLAGS_CHAIN_PART;
string->chain_gap_min = min_gap;
string->chain_gap_max = max_gap;
(*string)->g_flags |= STRING_GFLAGS_CHAIN_TAIL | STRING_GFLAGS_CHAIN_PART;
(*string)->chain_gap_min = min_gap;
(*string)->chain_gap_max = max_gap;
}
// Use "aux_string" from now on, we want to keep the value of "string"
// because it will returned.
aux_string = string;
aux_string = *string;
while (remainder_re_ast != NULL)
{
@@ -627,15 +627,15 @@ YR_STRING* yr_parser_reduce_string_declaration(
yr_re_ast_destroy(re_ast);
compiler->last_result = yr_re_ast_split_at_chaining_point(
result = yr_re_ast_split_at_chaining_point(
remainder_re_ast, &re_ast, &remainder_re_ast, &min_gap, &max_gap);
if (compiler->last_result != ERROR_SUCCESS)
if (result != ERROR_SUCCESS)
goto _exit;
prev_string = aux_string;
compiler->last_result = _yr_parser_write_string(
result = _yr_parser_write_string(
identifier,
string_flags,
compiler,
@@ -644,7 +644,7 @@ YR_STRING* yr_parser_reduce_string_declaration(
&aux_string,
&min_atom_quality_aux);
if (compiler->last_result != ERROR_SUCCESS)
if (result != ERROR_SUCCESS)
goto _exit;
if (min_atom_quality_aux < min_atom_quality)
@@ -665,38 +665,37 @@ YR_STRING* yr_parser_reduce_string_declaration(
}
else
{
compiler->last_result = _yr_parser_write_string(
result = _yr_parser_write_string(
identifier,
string_flags,
compiler,
str,
NULL,
&string,
string,
&min_atom_quality);
if (compiler->last_result != ERROR_SUCCESS)
if (result != ERROR_SUCCESS)
goto _exit;
}
if (!STRING_IS_ANONYMOUS(string))
if (!STRING_IS_ANONYMOUS(*string))
{
compiler->last_result = yr_hash_table_add(
result = yr_hash_table_add(
compiler->strings_table,
identifier,
NULL,
string);
*string);
if (compiler->last_result != ERROR_SUCCESS)
if (result != ERROR_SUCCESS)
goto _exit;
}
if (min_atom_quality < 3 && compiler->callback != NULL)
if (min_atom_quality < compiler->atoms_config.quality_warning_threshold)
{
yywarning(
yyscanner,
"%s is slowing down scanning%s",
string->identifier,
min_atom_quality < 2 ? " (critical!)" : "");
"%s is slowing down scanning",
(*string)->identifier);
}
_exit:
@@ -707,22 +706,21 @@ _exit:
if (remainder_re_ast != NULL)
yr_re_ast_destroy(remainder_re_ast);
if (compiler->last_result != ERROR_SUCCESS)
return NULL;
return string;
return result;
}
YR_RULE* yr_parser_reduce_rule_declaration_phase_1(
int yr_parser_reduce_rule_declaration_phase_1(
yyscan_t yyscanner,
int32_t flags,
const char* identifier)
const char* identifier,
YR_RULE** rule)
{
YR_FIXUP *fixup;
YR_INIT_RULE_ARGS *init_rule_args;
YR_COMPILER* compiler = yyget_extra(yyscanner);
YR_RULE* rule = NULL;
*rule = NULL;
if (yr_hash_table_lookup(
compiler->rules_table,
@@ -731,65 +729,52 @@ YR_RULE* yr_parser_reduce_rule_declaration_phase_1(
yr_hash_table_lookup(
compiler->objects_table,
identifier,
compiler->current_namespace->name) != NULL)
NULL) != NULL)
{
// A rule or variable with the same identifier already exists, return the
// appropriate error.
yr_compiler_set_error_extra_info(compiler, identifier);
compiler->last_result = ERROR_DUPLICATED_IDENTIFIER;
return NULL;
return ERROR_DUPLICATED_IDENTIFIER;
}
compiler->last_result = yr_arena_allocate_struct(
FAIL_ON_ERROR(yr_arena_allocate_struct(
compiler->rules_arena,
sizeof(YR_RULE),
(void**) &rule,
(void**) rule,
offsetof(YR_RULE, identifier),
offsetof(YR_RULE, tags),
offsetof(YR_RULE, strings),
offsetof(YR_RULE, metas),
offsetof(YR_RULE, ns),
EOL);
EOL))
if (compiler->last_result != ERROR_SUCCESS)
return NULL;
rule->g_flags = flags;
rule->ns = compiler->current_namespace;
(*rule)->g_flags = flags;
(*rule)->ns = compiler->current_namespace;
#ifdef PROFILING_ENABLED
rule->time_cost = 0;
(*rule)->time_cost = 0;
#endif
compiler->last_result = yr_arena_write_string(
FAIL_ON_ERROR(yr_arena_write_string(
compiler->sz_arena,
identifier,
(char**) &rule->identifier);
(char**) &(*rule)->identifier));
if (compiler->last_result != ERROR_SUCCESS)
return NULL;
compiler->last_result = yr_parser_emit(
FAIL_ON_ERROR(yr_parser_emit(
yyscanner,
OP_INIT_RULE,
NULL);
NULL));
if (compiler->last_result != ERROR_SUCCESS)
return NULL;
compiler->last_result = yr_arena_allocate_struct(
FAIL_ON_ERROR(yr_arena_allocate_struct(
compiler->code_arena,
sizeof(YR_INIT_RULE_ARGS),
(void**) &init_rule_args,
offsetof(YR_INIT_RULE_ARGS, rule),
offsetof(YR_INIT_RULE_ARGS, jmp_addr),
EOL);
EOL));
if (compiler->last_result != ERROR_SUCCESS)
return NULL;
init_rule_args->rule = rule;
init_rule_args->rule = *rule;
// jmp_addr holds the address to jump to when we want to skip the code for
// the rule. It is iniatialized as NULL at this point because we don't know
@@ -801,26 +786,24 @@ YR_RULE* yr_parser_reduce_rule_declaration_phase_1(
fixup = (YR_FIXUP*) yr_malloc(sizeof(YR_FIXUP));
if (fixup == NULL)
{
compiler->last_result = ERROR_INSUFFICIENT_MEMORY;
return NULL;
}
return ERROR_INSUFFICIENT_MEMORY;
fixup->address = (void*) &(init_rule_args->jmp_addr);
fixup->next = compiler->fixup_stack_head;
compiler->fixup_stack_head = fixup;
compiler->last_result = yr_hash_table_add(
compiler->rules_table,
identifier,
compiler->current_namespace->name,
(void*) rule);
// Clean strings_table as we are starting to parse a new rule.
yr_hash_table_clean(compiler->strings_table, NULL);
compiler->current_rule = rule;
return rule;
FAIL_ON_ERROR(yr_hash_table_add(
compiler->rules_table,
identifier,
compiler->current_namespace->name,
(void*) *rule));
compiler->current_rule = *rule;
return ERROR_SUCCESS;
}
int yr_parser_reduce_rule_declaration_phase_2(
@@ -831,6 +814,8 @@ int yr_parser_reduce_rule_declaration_phase_2(
uint32_t strings_in_rule = 0;
uint8_t* nop_inst_addr = NULL;
int result;
YR_FIXUP *fixup;
YR_COMPILER* compiler = yyget_extra(yyscanner);
@@ -852,16 +837,15 @@ int yr_parser_reduce_rule_declaration_phase_2(
string->chained_to == NULL)
{
yr_compiler_set_error_extra_info(compiler, string->identifier);
compiler->last_result = ERROR_UNREFERENCED_STRING;
return compiler->last_result;
return ERROR_UNREFERENCED_STRING;
}
strings_in_rule++;
if (strings_in_rule > max_strings_per_rule) {
if (strings_in_rule > max_strings_per_rule)
{
yr_compiler_set_error_extra_info(compiler, rule->identifier);
compiler->last_result = ERROR_TOO_MANY_STRINGS;
return compiler->last_result;
return ERROR_TOO_MANY_STRINGS;
}
string = (YR_STRING*) yr_arena_next_address(
@@ -870,7 +854,7 @@ int yr_parser_reduce_rule_declaration_phase_2(
sizeof(YR_STRING));
}
compiler->last_result = yr_parser_emit_with_arg_reloc(
result = yr_parser_emit_with_arg_reloc(
yyscanner,
OP_MATCH_RULE,
rule,
@@ -884,18 +868,15 @@ int yr_parser_reduce_rule_declaration_phase_2(
// be in the same arena page. As we don't have a reliable way of getting the
// address of the next instruction we generate the OP_NOP.
if (compiler->last_result == ERROR_SUCCESS)
compiler->last_result = yr_parser_emit(
yyscanner,
OP_NOP,
&nop_inst_addr);
if (result == ERROR_SUCCESS)
result = yr_parser_emit(yyscanner, OP_NOP, &nop_inst_addr);
fixup = compiler->fixup_stack_head;
*(void**)(fixup->address) = (void*) nop_inst_addr;
compiler->fixup_stack_head = fixup->next;
yr_free(fixup);
return compiler->last_result;
return result;
}
@@ -956,101 +937,94 @@ int yr_parser_reduce_string_identifier(
else
{
// Anonymous strings not allowed outside of a loop
compiler->last_result = ERROR_MISPLACED_ANONYMOUS_STRING;
return ERROR_MISPLACED_ANONYMOUS_STRING;
}
}
else
{
string = yr_parser_lookup_string(yyscanner, identifier);
FAIL_ON_ERROR(yr_parser_lookup_string(
yyscanner, identifier, &string));
if (string != NULL)
FAIL_ON_ERROR(yr_parser_emit_with_arg_reloc(
yyscanner,
OP_PUSH,
string,
NULL,
NULL));
if (instruction != OP_FOUND)
string->g_flags &= ~STRING_GFLAGS_SINGLE_MATCH;
if (instruction == OP_FOUND_AT)
{
yr_parser_emit_with_arg_reloc(
yyscanner,
OP_PUSH,
string,
NULL,
NULL);
// Avoid overwriting any previous fixed offset
if (instruction != OP_FOUND)
string->g_flags &= ~STRING_GFLAGS_SINGLE_MATCH;
if (string->fixed_offset == UNDEFINED)
string->fixed_offset = at_offset;
if (instruction == OP_FOUND_AT)
{
// Avoid overwriting any previous fixed offset
// If a previous fixed offset was different, disable
// the STRING_GFLAGS_FIXED_OFFSET flag because we only
// have room to store a single fixed offset value
if (string->fixed_offset == UNDEFINED)
string->fixed_offset = at_offset;
// If a previous fixed offset was different, disable
// the STRING_GFLAGS_FIXED_OFFSET flag because we only
// have room to store a single fixed offset value
if (string->fixed_offset == UNDEFINED ||
string->fixed_offset != at_offset)
{
string->g_flags &= ~STRING_GFLAGS_FIXED_OFFSET;
}
}
else
if (string->fixed_offset == UNDEFINED ||
string->fixed_offset != at_offset)
{
string->g_flags &= ~STRING_GFLAGS_FIXED_OFFSET;
}
yr_parser_emit(yyscanner, instruction, NULL);
string->g_flags |= STRING_GFLAGS_REFERENCED;
}
else
{
string->g_flags &= ~STRING_GFLAGS_FIXED_OFFSET;
}
FAIL_ON_ERROR(yr_parser_emit(yyscanner, instruction, NULL));
string->g_flags |= STRING_GFLAGS_REFERENCED;
}
return compiler->last_result;
return ERROR_SUCCESS;
}
YR_META* yr_parser_reduce_meta_declaration(
int yr_parser_reduce_meta_declaration(
yyscan_t yyscanner,
int32_t type,
const char* identifier,
const char* string,
int64_t integer)
int64_t integer,
YR_META** meta)
{
YR_COMPILER* compiler = yyget_extra(yyscanner);
YR_META* meta;
compiler->last_result = yr_arena_allocate_struct(
FAIL_ON_ERROR(yr_arena_allocate_struct(
compiler->metas_arena,
sizeof(YR_META),
(void**) &meta,
(void**) meta,
offsetof(YR_META, identifier),
offsetof(YR_META, string),
EOL);
EOL));
if (compiler->last_result != ERROR_SUCCESS)
return NULL;
compiler->last_result = yr_arena_write_string(
FAIL_ON_ERROR(yr_arena_write_string(
compiler->sz_arena,
identifier,
(char**) &meta->identifier);
if (compiler->last_result != ERROR_SUCCESS)
return NULL;
(char**) &(*meta)->identifier));
if (string != NULL)
compiler->last_result = yr_arena_write_string(
{
FAIL_ON_ERROR(yr_arena_write_string(
compiler->sz_arena,
string,
&meta->string);
&(*meta)->string));
}
else
meta->string = NULL;
{
(*meta)->string = NULL;
}
if (compiler->last_result != ERROR_SUCCESS)
return NULL;
(*meta)->integer = integer;
(*meta)->type = type;
meta->integer = integer;
meta->type = type;
return meta;
return ERROR_SUCCESS;
}
@@ -1058,12 +1032,12 @@ static int _yr_parser_valid_module_name(
SIZED_STRING* module_name)
{
if (module_name->length == 0)
return FALSE;
return false;
if (strlen(module_name->c_string) != module_name->length)
return FALSE;
return false;
return TRUE;
return true;
}
@@ -1071,6 +1045,8 @@ int yr_parser_reduce_import(
yyscan_t yyscanner,
SIZED_STRING* module_name)
{
int result;
YR_COMPILER* compiler = yyget_extra(yyscanner);
YR_OBJECT* module_structure;
@@ -1078,9 +1054,7 @@ int yr_parser_reduce_import(
if (!_yr_parser_valid_module_name(module_name))
{
compiler->last_result = ERROR_INVALID_MODULE_NAME;
yr_compiler_set_error_extra_info(compiler, module_name->c_string);
return ERROR_INVALID_MODULE_NAME;
}
@@ -1094,44 +1068,41 @@ int yr_parser_reduce_import(
if (module_structure != NULL)
return ERROR_SUCCESS;
compiler->last_result = yr_object_create(
FAIL_ON_ERROR(yr_object_create(
OBJECT_TYPE_STRUCTURE,
module_name->c_string,
NULL,
&module_structure);
&module_structure));
if (compiler->last_result == ERROR_SUCCESS)
compiler->last_result = yr_hash_table_add(
compiler->objects_table,
module_name->c_string,
compiler->current_namespace->name,
module_structure);
FAIL_ON_ERROR(yr_hash_table_add(
compiler->objects_table,
module_name->c_string,
compiler->current_namespace->name,
module_structure));
if (compiler->last_result == ERROR_SUCCESS)
{
compiler->last_result = yr_modules_do_declarations(
module_name->c_string,
module_structure);
result = yr_modules_do_declarations(
module_name->c_string,
module_structure);
if (compiler->last_result == ERROR_UNKNOWN_MODULE)
yr_compiler_set_error_extra_info(compiler, module_name->c_string);
}
if (result == ERROR_UNKNOWN_MODULE)
yr_compiler_set_error_extra_info(compiler, module_name->c_string);
if (compiler->last_result == ERROR_SUCCESS)
compiler->last_result = yr_arena_write_string(
compiler->sz_arena,
module_name->c_string,
&name);
if (result != ERROR_SUCCESS)
return result;
if (compiler->last_result == ERROR_SUCCESS)
compiler->last_result = yr_parser_emit_with_arg_reloc(
FAIL_ON_ERROR(yr_arena_write_string(
compiler->sz_arena,
module_name->c_string,
&name));
FAIL_ON_ERROR(yr_parser_emit_with_arg_reloc(
yyscanner,
OP_IMPORT,
name,
NULL,
NULL);
NULL));
return compiler->last_result;
return ERROR_SUCCESS;
}
@@ -1153,7 +1124,7 @@ static int _yr_parser_operator_to_opcode(
opcode = OP_STR_BEGIN;
break;
default:
assert(FALSE);
assert(false);
}
if (op[0] == '<')
@@ -1209,6 +1180,8 @@ int yr_parser_reduce_operation(
EXPRESSION left_operand,
EXPRESSION right_operand)
{
int expression_type;
YR_COMPILER* compiler = yyget_extra(yyscanner);
if ((left_operand.type == EXPRESSION_TYPE_INTEGER ||
@@ -1221,30 +1194,26 @@ int yr_parser_reduce_operation(
// One operand is double and the other is integer,
// cast the integer to double
compiler->last_result = yr_parser_emit_with_arg(
FAIL_ON_ERROR(yr_parser_emit_with_arg(
yyscanner,
OP_INT_TO_DBL,
(left_operand.type == EXPRESSION_TYPE_INTEGER) ? 2 : 1,
NULL,
NULL);
NULL));
}
if (compiler->last_result == ERROR_SUCCESS)
expression_type = EXPRESSION_TYPE_FLOAT;
if (left_operand.type == EXPRESSION_TYPE_INTEGER &&
right_operand.type == EXPRESSION_TYPE_INTEGER)
{
int expression_type = EXPRESSION_TYPE_FLOAT;
if (left_operand.type == EXPRESSION_TYPE_INTEGER &&
right_operand.type == EXPRESSION_TYPE_INTEGER)
{
expression_type = EXPRESSION_TYPE_INTEGER;
}
compiler->last_result = yr_parser_emit(
yyscanner,
_yr_parser_operator_to_opcode(op, expression_type),
NULL);
expression_type = EXPRESSION_TYPE_INTEGER;
}
FAIL_ON_ERROR(yr_parser_emit(
yyscanner,
_yr_parser_operator_to_opcode(op, expression_type),
NULL));
}
else if (left_operand.type == EXPRESSION_TYPE_STRING &&
right_operand.type == EXPRESSION_TYPE_STRING)
@@ -1253,24 +1222,25 @@ int yr_parser_reduce_operation(
if (opcode != OP_ERROR)
{
compiler->last_result = yr_parser_emit(
FAIL_ON_ERROR(yr_parser_emit(
yyscanner,
opcode,
NULL);
NULL));
}
else
{
yr_compiler_set_error_extra_info_fmt(
compiler, "strings don't support \"%s\" operation", op);
compiler->last_result = ERROR_WRONG_TYPE;
return ERROR_WRONG_TYPE;
}
}
else
{
yr_compiler_set_error_extra_info(compiler, "type mismatch");
compiler->last_result = ERROR_WRONG_TYPE;
return ERROR_WRONG_TYPE;
}
return compiler->last_result;
return ERROR_SUCCESS;
}
+1 -1
View File
@@ -48,7 +48,7 @@ int _yr_process_detach(
YR_API const uint8_t* yr_process_fetch_memory_block_data(
YR_MEMORY_BLOCK* block)
{
return ERROR_INVALID_ARGUMENT;
return NULL;
}
YR_API YR_MEMORY_BLOCK* yr_process_get_next_memory_block(
+1 -1
View File
@@ -157,7 +157,7 @@ YR_API YR_MEMORY_BLOCK* yr_process_get_next_memory_block(
{
// mbi.RegionSize can overflow address while scanning a 64-bit process
// with a 32-bit YARA.
if ((uint8_t*) address + mbi.RegionSize <= address)
if ((uint8_t*) address + mbi.RegionSize <= (uint8_t*) address)
break;
if (mbi.State == MEM_COMMIT && ((mbi.Protect & PAGE_NOACCESS) == 0))
+36 -36
View File
@@ -93,7 +93,7 @@ typedef struct _RE_EMIT_CONTEXT {
((cls)[(chr) / 8] & 1 << ((chr) % 8))
static int _yr_re_is_char_in_class(
static bool _yr_re_is_char_in_class(
RE_CLASS* re_class,
uint8_t chr,
int case_insensitive)
@@ -110,7 +110,7 @@ static int _yr_re_is_char_in_class(
}
static int _yr_re_is_word_char(
static bool _yr_re_is_word_char(
const uint8_t* input,
uint8_t character_size)
{
@@ -135,7 +135,7 @@ RE_NODE* yr_re_node_create(
result->type = type;
result->left = left;
result->right = right;
result->greedy = TRUE;
result->greedy = true;
result->forward_code = NULL;
result->backward_code = NULL;
}
@@ -250,7 +250,7 @@ int yr_re_compile(
yr_re_ast_destroy(re_ast));
FAIL_ON_ERROR_WITH_CLEANUP(
yr_re_ast_emit_code(re_ast, code_arena, FALSE),
yr_re_ast_emit_code(re_ast, code_arena, false),
yr_re_ast_destroy(re_ast));
yr_re_ast_destroy(re_ast);
@@ -360,15 +360,15 @@ int _yr_re_node_contains_dot_star(
{
if ((re_node->type == RE_NODE_STAR || re_node->type == RE_NODE_PLUS) &&
re_node->left->type == RE_NODE_ANY)
return TRUE;
return true;
if (re_node->left != NULL && _yr_re_node_contains_dot_star(re_node->left))
return TRUE;
return true;
if (re_node->right != NULL && _yr_re_node_contains_dot_star(re_node->right))
return TRUE;
return true;
return FALSE;
return false;
}
@@ -418,9 +418,9 @@ int yr_re_ast_split_at_chaining_point(
{
if (child->right != NULL &&
child->right->type == RE_NODE_RANGE_ANY &&
child->right->greedy == FALSE &&
(child->right->start > STRING_CHAINING_THRESHOLD ||
child->right->end > STRING_CHAINING_THRESHOLD))
child->right->greedy == false &&
(child->right->start > YR_STRING_CHAINING_THRESHOLD ||
child->right->end > YR_STRING_CHAINING_THRESHOLD))
{
result = yr_re_ast_create(remainder_re_ast);
@@ -656,10 +656,10 @@ static int _yr_re_emit(
size_t inst_size;
size_t jmp_size;
int emit_split;
int emit_repeat;
int emit_prolog;
int emit_epilog;
bool emit_split;
bool emit_repeat;
bool emit_prolog;
bool emit_epilog;
RE_REPEAT_ARGS repeat_args;
RE_REPEAT_ARGS* repeat_start_args_addr;
@@ -1326,7 +1326,7 @@ static int _yr_re_fiber_exists(
int i;
if (last_fiber == NULL)
return FALSE;
return false;
while (fiber != last_fiber->next)
{
@@ -1334,25 +1334,25 @@ static int _yr_re_fiber_exists(
fiber->sp == target_fiber->sp &&
fiber->rc == target_fiber->rc)
{
equal_stacks = TRUE;
equal_stacks = true;
for (i = 0; i <= fiber->sp; i++)
{
if (fiber->stack[i] != target_fiber->stack[i])
{
equal_stacks = FALSE;
equal_stacks = false;
break;
}
}
if (equal_stacks)
return TRUE;
return true;
}
fiber = fiber->next;
}
return FALSE;
return false;
}
@@ -1538,7 +1538,7 @@ static int _yr_re_fiber_sync(
case RE_OPCODE_SPLIT_B:
split_id = *(RE_SPLIT_ID_TYPE*)(fiber->ip + 1);
split_already_executed = FALSE;
split_already_executed = false;
for (splits_executed_idx = 0;
splits_executed_idx < splits_executed_count;
@@ -1546,7 +1546,7 @@ static int _yr_re_fiber_sync(
{
if (split_id == splits_executed[splits_executed_idx])
{
split_already_executed = TRUE;
split_already_executed = true;
break;
}
}
@@ -1935,10 +1935,10 @@ int yr_re_exec(
case '\n':
case '\v':
case '\f':
match = TRUE;
match = true;
break;
default:
match = FALSE;
match = false;
}
if (*ip == RE_OPCODE_NON_SPACE)
@@ -1967,11 +1967,11 @@ int yr_re_exec(
if (bytes_matched == 0 && input_backwards_size < character_size)
{
match = TRUE;
match = true;
}
else if (bytes_matched >= max_bytes_matched)
{
match = TRUE;
match = true;
}
else
{
@@ -2049,7 +2049,7 @@ int yr_re_exec(
break;
default:
assert(FALSE);
assert(false);
}
switch (action)
@@ -2125,9 +2125,9 @@ int yr_re_fast_exec(
{
RE_REPEAT_ANY_ARGS* repeat_any_args;
const uint8_t* code_stack[MAX_FAST_RE_STACK];
const uint8_t* input_stack[MAX_FAST_RE_STACK];
int matches_stack[MAX_FAST_RE_STACK];
const uint8_t* code_stack[YR_MAX_FAST_RE_STACK];
const uint8_t* input_stack[YR_MAX_FAST_RE_STACK];
int matches_stack[YR_MAX_FAST_RE_STACK];
const uint8_t* input = input_data;
const uint8_t* next_input;
@@ -2164,7 +2164,7 @@ int yr_re_fast_exec(
ip = code_stack[sp];
input = input_stack[sp];
bytes_matched = matches_stack[sp];
stop = FALSE;
stop = false;
while (!stop)
{
@@ -2204,7 +2204,7 @@ int yr_re_fast_exec(
}
else
{
stop = TRUE;
stop = true;
}
break;
@@ -2222,7 +2222,7 @@ int yr_re_fast_exec(
}
else
{
stop = TRUE;
stop = true;
}
break;
@@ -2251,7 +2251,7 @@ int yr_re_fast_exec(
(*(next_opcode) == RE_OPCODE_LITERAL &&
*(next_opcode + 1) == *next_input))
{
if (sp >= MAX_FAST_RE_STACK)
if (sp >= YR_MAX_FAST_RE_STACK)
return ERROR_TOO_MANY_RE_FIBERS;
code_stack[sp] = next_opcode;
@@ -2269,7 +2269,7 @@ int yr_re_fast_exec(
break;
default:
assert(FALSE);
assert(false);
}
}
}
@@ -2364,7 +2364,7 @@ static void _yr_re_print_node(
case RE_NODE_CLASS:
printf("Class(");
for (i = 0; i < 256; i++)
if (_yr_re_is_char_in_class(re_node->re_class, i, FALSE))
if (_yr_re_is_char_in_class(re_node->re_class, i, false))
printf("%02X,", i);
printf(")");
break;
+86 -87
View File
@@ -1,8 +1,8 @@
/* A Bison parser, made by GNU Bison 3.0.4. */
/* A Bison parser, made by GNU Bison 3.0.5. */
/* Bison implementation for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
Copyright (C) 1984, 1989-1990, 2000-2015, 2018 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -44,7 +44,7 @@
#define YYBISON 1
/* Bison version. */
#define YYBISON_VERSION "3.0.4"
#define YYBISON_VERSION "3.0.5"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -99,7 +99,7 @@
#define fail_if(x, error) \
if (x) \
{ \
lex_env->last_error_code = error; \
lex_env->last_error = error; \
YYABORT; \
} \
@@ -500,9 +500,9 @@ static const yytype_uint8 yytranslate[] =
static const yytype_uint16 yyrline[] =
{
0, 112, 112, 117, 121, 125, 141, 163, 167, 184,
198, 214, 228, 244, 267, 291, 313, 336, 340, 346,
352, 358, 367, 375, 381, 389, 395, 401, 407, 413,
419, 425
198, 214, 228, 244, 266, 289, 311, 334, 338, 344,
350, 356, 365, 373, 379, 387, 393, 399, 405, 411,
417, 423
};
#endif
@@ -982,6 +982,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
case N: \
yyformat = S; \
break
default: /* Avoid compiler warnings. */
YYCASE_(0, YY_("syntax error"));
YYCASE_(1, YY_("syntax error, unexpected %s"));
YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
@@ -1047,33 +1048,33 @@ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, void *yyscanner, R
switch (yytype)
{
case 6: /* _CLASS_ */
#line 104 "re_grammar.y" /* yacc.c:1257 */
#line 104 "re_grammar.y" /* yacc.c:1258 */
{ yr_free(((*yyvaluep).re_class)); ((*yyvaluep).re_class) = NULL; }
#line 1053 "re_grammar.c" /* yacc.c:1257 */
#line 1054 "re_grammar.c" /* yacc.c:1258 */
break;
case 26: /* alternative */
#line 105 "re_grammar.y" /* yacc.c:1257 */
#line 105 "re_grammar.y" /* yacc.c:1258 */
{ yr_re_node_destroy(((*yyvaluep).re_node)); ((*yyvaluep).re_node) = NULL; }
#line 1059 "re_grammar.c" /* yacc.c:1257 */
#line 1060 "re_grammar.c" /* yacc.c:1258 */
break;
case 27: /* concatenation */
#line 106 "re_grammar.y" /* yacc.c:1257 */
#line 106 "re_grammar.y" /* yacc.c:1258 */
{ yr_re_node_destroy(((*yyvaluep).re_node)); ((*yyvaluep).re_node) = NULL; }
#line 1065 "re_grammar.c" /* yacc.c:1257 */
#line 1066 "re_grammar.c" /* yacc.c:1258 */
break;
case 28: /* repeat */
#line 107 "re_grammar.y" /* yacc.c:1257 */
#line 107 "re_grammar.y" /* yacc.c:1258 */
{ yr_re_node_destroy(((*yyvaluep).re_node)); ((*yyvaluep).re_node) = NULL; }
#line 1071 "re_grammar.c" /* yacc.c:1257 */
#line 1072 "re_grammar.c" /* yacc.c:1258 */
break;
case 29: /* single */
#line 108 "re_grammar.y" /* yacc.c:1257 */
#line 108 "re_grammar.y" /* yacc.c:1258 */
{ yr_re_node_destroy(((*yyvaluep).re_node)); ((*yyvaluep).re_node) = NULL; }
#line 1077 "re_grammar.c" /* yacc.c:1257 */
#line 1078 "re_grammar.c" /* yacc.c:1258 */
break;
@@ -1339,24 +1340,24 @@ yyreduce:
switch (yyn)
{
case 2:
#line 113 "re_grammar.y" /* yacc.c:1646 */
#line 113 "re_grammar.y" /* yacc.c:1663 */
{
RE_AST* re_ast = yyget_extra(yyscanner);
re_ast->root_node = (yyvsp[0].re_node);
}
#line 1348 "re_grammar.c" /* yacc.c:1646 */
#line 1349 "re_grammar.c" /* yacc.c:1663 */
break;
case 4:
#line 122 "re_grammar.y" /* yacc.c:1646 */
#line 122 "re_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = (yyvsp[0].re_node);
}
#line 1356 "re_grammar.c" /* yacc.c:1646 */
#line 1357 "re_grammar.c" /* yacc.c:1663 */
break;
case 5:
#line 126 "re_grammar.y" /* yacc.c:1646 */
#line 126 "re_grammar.y" /* yacc.c:1663 */
{
mark_as_not_fast_regexp();
@@ -1372,11 +1373,11 @@ yyreduce:
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
}
#line 1376 "re_grammar.c" /* yacc.c:1646 */
#line 1377 "re_grammar.c" /* yacc.c:1663 */
break;
case 6:
#line 142 "re_grammar.y" /* yacc.c:1646 */
#line 142 "re_grammar.y" /* yacc.c:1663 */
{
RE_NODE* node;
@@ -1395,19 +1396,19 @@ yyreduce:
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
}
#line 1399 "re_grammar.c" /* yacc.c:1646 */
#line 1400 "re_grammar.c" /* yacc.c:1663 */
break;
case 7:
#line 164 "re_grammar.y" /* yacc.c:1646 */
#line 164 "re_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = (yyvsp[0].re_node);
}
#line 1407 "re_grammar.c" /* yacc.c:1646 */
#line 1408 "re_grammar.c" /* yacc.c:1663 */
break;
case 8:
#line 168 "re_grammar.y" /* yacc.c:1646 */
#line 168 "re_grammar.y" /* yacc.c:1663 */
{
fail_if_too_many_ast_levels({
yr_re_node_destroy((yyvsp[-1].re_node));
@@ -1421,11 +1422,11 @@ yyreduce:
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
}
#line 1425 "re_grammar.c" /* yacc.c:1646 */
#line 1426 "re_grammar.c" /* yacc.c:1663 */
break;
case 9:
#line 185 "re_grammar.y" /* yacc.c:1646 */
#line 185 "re_grammar.y" /* yacc.c:1663 */
{
RE_AST* re_ast;
@@ -1439,11 +1440,11 @@ yyreduce:
destroy_node_if((yyval.re_node) == NULL, (yyvsp[-1].re_node));
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
}
#line 1443 "re_grammar.c" /* yacc.c:1646 */
#line 1444 "re_grammar.c" /* yacc.c:1663 */
break;
case 10:
#line 199 "re_grammar.y" /* yacc.c:1646 */
#line 199 "re_grammar.y" /* yacc.c:1663 */
{
RE_AST* re_ast;
@@ -1457,13 +1458,13 @@ yyreduce:
destroy_node_if((yyval.re_node) == NULL, (yyvsp[-2].re_node));
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
(yyval.re_node)->greedy = FALSE;
(yyval.re_node)->greedy = false;
}
#line 1463 "re_grammar.c" /* yacc.c:1646 */
#line 1464 "re_grammar.c" /* yacc.c:1663 */
break;
case 11:
#line 215 "re_grammar.y" /* yacc.c:1646 */
#line 215 "re_grammar.y" /* yacc.c:1663 */
{
RE_AST* re_ast;
@@ -1477,11 +1478,11 @@ yyreduce:
destroy_node_if((yyval.re_node) == NULL, (yyvsp[-1].re_node));
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
}
#line 1481 "re_grammar.c" /* yacc.c:1646 */
#line 1482 "re_grammar.c" /* yacc.c:1663 */
break;
case 12:
#line 229 "re_grammar.y" /* yacc.c:1646 */
#line 229 "re_grammar.y" /* yacc.c:1663 */
{
RE_AST* re_ast;
@@ -1495,13 +1496,13 @@ yyreduce:
destroy_node_if((yyval.re_node) == NULL, (yyvsp[-2].re_node));
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
(yyval.re_node)->greedy = FALSE;
(yyval.re_node)->greedy = false;
}
#line 1501 "re_grammar.c" /* yacc.c:1646 */
#line 1502 "re_grammar.c" /* yacc.c:1663 */
break;
case 13:
#line 245 "re_grammar.y" /* yacc.c:1646 */
#line 245 "re_grammar.y" /* yacc.c:1663 */
{
RE_AST* re_ast = yyget_extra(yyscanner);
re_ast->flags |= RE_FLAGS_GREEDY;
@@ -1509,7 +1510,7 @@ yyreduce:
if ((yyvsp[-1].re_node)->type == RE_NODE_ANY)
{
(yyval.re_node) = yr_re_node_create(RE_NODE_RANGE_ANY, NULL, NULL);
destroy_node_if(TRUE, (yyvsp[-1].re_node));
destroy_node_if(true, (yyvsp[-1].re_node));
}
else
{
@@ -1518,17 +1519,16 @@ yyreduce:
destroy_node_if((yyval.re_node) == NULL, (yyvsp[-1].re_node));
}
destroy_node_if((yyval.re_node) == NULL, (yyvsp[-1].re_node));
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
(yyval.re_node)->start = 0;
(yyval.re_node)->end = 1;
}
#line 1528 "re_grammar.c" /* yacc.c:1646 */
#line 1528 "re_grammar.c" /* yacc.c:1663 */
break;
case 14:
#line 268 "re_grammar.y" /* yacc.c:1646 */
#line 267 "re_grammar.y" /* yacc.c:1663 */
{
RE_AST* re_ast = yyget_extra(yyscanner);
re_ast->flags |= RE_FLAGS_UNGREEDY;
@@ -1536,7 +1536,7 @@ yyreduce:
if ((yyvsp[-2].re_node)->type == RE_NODE_ANY)
{
(yyval.re_node) = yr_re_node_create(RE_NODE_RANGE_ANY, NULL, NULL);
destroy_node_if(TRUE, (yyvsp[-2].re_node));
destroy_node_if(true, (yyvsp[-2].re_node));
}
else
{
@@ -1545,18 +1545,17 @@ yyreduce:
destroy_node_if((yyval.re_node) == NULL, (yyvsp[-2].re_node));
}
destroy_node_if((yyval.re_node) == NULL, (yyvsp[-2].re_node));
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
(yyval.re_node)->start = 0;
(yyval.re_node)->end = 1;
(yyval.re_node)->greedy = FALSE;
(yyval.re_node)->greedy = false;
}
#line 1556 "re_grammar.c" /* yacc.c:1646 */
#line 1555 "re_grammar.c" /* yacc.c:1663 */
break;
case 15:
#line 292 "re_grammar.y" /* yacc.c:1646 */
#line 290 "re_grammar.y" /* yacc.c:1663 */
{
RE_AST* re_ast = yyget_extra(yyscanner);
re_ast->flags |= RE_FLAGS_GREEDY;
@@ -1564,7 +1563,7 @@ yyreduce:
if ((yyvsp[-1].re_node)->type == RE_NODE_ANY)
{
(yyval.re_node) = yr_re_node_create(RE_NODE_RANGE_ANY, NULL, NULL);
destroy_node_if(TRUE, (yyvsp[-1].re_node));
destroy_node_if(true, (yyvsp[-1].re_node));
}
else
{
@@ -1578,11 +1577,11 @@ yyreduce:
(yyval.re_node)->start = (yyvsp[0].range) & 0xFFFF;;
(yyval.re_node)->end = (yyvsp[0].range) >> 16;;
}
#line 1582 "re_grammar.c" /* yacc.c:1646 */
#line 1581 "re_grammar.c" /* yacc.c:1663 */
break;
case 16:
#line 314 "re_grammar.y" /* yacc.c:1646 */
#line 312 "re_grammar.y" /* yacc.c:1663 */
{
RE_AST* re_ast = yyget_extra(yyscanner);
re_ast->flags |= RE_FLAGS_UNGREEDY;
@@ -1590,7 +1589,7 @@ yyreduce:
if ((yyvsp[-2].re_node)->type == RE_NODE_ANY)
{
(yyval.re_node) = yr_re_node_create(RE_NODE_RANGE_ANY, NULL, NULL);
destroy_node_if(TRUE, (yyvsp[-2].re_node));
destroy_node_if(true, (yyvsp[-2].re_node));
}
else
{
@@ -1603,61 +1602,61 @@ yyreduce:
(yyval.re_node)->start = (yyvsp[-1].range) & 0xFFFF;;
(yyval.re_node)->end = (yyvsp[-1].range) >> 16;;
(yyval.re_node)->greedy = FALSE;
(yyval.re_node)->greedy = false;
}
#line 1609 "re_grammar.c" /* yacc.c:1646 */
#line 1608 "re_grammar.c" /* yacc.c:1663 */
break;
case 17:
#line 337 "re_grammar.y" /* yacc.c:1646 */
#line 335 "re_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = (yyvsp[0].re_node);
}
#line 1617 "re_grammar.c" /* yacc.c:1646 */
#line 1616 "re_grammar.c" /* yacc.c:1663 */
break;
case 18:
#line 341 "re_grammar.y" /* yacc.c:1646 */
#line 339 "re_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = yr_re_node_create(RE_NODE_WORD_BOUNDARY, NULL, NULL);
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
}
#line 1627 "re_grammar.c" /* yacc.c:1646 */
#line 1626 "re_grammar.c" /* yacc.c:1663 */
break;
case 19:
#line 347 "re_grammar.y" /* yacc.c:1646 */
#line 345 "re_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = yr_re_node_create(RE_NODE_NON_WORD_BOUNDARY, NULL, NULL);
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
}
#line 1637 "re_grammar.c" /* yacc.c:1646 */
#line 1636 "re_grammar.c" /* yacc.c:1663 */
break;
case 20:
#line 353 "re_grammar.y" /* yacc.c:1646 */
#line 351 "re_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = yr_re_node_create(RE_NODE_ANCHOR_START, NULL, NULL);
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
}
#line 1647 "re_grammar.c" /* yacc.c:1646 */
#line 1646 "re_grammar.c" /* yacc.c:1663 */
break;
case 21:
#line 359 "re_grammar.y" /* yacc.c:1646 */
#line 357 "re_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = yr_re_node_create(RE_NODE_ANCHOR_END, NULL, NULL);
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
}
#line 1657 "re_grammar.c" /* yacc.c:1646 */
#line 1656 "re_grammar.c" /* yacc.c:1663 */
break;
case 22:
#line 368 "re_grammar.y" /* yacc.c:1646 */
#line 366 "re_grammar.y" /* yacc.c:1663 */
{
fail_if_too_many_ast_levels({
yr_re_node_destroy((yyvsp[-1].re_node));
@@ -1665,21 +1664,21 @@ yyreduce:
(yyval.re_node) = (yyvsp[-1].re_node);
}
#line 1669 "re_grammar.c" /* yacc.c:1646 */
#line 1668 "re_grammar.c" /* yacc.c:1663 */
break;
case 23:
#line 376 "re_grammar.y" /* yacc.c:1646 */
#line 374 "re_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = yr_re_node_create(RE_NODE_ANY, NULL, NULL);
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
}
#line 1679 "re_grammar.c" /* yacc.c:1646 */
#line 1678 "re_grammar.c" /* yacc.c:1663 */
break;
case 24:
#line 382 "re_grammar.y" /* yacc.c:1646 */
#line 380 "re_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = yr_re_node_create(RE_NODE_LITERAL, NULL, NULL);
@@ -1687,71 +1686,71 @@ yyreduce:
(yyval.re_node)->value = (yyvsp[0].integer);
}
#line 1691 "re_grammar.c" /* yacc.c:1646 */
#line 1690 "re_grammar.c" /* yacc.c:1663 */
break;
case 25:
#line 390 "re_grammar.y" /* yacc.c:1646 */
#line 388 "re_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = yr_re_node_create(RE_NODE_WORD_CHAR, NULL, NULL);
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
}
#line 1701 "re_grammar.c" /* yacc.c:1646 */
#line 1700 "re_grammar.c" /* yacc.c:1663 */
break;
case 26:
#line 396 "re_grammar.y" /* yacc.c:1646 */
#line 394 "re_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = yr_re_node_create(RE_NODE_NON_WORD_CHAR, NULL, NULL);
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
}
#line 1711 "re_grammar.c" /* yacc.c:1646 */
#line 1710 "re_grammar.c" /* yacc.c:1663 */
break;
case 27:
#line 402 "re_grammar.y" /* yacc.c:1646 */
#line 400 "re_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = yr_re_node_create(RE_NODE_SPACE, NULL, NULL);
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
}
#line 1721 "re_grammar.c" /* yacc.c:1646 */
#line 1720 "re_grammar.c" /* yacc.c:1663 */
break;
case 28:
#line 408 "re_grammar.y" /* yacc.c:1646 */
#line 406 "re_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = yr_re_node_create(RE_NODE_NON_SPACE, NULL, NULL);
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
}
#line 1731 "re_grammar.c" /* yacc.c:1646 */
#line 1730 "re_grammar.c" /* yacc.c:1663 */
break;
case 29:
#line 414 "re_grammar.y" /* yacc.c:1646 */
#line 412 "re_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = yr_re_node_create(RE_NODE_DIGIT, NULL, NULL);
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
}
#line 1741 "re_grammar.c" /* yacc.c:1646 */
#line 1740 "re_grammar.c" /* yacc.c:1663 */
break;
case 30:
#line 420 "re_grammar.y" /* yacc.c:1646 */
#line 418 "re_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = yr_re_node_create(RE_NODE_NON_DIGIT, NULL, NULL);
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
}
#line 1751 "re_grammar.c" /* yacc.c:1646 */
#line 1750 "re_grammar.c" /* yacc.c:1663 */
break;
case 31:
#line 426 "re_grammar.y" /* yacc.c:1646 */
#line 424 "re_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = yr_re_node_create(RE_NODE_CLASS, NULL, NULL);
@@ -1759,11 +1758,11 @@ yyreduce:
(yyval.re_node)->re_class = (yyvsp[0].re_class);
}
#line 1763 "re_grammar.c" /* yacc.c:1646 */
#line 1762 "re_grammar.c" /* yacc.c:1663 */
break;
#line 1767 "re_grammar.c" /* yacc.c:1646 */
#line 1766 "re_grammar.c" /* yacc.c:1663 */
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
@@ -1991,5 +1990,5 @@ yyreturn:
#endif
return yyresult;
}
#line 434 "re_grammar.y" /* yacc.c:1906 */
#line 432 "re_grammar.y" /* yacc.c:1907 */
+4 -4
View File
@@ -1,8 +1,8 @@
/* A Bison parser, made by GNU Bison 3.0.4. */
/* A Bison parser, made by GNU Bison 3.0.5. */
/* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
Copyright (C) 1984, 1989-1990, 2000-2015, 2018 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -78,14 +78,14 @@ extern int re_yydebug;
union YYSTYPE
{
#line 81 "re_grammar.y" /* yacc.c:1909 */
#line 81 "re_grammar.y" /* yacc.c:1916 */
int integer;
uint32_t range;
RE_NODE* re_node;
RE_CLASS* re_class;
#line 89 "re_grammar.h" /* yacc.c:1909 */
#line 89 "re_grammar.h" /* yacc.c:1916 */
};
typedef union YYSTYPE YYSTYPE;
+9 -11
View File
@@ -57,7 +57,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define fail_if(x, error) \
if (x) \
{ \
lex_env->last_error_code = error; \
lex_env->last_error = error; \
YYABORT; \
} \
@@ -209,7 +209,7 @@ repeat
destroy_node_if($$ == NULL, $1);
fail_if($$ == NULL, ERROR_INSUFFICIENT_MEMORY);
$$->greedy = FALSE;
$$->greedy = false;
}
| single '+'
{
@@ -239,7 +239,7 @@ repeat
destroy_node_if($$ == NULL, $1);
fail_if($$ == NULL, ERROR_INSUFFICIENT_MEMORY);
$$->greedy = FALSE;
$$->greedy = false;
}
| single '?'
{
@@ -249,7 +249,7 @@ repeat
if ($1->type == RE_NODE_ANY)
{
$$ = yr_re_node_create(RE_NODE_RANGE_ANY, NULL, NULL);
destroy_node_if(TRUE, $1);
destroy_node_if(true, $1);
}
else
{
@@ -258,7 +258,6 @@ repeat
destroy_node_if($$ == NULL, $1);
}
destroy_node_if($$ == NULL, $1);
fail_if($$ == NULL, ERROR_INSUFFICIENT_MEMORY);
$$->start = 0;
@@ -272,7 +271,7 @@ repeat
if ($1->type == RE_NODE_ANY)
{
$$ = yr_re_node_create(RE_NODE_RANGE_ANY, NULL, NULL);
destroy_node_if(TRUE, $1);
destroy_node_if(true, $1);
}
else
{
@@ -281,12 +280,11 @@ repeat
destroy_node_if($$ == NULL, $1);
}
destroy_node_if($$ == NULL, $1);
fail_if($$ == NULL, ERROR_INSUFFICIENT_MEMORY);
$$->start = 0;
$$->end = 1;
$$->greedy = FALSE;
$$->greedy = false;
}
| single _RANGE_
{
@@ -296,7 +294,7 @@ repeat
if ($1->type == RE_NODE_ANY)
{
$$ = yr_re_node_create(RE_NODE_RANGE_ANY, NULL, NULL);
destroy_node_if(TRUE, $1);
destroy_node_if(true, $1);
}
else
{
@@ -318,7 +316,7 @@ repeat
if ($1->type == RE_NODE_ANY)
{
$$ = yr_re_node_create(RE_NODE_RANGE_ANY, NULL, NULL);
destroy_node_if(TRUE, $1);
destroy_node_if(true, $1);
}
else
{
@@ -331,7 +329,7 @@ repeat
$$->start = $2 & 0xFFFF;;
$$->end = $2 >> 16;;
$$->greedy = FALSE;
$$->greedy = false;
}
| single
{
File diff suppressed because it is too large Load Diff
+10 -10
View File
@@ -172,7 +172,7 @@ hex_digit [0-9a-fA-F]
BEGIN(char_class);
memset(LEX_ENV->re_class.bitmap, 0, 32);
LEX_ENV->re_class.negated = TRUE;
LEX_ENV->re_class.negated = true;
}
\[\^\] {
@@ -183,7 +183,7 @@ hex_digit [0-9a-fA-F]
BEGIN(char_class);
memset(LEX_ENV->re_class.bitmap, 0, 32);
LEX_ENV->re_class.negated = TRUE;
LEX_ENV->re_class.negated = true;
LEX_ENV->re_class.bitmap[']' / 8] |= 1 << ']' % 8;
}
@@ -196,7 +196,7 @@ hex_digit [0-9a-fA-F]
BEGIN(char_class);
memset(LEX_ENV->re_class.bitmap, 0, 32);
LEX_ENV->re_class.negated = FALSE;
LEX_ENV->re_class.negated = false;
LEX_ENV->re_class.bitmap[']' / 8] |= 1 << ']' % 8;
}
@@ -207,7 +207,7 @@ hex_digit [0-9a-fA-F]
BEGIN(char_class);
memset(LEX_ENV->re_class.bitmap, 0, 32);
LEX_ENV->re_class.negated = FALSE;
LEX_ENV->re_class.negated = false;
}
@@ -577,14 +577,14 @@ void yyerror(
RE_LEX_ENVIRONMENT* lex_env,
const char *error_message)
{
// if lex_env->last_error_code was set to some error code before
// if lex_env->last_error was set to some error code before
// don't overwrite it, we are interested in the first error, not in
// subsequent errors like "syntax error, unexpected $end" caused by
// early parser termination.
if (lex_env->last_error_code == ERROR_SUCCESS)
if (lex_env->last_error == ERROR_SUCCESS)
{
lex_env->last_error_code = ERROR_INVALID_REGULAR_EXPRESSION;
lex_env->last_error = ERROR_INVALID_REGULAR_EXPRESSION;
strlcpy(
lex_env->last_error_message,
@@ -603,7 +603,7 @@ int yr_parse_re_string(
jmp_buf recovery_state;
RE_LEX_ENVIRONMENT lex_env;
lex_env.last_error_code = ERROR_SUCCESS;
lex_env.last_error = ERROR_SUCCESS;
lex_env.last_error_message[0] = '\0';
yr_thread_storage_set_value(&yr_recovery_state_key, &recovery_state);
@@ -619,7 +619,7 @@ int yr_parse_re_string(
yyparse(yyscanner, &lex_env);
yylex_destroy(yyscanner);
if (lex_env.last_error_code != ERROR_SUCCESS)
if (lex_env.last_error != ERROR_SUCCESS)
{
yr_re_ast_destroy(*re_ast);
*re_ast = NULL;
@@ -629,7 +629,7 @@ int yr_parse_re_string(
lex_env.last_error_message,
sizeof(error->message));
return lex_env.last_error_code;
return lex_env.last_error;
}
return ERROR_SUCCESS;
+91 -5
View File
@@ -264,7 +264,7 @@ YR_API int yr_rules_scan_mem(
YR_API int yr_rules_scan_file(
YR_RULES* rules,
const char* filename,
const wchar_t* filename,
int flags,
YR_CALLBACK_FUNC callback,
void* user_data,
@@ -374,8 +374,10 @@ YR_API int yr_rules_load_stream(
new_rules->code_start = header->code_start;
new_rules->externals_list_head = header->externals_list_head;
new_rules->rules_list_head = header->rules_list_head;
new_rules->match_table = header->match_table;
new_rules->transition_table = header->transition_table;
new_rules->ac_match_table = header->ac_match_table;
new_rules->ac_transition_table = header->ac_transition_table;
new_rules->ac_tables_size = header->ac_tables_size;
memset(new_rules->tidx_mask, 0, sizeof(new_rules->tidx_mask));
FAIL_ON_ERROR_WITH_CLEANUP(
@@ -417,7 +419,7 @@ YR_API int yr_rules_save_stream(
{
int i;
for (i = 0; i < YR_BITARRAY_NCHARS(MAX_THREADS); ++i)
for (i = 0; i < YR_BITARRAY_NCHARS(YR_MAX_THREADS); ++i)
assert(rules->tidx_mask[i] == 0);
return yr_arena_save_stream(rules->arena, stream);
@@ -446,6 +448,90 @@ YR_API int yr_rules_save(
}
static int _uint32_cmp (
const void * a,
const void * b)
{
return (*(uint32_t*) a - *(uint32_t*) b);
}
YR_API int yr_rules_get_stats(
YR_RULES* rules,
YR_RULES_STATS *stats)
{
YR_RULE* rule;
YR_STRING* string;
uint32_t* match_list_lengths = (uint32_t*) yr_malloc(
sizeof(uint32_t) * rules->ac_tables_size);
float match_list_length_sum = 0;
int i, c = 0;
if (match_list_lengths == NULL)
return ERROR_INSUFFICIENT_MEMORY;
stats->ac_tables_size = rules->ac_tables_size;
stats->ac_matches = 0;
stats->rules = 0;
stats->strings = 0;
for (i = 0; i < rules->ac_tables_size; i++)
{
YR_AC_MATCH* match = rules->ac_match_table[i].match;
int match_list_length = 0;
while (match != NULL)
{
match_list_length++;
stats->ac_matches++;
match = match->next;
}
if (i == 0)
stats->ac_root_match_list_length = match_list_length;
match_list_length_sum += match_list_length;
if (match_list_length > 0)
{
match_list_lengths[c] = match_list_length;
c++;
}
}
// sort match_list_lengths in increasing order for computing percentiles.
qsort(match_list_lengths, c, sizeof(match_list_lengths[0]), _uint32_cmp);
for (i = 0; i < 100; i++)
{
if (i < c)
stats->top_ac_match_list_lengths[i] = match_list_lengths[c-i-1];
else
stats->top_ac_match_list_lengths[i] = 0;
}
stats->ac_average_match_list_length = match_list_length_sum / c;
stats->ac_match_list_length_pctls[0] = match_list_lengths[0];
stats->ac_match_list_length_pctls[100] = match_list_lengths[c-1];
for (i = 1; i < 100; i++)
stats->ac_match_list_length_pctls[i] = match_list_lengths[(c * i) / 100];
yr_free(match_list_lengths);
yr_rules_foreach(rules, rule)
{
stats->rules++;
yr_rule_strings_foreach(rule, string)
stats->strings++;
}
return ERROR_SUCCESS;
}
YR_API int yr_rules_destroy(
YR_RULES* rules)
{
@@ -481,7 +567,7 @@ YR_API void yr_rule_disable(
YR_API void yr_rule_enable(
YR_RULE* rule)
YR_RULE* rule)
{
YR_STRING* string;
+13 -8
View File
@@ -248,7 +248,7 @@ static int _yr_scan_add_match_to_list(
{
YR_MATCH* insertion_point = matches_list->tail;
if (matches_list->count == MAX_STRING_MATCHES)
if (matches_list->count == YR_MAX_STRING_MATCHES)
return ERROR_TOO_MANY_MATCHES;
while (insertion_point != NULL)
@@ -335,11 +335,11 @@ static int _yr_scan_verify_chained_string_match(
int32_t full_chain_length;
int tidx = context->tidx;
int add_match = FALSE;
bool add_match = false;
if (matching_string->chained_to == NULL)
{
add_match = TRUE;
add_match = true;
}
else
{
@@ -365,7 +365,7 @@ static int _yr_scan_verify_chained_string_match(
if (ending_offset + matching_string->chain_gap_max >= match_offset &&
ending_offset + matching_string->chain_gap_min <= match_offset)
{
add_match = TRUE;
add_match = true;
break;
}
}
@@ -437,7 +437,7 @@ static int _yr_scan_verify_chained_string_match(
(void**) &match->data));
FAIL_ON_ERROR(_yr_scan_add_match_to_list(
match, &string->matches[tidx], FALSE));
match, &string->matches[tidx], false));
}
match = next_match;
@@ -488,7 +488,7 @@ static int _yr_scan_verify_chained_string_match(
FAIL_ON_ERROR(_yr_scan_add_match_to_list(
new_match,
&matching_string->unconfirmed_matches[tidx],
FALSE));
false));
}
}
@@ -872,8 +872,13 @@ int yr_scan_verify_match(
#ifdef PROFILING_ENABLED
uint64_t finish_time = yr_stopwatch_elapsed_us(&context->stopwatch);
string->time_cost += (finish_time - start_time);
string->rule->time_cost += (finish_time - start_time);
#ifdef _WIN32
InterlockedAdd64(&string->time_cost, finish_time - start_time);
InterlockedAdd64(&string->rule->time_cost, finish_time - start_time);
#else
__sync_fetch_and_add(&string->time_cost, finish_time - start_time);
__sync_fetch_and_add(&string->rule->time_cost, finish_time - start_time);
#endif
#endif
return result;

Some files were not shown because too many files have changed in this diff Show More