mirror of
https://github.com/stellarbear/YaraSharp
synced 2026-06-08 17:36:09 +00:00
1.2. Yara patched to support unicode paths. Update to 3.8.1
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Binary file not shown.
+2
-2
@@ -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.
@@ -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.
@@ -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>
|
||||
@@ -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');
|
||||
@@ -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
@@ -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>
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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*
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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
@@ -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)*
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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 executable’s 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 executable’s 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 we’re using a range (1..3) instead of enumerating the index
|
||||
values (1,2,3). Of course, we’re 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 don’t 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"
|
||||
|
||||
@@ -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>)`.
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+108
-104
@@ -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;
|
||||
|
||||
+325
-331
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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,
|
||||
|
||||
@@ -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; \
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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];
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
+477
-712
File diff suppressed because it is too large
Load Diff
+67
-56
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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]);
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
+324
-573
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user