├── test ├── Makefile └── db │ └── extras │ └── yara ├── dist └── debian │ ├── DESCR │ ├── CONFIG │ ├── Makefile │ └── deb.mk ├── yara-r2-module ├── rules │ ├── simple_test.yar │ ├── number_of_exports.yar │ ├── fields.yar │ ├── lib.yar │ ├── upx.yar │ ├── sections.yar │ ├── bin.yar │ ├── resources_array.yar │ ├── section_entropy.yar │ ├── resource_func.yar │ ├── section_functions.yar │ ├── export.yar │ ├── use_cases.yar │ ├── exports_array.yar │ ├── info.yar │ ├── hash.yar │ └── imports.yar ├── doc │ ├── installation │ │ ├── tests.md │ │ └── installation.md │ ├── r2yara │ │ ├── lib.md │ │ ├── hashes.md │ │ ├── exports.md │ │ ├── resources.md │ │ ├── imports.md │ │ ├── sections.md │ │ └── info.md │ ├── mkdocs.yml │ ├── use_cases.md │ └── index.md ├── dist │ └── yara-3.6.3 │ │ ├── libyara │ │ ├── modules │ │ │ └── module_list │ │ └── Makefile.am │ │ └── configure.ac ├── .travis.yml ├── generate_report.py ├── LICENSE.md ├── README.md ├── ChangeLog.orig └── launch_tests.py ├── .github ├── dependabot.yml └── workflows │ └── ci.yml ├── rules ├── hello.yara └── crypto.yara ├── configure.acr ├── Makefile.acr ├── autogen.sh ├── config.mk.acr ├── src ├── Makefile └── core_r2yara.c ├── meson.build ├── doc └── r2yara.7 ├── README.md ├── .gitignore ├── COPYING.LESSER ├── configure └── COPYING /test/Makefile: -------------------------------------------------------------------------------- 1 | all: run 2 | 3 | run: 4 | r2r -L db/extras 5 | 6 | .PHONY: all run -------------------------------------------------------------------------------- /dist/debian/DESCR: -------------------------------------------------------------------------------- 1 | Yara plugin for radare2 2 | This plugin lets you use Yara from inside radare2 3 | -------------------------------------------------------------------------------- /yara-r2-module/rules/simple_test.yar: -------------------------------------------------------------------------------- 1 | rule simple 2 | { 3 | strings: 4 | $elf = "ELF" 5 | condition: 6 | $elf 7 | } -------------------------------------------------------------------------------- /yara-r2-module/rules/number_of_exports.yar: -------------------------------------------------------------------------------- 1 | import "r2" 2 | 3 | rule rule_number_of_exports 4 | { 5 | condition: 6 | r2.number_of_exports > 3 7 | } 8 | -------------------------------------------------------------------------------- /yara-r2-module/rules/fields.yar: -------------------------------------------------------------------------------- 1 | import "r2" 2 | 3 | rule fields { 4 | condition: 5 | for any i in ( 0..r2.number_of_fields ) : 6 | (r2.fields[i].name == "phdr_6" and 7 | r2.fields[i].paddr > 300KB) 8 | } -------------------------------------------------------------------------------- /yara-r2-module/rules/lib.yar: -------------------------------------------------------------------------------- 1 | import "r2" 2 | 3 | rule rule_lib_s 4 | { 5 | condition: 6 | r2.lib("libselinux.so.1") 7 | } 8 | 9 | rule rule_lib_r 10 | { 11 | condition: 12 | r2.lib(/selinux/) 13 | } 14 | 15 | -------------------------------------------------------------------------------- /yara-r2-module/rules/upx.yar: -------------------------------------------------------------------------------- 1 | import "r2" 2 | 3 | rule UPX { 4 | condition: true 5 | } 6 | rule UPX2 { 7 | strings: 8 | $upx = "UPX" 9 | condition: 10 | r2.section("UPX0", "") and 11 | r2.section("UPX1", "") and 12 | $upx 13 | } 14 | -------------------------------------------------------------------------------- /yara-r2-module/rules/sections.yar: -------------------------------------------------------------------------------- 1 | import "r2" 2 | 3 | rule sections { 4 | condition: 5 | for any i in ( 0..r2.number_of_sections ) : 6 | (r2.sections[i].size > 28KB and 7 | r2.sections[i].flags contains "r-x" and 8 | r2.sections[i].name contains "text") 9 | } -------------------------------------------------------------------------------- /yara-r2-module/rules/bin.yar: -------------------------------------------------------------------------------- 1 | import "r2" 2 | rule rule_bins_si 3 | { 4 | condition: 5 | r2.bins("x86", 64) 6 | } 7 | 8 | rule rule_bins_ri 9 | { 10 | condition: 11 | r2.bins(/86/, 64) 12 | } 13 | 14 | rule rule_bins_ri_2 15 | { 16 | condition: 17 | r2.bins(/86/, -1) 18 | } -------------------------------------------------------------------------------- /yara-r2-module/rules/resources_array.yar: -------------------------------------------------------------------------------- 1 | import "r2" 2 | 3 | rule resources { 4 | condition: 5 | for any i in ( 0..r2.number_of_resources ) : 6 | (r2.resources[i].size > 2KB and 7 | r2.resources[i].type == "ICON" and 8 | r2.resources[i].lang contains "JAPANESE") 9 | } 10 | -------------------------------------------------------------------------------- /dist/debian/CONFIG: -------------------------------------------------------------------------------- 1 | PACKAGE=r2yara 2 | DEPENDS=radare2 3 | SECTION=user/shell 4 | PRIORITY=optional 5 | MAINTAINER=pancake 6 | include ../../config.mk 7 | # arch 8 | UNAMEM=$(shell uname -m) 9 | ifeq ($(UNAMEM),x86_64) 10 | ARCH=amd64 11 | else 12 | ARCH=arm64 13 | endif 14 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | commit-message: 8 | prefix: "##build " 9 | prefix-development: "##build " 10 | labels: 11 | - buildsystem 12 | -------------------------------------------------------------------------------- /rules/hello.yara: -------------------------------------------------------------------------------- 1 | rule HelloWorld : foo { 2 | meta: 3 | author = "pancake" 4 | description = "hello world" 5 | date = "2023-10" 6 | version = "0.1" 7 | strings: 8 | $ = "lib" 9 | condition: 10 | all of them 11 | } 12 | -------------------------------------------------------------------------------- /yara-r2-module/rules/section_entropy.yar: -------------------------------------------------------------------------------- 1 | import "r2" 2 | import "math" 3 | 4 | rule rule_sections_entropy_s 5 | { 6 | condition: 7 | for any i in ( 0..r2.number_of_sections ) : 8 | (r2.sections[i].name contains "note.ABI_tag" and 9 | math.entropy(r2.sections[i].paddr, r2.sections[i].size) > 1.5) 10 | } 11 | -------------------------------------------------------------------------------- /yara-r2-module/doc/installation/tests.md: -------------------------------------------------------------------------------- 1 | # Tests 2 | 3 | We prepared several tests in order to maintain the quality and correct functionality of the module. 4 | 5 | ## How to run? 6 | Easy, from the main folder, run this 7 | ```bash 8 | python tests/run.py 9 | ``` 10 | 11 | This will try to covert all the cases included in the module. -------------------------------------------------------------------------------- /yara-r2-module/doc/r2yara/lib.md: -------------------------------------------------------------------------------- 1 | #Libraries 2 | You can check the libraries used by a binary in a simple way. 3 | 4 | ##Functions 5 | ``` 6 | r2.lib(name) 7 | ``` 8 | 9 | Examples: 10 | ``` 11 | r2.lib("libselinux.so.1") 12 | ``` 13 | ``` 14 | r2.lib(/selinux/) 15 | ``` 16 | 17 | You can use with regular expressions or with a simple string. 18 | -------------------------------------------------------------------------------- /yara-r2-module/dist/yara-3.6.3/libyara/modules/module_list: -------------------------------------------------------------------------------- 1 | MODULE(tests) 2 | MODULE(pe) 3 | MODULE(elf) 4 | MODULE(math) 5 | 6 | #ifdef DOTNET_MODULE 7 | MODULE(dotnet) 8 | #endif 9 | 10 | #ifdef CUCKOO_MODULE 11 | MODULE(cuckoo) 12 | MODULE(r2) 13 | #endif 14 | 15 | #ifdef MAGIC_MODULE 16 | MODULE(magic) 17 | #endif 18 | 19 | #ifdef HASH_MODULE 20 | MODULE(hash) 21 | #endif 22 | -------------------------------------------------------------------------------- /yara-r2-module/rules/resource_func.yar: -------------------------------------------------------------------------------- 1 | import "r2" 2 | 3 | rule resource_ss { 4 | condition: 5 | r2.resource("ICON", "LANG_JAPANESE") 6 | } 7 | 8 | rule resource_sr { 9 | condition: 10 | r2.resource("ICON", /japanese/i) 11 | } 12 | 13 | rule resource_rs { 14 | condition: 15 | r2.resource(/icon/i, "LANG_JAPANESE") 16 | } 17 | 18 | rule resource_rr { 19 | condition: 20 | r2.resource(/ICO/, /LANG_JAP/) 21 | } -------------------------------------------------------------------------------- /yara-r2-module/rules/section_functions.yar: -------------------------------------------------------------------------------- 1 | import "r2" 2 | 3 | rule rule_sections_ss 4 | { 5 | condition: 6 | r2.section(".note.ABI_tag","--r--") 7 | } 8 | 9 | rule rule_sections_sr 10 | { 11 | condition: 12 | r2.section(".note.gnu.build_id", /r/) 13 | } 14 | 15 | rule rule_sections_rs 16 | { 17 | condition: 18 | r2.section(/LOAD/, "m-r-x") 19 | } 20 | 21 | rule rule_sections_rr 22 | { 23 | condition: 24 | r2.section(/LOAD/, /x/) 25 | } -------------------------------------------------------------------------------- /configure.acr: -------------------------------------------------------------------------------- 1 | PKGNAME r2yara 2 | VERSION 1.4.4 3 | DESCRIPTION yara plugin for radare2 ; 4 | CONTACT jfrankowski ; judy.frankowski@gmail.com 5 | 6 | REPORT PREFIX ; 7 | USE_PKGCONFIG! 8 | 9 | LANG_C! 10 | 11 | (( CHKLIB! yara )) 12 | PKGCFG! YR_CFLAGS YR_LDFLAGS yara 13 | PKGCFG! R2_CFLAGS R2_LDFLAGS r_core 14 | 15 | (( OPTIONS )) 16 | 17 | ARG_WITH USE_YARAX yarax build and link to the Rust Yara-X library ; 18 | 19 | SUBDIRS . config.mk ; 20 | -------------------------------------------------------------------------------- /yara-r2-module/rules/export.yar: -------------------------------------------------------------------------------- 1 | import "r2" 2 | 3 | rule rule_export_ss 4 | { 5 | condition: 6 | r2.export("ADVAPI32.dll_WmiQuerySingleInstanceW", "FUNC") 7 | } 8 | 9 | rule rule_export_sr 10 | { 11 | condition: 12 | r2.export("ADVAPI32.dll_WmiQuerySingleInstanceW", /FUN/i) 13 | } 14 | 15 | rule rule_export_rs 16 | { 17 | condition: 18 | r2.export(/WmiQuerySingleInstanceW/, "FUNC") 19 | } 20 | rule rule_export_rr 21 | { 22 | condition: 23 | r2.export(/WmiQuerySingleInstance/, /fun/i) 24 | } 25 | -------------------------------------------------------------------------------- /yara-r2-module/doc/mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: r2yara Documentation 2 | strict: true 3 | theme: readthedocs 4 | docs_dir: . 5 | pages: 6 | - Home: 7 | - Index: 'index.md' 8 | - Installation: 'installation/installation.md' 9 | - Tests: 'installation/tests.md' 10 | - Use Cases: 'use_cases.md' 11 | - r2yara module: 12 | - Imports: 'r2yara/imports.md' 13 | - Exports: 'r2yara/exports.md' 14 | - Hash: 'r2yara/hashes.md' 15 | - Sections: 'r2yara/sections.md' 16 | - Libraries: 'r2yara/lib.md' 17 | - Resources: 'r2yara/resources.md' 18 | - Info: 'r2yara/info.md' 19 | -------------------------------------------------------------------------------- /yara-r2-module/doc/r2yara/hashes.md: -------------------------------------------------------------------------------- 1 | #Hash 2 | Radare2 supports a lot of different hashes, more that yara supports by default, so, of course, we extract them to use inside Yara. Following the complete list of them: 3 | 4 | - md5 5 | - sha1 6 | - sha256 7 | - sha384 8 | - sha512 9 | - crc16 10 | - crc32 11 | - md4 12 | - xor 13 | - xorpair 14 | - parity 15 | - entropy 16 | - hamdist 17 | - pcprint 18 | - mod255 19 | - adler32 20 | - luhn 21 | 22 | The way to use them is easy too, simply by comparison: 23 | 24 | ``` 25 | rule rule_hash 26 | { 27 | condition: 28 | r2.hash.md5 != "945fedb3a3c290d69f075f997e5320fc" or 29 | r2.hash.crc32 contains "b053d" 30 | } 31 | ``` -------------------------------------------------------------------------------- /Makefile.acr: -------------------------------------------------------------------------------- 1 | include config.mk 2 | ifeq ($(USE_YARAX),1) 3 | CFLAGS+=USE_YARAX=1 4 | YARADEP=yara-x/target/release/libyara_x.rlib 5 | else 6 | YARADEP= 7 | endif 8 | 9 | all clean user-install install symstall user-uninstall uninstall: $(YARADEP) 10 | $(MAKE) -C src $@ 11 | 12 | ifeq ($(USE_YARAX),1) 13 | yara-x/target/release/libyara_x.rlib: 14 | $(MAKE) yarax 15 | endif 16 | 17 | fmt: 18 | clang-format-radare2 src/*.c 19 | 20 | mrproper: clean 21 | rm -f config.mk 22 | 23 | yarax: yara-x 24 | cd yara-x && cargo build -r 25 | cd yara-x/capi && cargo build -r 26 | 27 | yara-x: 28 | git clone https://github.com/VirusTotal/yara-x 29 | 30 | RULESDIR=$(R2PM_USRPLUGIN_DIR)/rules-yara3 31 | -------------------------------------------------------------------------------- /yara-r2-module/doc/r2yara/exports.md: -------------------------------------------------------------------------------- 1 | #Exports 2 | There are two ways to look for specific exports in a binary. 3 | 4 | ##Functions 5 | ``` 6 | r2.export(name, type) 7 | ``` 8 | 9 | Each parameter could be string or regex. In case any parameter is indiferent for you, can use empty string "", for instance: 10 | 11 | We can look for DLLs with an exported "function" called "ADVAPI32.dll_WriteEncryptedFileRaw", we can write any of the following conditions: 12 | 13 | ``` 14 | r2.export("ADVAPI32.dll_WmiQuerySingleInstanceW", "FUNC") 15 | 16 | r2.export("ADVAPI32.dll_WmiQuerySingleInstanceW", /FUNC/) 17 | 18 | r2.export(/WmiQuerySingleInstanceW/, "FUNC") 19 | 20 | r2.export(/WmiQuerySingleInstance/, /func/i) 21 | ``` 22 | -------------------------------------------------------------------------------- /yara-r2-module/rules/use_cases.yar: -------------------------------------------------------------------------------- 1 | import "r2" 2 | import "math" 3 | 4 | rule difference_size_and_vsize { 5 | meta: 6 | description = "Rule to detect binaries with a big difference between section size and section vsize (after unpack). Also, it includes a big entropy and executable flags" 7 | author = "A.Sánchez , M.Moreno " 8 | reference = "Practical Malware Analysis. BlackHat. Kris Kendall and Chad McMillan. Page 52" 9 | 10 | condition: 11 | for any i in ( 0..r2.number_of_sections ) : 12 | ((r2.sections[i].vsize > r2.sections[i].size*2) and 13 | r2.sections[i].flags contains "x" and 14 | math.entropy(r2.sections[i].paddr, r2.sections[i].size) > 1.5) 15 | } -------------------------------------------------------------------------------- /yara-r2-module/rules/exports_array.yar: -------------------------------------------------------------------------------- 1 | import "r2" 2 | 3 | rule rule_exports_array 4 | { 5 | condition: 6 | for any i in ( 0..r2.number_of_exports ) : 7 | (r2.exports[i].name == "ADVAPI32.dll_WriteEncryptedFileRaw" and 8 | r2.exports[i].demname == "" and 9 | r2.exports[i].flagname == "sym.ADVAPI32.dll_WriteEncryptedFileRaw" and 10 | r2.exports[i].size == 0 and 11 | r2.exports[i].type == "FUNC" and 12 | r2.exports[i].vaddr > 1024 and 13 | r2.exports[i].paddr > 512) 14 | 15 | /*{"name":"ADVAPI32.dll_WriteEncryptedFileRaw","demname":"", 16 | "flagname":"sym.ADVAPI32.dll_WriteEncryptedFileRaw","size":0, 17 | "type":"FUNC","vaddr":2009733322, 18 | "paddr":265930}*/ 19 | } -------------------------------------------------------------------------------- /dist/debian/Makefile: -------------------------------------------------------------------------------- 1 | include ./CONFIG 2 | 3 | UNAME=$(shell uname) 4 | SUDO?=sudo 5 | DEPENDS= 6 | CROSSARCH=x64 7 | R2CFG_FLAGS?= 8 | PWD=$(shell pwd) 9 | PACKAGE_DIR?=${PWD} 10 | 11 | R2_VERSION=$(shell r2 -qv) 12 | 13 | DOCKCROSS=$(PWD)/../dockcross 14 | R2PLUGDIR=/usr/lib/radare2/$(R2_VERSION) 15 | 16 | all: root 17 | $(SUDO) rm -rf control data 18 | $(MAKE) clean 19 | mkdir -p data 20 | cp -rf root/* data 21 | $(MAKE) control 22 | $(MAKE) deb 23 | 24 | root: 25 | cd ../.. && $(MAKE) clean ; ./configure --prefix=/usr $(R2CFG_FLAGS) ; make 26 | mkdir -p root/$(R2PLUGDIR) 27 | cp -f ../../src/core_r2yara.so root/$(R2PLUGDIR) 28 | 29 | purge: clean 30 | rm -rf root 31 | 32 | summary: 33 | echo $(VERSION) 34 | 35 | include deb.mk 36 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Look for the 'acr' tool here: https://github.com/radare/acr 4 | # Clone last version of ACR from here: 5 | # git clone https://github.com/radare/acr 6 | # 7 | # -- pancake 8 | 9 | r2pm -h >/dev/null 2>&1 10 | if [ $? = 0 ]; then 11 | echo "Installing the last version of 'acr'..." 12 | r2pm -i acr > /dev/null 13 | r2pm -r acr -h > /dev/null 2>&1 14 | if [ $? = 0 ]; then 15 | echo "Running 'acr -p'..." 16 | r2pm -r acr -p 17 | else 18 | echo "Cannot find 'acr' in PATH" 19 | fi 20 | else 21 | echo "Running acr..." 22 | acr -p 23 | fi 24 | exit 0 25 | V=`./configure -qV | cut -d - -f -1` 26 | meson rewrite kwargs set project / version "$V" 27 | if [ -n "$1" ]; then 28 | echo "./configure $*" 29 | ./configure $* 30 | fi 31 | 32 | [ -z "$EDITOR" ] && EDITOR=vim 33 | $EDITOR README.md 34 | -------------------------------------------------------------------------------- /config.mk.acr: -------------------------------------------------------------------------------- 1 | VERSION=@VERSION@ 2 | DESTDIR= 3 | PREFIX=@PREFIX@ 4 | HOST_OS=@HOST_OS@ 5 | LIBDIR=@LIBDIR@ 6 | MANDIR=@MANDIR@ 7 | INSTALL_LIB=@INSTALL_LIB@ 8 | 9 | USE_YARAX=@USE_YARAX@ 10 | R2_LIBR_PLUGINS_DIR=$(shell r2 -H R2_LIBR_PLUGINS) 11 | R2PM_USRPLUGIN_DIR=$(shell r2 -H R2_USER_PLUGINS) 12 | LIBEXT=$(shell r2 -H R2_LIBEXT) 13 | #LIBYARA_CFLAGS=@LIBYARA_CFLAGS@ 14 | #LIBYARA_LDFLAGS=@LIBYARA_LDFLAGS@ 15 | LIBYARA_CFLAGS= 16 | LIBYARA_LDFLAGS=-lyara 17 | R2_CFLAGS=@R2_CFLAGS@ 18 | R2_LDFLAGS=@R2_LDFLAGS@ 19 | YR_CFLAGS=@YR_CFLAGS@ 20 | YR_LDFLAGS=@YR_LDFLAGS@ 21 | 22 | ifeq ($(USE_YARAX),1) 23 | CFLAGS+=-DUSE_YARAX=1 24 | CFLAGS+=${R2_CFLAGS} -I $(ROOT)/yara-x/capi/include 25 | LDFLAGS+=${R2_LDFLAGS} $(ROOT)/yara-x/target/release/libyara_x_capi.a 26 | else 27 | CFLAGS+=${R2_CFLAGS} ${LIBYARA_CFLAGS} ${YR_CFLAGS} 28 | LDFLAGS+=${R2_LDFLAGS} ${LIBYARA_LDFLAGS} ${YR_LDFLAGS} 29 | endif 30 | CFLAGS+=-I. -fPIC 31 | LDFLAGS+=-shared 32 | CFLAGS+=-DR2Y_VERSION=\"$(VERSION)\" 33 | -------------------------------------------------------------------------------- /yara-r2-module/rules/info.yar: -------------------------------------------------------------------------------- 1 | import "r2" 2 | 3 | rule rule_info 4 | { 5 | condition: 6 | r2.info.havecode == 1 and 7 | r2.info.pic == 0 and 8 | r2.info.canary == 1 and 9 | r2.info.nx == 1 and 10 | r2.info.crypto == 0 and 11 | r2.info.va == 1 and 12 | r2.info.intrp contains "linux-x86" and 13 | r2.info.bintype == "elf" and 14 | r2.info.class contains "ELF64" and 15 | r2.info.lang == "c" and 16 | r2.info.arch == "x86" and 17 | r2.info.bits == 64 and 18 | r2.info.machine == "AMD x86-64 architecture" and 19 | r2.info.os == "linux" and 20 | r2.info.minopsz == 1 and 21 | r2.info.maxopsz == 16 and 22 | r2.info.pcalign == 0 and 23 | r2.info.subsys == "linux" and 24 | r2.info.endian == "little" and 25 | r2.info.stripped == 1 and 26 | r2.info.static == 0 and 27 | r2.info.linenum == 0 and 28 | r2.info.lsyms == 0 and 29 | r2.info.relocs == 0 and 30 | r2.info.binsz > 100000 and 31 | r2.info.rpath == "NONE" and 32 | r2.info.compiled == "" and 33 | r2.info.dbg_file == "" and 34 | r2.info.guid == "" 35 | } 36 | -------------------------------------------------------------------------------- /yara-r2-module/doc/r2yara/resources.md: -------------------------------------------------------------------------------- 1 | #Resources 2 | There are two ways to look for specific exports in a binary. 3 | 4 | ##Functions 5 | ``` 6 | r2.resource(type, language) 7 | ``` 8 | 9 | Each parameter could be string or regex. In case any parameter is indiferent for you, can use empty string "", for instance: 10 | 11 | We can want to look for binaries with an resource type "STRING" and in "JAPANESE": 12 | 13 | ``` 14 | r2.resource("STRING", "LANG_JAPANESE") 15 | ``` 16 | 17 | Or simply something in RUSSIAN: 18 | 19 | ``` 20 | r2.resource("", /RUSSIAN/) 21 | ``` 22 | 23 | ##Array 24 | The array called "resources" contains the following attributes: 25 | 26 | - size 27 | - paddr 28 | - lang 29 | - type 30 | 31 | So with those you can construct simple or very complex rules, for instance: 32 | 33 | ``` 34 | rule resources { 35 | condition: 36 | for any i in ( 0..r2.number_of_resources ) : 37 | (r2.resources[i].size > 2KB and 38 | r2.resources[i].paddr > 1024 and 39 | r2.resources[i].type == "ICON" and 40 | r2.resources[i].lang contains "JAPANESE") 41 | } 42 | ``` -------------------------------------------------------------------------------- /yara-r2-module/rules/hash.yar: -------------------------------------------------------------------------------- 1 | import "r2" 2 | 3 | rule rule_hashes 4 | { 5 | condition: 6 | r2.hash.md5 != "945fedb3a3c290d69f075f997e5320fc" and 7 | r2.hash.sha1 != "2df1502114171d5213f7e5f699a4a80ac47974e1" and 8 | r2.hash.sha256 != "a90ba058c747458330ba26b5e2a744f4fc57f92f9d0c9112b1cb2f76c66c4ba0" and 9 | r2.hash.sha384 != "3f239e271db8015cbcd367d721ef2c21289caad75c08b318ae18b203824023251410d5df80c8f92a1a116f90ac67c0cb" and 10 | r2.hash.sha512 != "11ad52bdd829a1dfae20f2e90ecc4cfc6e3065ddb23afc02d54aea2a710b3a5da5e4d67a3f346ecd1f962c15797f3cedac7e0d97bb25b1106f92a5327ee9c6d1" and 11 | r2.hash.md4 != "fe4d52ab4d7555deb04e71c727a53814" and 12 | r2.hash.crc16 != "0797" and 13 | r2.hash.crc32 != "77b053d3" and 14 | r2.hash.xor != "8d" and 15 | r2.hash.xorpair != "971a" and 16 | r2.hash.parity != "00" and 17 | r2.hash.entropy != "05000001" and 18 | r2.hash.hamdist != "01" and 19 | r2.hash.pcprint != "24" and 20 | r2.hash.mod255 != "42" and 21 | r2.hash.adler32 != "5e759306" and 22 | r2.hash.luhn != "2" 23 | 24 | } -------------------------------------------------------------------------------- /yara-r2-module/rules/imports.yar: -------------------------------------------------------------------------------- 1 | import "r2" 2 | 3 | 4 | rule rule_import_isss_1 5 | { 6 | condition: 7 | r2.imports(1, "GLOBAL", "FUNC", "__ctype_toupper_loc") 8 | } 9 | rule rule_import_isss_2 10 | { 11 | condition: 12 | not r2.imports(5, "GLOBAL", "FUNC", "__ctype_toupper_loc") 13 | } 14 | 15 | 16 | rule rule_import_ssr 17 | { 18 | condition: 19 | r2.imports(1, "GLOBAL", "FUNC", /ctype_toupper/i) 20 | } 21 | 22 | rule rule_import_srs 23 | { 24 | condition: 25 | r2.imports(1, "GLOBAL", /FUNC/, "__ctype_toupper_loc") 26 | } 27 | 28 | rule rule_import_srr 29 | { 30 | condition: 31 | r2.imports(1, "GLOBAL", /UNC/, /ctype_toupper/) 32 | } 33 | 34 | rule rule_import_rss 35 | { 36 | condition: 37 | r2.imports(-1, /LOBAL/i, "FUNC", "__ctype_toupper_loc") 38 | } 39 | 40 | 41 | rule rule_import_rsr 42 | { 43 | condition: 44 | r2.imports(1, /LOBAL/, "FUNC", /ctype_toupper/) 45 | } 46 | 47 | rule rule_import_rrs 48 | { 49 | condition: 50 | r2.imports(1, /LOBAL/, /FUNC/, "__ctype_toupper_loc") 51 | } 52 | 53 | rule rule_import_rrr 54 | { 55 | condition: 56 | r2.imports(1, /LOBAL/, /FUNC/, /TOUPPER/i) 57 | } -------------------------------------------------------------------------------- /yara-r2-module/doc/r2yara/imports.md: -------------------------------------------------------------------------------- 1 | #Imports 2 | There is only one way to look imports in a binary, using functions 3 | 4 | ##Functions 5 | ``` 6 | r2.imports(integer, string, string, string) 7 | 8 | r2.imports(ordinal, bind, type, name) 9 | ``` 10 | 11 | Each parameter could be string or regex (except the first one). In case any parameter is indiferent for you, can use empty string "", or -1 if you mean the ordinal, for instance: 12 | 13 | We can look for binaries with import called "__ctype_toupper_loc", type "function" and Global and doesn't matter ordinal: 14 | ``` 15 | r2.imports(-1, "GLOBAL", "FUNC", "__ctype_toupper_loc") 16 | ``` 17 | ##Examples 18 | 19 | Some Yara rules examples we can generate: 20 | If a binary imports function URLDownloadToFile, we can intuit the sample connects to Internet to download something that it stores to disk: 21 | ```sh 22 | r2.import(-1,"","",URLDownloadToFile) 23 | ``` 24 | Function CreateProcessA said us the binary probably will create another process. it suggest when we run the program we must look the additional programs lauch: 25 | ```sh 26 | r2.import(-1,"","",CreateProcessA) 27 | ``` 28 | To end this part, remember there're common Windows [functions](http://yararules.com/2017/04/06/yara-rules-strings-statistical-study/) found in malware and you can build Yara signatures to detect them. -------------------------------------------------------------------------------- /yara-r2-module/.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | sudo: required 3 | #dist: trusty 4 | before_install: 5 | # Yara 6 | - wget https://github.com/VirusTotal/yara/archive/v3.6.3.tar.gz -O yara.tar.gz 7 | - tar -xzvf yara.tar.gz 8 | # R2 module for Yara 9 | - cp r2.c yara-3.6.3/libyara/modules/r2.c 10 | - cp dist/yara-3.6.3/libyara/modules/module_list yara-3.6.3/libyara/modules/module_list 11 | - cp dist/yara-3.6.3/libyara/Makefile.am yara-3.6.3/libyara/Makefile.am 12 | - cp dist/yara-3.6.3/configure.ac yara-3.6.3/configure.ac 13 | - echo "AM_CFLAGS += @DOLLAR_SIGN@(shell pkg-config --cflags r_socket)" >> yara-3.6.3/Makefile.am 14 | - echo "LIBS += @DOLLAR_SIGN@(shell pkg-config --libs r_socket)" >> yara-3.6.3/Makefile.am 15 | 16 | # libjansson 17 | - wget http://www.digip.org/jansson/releases/jansson-2.7.tar.gz 18 | - tar -xzvf jansson-2.7.tar.gz 19 | - cd jansson-2.7 20 | - ./configure 21 | - make 22 | - sudo make install 23 | - cd .. 24 | 25 | # Install radare2 26 | - git clone https://github.com/radare/radare2.git 27 | - cd radare2 && ./sys/install.sh 28 | 29 | # Compile Yara 30 | - cd ../yara-3.6.3 31 | - ./bootstrap.sh 32 | - ./configure --enable-cuckoo 33 | - make 34 | - sudo make install 35 | - sudo ldconfig 36 | 37 | # Download requirements.txt 38 | # - sudo pip install -r requirements.txt 39 | 40 | script: 41 | - cd ../ 42 | - ls 43 | - python launch_tests.py 44 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | ROOT=$(shell pwd)/.. 2 | include ../config.mk 3 | 4 | CFLAGS+=-g 5 | LDFLAGS+=-lm 6 | 7 | MOD=core_r2yara 8 | MKDIR=mkdir -p 9 | RULESDIR=rules-yara3 10 | 11 | all: $(MOD).$(LIBEXT) 12 | 13 | $(MOD).$(LIBEXT): ${MOD}.o 14 | $(CC) -g ${MOD}.o ${CFLAGS} ${LDFLAGS} -o ${MOD}.${LIBEXT} 15 | 16 | clean: 17 | rm -f ${MOD}.o ${MOD}.${LIBEXT} 18 | 19 | mrproper: clean 20 | rm -f Makefile 21 | 22 | install: 23 | ${INSTALL_LIB} ${MOD}.${LIBEXT} $(R2_LIBR_PLUGINS_DIR)/${MOD}.${LIBEXT} 24 | $(MKDIR) $(R2_LIBR_PLUGINS_DIR)/$(RULESDIR) 25 | cp -f ../rules/*.yara $(R2_LIBR_PLUGINS_DIR)/$(RULESDIR)/ 26 | $(MKDIR) $(MANDIR)/man7 27 | cp -f ../doc/r2yara.7 $(MANDIR)/man7/r2yara.7 28 | 29 | user-install: 30 | ${INSTALL_LIB} ${MOD}.${LIBEXT} $(R2PM_USRPLUGIN_DIR)/${MOD}.${LIBEXT} 31 | mkdir -p $(R2PM_USRPLUGIN_DIR)/$(RULESDIR) 32 | cp -f ../rules/*.yara $(R2PM_USRPLUGIN_DIR)/$(RULESDIR)/ 33 | 34 | symstall: 35 | ln -fs ${PWD}/${MOD}.${LIBEXT} $(R2PM_USRPLUGIN_DIR)/$(MOD).$(LIBEXT) 36 | mkdir -p $(R2PM_USRPLUGIN_DIR)/$(RULESDIR) 37 | for a in *.gz ; do ln -fs $(PWD)/$$a $(R2PM_USRPLUGIN_DIR)/$(RULESDIR)/$$a ; done 38 | $(MKDIR) $(MANDIR)/man7 39 | ln -fs $(shell pwd)/../doc/r2yara.7 $(MANDIR)/man7/r2yara.7 40 | 41 | uninstall: 42 | rm -f ${R2_LIBR_PLUGINS_DIR}/$(MOD).$(LIBEXT) 43 | rm -rf $(R2_LIBR_PLUGINS_DIR)/$(RULESDIR) 44 | rm -f $(MANDIR)/man7/r2yara.7 45 | 46 | user-uninstall: 47 | rm -f ${R2PM_USRPLUGIN_DIR}/$(MOD).$(LIBEXT) 48 | rm -rf $(R2PM_USRPLUGIN_DIR)/$(RULESDIR) 49 | -------------------------------------------------------------------------------- /yara-r2-module/generate_report.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import subprocess 3 | import json 4 | import sys 5 | 6 | def rabin2_call(binary): 7 | """ 8 | rabin2 9 | -i imports 10 | -U resoUrces 11 | -S sections 12 | -E globally exportable symbols 13 | -I binary info 14 | -l linked libraries 15 | -j output in json 16 | """ 17 | args = ["rabin2", "-iUSEIlj", binary] 18 | 19 | value, _ = subprocess.Popen(args, stdout = subprocess.PIPE).communicate() 20 | try: 21 | #print value 22 | value = json.loads(value.replace('\n', ' ')) 23 | except Exception, why: 24 | print "Cannot generate bin information with rabin2 rahash2, reason: {}".format(why) 25 | print why 26 | value = {} 27 | return value 28 | 29 | def rahash2_call(binary): 30 | args = ["rahash2", "-a", "all", "-j", binary] 31 | 32 | value, _ = subprocess.Popen(args, stdout = subprocess.PIPE).communicate() 33 | try: 34 | value = json.loads(value.replace('\n', ' ')) 35 | except Exception, why: 36 | print "Cannot generate hashes with rahash2, reason: {}".format(why) 37 | value = {} 38 | return value 39 | 40 | def main(): 41 | rabin2_json = rabin2_call(sys.argv[1]) 42 | rahash2_json = rahash2_call(sys.argv[1]) 43 | rabin2_json['hash'] = rahash2_json 44 | print json.dumps(rabin2_json) 45 | 46 | 47 | if __name__ == '__main__': 48 | main() -------------------------------------------------------------------------------- /yara-r2-module/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017. The r2yara authors. All Rights Reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without modification, 4 | are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation and/or 11 | other materials provided with the distribution. 12 | 13 | 3. Neither the name of the copyright holder nor the names of its contributors 14 | may be used to endorse or promote products derived from this software without 15 | specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 21 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 24 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /yara-r2-module/README.md: -------------------------------------------------------------------------------- 1 | # R2Yara module 2 | 3 | This directory contains the source code for the r2 yara module. 4 | 5 | By importing this module in your yara rules it is possible to use `radare2` to perform some advanced checks on the target binary. 6 | 7 | ## Author 8 | 9 | This yara plugin was made in 2017 by @plutec and @mmorenog, see [ChangeLog.orig](ChangeLog.orig) the original commit history. 10 | 11 | * Antonio Sanchez @plutec 12 | * mmorenog @mmorenog 13 | 14 | ## Example 15 | 16 | This is a very simple rule, but you can find more under the `rules` directory. 17 | 18 | ``` 19 | import "r2" 20 | rule rule_intel_programs { 21 | condition: 22 | r2.bins("x86", 64) 23 | } 24 | ``` 25 | 26 | Note that right now, this module is just a JSON-like processor, that takes a report generated with an r2pipe script which is then feeded to yara like this: 27 | 28 | ``` 29 | $ ./generate_report.py binary > report.json 30 | $ yara -x r2=report.json file.yar binary 31 | ``` 32 | 33 | ## TODO 34 | 35 | Note that this repository contains a copy of the original https://github.com/Yara-Rules/r2yara repository, which was not updated since 2017. So there are a bunch of things to improve. Moving the code under the `radareorg` umbrella is the first step towards this. 36 | 37 | * [ ] Bring back the tests, but using r2r and don't use commited files 38 | * [ ] Run r2 from inside yara, instead of depending on a JSON file 39 | * [ ] Sync the code for the latest Yara (this module requires yara-3.6.3) 40 | * [ ] Add makefile to simplify the use 41 | 42 | ## Documentation 43 | 44 | Read the documentation and examples of use: 45 | 46 | => http://r2yara.readthedocs.io/en/latest/ 47 | 48 | [![Build Status](https://travis-ci.org/Yara-Rules/r2yara.svg)](https://travis-ci.org/Yara-Rules/r2yara) 49 | 50 | [![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) 51 | 52 | -------------------------------------------------------------------------------- /yara-r2-module/doc/r2yara/sections.md: -------------------------------------------------------------------------------- 1 | #Sections 2 | As usual, there are 2 ways to look for sections in a binary. The easy way is using functions: 3 | 4 | ##Functions 5 | ``` 6 | r2.section(name, flag) 7 | ``` 8 | 9 | Each parameter could be string or regex. In case any parameter is indiferent for you, can use empty string "", for instance: 10 | 11 | We can search binaries with any section name called "dhscf" and doesn't matter flags: 12 | ``` 13 | r2.section("dhscf", "") 14 | ``` 15 | 16 | #Array 17 | The second way is using array of sections with the following fields: 18 | 19 | ``` 20 | name: string 21 | flags: string 22 | size: integer 23 | vsize: integer 24 | paddr: integer 25 | ``` 26 | 27 | To explain the array, we want to look for apps with a section size > 28KB, "writeable and executable" and which name contains "test", so, we need to iterate over the array checking those values: 28 | 29 | ``` 30 | rule sections { 31 | condition: 32 | for any i in ( 0..r2.number_of_sections ) : 33 | (r2.sections[i].size > 28KB and 34 | r2.sections[i].flags contains "r-x" and 35 | r2.sections[i].name contains "text") 36 | } 37 | ``` 38 | 39 | ##Examples 40 | 41 | Some Yara rules examples we can generate: 42 | 43 | Rule to looking for sections writables with “.text” name and size > 28KB 44 | ```sh 45 | import "r2" 46 | rule sections { 47 | Condition: 48 | for any i in ( 0..r2.number_of_sections ) : 49 | (r2.sections[i].size > 28KB and 50 | r2.sections[i].flags contains "-w-" and 51 | r2.sections[i].name contains "text") } 52 | ``` 53 | 54 | We can to be interested in calculate the entropy by sections, and for example we can write a rule like this: 55 | ```sh 56 | import "r2" 57 | import "math" 58 | 59 | rule rule_sections_entropy_s 60 | { 61 | condition: 62 | for any i in ( 0..r2.number_of_sections ) : 63 | (r2.sections[i].name contains "note.ABI_tag" and 64 | math.entropy(r2.sections[i].paddr, 65 | r2.section_array[i].size) > 1.5) 66 | } 67 | 68 | ``` -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project( 2 | 'r2yara', 3 | ['c'], 4 | license : 'LGPL3', 5 | meson_version : '>=0.50.1', 6 | version : '1.2.0' 7 | ) 8 | 9 | r2yara_sources = [ 10 | 'src/core_r2yara.c', 11 | ] 12 | 13 | incdirs = [ 14 | 'src', 15 | ] 16 | 17 | res = run_command(['radare2','-HR2_LIBR_PLUGINS'], capture:true, check:false) 18 | if res.returncode() == 0 19 | r2_plugdir = res.stdout().strip() 20 | else 21 | prefix = get_option('prefix') 22 | r2_plugdir = prefix + '/lib/radare2/plugins' 23 | endif 24 | 25 | add_global_arguments('-DR2Y_VERSION="1.1.2"', language:'c') 26 | c = meson.get_compiler('c') 27 | if c.get_id() == 'msvc' 28 | incdirs += [ 29 | 'radare2/include/libr', 30 | 'radare2/include/libr/sdb', 31 | ] 32 | add_global_arguments('-D_WINDOWS', language:'c') 33 | r2libdir = [ 34 | meson.current_source_dir() + '\\radare2\\lib', 35 | 'C:\\radare2\\lib' 36 | ] 37 | r_core = [ 38 | c.find_library('r_core', dirs: r2libdir), 39 | c.find_library('r_io', dirs: r2libdir), 40 | c.find_library('r_bin', dirs: r2libdir), 41 | c.find_library('r_cons', dirs: r2libdir), 42 | c.find_library('r_asm', dirs: r2libdir), 43 | c.find_library('r_esil', dirs: r2libdir), 44 | c.find_library('r_arch', dirs: r2libdir), 45 | c.find_library('r_flag', dirs: r2libdir), 46 | c.find_library('r_reg', dirs: r2libdir), 47 | c.find_library('r_util', dirs: r2libdir), 48 | c.find_library('r_anal', dirs: r2libdir), 49 | c.find_library('r_config', dirs: r2libdir), 50 | ] 51 | else 52 | r_core = dependency('r_core') 53 | endif 54 | libyara = dependency('yara') 55 | 56 | r2yara_incdirs = include_directories(incdirs) 57 | 58 | r2yara_core_sources = [ 59 | r2yara_sources, 60 | 'src/core_r2yara.c' 61 | ] 62 | 63 | threads = dependency('threads') 64 | 65 | r2yara_core_plugin = library('core_r2yara', 66 | r2yara_core_sources, 67 | dependencies: [r_core, libyara, threads], 68 | link_args: ['-lm'], 69 | include_directories: r2yara_incdirs, 70 | install: true, 71 | install_dir: r2_plugdir 72 | ) 73 | -------------------------------------------------------------------------------- /yara-r2-module/doc/r2yara/info.md: -------------------------------------------------------------------------------- 1 | #Info 2 | 3 | 4 | Rabin2 generates some information about the binary like compiled timestamp, if it has overlay or canary protection, the command used in r2 to extract this information is **iI**. The complete list of values is: 5 | 6 | - havecode (integer) 7 | - pic (integer) 8 | - canary (integer) 9 | - nx (integer) 10 | - crypto (integer) 11 | - va (integer) 12 | - intrp (string) 13 | - bintype (string) 14 | - class (string) 15 | - lang (string) 16 | - arch (string) 17 | - bits (integer) 18 | - machine (integer) 19 | - os (string) 20 | - minopsz (integer) 21 | - maxopsz (integer) 22 | - pcalign (integer) 23 | - subsys (string) 24 | - endian (string) 25 | - stripped (integer) 26 | - static (integer) 27 | - linenum (integer) 28 | - lsyms (integer) 29 | - relocs (integer) 30 | - binsz (integer) 31 | - rpath (string) 32 | - compiled (string) 33 | - dbg_file (string) 34 | - guid (string) 35 | 36 | Almost the parameters are auto-descriptived, so, with an example it's enough to undestand the parameters: 37 | 38 | ``` 39 | rule rule_info 40 | { 41 | condition: 42 | r2.info.havecode == 1 and 43 | r2.info.pic == 0 and 44 | r2.info.canary == 1 and 45 | r2.info.nx == 1 and 46 | r2.info.crypto == 0 and 47 | r2.info.va == 1 and 48 | r2.info.intrp contains "linux-x86" and 49 | r2.info.bintype == "elf" and 50 | r2.info.class contains "ELF64" and 51 | r2.info.lang == "c" and 52 | r2.info.arch == "x86" and 53 | r2.info.bits == 64 and 54 | r2.info.machine == "AMD x86-64 architecture" and 55 | r2.info.os == "linux" and 56 | r2.info.minopsz == 1 and 57 | r2.info.maxopsz == 16 and 58 | r2.info.pcalign == 0 and 59 | r2.info.subsys == "linux" and 60 | r2.info.endian == "little" and 61 | r2.info.stripped == 1 and 62 | r2.info.static == 0 and 63 | r2.info.linenum == 0 and 64 | r2.info.lsyms == 0 and 65 | r2.info.relocs == 0 and 66 | r2.info.binsz > 100000 and 67 | r2.info.rpath == "NONE" and 68 | r2.info.compiled != "Sat Sep 9 11:32:42 2006" and 69 | r2.info.dbg_file not contains "test" and 70 | r2.info.guid == "" 71 | } 72 | ``` -------------------------------------------------------------------------------- /yara-r2-module/doc/installation/installation.md: -------------------------------------------------------------------------------- 1 | These instructions detailed the steps to install al the requirements to use this module. 2 | 3 | # Install radare2 4 | The first step is download & install radare2: 5 | 6 | ```sh 7 | git clone https://github.com/radare/radare2 8 | cd radare2 9 | sys/install.sh # just run this script to update r2 from git 10 | ``` 11 | 12 | # Download Yara 13 | You must download the last version of Yara from GitHub: 14 | 15 | [https://github.com/VirusTotal/yara/releases](https://github.com/VirusTotal/yara/releases) 16 | 17 | and uncompress for instance in your home folder (/home/user/yara) 18 | 19 | # Integrate r2yara inside Yara 20 | This is the "complicated" part of the installation, you need to include the file r2.c inside Yara, modify some files and compile all. But better step by step: 21 | 22 | 1. Download r2.c from our repo [https://github.com/Yara-Rules/r2yara/blob/master/r2.c](https://github.com/Yara-Rules/r2yara/blob/master/r2.c) to libyara/modules/ 23 | 2. Modify "libyara/modules/module_list" and add r2 module in the Cuckoo block. The file should look similar to: 24 | 25 | ``` 26 | MODULE(pe) 27 | MODULE(elf) 28 | MODULE(math) 29 | 30 | #ifdef CUCKOO 31 | MODULE(cuckoo) 32 | MODULE(r2) 33 | #endif 34 | ``` 35 | 36 | 3. Modify "libyara/Makefile.am" to add r2 module in the Cuckoo block: 37 | 38 | ``` 39 | MODULES = modules/tests.c 40 | MODULES += modules/pe.c 41 | [...] 42 | 43 | if CUCKOO_MODULE 44 | MODULES += modules/cuckoo.c 45 | MODULES += modules/r2.c 46 | endif 47 | ``` 48 | 49 | 4. Define the simbol DOLLAR_SIGN in file "configure.ac", at the end of file: 50 | ``` 51 | #Just before AC_OUTPUT 52 | AC_SUBST([DOLLAR_SIGN],[$]) 53 | 54 | AC_OUTPUT 55 | ``` 56 | 57 | 5. Modify "libyara/Makefile.am" to include the flags to compile with r2pipe: 58 | 59 | ``` 60 | AM_CFLAGS=-O3 -Wall -Wno-deprecated-declarations -std=gnu99 -I$(srcdir)/include 61 | #Just after the declaration of AM_CFLAGS include this: 62 | 63 | AM_CFLAGS+=@DOLLAR_SIGN@(shell pkg-config --cflags r_socket) 64 | LIBS += @DOLLAR_SIGN@(shell pkg-config --libs r_socket) 65 | ``` 66 | 67 | 6. Include more flags in "Makefile.am", just in the end of file: 68 | ``` 69 | AM_CFLAGS += @DOLLAR_SIGN@(shell pkg-config --cflags r_socket) 70 | LIBS += @DOLLAR_SIGN@(shell pkg-config --libs r_socket) 71 | ``` 72 | 73 | 7. Compile Yara... 74 | ```sh 75 | ./bootstrap.sh 76 | ./configure --enable-cuckoo 77 | make 78 | sudo make install 79 | ``` 80 | 81 | 8. Enjoy! 82 | ```sh 83 | cd r2yara_folder && ./launch_tests.py 84 | ``` 85 | -------------------------------------------------------------------------------- /doc/r2yara.7: -------------------------------------------------------------------------------- 1 | .Dd Apr 15, 2024 2 | .Dt R2YARA 7 3 | .Sh NAME 4 | .Nm r2yara 5 | .Nd Yara plugin for radare2 6 | .Sh SYNOPSIS 7 | .Nm yr 8 | .Op Fl stv?-* 9 | .Op [args] ... 10 | .Sh DESCRIPTION 11 | This is a plugin for radare2, not available as a shell command. 12 | .Pp 13 | Yara is a pattern matching rule scanner tool that is widely used by the malware analysis community. 14 | This plugin is available via r2pm `r2pm -ci r2yara` and it doesn't depend on any yara system installation because it will build and statically link it. 15 | .Pp 16 | r2yara is a plugin for radare2 that adds the 'yr' command. 17 | .Sh SUBCOMMANDS 18 | .Bl -tag -width Fl 19 | .It Fl yr Ar [file] 20 | List loaded rules or load a new one if a file is passed as argument 21 | .It Fl yrs 22 | Scan in current memory for loaded rules 23 | .It Fl yrt 24 | List loaded yara tags 25 | .It Fl yrv 26 | Show version information 27 | .Sh YARA RULES 28 | .Pp 29 | This is a sample yara rule 30 | .Pp 31 | rule HelloWorld : foo { 32 | meta: 33 | author = "pancake" 34 | description = "hello world" 35 | date = "2023-10" 36 | version = "0.1" 37 | strings: 38 | $ = "lib" 39 | condition: 40 | all of them 41 | } 42 | .Pp 43 | .Sh USAGE 44 | Available variable types are: 45 | .Pp 46 | [0x00000000]> yr? 47 | Usage: yr [action] [args..] load and run yara rules inside r2 48 | | yr [file] add yara rules from file 49 | | yr-* unload all the rules 50 | | yr? show this help (same as 'yara?') 51 | | yr list loaded rules 52 | | yrs[S] scan the current file, if S option is given it prints matching strings 53 | | yrt list tags from the loaded rules 54 | | yrt [tagname] list rules with given tag 55 | | yrv show version information about r2yara and yara 56 | [0x00000000]> q 57 | .Pp 58 | .Sh EXAMPLES 59 | Some usage examples: 60 | .Pp 61 | $ radare2 /bin/ls 62 | > yr hello.yara # load this rule 63 | > yrs # scan for all the loaded rules 64 | HelloWorld 65 | 0x000045f9: yara0.HelloWorld_0 : 6c6962 66 | 0x00004685: yara0.HelloWorld_1 : 6c6962 67 | 0x00004689: yara0.HelloWorld_2 : 6c6962 68 | 0x00004693: yara0.HelloWorld_3 : 6c6962 69 | 0x000046b5: yara0.HelloWorld_4 : 6c6962 70 | 0x000046b9: yara0.HelloWorld_5 : 6c6962 71 | 0x000046ca: yara0.HelloWorld_6 : 6c6962 72 | 0x000046ed: yara0.HelloWorld_7 : 6c6962 73 | 0x000046f1: yara0.HelloWorld_8 : 6c6962 74 | 0x000046ff: yara0.HelloWorld_9 : 6c6962 75 | .Pp 76 | Show version information of r2, yara and r2yara: 77 | .Pp 78 | [0x100003a84]> yrv 79 | r2 5.9.1 80 | yara 4.5.0 81 | r2yara 1.2.0 82 | .Pp 83 | .Sh SEE ALSO 84 | .Pp 85 | .Xr radare2(1) 86 | .Sh WWW 87 | .Pp 88 | https://www.radare.org 89 | .Sh AUTHORS 90 | .Pp 91 | Written by pancake . 92 | -------------------------------------------------------------------------------- /test/db/extras/yara: -------------------------------------------------------------------------------- 1 | NAME=yara: list 2 | FILE=malloc://1024 3 | CMDS=< yr? 24 | Usage: yr [action] [args..] load and run yara rules inside r2 25 | | yr [file] add yara rules from file 26 | | yr same as yr? 27 | | yr-* unload all the rules 28 | | yr? show this help (same as 'yara?') 29 | | yrg[?][-sx] generate yara rule 30 | | yrl list loaded rules 31 | | yrs[q] scan the current file, suffix with 'q' for quiet mode 32 | | yrt ([tagname]) list tags from loaded rules, or list rules from given tag 33 | | yrv show version information about r2yara and yara 34 | ``` 35 | 36 | See `man 7 r2yara` for some examples. 37 | 38 | ### Yara generator usage 39 | 40 | r2yara allows the creation of YARA rules directement inside radare2. 41 | 42 | **Commands Overview** 43 | 44 | ```bash 45 | [0x100003a84]> yrg? 46 | Usage: yrg [action] [args..] load and run yara rules inside r2 47 | | yrg- delete last pattern added to the yara rule 48 | | yrg-* delete all the patterns in the current rule 49 | | yrgs ([len]) add string (optionally specify the length) 50 | | yrgx ([len]) add hexpairs of blocksize (or custom length) 51 | | yrgf ([len]) add function bytepattern signature 52 | | yrgz add all strings referenced from current function 53 | ``` 54 | 55 | To start using r2yara to create YARA rules automatically, follow these steps: 56 | 57 | **Generate a YARA rule:** 58 | 59 | ``` 60 | [0x100003a84]> yrg 61 | WARN: See 'yrg?' to find out which subcommands use to append patterns to the rule 62 | rule rulename : test { 63 | meta: 64 | author = "user" 65 | description = "My first yara rule" 66 | date = "2024-10-22" 67 | version = "0.1" 68 | } 69 | ``` 70 | 71 | This shows the current YARA rule. 72 | 73 | **Add strings from the binary as patterns:** 74 | 75 | ``` 76 | [0x100003a84]> yrgs 77 | ``` 78 | 79 | **Add hex patterns:** 80 | 81 | ``` 82 | [0x100003a84]> yrgx 83 | ``` 84 | 85 | **Optionally, add function signatures:** 86 | 87 | ``` 88 | [0x100003a84]> yrgf 89 | ``` 90 | 91 | **Once you've added the desired patterns, add the currently generated yara rule:** 92 | 93 | ``` 94 | [0x100003a84]> yr+ 95 | [0x100003a84]> yrl 96 | rulename 97 | ``` 98 | 99 | Then the rule can be used directly as any other rules. 100 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Makefile 2 | clang-log/ 3 | .clang_complete 4 | .tmp-format 5 | .#* 6 | *._d 7 | *._o 8 | *.[ado] 9 | *.so 10 | *.pc 11 | *.sdb 12 | *.dylib 13 | *.dll 14 | *.lib 15 | *.obj 16 | *.ilk 17 | *.dSYM 18 | supported.* 19 | config.mk 20 | plugins.cfg 21 | langs.cfg 22 | .test.c 23 | .*.swp 24 | .*.swo 25 | *.un~ 26 | *.pdb 27 | *.lib 28 | *.ilk 29 | binr/r2agent/r2agent 30 | binr/r2agent/r2agent.exe 31 | binr/rvc2/rvc2 32 | binr/rvc2/rvc2.exe 33 | binr/ravc2/ravc2 34 | binr/ravc2/ravc2.exe 35 | binr/r2r/r2r 36 | binr/r2r/r2r.exe 37 | binr/rabin2/rabin2 38 | binr/rabin2/rabin2.exe 39 | binr/radare2/radare2 40 | binr/radare2/radare2.exe 41 | binr/radiff2/radiff2 42 | binr/radiff2/radiff2.exe 43 | binr/rafind2/rafind2 44 | binr/rafind2/rafind2.exe 45 | binr/ragg2/ragg2 46 | binr/ragg2/ragg2.exe 47 | binr/rahash2/rahash2 48 | binr/rahash2/rahash2.exe 49 | binr/ranal2/ranal2 50 | binr/ranal2/ranal2.exe 51 | binr/rarun2/rarun2 52 | binr/rarun2/rarun2.exe 53 | binr/rasm2/rasm2 54 | binr/rasm2/rasm2.exe 55 | binr/rax2/rax2 56 | binr/rax2/rax2.exe 57 | binr/r2pm/r2pm 58 | binr/r2pm/r2pm.exe 59 | binr/*/_CodeSignature/* 60 | build 61 | build_sdb 62 | config-user.mk 63 | libr/bin/d/dll/dll 64 | libr/config.h 65 | libr/include/r_userconf.h 66 | libr/include/r_version.h 67 | libr/include/r_version.h.tmp 68 | libr/arch/p/arm/v35/arch-arm64 69 | libr/arch/p/arm/v35/arch-armv7 70 | shlr/capstone/ 71 | shlr/java/out 72 | shlr/java/out.exe 73 | shlr/sdb/sdb 74 | shlr/sdb/sdb.exe 75 | shlr/sdb/src/sdb 76 | shlr/sdb/src/.sdb 77 | shlr/sdb/src/sdb.exe 78 | shlr/sdb/src/.sdb.exe 79 | shlr/sdb/include/sdb/version.h 80 | shlr/sdb/src/sdb-version.h 81 | shlr/sdb/src/sdb_version.h 82 | shlr/sdb/include/sdb/version.h 83 | shlr/sdb/src/libsdb.so* 84 | shlr/spp/config.h 85 | shlr/.cs_tmp.zip 86 | sys/travis/*.txt 87 | sys/.mark_python-deps 88 | sys/.mark_swig 89 | sys/_work 90 | radare2-bindings 91 | radare2-regressions 92 | radare2-w32-* 93 | radare2-w64-* 94 | tags 95 | **/GPATH 96 | **/GRTAGS 97 | **/GTAGS 98 | **/.gdb_history 99 | .lvimrc 100 | .nconfig.tmp 101 | .ycm_extra_conf.py 102 | .ycm_extra_conf.pyc 103 | .kdev4/* 104 | *.kdev4 105 | radare2-*.zip 106 | # Ignore meson related files 107 | ./bin 108 | ninja.exe 109 | .DS_Store 110 | infer_out 111 | infer-out/ 112 | cscope.out 113 | r2-static/* 114 | binr/rasign2/rasign2 115 | binr/rasign2/rasign2.exe 116 | compile_commands.json 117 | libr/flag/d/tags.r2 118 | # CLion 119 | .idea/ 120 | # VSCode 121 | .vscode/ 122 | CMakeLists.txt 123 | *.cmake 124 | cmake-build-* 125 | # Snap packaging 126 | /parts 127 | /prime 128 | /stage 129 | /snap 130 | /*.snap 131 | # doxygen autogen 132 | doc/doxygen/html 133 | # Python 134 | __pycache__ 135 | # Dynamic docker building folder to minimize docker context 136 | .docker_alpine 137 | .ccls-cache/ 138 | vgcore.* 139 | libr/include/sdb 140 | **/d/*.c 141 | **/d/*.h 142 | **/d/*.gperf 143 | **/d/*.out 144 | **/d/*.inc 145 | **/d/*.sdb.txt.tmp 146 | # Artifacts 147 | /dist/artifacts 148 | # libFuzzer 149 | crash-* 150 | corpus* 151 | -------------------------------------------------------------------------------- /yara-r2-module/doc/use_cases.md: -------------------------------------------------------------------------------- 1 | # Use Cases 2 | > ## Side effects of Packing 3 | 4 | Packed and obfuscated code will often include at least the functions LoadLibrary and GetProcAddress, which are used to load and gain Access to additional functions. The section sizes can be useful in detecting packed executables. For example, if the Vsize is much larger than the size of raw data, you know that the section takes up more space in memory than it does on disk. This is often indicative of packed code, particularly if the .text section is larger in memory than on disk and marked as code/executable (reference = "Practical Malware Analysis. BlackHat. Kris Kendall and Chad McMillan. Page 52") 5 | 6 | To model a behaviour of packed/obfuscated code, for example, we can build rules like this (it's only an approach): 7 | ``` 8 | import "r2" 9 | import "math" 10 | 11 | rule difference_size_and_vsize { 12 | meta: 13 | description = "Rule to detect binaries with a big difference between section size and section vsize (after unpack). Also, it includes a big entropy and executable flags" 14 | author = "@plutec_net, @mmorenog" 15 | reference = "Practical Malware Analysis. BlackHat. Kris Kendall and Chad McMillan. Page 52" 16 | 17 | condition: 18 | for any i in ( 0..r2.number_of_sections ) : 19 | ((r2.section[i].vsize > r2.section[i].size*2) and 20 | r2.section[i].flags contains "x" and 21 | math.entropy(r2.section[i].paddr, r2.section[i].size) > 7) 22 | 23 | } 24 | 25 | ``` 26 | > ## Potential keylogger 27 | 28 | Detection of an hypothetical keylogger behaviour looking for “exports” symbols like: LowLevelKeyboardProc, LoveLevelMouseProc, functions like: SetWindowsHookEx, RegisterHotKey and string “Software\Microsoft\Windows\CurrentVersion\Run” usually found in malware. 29 | 30 | ``` 31 | import "r2" 32 | 33 | rule potential_keylogger { 34 | 35 | meta: 36 | description = "Rule to detect a potential keylogger" 37 | author = "@plutec_net, @mmorenog" 38 | reference "Practical Malware Analysis (book), page 18" 39 | 40 | strings: 41 | $autorun = "Software\\Microsoft\\Windows\\CurrentVersion\\Run" wide ascii 42 | 43 | condition: 44 | r2.import(-1,"", "SetWindowsHookEx") and 45 | r2.import(-1,"", "RegisterHotKey") and 46 | r2.symbol("LowLevelKeyboardProc","") and 47 | r2.symbol("LowLevelMouseProc","") and 48 | $autorun 49 | 50 | } 51 | ``` 52 | > ## UPX Packer Example 53 | 54 | UPX packer is defined for 2 sections (UPX0 and UPX1), and it's so easy detect them with this module: 55 | 56 | ``` 57 | import "r2" 58 | 59 | rule UPX { 60 | 61 | strings: 62 | $upx = "UPX" 63 | 64 | condition: 65 | r2.section("UPX0","") and 66 | r2.section("UPX1","") and 67 | $upx 68 | 69 | } 70 | ``` 71 | > ## Resources & Languages 72 | 73 | At this point we can look for certain resources. For instance, a resource “STRING” with “LANG_RUSSIAN” or “LANG_CHINESE” as language: 74 | ``` 75 | import "r2" 76 | 77 | rule res_string_jap { 78 | condition: 79 | r2.resource("STRING", "LANG_RUSSIAN") or 80 | r2.resource("STRING", "LANG_CHINESE") 81 | } 82 | ``` 83 | 84 | Or increase the complexity using size (>2KB): 85 | ``` 86 | import "r2" 87 | 88 | rule resource { 89 | condition: 90 | for any i in ( 0..r2.number_of_resources ) : 91 | (r2.resources[i].size > 2KB and 92 | r2.resources[i].type == "STRING" and 93 | r2.resources[i].lang contains "RUSSIAN" or 94 | r2.resources[i].lang contains "CHINESE") 95 | 96 | } 97 | ``` 98 | -------------------------------------------------------------------------------- /yara-r2-module/dist/yara-3.6.3/libyara/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | MODULES = modules/tests.c 3 | MODULES += modules/pe.c 4 | MODULES += modules/elf.c 5 | MODULES += modules/math.c 6 | 7 | if CUCKOO_MODULE 8 | MODULES += modules/cuckoo.c 9 | MODULES += modules/r2.c 10 | endif 11 | 12 | if MAGIC_MODULE 13 | MODULES += modules/magic.c 14 | endif 15 | 16 | if HASH_MODULE 17 | MODULES += modules/hash.c 18 | endif 19 | 20 | if DOTNET_MODULE 21 | MODULES += modules/dotnet.c 22 | endif 23 | 24 | # This isn't really a module, but needs to be compiled with them. 25 | MODULES += modules/pe_utils.c 26 | 27 | # 28 | # Add your modules here: 29 | # 30 | # MODULES += modules/yourmodule.c 31 | # 32 | 33 | AM_YFLAGS=-d 34 | 35 | AM_CFLAGS=-Wall -Wno-deprecated-declarations -std=gnu99 -I$(srcdir)/include 36 | 37 | AM_CFLAGS+=@DOLLAR_SIGN@(shell pkg-config --cflags r_socket) 38 | LIBS += @DOLLAR_SIGN@(shell pkg-config --libs r_socket) 39 | 40 | if DEBUG 41 | AM_CFLAGS+=-g 42 | endif 43 | 44 | if OPTIMIZATION 45 | AM_CFLAGS+=-O3 46 | else 47 | AM_CFLAGS+=-O0 48 | endif 49 | 50 | if ADDRESS_SANITIZER 51 | AM_CFLAGS+=-fsanitize=address 52 | endif 53 | 54 | if GCC 55 | AM_CFLAGS+=-fvisibility=hidden 56 | endif 57 | 58 | ACLOCAL_AMFLAGS=-I m4 59 | 60 | include_HEADERS = include/yara.h 61 | 62 | yaraincludedir = $(includedir)/yara 63 | yarainclude_HEADERS = \ 64 | include/yara/ahocorasick.h \ 65 | include/yara/atoms.h \ 66 | include/yara/limits.h \ 67 | include/yara/re.h \ 68 | include/yara/arena.h \ 69 | include/yara/sizedstr.h \ 70 | include/yara/types.h \ 71 | include/yara/hash.h \ 72 | include/yara/exec.h \ 73 | include/yara/scan.h \ 74 | include/yara/rules.h \ 75 | include/yara/error.h \ 76 | include/yara/utils.h \ 77 | include/yara/filemap.h \ 78 | include/yara/compiler.h \ 79 | include/yara/modules.h \ 80 | include/yara/object.h \ 81 | include/yara/strutils.h \ 82 | include/yara/stream.h \ 83 | include/yara/threading.h \ 84 | include/yara/integers.h \ 85 | include/yara/libyara.h 86 | 87 | lib_LTLIBRARIES = libyara.la 88 | 89 | libyara_la_LDFLAGS = -version-number 3:6:0 90 | 91 | BUILT_SOURCES = \ 92 | lexer.c \ 93 | hex_lexer.c \ 94 | re_lexer.c \ 95 | grammar.c \ 96 | hex_grammar.c \ 97 | re_grammar.c 98 | 99 | libyara_la_SOURCES = \ 100 | $(MODULES) \ 101 | grammar.y \ 102 | ahocorasick.c \ 103 | arena.c \ 104 | atoms.c \ 105 | compiler.c \ 106 | endian.c \ 107 | exec.c \ 108 | exefiles.c \ 109 | exefiles.h \ 110 | filemap.c \ 111 | filemap.h \ 112 | hash.c \ 113 | hash.h \ 114 | hex_grammar.y \ 115 | hex_lexer.l \ 116 | lexer.l \ 117 | libyara.c \ 118 | mem.c \ 119 | mem.h \ 120 | modules.c \ 121 | modules.h \ 122 | object.c \ 123 | object.h \ 124 | parser.c \ 125 | parser.h \ 126 | pe.h \ 127 | proc.c \ 128 | proc.h \ 129 | re.c \ 130 | re.h \ 131 | re_grammar.y \ 132 | re_lexer.l \ 133 | rules.c \ 134 | scan.c \ 135 | sizedstr.c \ 136 | sizedstr.h \ 137 | strutils.c \ 138 | strutils.h \ 139 | stream.c \ 140 | stream.h \ 141 | threading.c \ 142 | threading.h \ 143 | utils.h 144 | 145 | pkgconfigdir = $(libdir)/pkgconfig 146 | nodist_pkgconfig_DATA = yara.pc 147 | 148 | yara.pc: yara.pc.in 149 | sed -e 's![@]prefix[@]!$(prefix)!g' \ 150 | -e 's![@]exec_prefix[@]!$(exec_prefix)!g' \ 151 | -e 's![@]includedir[@]!$(includedir)!g' \ 152 | -e 's![@]libdir[@]!$(libdir)!g' \ 153 | -e 's![@]PACKAGE_VERSION[@]!$(PACKAGE_VERSION)!g' \ 154 | $(srcdir)/yara.pc.in > $@ 155 | -------------------------------------------------------------------------------- /yara-r2-module/doc/index.md: -------------------------------------------------------------------------------- 1 | # Radare2 module for Yara 2 | 3 | From [YaraRules Project](http://yararules.com/) we would like to introduce you a new Yara module that pretends to use information retrieved from radare2 (r2) to use with Yara. 4 | 5 | To use this module it is important to know basic concepts about r2 and Yara. 6 | 7 | 8 | ## Yara Modules 9 | 10 | Modules are the way Yara provides for extending its features. They allow to define data structures and functions which can be used in your rules to express more complex conditions. There’re some modules (PE, ELF, Cuckoo, Math, etc.) officially distributed with Yara, but you can also write your own modules. 11 | 12 | ## Radare2 13 | 14 | [Radare2](https://rada.re/r/) is a strong open-source reversing framework that allows -furtherother more functionalities- provides information over executables files that other tools doesn’t have in a direct way and it supports a lot of file format!: ELF, Java Class, Mach-O, COFF, Gameboy, Nintendo Switch bins, SNES roms, WASM, Compiled LUA, PCAP files, etc. 15 | 16 | From YaraRules Project cooked this recipe: 17 | 18 | Radare2 versatility + Power of Yara = r2.c (Radare2 module for Yara) 19 | 20 | And we hope you find it interesting :) 21 | 22 | ## Installation 23 | 24 | In the [installation section](https://github.com/Yara-Rules/r2yara/blob/master/docs/installation/installation.md) you will found detailed instructions about the r2 installation and Yara configuration + installation. 25 | 26 | ## Use 27 | 28 | There’re two ways to use r2.c: 29 | 30 | * First way to use r2.c is passing Json report generated with `generate_report.py` that use radare2. This is the quickly way to use with a lot amount samples, because you can **generate the report one time and use whenever you want**. 31 | 32 | ```sh 33 | $ ./generate_report.py binary > report.json 34 | $ yara -x r2=report.json file.yar binary 35 | ``` 36 | 37 | * Second way is invoking automatically Radare2 from Yara. This method is recommendable to use manually. One of the powers of Yara, the speed, is considerably decreased using this method, but is very userful to quick tests. 38 | 39 | ```sh 40 | $ yara file.yar binary 41 | ``` 42 | ## What radare2 information can be used with the module? 43 | 44 | We can write Yara rules with a lot of information from [rabin2](https://radare.gitbooks.io/radare2book/content/rabin2/intro.html) and [rahash2](https://radare.gitbooks.io/radare2book/content/rahash2/intro.html). 45 | 46 | Rabin2 is a powerful tool from radare2 framework to handle binary files, to get information on "imports", "sections", "exports", list archs, headers fields, binary info, libraries, etc. 47 | 48 | With Rahash2 we can calculate a checksum with a lot of different 49 | Algorithms: md5, sha1, sha256, sha384, sha512, crc16, crc32, md4, xor, xorpair, parity, entropy, hamdist, pcprint, mod255, xxhash...etc. 50 | 51 | ## Feedback and Contribution 52 | 53 | Your feedback is highly appreciated!!! Please, If you’re interested in contributing with us, ask a question or sharing your Yara rules with us and Security Community, you can send a message to our Twitter account @YaraRules, or submit a pull request or issue on any of our Github Repository. 54 | 55 | Our module is under the GNU-GPLv2 license. It’s open to any user or organization, as long as you use it under this license 56 | 57 | ## Thanks 58 | 59 | Thanks for all the people that give us feedback during the development, specially: 60 | 61 | - [@pancake](https://twitter.com/trufae) and other r2 contributors 62 | - [@newlog](https://twitter.com/Newlog_) 63 | - [@plusvic](https://twitter.com/plusvic) 64 | 65 | # Authors 66 | 67 | - [@plutec_net](https://twitter.com/plutec_net) 68 | - [@mmorenog](https://twitter.com/mmorenog) 69 | -------------------------------------------------------------------------------- /dist/debian/deb.mk: -------------------------------------------------------------------------------- 1 | # Create .deb without using dpkg tools. 2 | # 3 | # Author: Tim Wegener 4 | # 5 | # Use 'include deb_hand.mak' after defining the user variables in a local 6 | # makefile. 7 | # 8 | # The 'data' rule must be customised in the local make file. 9 | # This rule should make a 'data' directory containing the full file 10 | # layout of the installed package. 11 | # 12 | # This makefile will create a debian-binary file a control directory and a 13 | # a build directory in the current directory. 14 | # Do 'make clobber' to remove these generated files. 15 | # 16 | # Destination: 17 | # PACKAGE_DIR - directory where package (and support files) will be built 18 | # defaults to the current directory 19 | # 20 | # Sources: 21 | # SOURCE_DIR - directory containing files to be packaged 22 | # ICON_SOURCE - 26x26 icon file for maemo 23 | # DESCR - description with summary on first line 24 | # preinst, postinst, prerm, postrm - optional control shell scripts 25 | 26 | # These fields are used to build the control file: 27 | # PACKAGE = 28 | # VERSION = 29 | # ARCH = 30 | # SECTION = 31 | # PRIORITY = 32 | # MAINTAINER = 33 | # DEPENDS = 34 | # 35 | # SOURCE_DIR = 36 | # ICON_SOURCE = 37 | # (ICON_SOURCE is optional) 38 | 39 | # *** NO USER CHANGES REQUIRED BEYOND THIS POINT *** 40 | ifeq ($(shell uname),Darwin) 41 | MD5SUM=md5 42 | else 43 | MD5SUM=md5sum 44 | endif 45 | 46 | GAWK=awk 47 | PACKAGE_DIR=$(shell pwd) 48 | CONTROL_EXTRAS ?= ${wildcard preinst postinst prerm postrm} 49 | 50 | ${PACKAGE_DIR}/control: ${PACKAGE_DIR}/data ${CONTROL_EXTRAS} DESCR \ 51 | ${ICON_SOURCE} 52 | #rm -rf $@ 53 | mkdir -p $@ 54 | ifneq (${CONTROL_EXTRAS},) 55 | cp ${CONTROL_EXTRAS} $@ 56 | endif 57 | # Make control file. 58 | echo "Package: ${PACKAGE}" > $@/control 59 | echo "Version: ${VERSION}" >> $@/control 60 | echo "Section: ${SECTION}" >> $@/control 61 | echo "Priority: ${PRIORITY}" >> $@/control 62 | echo "Architecture: ${ARCH}" >> $@/control 63 | ifneq (${DEPENDS},) 64 | echo "Depends: ${DEPENDS}" >> $@/control 65 | endif 66 | echo "Installed-Size: ${shell du -s ${PACKAGE_DIR}/data|cut -f1}" \ 67 | >> $@/control 68 | echo "Maintainer: ${MAINTAINER}" >> $@/control 69 | printf "Description:" >> $@/control 70 | cat DESCR | ${GAWK} '{print " "$$0;}' >> $@/control 71 | #ifneq (${ICON_SOURCE},) 72 | # echo "Maemo-Icon-26:" >> $@/control 73 | # base64 ${ICON_SOURCE} | ${GAWK} '{print " "$$0;}' >> $@/control 74 | #endif 75 | # Make md5sums. 76 | cd ${PACKAGE_DIR}/data && find . -type f -exec ${MD5SUM} {} \; \ 77 | | sed -e 's| \./||' \ 78 | > $@/md5sums 79 | 80 | ${PACKAGE_DIR}/debian-binary: 81 | echo "2.0" > $@ 82 | 83 | ${PACKAGE_DIR}/clean: 84 | rm -rf ${PACKAGE_DIR}/data ${PACKAGE_DIR}/control ${PACKAGE_DIR}/build *.deb 85 | 86 | ${PACKAGE_DIR}/build: ${PACKAGE_DIR}/debian-binary ${PACKAGE_DIR}/control \ 87 | ${PACKAGE_DIR}/data 88 | rm -rf $@ 89 | mkdir $@ 90 | cp ${PACKAGE_DIR}/debian-binary $@/ 91 | cd ${PACKAGE_DIR}/control && tar czvf $@/control.tar.gz * 92 | cd ${PACKAGE_DIR}/data && \ 93 | COPY_EXTENDED_ATTRIBUTES_DISABLE=true \ 94 | COPYFILE_DISABLE=true \ 95 | tar cpzvf $@/data.tar.gz * 96 | 97 | # Convert GNU ar to BSD ar that debian requires. 98 | # Note: Order of files within ar archive is important! 99 | ${PACKAGE_DIR}/${PACKAGE}_${VERSION}_${ARCH}.deb: ${PACKAGE_DIR}/build 100 | ar -rc $@ $ $@fail 102 | #rm -f $@tmp 103 | #mv $@fail $@ 104 | 105 | .PHONY: data 106 | data: ${PACKAGE_DIR}/data 107 | 108 | .PHONY: control 109 | control: ${PACKAGE_DIR}/control 110 | 111 | .PHONY: build 112 | build: ${PACKAGE_DIR}/build 113 | 114 | .PHONY: clean 115 | clean: ${PACKAGE_DIR}/clean $(EXTRA_CLEAN) 116 | rm -f debian-binary 117 | 118 | .PHONY: deb 119 | deb: ${PACKAGE_DIR}/${PACKAGE}_${VERSION}_${ARCH}.deb 120 | 121 | 122 | clobber:: 123 | rm -rf ${PACKAGE_DIR}/debian_binary ${PACKAGE_DIR}/control \ 124 | ${PACKAGE_DIR}/data ${PACKAGE_DIR}/build 125 | 126 | push: 127 | scp *.deb radare.org:/srv/http/radareorg/cydia/debs 128 | 129 | mrproper: clean 130 | rm -rf root 131 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | # TODO: add windows 2 | name: ci 3 | 4 | env: 5 | R2V: 6.0.4 6 | 7 | on: 8 | push: 9 | branches: 10 | - main 11 | pull_request: 12 | workflow_dispatch: 13 | 14 | jobs: 15 | build-linux24: 16 | runs-on: ubuntu-24.04 17 | steps: 18 | - uses: actions/checkout@v5 19 | - name: Installing radare2 20 | run: | 21 | wget "https://github.com/radareorg/radare2/releases/download/${R2V}/radare2_${R2V}_amd64.deb" 22 | wget "https://github.com/radareorg/radare2/releases/download/${R2V}/radare2-dev_${R2V}_amd64.deb" 23 | sudo dpkg -i "radare2_${R2V}_amd64.deb" 24 | sudo dpkg -i "radare2-dev_${R2V}_amd64.deb" 25 | - name: Installing yara via r2pm 26 | run: r2pm -Ui yara 27 | - name: Building with meson 28 | run: | 29 | sudo apt install meson 30 | r2pm -ci ninja 31 | r2pm -r meson b 32 | r2pm -r ninja -C b 33 | - name: Building r2yara 34 | run: | 35 | r2pm -r ./configure 36 | r2pm -r make -j 37 | make user-install 38 | - name: Packaging 39 | run: make -C dist/debian 40 | - name: Pub 41 | uses: actions/upload-artifact@v5 42 | with: 43 | name: build-linux 44 | path: dist/debian/*.deb 45 | build-linux22: 46 | runs-on: ubuntu-22.04 47 | steps: 48 | - uses: actions/checkout@v5 49 | with: 50 | repository: radareorg/radare2 51 | ref: master 52 | path: ./radare2 53 | - name: Installing radare2 54 | run: | 55 | cd radare2 56 | sys/install.sh 57 | - uses: actions/checkout@v5 58 | with: 59 | ref: ${{ github.event.pull_request.head.sha }} 60 | path: ./r2yara 61 | - name: Init r2pm in a local folder 62 | run: | 63 | export R2PM_GITDIR=`pwd` 64 | r2pm -Uci yara 65 | r2pm -i r2yara 66 | - name: Testing r2yara installation 67 | run: R2_DEBUG=1 r2 -qcq -c 'yrv' -- 68 | - name: Running Testsuite 69 | run: | 70 | cd r2yara 71 | r2pm -r make -C test 72 | build-macos: 73 | runs-on: macos-latest 74 | steps: 75 | - uses: actions/checkout@v5 76 | - name: Install dependencies 77 | run: | 78 | brew update 79 | brew install autoconf automake libtool pkg-config bison flex m4 80 | echo "LIBTOOLIZE=$(command -v glibtoolize)" >> "$GITHUB_ENV" 81 | echo "ACLOCAL_PATH=/opt/homebrew/share/aclocal" >> "$GITHUB_ENV" 82 | - name: Building Radare2 from git 83 | run: | 84 | brew install automake autoconf 85 | export CFLAGS=-O0 86 | git clone --branch "${R2V}" --depth=1 https://github.com/radareorg/radare2 && cd radare2 87 | ./configure 88 | make -j && sudo make install 89 | - name: Installing yara via r2pm 90 | run: r2pm -Ui yara 91 | - name: Building r2yara 92 | run: | 93 | r2pm -r ./configure 94 | r2pm -r make -j 95 | make user-install 96 | # - name: Packaging 97 | # run: make -C dist/macos 98 | # - name: Pub 99 | # uses: actions/upload-artifact@v5 100 | # with: 101 | # if-no-files-found: error 102 | # name: build-macos 103 | # path: dist/macos/r2yara-*.pkg 104 | 105 | check_release: 106 | if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} 107 | outputs: 108 | is_release: ${{ steps.release.outputs.is }} 109 | tag_name: ${{ steps.release.outputs.tag }} 110 | needs: 111 | - build-linux24 112 | - build-linux22 113 | - build-macos 114 | runs-on: ubuntu-latest 115 | steps: 116 | - name: Checkout code 117 | uses: actions/checkout@v5 118 | with: 119 | fetch-depth: 0 # Download all git history and tags 120 | - name: Check if is a release 121 | run: | 122 | TAG="`git describe --exact-match --tags ${{ github.sha }} || true`" 123 | if [ -n "$TAG" ]; then 124 | echo "tag=$TAG" >> $GITHUB_OUTPUT 125 | echo "is=yes" >> $GITHUB_OUTPUT 126 | else 127 | echo "is=no" >> $GITHUB_OUTPUT 128 | fi 129 | id: release 130 | 131 | release: 132 | if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' && needs.check_release.outputs.is_release == 'yes' }} 133 | needs: 134 | - check_release 135 | runs-on: ubuntu-latest 136 | steps: 137 | - name: Checkout code 138 | uses: actions/checkout@v5 139 | with: 140 | fetch-depth: 0 # Download all git history and tags 141 | - name: Extract r2y version 142 | shell: bash 143 | run: echo "branch=`./configure -qV`" >> $GITHUB_OUTPUT 144 | id: r2yv 145 | - name: Prepare release notes 146 | run: echo Release > ./RELEASE_NOTES.md 147 | - name: Download artifacts 148 | uses: actions/download-artifact@v6 149 | with: 150 | path: dist/artifacts 151 | - name: Create GitHub release 152 | id: create_release 153 | uses: softprops/action-gh-release@v2.5.0 154 | with: 155 | name: ${{ steps.r2yv.outputs.branch }} 156 | tag_name: ${{ needs.check_release.outputs.tag_name }} 157 | body_path: ./RELEASE_NOTES.md 158 | draft: false 159 | prerelease: false 160 | generate_release_notes: false 161 | files: | 162 | dist/artifacts/build-linux/r2yara_${{ steps.r2yv.outputs.branch }}_amd64.deb 163 | # dist/artifacts/build-macos/r2yara-${{ steps.r2fv.outputs.branch }}-x64.pkg 164 | -------------------------------------------------------------------------------- /yara-r2-module/dist/yara-3.6.3/configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT([yara], [3.6.0], [vmalvarez@virustotal.com]) 2 | 3 | AC_CONFIG_SRCDIR([yara.c]) 4 | 5 | AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) 6 | 7 | AC_CONFIG_MACRO_DIR([m4]) 8 | 9 | # AC_PROG_CC sets CFLAGS to "-g -O2" if it wasn't previously set. Let's set 10 | # an empty CFLAGS 11 | : ${CFLAGS=""} 12 | 13 | # automake 1.12 seems to require AM_PROG_AR, but automake 1.11 doesn't 14 | # recognize it 15 | m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) 16 | 17 | AC_PROG_CC 18 | AM_PROG_CC_C_O 19 | AM_PROG_LEX 20 | AC_PROG_YACC 21 | 22 | LT_INIT 23 | AC_PROG_LIBTOOL 24 | 25 | AC_CANONICAL_HOST 26 | 27 | case $host_alias in 28 | i?86-*-mingw*) CFLAGS="$CFLAGS -D__MINGW_USE_VC2005_COMPAT" ;; 29 | esac 30 | 31 | case $host_os in 32 | darwin*) CFLAGS="$CFLAGS -I/opt/local/include" 33 | # Starting with Mac OS X 10.11 (El Capitan) the OpenSSL headers 34 | # are in /usr/local/opt/openssl/include 35 | CFLAGS="$CFLAGS -I/usr/local/opt/openssl/include" ;; 36 | esac 37 | 38 | AC_C_BIGENDIAN 39 | 40 | ACX_PTHREAD( 41 | [LIBS="$PTHREAD_LIBS $LIBS" 42 | CFLAGS="$CFLAGS $PTHREAD_CFLAGS" 43 | CC="$PTHREAD_CC"], 44 | [AC_MSG_ERROR([pthread API support is required.])]) 45 | 46 | AC_CHECK_LIB(m, isnan) 47 | AC_CHECK_LIB(m, log2) 48 | AC_CHECK_FUNCS([strlcpy strlcat memmem timegm]) 49 | 50 | AC_ARG_ENABLE([debug], 51 | [AS_HELP_STRING([--enable-debug], [compiles with -g option])], 52 | [if test x$enableval = xyes; then 53 | debug=true 54 | fi]) 55 | 56 | AC_ARG_ENABLE([optimization], 57 | [AS_HELP_STRING([--disable-optimization], [disable compiler optimizations with -O0])], 58 | [if test x$enableval = xyes; then 59 | optimization=false 60 | fi], 61 | [optimization=true]) 62 | 63 | AC_ARG_ENABLE([address-sanitizer], 64 | [AS_HELP_STRING([--enable-address-sanitizer], [compiles with -fsanitize=address])], 65 | [if test x$enableval = xyes; then 66 | address_sanitizer=true 67 | fi]) 68 | 69 | AC_ARG_ENABLE([profiling], 70 | [AS_HELP_STRING([--enable-profiling], [enable profiling support])], 71 | [if test x$enableval = xyes; then 72 | CFLAGS="$CFLAGS -DPROFILING_ENABLED" 73 | fi]) 74 | 75 | AC_ARG_ENABLE([dmalloc], 76 | [AS_HELP_STRING([--enable-dmalloc], 77 | [enable dmalloc to debug heap-related issues])], 78 | [if test x$enableval = xyes; then 79 | AC_CHECK_LIB(dmalloc, dmalloc_malloc,, 80 | AC_MSG_ERROR([please install dmalloc library])) 81 | CFLAGS="$CFLAGS -DDMALLOC" 82 | fi]) 83 | 84 | AC_ARG_ENABLE([cuckoo], 85 | [AS_HELP_STRING([--enable-cuckoo], [enable cuckoo module])], 86 | [if test x$enableval = xyes; then 87 | build_cuckoo_module=true 88 | AC_CHECK_HEADERS([jansson.h],, 89 | AC_MSG_ERROR([please install Jansson library])) 90 | AC_CHECK_LIB(jansson, json_loadb,, 91 | AC_MSG_ERROR([please install Jansson library])) 92 | CFLAGS="$CFLAGS -DCUCKOO_MODULE" 93 | fi]) 94 | 95 | AC_ARG_ENABLE([magic], 96 | [AS_HELP_STRING([--enable-magic], [enable magic module])], 97 | [if test x$enableval = xyes; then 98 | build_magic_module=true 99 | AC_CHECK_HEADERS([magic.h],, 100 | AC_MSG_ERROR([please install libmagic library])) 101 | AC_CHECK_LIB(magic, magic_open,, 102 | AC_MSG_ERROR([please install libmagic library])) 103 | CFLAGS="$CFLAGS -DMAGIC_MODULE" 104 | fi]) 105 | 106 | AC_ARG_ENABLE([dotnet], 107 | [AS_HELP_STRING([--enable-dotnet], [enable dotnet module])], 108 | [if test x$enableval = xyes; then 109 | build_dotnet_module=true 110 | CFLAGS="$CFLAGS -DDOTNET_MODULE" 111 | fi]) 112 | 113 | AC_ARG_WITH([crypto], 114 | AS_HELP_STRING([--without-crypto], 115 | [ignore presence of OpenSSL and disable it])) 116 | 117 | AS_IF([test "x$with_crypto" != "xno"], 118 | [ 119 | AC_CHECK_HEADERS([openssl/md5.h],, [have_crypto=no]) 120 | AC_CHECK_HEADERS([openssl/sha.h],, [have_crypto=no]) 121 | AC_CHECK_HEADERS([openssl/asn1.h],, [have_crypto=no]) 122 | AC_CHECK_HEADERS([openssl/crypto.h],, [have_crypto=no]) 123 | AC_CHECK_HEADERS([openssl/bio.h],, [have_crypto=no]) 124 | AC_CHECK_HEADERS([openssl/pkcs7.h],, [have_crypto=no]) 125 | AC_CHECK_HEADERS([openssl/x509.h],, [have_crypto=no]) 126 | AC_CHECK_HEADERS([openssl/safestack.h],, [have_crypto=no]) 127 | AC_CHECK_LIB(crypto, MD5_Init,, [have_crypto=no]) 128 | AC_CHECK_LIB(crypto, MD5_Update,, [have_crypto=no]) 129 | AC_CHECK_LIB(crypto, MD5_Final,, [have_crypto=no]) 130 | AC_CHECK_LIB(crypto, SHA256_Init,, [have_crypto=no]) 131 | AC_CHECK_LIB(crypto, SHA256_Update,, [have_crypto=no]) 132 | AC_CHECK_LIB(crypto, SHA256_Final,, [have_crypto=no]) 133 | ], 134 | [ 135 | have_crypto=no 136 | ]) 137 | 138 | AS_IF([test "x$have_crypto" = "xno"], 139 | [ 140 | AS_IF([test "x$with_crypto" = "xyes"], 141 | [ 142 | AC_MSG_ERROR([please install OpenSSL library]) 143 | ], 144 | [ 145 | AC_MSG_WARN([ 146 | ******************************************************************************* 147 | Could not find OpenSSL library. The "hash" module and some features in "pe" 148 | module have been disabled. If you want to enable all features please install 149 | it and run this script again. 150 | ******************************************************************************* 151 | ]) 152 | ]) 153 | ], 154 | [ 155 | build_hash_module=true 156 | CFLAGS="$CFLAGS -DHASH_MODULE" 157 | ]) 158 | 159 | AM_CONDITIONAL([DEBUG], [test x$debug = xtrue]) 160 | AM_CONDITIONAL([OPTIMIZATION], [test x$optimization = xtrue]) 161 | AM_CONDITIONAL([ADDRESS_SANITIZER], [test x$address_sanitizer = xtrue]) 162 | AM_CONDITIONAL([CUCKOO_MODULE], [test x$build_cuckoo_module = xtrue]) 163 | AM_CONDITIONAL([MAGIC_MODULE], [test x$build_magic_module = xtrue]) 164 | AM_CONDITIONAL([HASH_MODULE], [test x$build_hash_module = xtrue]) 165 | AM_CONDITIONAL([DOTNET_MODULE], [test x$build_dotnet_module = xtrue]) 166 | AM_CONDITIONAL([GCC], [test "x$GCC" = xyes]) 167 | 168 | AC_CONFIG_FILES([Makefile]) 169 | AC_CONFIG_FILES([libyara/Makefile]) 170 | AC_SUBST([DOLLAR_SIGN],[$]) 171 | 172 | AC_OUTPUT 173 | -------------------------------------------------------------------------------- /rules/crypto.yara: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2014, Colin Childs 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | * Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above 13 | copyright notice, this list of conditions and the following disclaimer 14 | in the documentation and/or other materials provided with the 15 | distribution. 16 | 17 | * Neither the names of the copyright owners nor the names of its 18 | contributors may be used to endorse or promote products derived from 19 | this software without specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | rule BLOWFISH_Constants : crypto { 35 | meta: 36 | author = "phoul (@phoul)" 37 | description = "Look for Blowfish constants" 38 | date = "2014-01" 39 | version = "0.1" 40 | strings: 41 | $c0 = { D1310BA6 } 42 | $c1 = { A60B31D1 } 43 | $c2 = { 98DFB5AC } 44 | $c3 = { ACB5DF98 } 45 | $c4 = { 2FFD72DB } 46 | $c5 = { DB72FD2F } 47 | $c6 = { D01ADFB7 } 48 | $c7 = { B7DF1AD0 } 49 | $c8 = { 4B7A70E9 } 50 | $c9 = { E9707A4B } 51 | $c10 = { F64C261C } 52 | $c11 = { 1C264CF6 } 53 | condition: 54 | 6 of them 55 | } 56 | rule MD5_Constants : crypto { 57 | meta: 58 | author = "phoul (@phoul)" 59 | description = "Look for MD5 constants" 60 | date = "2014-01" 61 | version = "0.2" 62 | strings: 63 | // Init constants 64 | $c0 = { 67452301 } 65 | $c1 = { efcdab89 } 66 | $c2 = { 98badcfe } 67 | $c3 = { 10325476 } 68 | $c4 = { 01234567 } 69 | $c5 = { 89ABCDEF } 70 | $c6 = { FEDCBA98 } 71 | $c7 = { 76543210 } 72 | // Round 2 73 | $c8 = { F4D50d87 } 74 | $c9 = { 78A46AD7 } 75 | condition: 76 | 5 of them 77 | } 78 | rule RC6_Constants : crypto { 79 | meta: 80 | author = "chort (@chort0)" 81 | description = "Look for RC6 magic constants in binary" 82 | reference = "https://twitter.com/mikko/status/417620511397400576" 83 | reference2 = "https://twitter.com/dyngnosis/status/418105168517804033" 84 | date = "2013-12" 85 | version = "0.2" 86 | strings: 87 | $c1 = { B7E15163 } 88 | $c2 = { 9E3779B9 } 89 | $c3 = { 6351E1B7 } 90 | $c4 = { B979379E } 91 | condition: 92 | 2 of them 93 | }rule RIPEMD160_Constants : crypto { 94 | meta: 95 | author = "phoul (@phoul)" 96 | description = "Look for RIPEMD-160 constants" 97 | date = "2014-01" 98 | version = "0.1" 99 | strings: 100 | $c0 = { 67452301 } 101 | $c1 = { EFCDAB89 } 102 | $c2 = { 98BADCFE } 103 | $c3 = { 10325476 } 104 | $c4 = { C3D2E1F0 } 105 | $c5 = { 01234567 } 106 | $c6 = { 89ABCDEF } 107 | $c7 = { FEDCBA98 } 108 | $c8 = { 76543210 } 109 | $c9 = { F0E1D2C3 } 110 | condition: 111 | 5 of them 112 | } 113 | rule SHA1_Constants : crypto { 114 | meta: 115 | author = "phoul (@phoul)" 116 | description = "Look for SHA1 constants" 117 | date = "2014-01" 118 | version = "0.1" 119 | strings: 120 | $c0 = { 67452301 } 121 | $c1 = { EFCDAB89 } 122 | $c2 = { 98BADCFE } 123 | $c3 = { 10325476 } 124 | $c4 = { C3D2E1F0 } 125 | $c5 = { 01234567 } 126 | $c6 = { 89ABCDEF } 127 | $c7 = { FEDCBA98 } 128 | $c8 = { 76543210 } 129 | $c9 = { F0E1D2C3 } 130 | condition: 131 | 5 of them 132 | } 133 | rule SHA256_Constants : crypto { 134 | meta: 135 | author = "phoul (@phoul)" 136 | description = "Look for SHA224/SHA256 constants" 137 | date = "2014-01" 138 | version = "0.1" 139 | strings: 140 | $c0 = { 428a2f98 } 141 | $c1 = { 982F8A42 } 142 | $c2 = { 71374491 } 143 | $c3 = { 91443771 } 144 | $c4 = { B5C0FBCF } 145 | $c5 = { CFFBC0B5 } 146 | $c6 = { E9B5DBA5 } 147 | $c7 = { A5DBB5E9 } 148 | // Exclude 149 | $e0 = { D728AE22 } 150 | $e1 = { 22AE28D7 } 151 | condition: 152 | 4 of ($c0,$c1,$c2,$c3,$c4,$c5,$c6,$c7) and not ($e0 or $e1) 153 | } 154 | rule SHA512_Constants : crypto { 155 | meta: 156 | author = "phoul (@phoul)" 157 | description = "Look for SHA384/SHA512 constants" 158 | date = "2014-01" 159 | version = "0.1" 160 | strings: 161 | $c0 = { 428a2f98 } 162 | $c1 = { 982F8A42 } 163 | $c2 = { 71374491 } 164 | $c3 = { 91443771 } 165 | $c4 = { B5C0FBCF } 166 | $c5 = { CFFBC0B5 } 167 | $c6 = { E9B5DBA5 } 168 | $c7 = { A5DBB5E9 } 169 | $c8 = { D728AE22 } 170 | $c9 = { 22AE28D7 } 171 | condition: 172 | 5 of them 173 | } 174 | rule WHIRLPOOL_Constants : crypto { 175 | meta: 176 | author = "phoul (@phoul)" 177 | description = "Look for WhirlPool constants" 178 | date = "2014-02" 179 | version = "0.1" 180 | strings: 181 | $c0 = { 18186018c07830d8 } 182 | $c1 = { d83078c018601818 } 183 | $c2 = { 23238c2305af4626 } 184 | $c3 = { 2646af05238c2323 } 185 | condition: 186 | 2 of them 187 | } 188 | -------------------------------------------------------------------------------- /COPYING.LESSER: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /yara-r2-module/ChangeLog.orig: -------------------------------------------------------------------------------- 1 | commit cc10c5aadb38773533d443aff25fe2ad0fcc6f3b 2 | Author: Antonio S 3 | Date: Wed Sep 6 17:58:50 2017 +0200 4 | 5 | Trying 6 | 7 | commit dabd464481900335426722b54bd48ebc0fd44322 8 | Author: Antonio S 9 | Date: Wed Sep 6 17:39:18 2017 +0200 10 | 11 | Fixed tests 12 | 13 | commit 374d720e7749fedcff0828c7e1674d5cb2d5cb29 14 | Author: Antonio S 15 | Date: Wed Sep 6 16:57:54 2017 +0200 16 | 17 | another test 18 | 19 | commit 84eebd094655e5c0536360a2d99449bb914697fe 20 | Author: Antonio S 21 | Date: Wed Sep 6 15:54:06 2017 +0200 22 | 23 | Final steps 24 | 25 | commit 4eb85bcaf9009c6c91b4500218007c9f798a50ac 26 | Author: Antonio S 27 | Date: Wed Sep 6 15:47:42 2017 +0200 28 | 29 | Fixed filename 30 | 31 | commit bac040087981fb15bccb7f48a6294966157bd8a9 32 | Author: Antonio S 33 | Date: Wed Sep 6 13:28:15 2017 +0200 34 | 35 | another try 36 | 37 | commit df1b859ac8d4928ec795722fa272a70ad4fa24fb 38 | Author: Antonio S 39 | Date: Wed Sep 6 13:23:28 2017 +0200 40 | 41 | another try 42 | 43 | commit b5e488870ec5e6b8774e5a6f688ad7e43e1efcd3 44 | Author: Antonio S 45 | Date: Wed Sep 6 13:16:16 2017 +0200 46 | 47 | Added travis badge 48 | 49 | commit 6a149d4a46379af8609274811861ec8b1f455424 50 | Author: Antonio S 51 | Date: Wed Sep 6 11:51:10 2017 +0200 52 | 53 | Install radare2 missing 54 | 55 | commit 12eebf39433a1644082356f27a4b5ebae6d85c2a 56 | Author: Antonio S 57 | Date: Wed Sep 6 11:46:51 2017 +0200 58 | 59 | Anoooother try 60 | 61 | commit 254671c46215a9199d5ef118774a43056dda9049 62 | Author: Antonio S 63 | Date: Wed Sep 6 11:37:14 2017 +0200 64 | 65 | Another try 66 | 67 | commit 568a13c7c2f4f94ada682ea6b689f4d9bda8af66 68 | Author: Antonio S 69 | Date: Wed Sep 6 11:28:19 2017 +0200 70 | 71 | Missing file 72 | 73 | commit 8f2d03b0a06f3ff4126da9d0deed8e70625c5d11 74 | Author: Antonio S 75 | Date: Wed Sep 6 11:25:19 2017 +0200 76 | 77 | Second try 78 | 79 | commit ec7c9bf83a4b6ca42eeee26f350eec9ae07402c4 80 | Author: Antonio S 81 | Date: Wed Sep 6 11:19:52 2017 +0200 82 | 83 | First tests for travis 84 | 85 | commit 8d1d72309a26e880accfc535843a31411a920e0a 86 | Author: Antonio S 87 | Date: Thu Jul 27 20:04:22 2017 +0200 88 | 89 | Added doc information to generate reports 90 | 91 | commit 9729d8ccc4946fe9642ddc0c62726938d4235a7c 92 | Author: Antonio S 93 | Date: Thu Jul 27 20:04:09 2017 +0200 94 | 95 | To use with python 96 | 97 | commit 92a00fade571100bfb5350a1e315bf3508940917 98 | Author: Antonio S 99 | Date: Thu Jul 27 19:43:50 2017 +0200 100 | 101 | Added reports for more bins 102 | 103 | commit ce7b0b5d6ecd383d4a753b8fe4a8c5ba2de33090 104 | Author: Antonio S 105 | Date: Thu Jul 27 19:43:38 2017 +0200 106 | 107 | changed tests for hashes 108 | 109 | commit b0b51aae477d74fde1f05ebb8633abc939df44ef 110 | Author: Antonio S 111 | Date: Thu Jul 27 19:43:09 2017 +0200 112 | 113 | Added tests for reports 114 | 115 | commit 443c944412c8aa67861ffff5e31c21fdcddfea06 116 | Author: Antonio S 117 | Date: Thu Jul 27 19:42:19 2017 +0200 118 | 119 | Added more hashes 120 | 121 | commit c1d8c58101115332b0f850e135d87c219cd11629 122 | Author: Antonio S 123 | Date: Thu Jul 27 19:09:26 2017 +0200 124 | 125 | Created generate_report.py script 126 | 127 | commit f6f1e5f2b0fc77363b0f18008c7d3e9ef2f3331e 128 | Author: Antonio S 129 | Date: Thu Jul 27 19:08:49 2017 +0200 130 | 131 | Fixed some problems 132 | 133 | commit 14d105e37989752a15839f5108ed2168406ab628 134 | Author: Antonio S 135 | Date: Tue Jul 11 14:50:41 2017 +0200 136 | 137 | Missing header un License 138 | 139 | commit d8e689fc040e78efa5eaec56f23fae066ca1e5e2 140 | Author: Antonio S 141 | Date: Tue Jul 11 14:50:09 2017 +0200 142 | 143 | Added badge 144 | 145 | commit 0c87bc099dc110dbe72543a2cd493397c78a530d 146 | Merge: d5b8493 cdc7c19 147 | Author: Antonio S 148 | Date: Tue Jul 11 14:48:12 2017 +0200 149 | 150 | Merge branch 'master' of github.com:Yara-Rules/r2yara 151 | 152 | commit d5b8493c9964194feab70ee4853988baab3d1384 153 | Author: Antonio S 154 | Date: Tue Jul 11 14:47:56 2017 +0200 155 | 156 | Changed license to BSD 3-clause 157 | 158 | commit cdc7c1961cdc306f7fb0545e53ca0fbf6282d253 159 | Author: Antonio Sánchez 160 | Date: Wed Jul 5 18:26:23 2017 +0200 161 | 162 | Added license in README 163 | 164 | commit 7b9fc2c42eb9e43090b15fdff3c2fb6332b26b22 165 | Merge: 47b2204 02ff69a 166 | Author: Antonio S 167 | Date: Wed Jul 5 18:16:28 2017 +0200 168 | 169 | Merge branch 'master' of github.com:Yara-Rules/r2yara 170 | 171 | commit 47b22044b41e2c1b05c2a626022882221db5fd2b 172 | Author: Antonio S 173 | Date: Wed Jul 5 18:16:21 2017 +0200 174 | 175 | Fixed #2 176 | 177 | commit 02ff69a8f369ee416510c02d95a4210426adfe0f 178 | Author: Antonio Sánchez 179 | Date: Wed Jul 5 17:22:43 2017 +0200 180 | 181 | Update README.md 182 | 183 | commit f85c02d0af0f209cba19cce589e1c6ed75560b25 184 | Author: Antonio S 185 | Date: Wed Jul 5 17:12:48 2017 +0200 186 | 187 | Added first source code version 188 | 189 | commit 3efd8f300ac44611670b5b39a74f47e4f17fbd2a 190 | Author: Antonio S 191 | Date: Wed Jul 5 17:12:24 2017 +0200 192 | 193 | More documentation 194 | 195 | commit 0a809762cbc1f507987493d22db842fffb61ed5e 196 | Author: Antonio S 197 | Date: Wed Jul 5 16:34:39 2017 +0200 198 | 199 | Changed README 200 | 201 | commit 0bd150e11e03b8cd3e1a5dcf7b47db393ae304f1 202 | Author: Antonio S 203 | Date: Wed Jul 5 16:33:49 2017 +0200 204 | 205 | Added installation instructions 206 | 207 | commit 456eb7260dad5beebf35887793826bea545453cc 208 | Author: Antonio S 209 | Date: Mon Jul 3 15:34:24 2017 +0200 210 | 211 | Added info 212 | 213 | commit 632b55912e9f5a009f7cc4ed5c638056845e7443 214 | Author: Antonio S 215 | Date: Mon Jul 3 15:03:45 2017 +0200 216 | 217 | Added hash use 218 | 219 | commit 4d485d9228115b944311d092a9f0725d41d31df5 220 | Author: Antonio S 221 | Date: Mon Jul 3 14:54:49 2017 +0200 222 | 223 | Added resources 224 | 225 | commit bb66899243dcd4a7f9cfe04964d8b994013a8711 226 | Author: Antonio S 227 | Date: Fri Jun 16 15:21:52 2017 +0200 228 | 229 | Added exports docs and tests 230 | 231 | commit 50504a9b5712caa768423f1f5a97561020a89125 232 | Author: mmorenog 233 | Date: Thu Jun 15 18:08:51 2017 +0200 234 | 235 | Update index.md 236 | 237 | commit 35d060edf61a65870d5cad8f5f8d87c529ae5581 238 | Author: mmorenog 239 | Date: Thu Jun 15 18:07:55 2017 +0200 240 | 241 | Delete post.md 242 | 243 | commit ff38550ece546cb601ac0f818f3adb9c88030b47 244 | Author: mmorenog 245 | Date: Thu Jun 15 18:07:25 2017 +0200 246 | 247 | Create index.md 248 | 249 | commit 6cd9fddb4fd6262bbd503e10c9a3dd6b478f2ca7 250 | Author: mmorenog 251 | Date: Thu Jun 15 18:06:52 2017 +0200 252 | 253 | Create index.md 254 | 255 | commit 6b72867b689a373acdd1cfd4abfbbdb5e4c7808c 256 | Author: mmorenog 257 | Date: Thu Jun 15 18:05:11 2017 +0200 258 | 259 | Create index.md 260 | 261 | commit 375b4f955acd7ba3cb151f652bb7204182aa11b8 262 | Author: mmorenog 263 | Date: Thu Jun 15 18:04:23 2017 +0200 264 | 265 | Update index.md 266 | 267 | commit ff78a9c2dd0c18bb3bec5e98755c267aa3b0c496 268 | Author: mmorenog 269 | Date: Thu Jun 15 18:03:47 2017 +0200 270 | 271 | Create index.md 272 | 273 | commit 89bec16c5815a126d579ba203dd92151fb8d0ab6 274 | Author: mmorenog 275 | Date: Thu Jun 15 16:32:58 2017 +0200 276 | 277 | Create post.md 278 | 279 | commit cdb4b3b4b6bdba567e5ec585a4b4511b5713e162 280 | Author: Antonio S 281 | Date: Thu Jun 15 09:48:22 2017 +0200 282 | 283 | Added doc for libraries 284 | 285 | commit 659b9f040119981e88f621311ec38839a16bbd32 286 | Author: Antonio S 287 | Date: Thu Jun 15 09:44:52 2017 +0200 288 | 289 | Added tests for section functions 290 | 291 | commit 824c48e8a9da797b015fca82a32a9aae312092d1 292 | Author: Antonio S 293 | Date: Thu Jun 15 09:41:39 2017 +0200 294 | 295 | Added tests for lib 296 | 297 | commit de9571cf9124276eec10f14e9897ebc7f21da03a 298 | Author: Antonio S 299 | Date: Wed Jun 14 12:23:17 2017 +0200 300 | 301 | Added basic tests, under development 302 | 303 | commit 7d4b47aaaed52a399d1efd9d91da4cecf55615bf 304 | Author: Antonio S 305 | Date: Wed Jun 14 12:22:13 2017 +0200 306 | 307 | doc for imports 308 | 309 | commit 2193c528a5f20f9cca1e02533f518f1b3cb044dc 310 | Author: Antonio S 311 | Date: Tue Jun 13 12:28:04 2017 +0200 312 | 313 | Added sections doc 314 | 315 | commit 17ca8d08ed7bf390998456b17661a625dcb4ac63 316 | Author: Antonio S 317 | Date: Tue Jun 13 10:06:53 2017 +0200 318 | 319 | First commit 320 | 321 | commit d79d2a041f5d97a15a6421db603c4977177655ad 322 | Author: mmorenog 323 | Date: Fri Jan 27 13:38:30 2017 +0100 324 | 325 | Initial commit 326 | -------------------------------------------------------------------------------- /yara-r2-module/launch_tests.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import json 3 | import sys 4 | import subprocess 5 | import unittest 6 | 7 | __author__ = "Antonio Sanchez " 8 | 9 | YARABIN = "yara" 10 | 11 | """ 12 | Aux method to run yara from command line 13 | """ 14 | def command_line(yararule, binary, report=None): 15 | if not report: 16 | args = [YARABIN, yararule, binary] 17 | else: 18 | args = [YARABIN, "-x", "r2={}".format(report), yararule, binary] 19 | value, _ = subprocess.Popen(args, stdout = subprocess.PIPE).communicate() 20 | value = value.split('\n') 21 | to_ret = list() 22 | for i in value: 23 | if len(i) > 0: 24 | to_ret.append(i.split(' ')[0]) 25 | 26 | return to_ret 27 | 28 | 29 | """ 30 | Test r2yara using r2 report 31 | """ 32 | 33 | class TestR2YaraReport(unittest.TestCase): 34 | 35 | def test_info_array(self): 36 | rule = "tests/rules/info.yar" 37 | report_file = "tests/ls_report.json" 38 | rules = ["rule_info"] 39 | binary = "tests/bins/ls" 40 | matches = command_line(rule, binary, report_file) 41 | total_rules = len(rules) 42 | for match in matches: 43 | if match in rules: 44 | total_rules -= 1 45 | 46 | self.assertTrue(total_rules == 0) 47 | 48 | 49 | def test_hashes_array(self): 50 | rule = "tests/rules/hash.yar" 51 | report_file = "tests/ls_report.json" 52 | rules = ["rule_hashes"] 53 | binary = "tests/bins/ls" 54 | matches = command_line(rule, binary, report_file) 55 | total_rules = len(rules) 56 | for match in matches: 57 | if match in rules: 58 | total_rules -= 1 59 | 60 | self.assertTrue(total_rules == 0) 61 | 62 | 63 | def test_resource_function(self): 64 | rule = "tests/rules/resource_func.yar" 65 | rules = ["resource_ss", "resource_rs", "resource_sr", "resource_rr"] 66 | report_file = "tests/f61dc6f07401b8bc383d4bb69c001a6bf38f6557eeec7a9c261b581a4effdc1a_report.json" 67 | binary = "tests/bins/f61dc6f07401b8bc383d4bb69c001a6bf38f6557eeec7a9c261b581a4effdc1a" 68 | matches = command_line(rule, binary, report_file) 69 | total_rules = len(rules) 70 | for match in matches: 71 | if match in rules: 72 | total_rules -= 1 73 | 74 | 75 | self.assertTrue(total_rules == 0) 76 | 77 | 78 | def test_resource_array(self): 79 | rule = "tests/rules/resources_array.yar" 80 | rules = ["resources"] 81 | report_file = "tests/f61dc6f07401b8bc383d4bb69c001a6bf38f6557eeec7a9c261b581a4effdc1a_report.json" 82 | binary = "tests/bins/f61dc6f07401b8bc383d4bb69c001a6bf38f6557eeec7a9c261b581a4effdc1a" 83 | matches = command_line(rule, binary, report_file) 84 | total_rules = len(rules) 85 | for match in matches: 86 | if match in rules: 87 | total_rules -= 1 88 | 89 | 90 | self.assertTrue(total_rules == 0) 91 | 92 | def test_export_array(self): 93 | rule = "tests/rules/exports_array.yar" 94 | rules = ["rule_exports_array"] 95 | report_file = "tests/dll_report.json" 96 | binary = "tests/bins/dll.dll_" 97 | matches = command_line(rule, binary, report_file) 98 | total_rules = len(rules) 99 | for match in matches: 100 | if match in rules: 101 | total_rules -= 1 102 | 103 | 104 | self.assertTrue(total_rules == 0) 105 | 106 | def test_export_function(self): 107 | rule = "tests/rules/export.yar" 108 | rules = ["rule_export_ss", "rule_export_sr", "rule_export_rs", "rule_export_rr"] 109 | report_file = "tests/dll_report.json" 110 | binary = "tests/bins/dll.dll_" 111 | matches = command_line(rule, binary, report_file) 112 | total_rules = len(rules) 113 | for match in matches: 114 | if match in rules: 115 | total_rules -= 1 116 | 117 | 118 | self.assertTrue(total_rules == 0) 119 | 120 | def test_lib(self): 121 | rule = "tests/rules/lib.yar" 122 | rules = ["rule_lib_s", "rule_lib_r"] 123 | report_file = "tests/ls_report.json" 124 | binary = "tests/bins/ls" 125 | matches = command_line(rule, binary, report_file) 126 | total_rules = len(rules) 127 | for match in matches: 128 | if match in rules: 129 | total_rules -= 1 130 | 131 | 132 | self.assertTrue(total_rules == 0) 133 | 134 | def test_section_array(self): 135 | rule = "tests/rules/sections.yar" 136 | rules = ["sections"] 137 | report_file = "tests/ls_report.json" 138 | binary = "tests/bins/ls" 139 | matches = command_line(rule, binary, report_file) 140 | total_rules = len(rules) 141 | for match in matches: 142 | if match in rules: 143 | total_rules -= 1 144 | 145 | 146 | self.assertTrue(total_rules == 0) 147 | 148 | def test_section_function(self): 149 | rule = "tests/rules/section_functions.yar" 150 | rules = ["rule_sections_ss", "rule_sections_sr", "rule_sections_rs", "rule_sections_rr"] 151 | report_file = "tests/ls_report.json" 152 | binary = "tests/bins/ls" 153 | matches = command_line(rule, binary, report_file) 154 | total_rules = len(rules) 155 | for match in matches: 156 | if match in rules: 157 | total_rules -= 1 158 | 159 | 160 | self.assertTrue(total_rules == 0) 161 | 162 | def test_imports_function(self): 163 | rule = "tests/rules/imports.yar" 164 | rules = ["rule_import_isss_1", 165 | "rule_import_isss_2", 166 | "rule_import_ssr", 167 | "rule_import_srs", 168 | "rule_import_srr", 169 | "rule_import_rss", 170 | "rule_import_rsr", 171 | "rule_import_rrs", 172 | "rule_import_rrr"] 173 | 174 | report_file = "tests/ls_report.json" 175 | binary = "tests/bins/ls" 176 | matches = command_line(rule, binary, report_file) 177 | total_rules = len(rules) 178 | for match in matches: 179 | if match in rules: 180 | total_rules -= 1 181 | 182 | 183 | self.assertTrue(total_rules == 0) 184 | 185 | 186 | """ 187 | Test r2yara using r2 standalone 188 | """ 189 | class TestR2YaraAutoInvoke(unittest.TestCase): 190 | 191 | def test_info_array(self): 192 | rule = "tests/rules/info.yar" 193 | rules = ["rule_info"] 194 | matches = command_line(rule, "tests/bins/ls") 195 | total_rules = len(rules) 196 | for match in matches: 197 | if match in rules: 198 | total_rules -= 1 199 | 200 | 201 | self.assertTrue(total_rules == 0) 202 | 203 | def test_hashes_array(self): 204 | rule = "tests/rules/hash.yar" 205 | rules = ["rule_hashes"] 206 | matches = command_line(rule, "tests/bins/ls") 207 | total_rules = len(rules) 208 | for match in matches: 209 | if match in rules: 210 | total_rules -= 1 211 | 212 | 213 | self.assertTrue(total_rules == 0) 214 | 215 | def test_resource_function(self): 216 | rule = "tests/rules/resource_func.yar" 217 | rules = ["resource_ss", "resource_rs", "resource_sr", "resource_rr"] 218 | matches = command_line(rule, "tests/bins/f61dc6f07401b8bc383d4bb69c001a6bf38f6557eeec7a9c261b581a4effdc1a") 219 | total_rules = len(rules) 220 | for match in matches: 221 | if match in rules: 222 | total_rules -= 1 223 | 224 | 225 | self.assertTrue(total_rules == 0) 226 | 227 | def test_resource_array(self): 228 | rule = "tests/rules/resources_array.yar" 229 | rules = ["resources"] 230 | matches = command_line(rule, "tests/bins/f61dc6f07401b8bc383d4bb69c001a6bf38f6557eeec7a9c261b581a4effdc1a") 231 | total_rules = len(rules) 232 | for match in matches: 233 | if match in rules: 234 | total_rules -= 1 235 | 236 | 237 | self.assertTrue(total_rules == 0) 238 | 239 | def test_export_array(self): 240 | rule = "tests/rules/exports_array.yar" 241 | rules = ["rule_exports_array"] 242 | matches = command_line(rule, "tests/bins/dll.dll_") 243 | print matches 244 | total_rules = len(rules) 245 | for match in matches: 246 | if match in rules: 247 | total_rules -= 1 248 | 249 | 250 | self.assertTrue(total_rules == 0) 251 | 252 | def test_export_function(self): 253 | rule = "tests/rules/export.yar" 254 | rules = ["rule_export_ss", "rule_export_sr", "rule_export_rs", "rule_export_rr"] 255 | matches = command_line(rule, "tests/bins/dll.dll_") 256 | total_rules = len(rules) 257 | for match in matches: 258 | if match in rules: 259 | total_rules -= 1 260 | 261 | 262 | self.assertTrue(total_rules == 0) 263 | 264 | def test_lib(self): 265 | rule = "tests/rules/lib.yar" 266 | rules = ["rule_lib_s", "rule_lib_r"] 267 | matches = command_line(rule, "tests/bins/ls") 268 | total_rules = len(rules) 269 | for match in matches: 270 | if match in rules: 271 | total_rules -= 1 272 | 273 | 274 | self.assertTrue(total_rules == 0) 275 | 276 | def test_section_array(self): 277 | rule = "tests/rules/sections.yar" 278 | rules = ["sections"] 279 | matches = command_line(rule, "tests/bins/ls") 280 | total_rules = len(rules) 281 | for match in matches: 282 | if match in rules: 283 | total_rules -= 1 284 | 285 | 286 | self.assertTrue(total_rules == 0) 287 | 288 | def test_section_function(self): 289 | rule = "tests/rules/section_functions.yar" 290 | rules = ["rule_sections_ss", "rule_sections_sr", "rule_sections_rs", "rule_sections_rr"] 291 | matches = command_line(rule, "tests/bins/ls") 292 | total_rules = len(rules) 293 | for match in matches: 294 | if match in rules: 295 | total_rules -= 1 296 | 297 | 298 | self.assertTrue(total_rules == 0) 299 | 300 | 301 | def test_imports_function(self): 302 | rule = "tests/rules/imports.yar" 303 | rules = ["rule_import_isss_1", 304 | "rule_import_isss_2", 305 | "rule_import_ssr", 306 | "rule_import_srs", 307 | "rule_import_srr", 308 | "rule_import_rss", 309 | "rule_import_rsr", 310 | "rule_import_rrs", 311 | "rule_import_rrr"] 312 | 313 | matches = command_line(rule, "tests/bins/ls") 314 | total_rules = len(rules) 315 | for match in matches: 316 | if match in rules: 317 | total_rules -= 1 318 | 319 | 320 | self.assertTrue(total_rules == 0) 321 | 322 | 323 | 324 | if __name__ == '__main__': 325 | unittest.main() 326 | 327 | -------------------------------------------------------------------------------- /configure: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # This script was automatically generated by ACR v2.2.2 3 | # @author: pancake 4 | # @url: http://www.nopcode.org 5 | # @repo: git clone https://github.com/radare/acr 6 | 7 | [ -z "${AWK}" ] && AWK=awk 8 | do_remove() { 9 | if [ "${ACR_RMFILES}" ]; then 10 | printf "cleaning temporally files... " 11 | rm -f ${ACR_RMFILES} 12 | echo "done" 13 | fi 14 | } 15 | control_c() { 16 | printf "\n\n^C control-c : script execution interrupted.\n" 17 | do_remove 18 | exit 1 19 | } 20 | trap control_c 2 21 | USE_YARAX=0 22 | split_host() { 23 | S="$" 24 | while : ; do 25 | ENVWORDS="${ENVWORDS} $1_CPU $1_OS" 26 | STR=`eval "echo ${S}$1"` 27 | SPLIT_CPU="`echo "$STR" | cut -d - -f 1`" 28 | SPLIT_OS="`echo "$STR" | $AWK -F - '{ 29 | if ($2=="unknown"){ 30 | if (NF<3) { print $2; } else { print $3; } 31 | } else { 32 | if ($2=="linux") { print $2; } else 33 | if (NF<3) { print $2; } else { print $3; } 34 | } 35 | }'`" 36 | eval "$1_CPU=\"$SPLIT_CPU\"" 37 | eval "$1_OS=\"$SPLIT_OS\"" 38 | shift 39 | [ -z "$1" ] && break 40 | done 41 | } 42 | 43 | QUIET=0 44 | be_quiet() { 45 | QUIET=1 46 | } 47 | 48 | VPATH=`dirname ${0}` 49 | if [ "${VPATH}" = "." ]; then 50 | WODIS=current 51 | else 52 | if [ "${VPATH}" = "${PWD}" ]; then 53 | VPATH=. 54 | WODIS=current 55 | else 56 | WODIS=crosspath 57 | CURDIR=$PWD 58 | cd $VPATH 59 | VPATH="${PWD}/" 60 | cd $CURDIR 61 | fi 62 | fi 63 | 64 | guess_os() { 65 | if [ -e "${VPATH}/config.guess" ]; then 66 | sh ${VPATH}/config.guess 67 | return 68 | fi 69 | CPU="`uname -m|sed -e 's, ,,g'|cut -d - -f 1`" 70 | OS="`uname -s|tr A-Z a-z`" 71 | uname -r | grep -qE "(Microsoft|WSL)" 2>/dev/null && OS="wsl" 72 | GNU="`uname --help 2>&1 | grep gnu`" 73 | [ "${GNU}" ] && OS="${OS}-gnu" 74 | [ "${CPU}" = ppc ] && CPU="powerpc" 75 | echo "${CPU}-unknown-${OS}" 76 | } 77 | 78 | SEARCHPATH="/usr /usr/local /usr/pkg /sw" 79 | 80 | : ${PREFIX:=/usr/local} 81 | CROSSBUILD=0 82 | BUILD=`guess_os` 83 | HOST="${BUILD}" 84 | TARGET="${HOST}" 85 | ETCDIR="/etc" 86 | SYSCONFDIR="" 87 | DESCRIPTION="yara plugin for radare2" 88 | 89 | create_environ() { 90 | : ${EPREFIX:="${PREFIX}"} 91 | : ${SPREFIX:="${PREFIX}"} 92 | : ${BINDIR:="${SPREFIX}/bin"} 93 | : ${SBINDIR:="${PREFIX}/sbin"} 94 | : ${ETCDIR:="${SPREFIX}/etc"} 95 | : ${LIBDIR:="${SPREFIX}/lib"} 96 | : ${PKGCFG_LIBDIR:='${exec_prefix}/lib'} 97 | : ${PKGCFG_INCDIR:='${prefix}/include'} 98 | : ${LIBEXECDIR:="${SPREFIX}/libexec"} 99 | : ${INCLUDEDIR:="${SPREFIX}/include"} 100 | : ${DATADIR:="${SPREFIX}/share"} 101 | : ${INFODIR:="${DATADIR}/info"} 102 | : ${MANDIR:="${DATADIR}/man"} 103 | : ${DOCDIR:="${DATADIR}/doc/r2yara"} 104 | : ${LOCALSTATEDIR:="${SPREFIX}/var"} 105 | for A in `echo ${PATH} | sed -e 's,:, ,g'` ; do 106 | [ -e "$A"/ginstall ] && : ${INSTALL:="$A"/ginstall} && break 107 | [ -e "$A"/install ] && : ${INSTALL:="$A"/install} && break 108 | done 109 | : ${INSTALL_DIR:=${INSTALL} -d} 110 | : ${INSTALL_DATA:=${INSTALL} -m 644} 111 | : ${INSTALL_SCRIPT:=${INSTALL} -m 755} 112 | : ${INSTALL_PROGRAM:=${INSTALL} -m 755} 113 | : ${INSTALL_PROGRAM_STRIP:=${INSTALL} -m 755 -s} 114 | : ${INSTALL_MAN:=${INSTALL} -m 444} 115 | : ${INSTALL_LIB:=${INSTALL} -m 755 -c} 116 | PKGNAME='r2yara' ; VERSION='1.4.4' ; VERSION_MAJOR=1; VERSION_MINOR=4; VERSION_PATCH=4; VERSION_NUMBER=10404; CONTACT_MAIL="judy.frankowski@gmail.com" ; CONTACT_NAME="jfrankowski" ; CONTACT="jfrankowski " ; 117 | } 118 | 119 | show_usage() { 120 | cat < if you have libraries in a 172 | nonstandard directory 173 | CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have 174 | headers in a nonstandard directory 175 | CPP C preprocessor 176 | " 177 | printf " 178 | Report bugs to: jfrankowski " 179 | echo "" 180 | exit 0 181 | } 182 | 183 | take_environ() { 184 | : ${SH:=/bin/sh} 185 | : ${CPP:=cpp} 186 | : ${CC:=gcc} 187 | : ${PREFIX:=/usr/local/} 188 | } 189 | 190 | ochof() { 191 | [ "$QUIET" = 1 ] && return 192 | printf "$*" 193 | } 194 | 195 | ocho() { 196 | [ "$QUIET" = 1 ] && return 197 | echo "$*" 198 | } 199 | 200 | show_version() { 201 | if [ "$QUIET" = 1 ]; then 202 | echo "1.4.4" 203 | exit 0 204 | fi 205 | echo "r2yara-1.4.4 configuration script done with acr v2.2.2. 206 | The 'Free Software Foundation' message is only for autodetection. 207 | Originally written by pancake ." 208 | exit 0 209 | } 210 | 211 | parse_options() { 212 | flag=`echo $1| cut -d = -f 1` 213 | value=`echo $1| $AWK 'BEGIN{FS="=";}{print $2}'` 214 | flag2=`echo $flag|cut -f2- -d -| sed -e 's,-,_,g' -e 's,^_,,g'|tr '[a-z]' '[A-Z]'` 215 | 216 | if [ "${TARGET_OS}" = "darwin" ]; then 217 | LIBPATH=-Wl,-install_name, 218 | else 219 | LIBPATH=-Wl,-R 220 | fi 221 | 222 | case $flag in 223 | -h|--help|--hel|--h|--he|-help) 224 | show_usage ; ;; 225 | -qV|-quiet-version|--quiet-version) 226 | be_quiet 227 | show_version ; ;; 228 | -q|-quiet|--quiet) 229 | be_quiet ; ;; 230 | -V|-version|--version) 231 | show_version ; ;; 232 | -r|--r|--report) 233 | echo "PKGNAME: r2yara" 234 | echo "VERSION: 1.4.4" 235 | echo "AUTHOR: jfrankowski" 236 | echo "EMAIL: judy.frankowski@gmail.com" 237 | echo "DESCRIPTION: yara plugin for radare2" 238 | echo "LANGS: c" 239 | echo "PKGCONFIG: yara r_core" 240 | echo "FLAGS: --with-yarax" 241 | exit 0 242 | ;; 243 | --cache-file) 244 | # ignored: acr have no cache 245 | ;; 246 | --build) 247 | BUILD="$value"; split_host BUILD ; ;; 248 | --host) 249 | CROSSBUILD=1 # XXX 250 | HOST="$value"; split_host HOST ; ;; 251 | --target) 252 | TARGET="$value"; split_host TARGET ; ;; 253 | --prefix) 254 | PREFIX="$value"; ;; 255 | --exec-prefix) 256 | EPREFIX="$value"; ;; 257 | --sandbox|--sprefix) 258 | SPREFIX="$value"; ;; 259 | --bindir) 260 | BINDIR="$value"; ;; 261 | --sbindir) 262 | SBINDIR="$value"; ;; 263 | --libexecdir) 264 | LIBEXECDIR="$value"; ;; 265 | --docdir) 266 | DOCDIR="$value"; ;; 267 | --datadir) 268 | DATADIR="$value"; ;; 269 | --sysconfdir) 270 | SYSCONFDIR="$value" 271 | ETCDIR="$value"; ;; 272 | --etcdir) 273 | SYSCONFDIR="$value" 274 | ETCDIR="$value"; ;; 275 | --sharedstatedir) 276 | SHAREDSTATEDIR="$value"; ;; 277 | --localstatedir) 278 | LOCALSTATEDIR="$value"; ;; 279 | --libdir) 280 | LIBDIR="$value" 281 | PKGCFG_LIBDIR="$value"; ;; 282 | --libpath) 283 | LDFLAGS="${LDFLAGS} ${LIBPATH}$value"; ;; 284 | --includedir) 285 | PKGCFG_INCDIR="$value" 286 | INCLUDEDIR="$value"; CFLAGS="${CFLAGS} -I$value"; ;; 287 | --infodir) 288 | INFODIR="$value"; ;; 289 | --mandir) 290 | MANDIR="$value"; ;; 291 | 292 | "--with-yarax") USE_YARAX="1"; ;; 293 | *) if [ "$value" ]; then eval "`echo $flag2=$value`" ; 294 | else echo ; echo "WARNING: Unknown flag '$flag'." >&2 ; echo ; fi ;; 295 | esac 296 | } 297 | 298 | # MAIN # 299 | take_environ 300 | split_host BUILD HOST TARGET 301 | [ -z "$ACRHOOK" ] && ACRHOOK=./configure.hook 302 | [ -e "$ACRHOOK" ] && . ${ACRHOOK} 303 | 304 | while : ; do 305 | [ -z "$1" ] && break 306 | parse_options "$1" 307 | shift 308 | done 309 | 310 | ENVWORDS="MANDIR DESCRIPTION INFODIR LIBDIR INCLUDEDIR LOCALSTATEDIR ETCDIR SYSCONFDIR DATADIR DOCDIR LIBEXECDIR SBINDIR BINDIR EPREFIX PREFIX SPREFIX TARGET HOST BUILD INSTALL INSTALL_LIB INSTALL_MAN INSTALL_PROGRAM INSTALL_PROGRAM_STRIP INSTALL_DIR INSTALL_SCRIPT INSTALL_DATA HOST_OS HOST_CPU BUILD_OS BUILD_CPU TARGET_OS TARGET_CPU VERSION VERSION_MAJOR VERSION_MINOR VERSION_PATCH VERSION_NUMBER PKGCFG_LIBDIR PKGCFG_INCDIR PKGNAME VPATH CONTACT CONTACT_NAME CONTACT_MAIL PKGCONFIG CC CFLAGS CPPFLAGS LDFLAGS HAVE_LANG_C YR_CFLAGS YR_LDFLAGS HAVE_PKGCFG_YARA R2_CFLAGS R2_LDFLAGS HAVE_PKGCFG_R_CORE USE_YARAX" 311 | 312 | create_environ 313 | 314 | ocho "checking build system type... ${BUILD}" 315 | ocho "checking host system type... ${HOST}" 316 | ocho "checking target system type... ${TARGET}" 317 | [ "${CROSSBUILD}" = 1 ] && echo "using crosscompilation mode." 318 | 319 | #split_host BUILD HOST TARGET 320 | [ -n "${prefix}" ] && PREFIX="${prefix}" 321 | ocho "checking for working directories... ${WODIS}" 322 | ocho "using prefix '${PREFIX}'" 323 | ACR_RMFILES=" test.c a.out a.exe" 324 | 325 | ochof "checking for pkg-config... " 326 | ENVWORDS="${ENVWORDS} HAVE_PKGCONFIG" 327 | if [ -n "$PKGCONFIG" ]; then 328 | if [ -x "$PKGCONFIG" ]; then 329 | _HAVE_PKGCONFIG="${PKGCONFIG}" 330 | else 331 | ocho "PKGCONFIG env is not executable" 332 | PKGCONFIG="" 333 | fi 334 | else 335 | IFS=: 336 | for A in ${PATH} ; do 337 | if [ -x "${A}/pkg-config" ]; then 338 | PKGCONFIG="${A}/pkg-config" 339 | elif [ -x "${A}/pkgconf" ]; then 340 | PKGCONFIG="${A}/pkgconf" 341 | else 342 | continue 343 | fi 344 | break 345 | done 346 | unset IFS 347 | fi 348 | if [ -n "${PKGCONFIG}" ]; then 349 | ocho ${PKGCONFIG} 350 | HAVE_PKGCONFIG=1 351 | else 352 | HAVE_PKGCONFIG=0 353 | echo "Cannot find pkg-config or pkgconf in PATH" >&2 354 | exit 1 355 | ocho no; fi 356 | COMPILER=CC 357 | ochof "checking for c compiler... " 358 | HAVE_LANG_C=1 359 | if [ "${CROSSBUILD}" = 1 ]; then 360 | (command -v ${HOST}-${CC} >/dev/null 2>&1) 361 | if [ $? = 0 ]; then CC="${HOST}-${CC}"; fi 362 | fi 363 | echo "int main(int argc, char **argv){return 0;}" > test.c 364 | (exec ${CC} -o a.out ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} test.c >/dev/null 2>&1) 365 | if [ $? = 0 ]; then echo ${CC}; else 366 | echo no ; HAVE_LANG_C=0 367 | do_remove 368 | echo "ERROR: ${CC} cannot create executables" >&2 ; 369 | exit 1 ; fi 370 | if [ -z "${PKGCONFIG}" ]; then pkg-config --version >/dev/null 2>&1 ; if [ 0 = 0 ]; then PKGCONFIG=pkg-config ; else PKGCONFIG=pkgconf ; fi; fi 371 | type ${PKGCONFIG} > /dev/null 2>&1 || echo "ERROR: Cannot find valid PKGCONFIG, pkg-config or pkgconf in PATH" 372 | echo 'Using PKGCONFIG: '${PKGCONFIG} 373 | printf 'checking pkg-config flags for yara... ' 374 | tmp=`${PKGCONFIG} --cflags yara 2>/dev/null` 375 | if [ $? != 0 ]; then echo no ; HAVE_PKGCFG_YARA=0; 376 | YR_CFLAGS='';YR_LDFLAGS=''; 377 | echo 'This package is required' 378 | exit 1 379 | else 380 | YR_CFLAGS=$tmp; 381 | tmp=`${PKGCONFIG} --libs yara 2>/dev/null` 382 | if [ $? = 0 ]; then 383 | echo yes; HAVE_PKGCFG_YARA=1; 384 | YR_LDFLAGS=$tmp; fi; fi 385 | if [ -z "${PKGCONFIG}" ]; then pkg-config --version >/dev/null 2>&1 ; if [ 0 = 0 ]; then PKGCONFIG=pkg-config ; else PKGCONFIG=pkgconf ; fi; fi 386 | printf 'checking pkg-config flags for r_core... ' 387 | tmp=`${PKGCONFIG} --cflags r_core 2>/dev/null` 388 | if [ $? != 0 ]; then echo no ; HAVE_PKGCFG_R_CORE=0; 389 | R2_CFLAGS='';R2_LDFLAGS=''; 390 | echo 'This package is required' 391 | exit 1 392 | else 393 | R2_CFLAGS=$tmp; 394 | tmp=`${PKGCONFIG} --libs r_core 2>/dev/null` 395 | if [ $? = 0 ]; then 396 | echo yes; HAVE_PKGCFG_R_CORE=1; 397 | R2_LDFLAGS=$tmp; fi; fi 398 | SEDFLAGS=" -e '" 399 | COUNT=0 400 | for A in ${ENVWORDS} ; do 401 | [ "${A}" = VPATH ] && continue 402 | [ "${A}" = srcdir ] && continue 403 | eval "VAR=\$${A}" 404 | VAR="`echo ${VAR} | sed -e 's/\,/\\\,/g'`" 405 | [ $COUNT = 10 ] && COUNT=0 && SEDFLAGS="${SEDFLAGS}' -e '" 406 | COUNT=$(($COUNT+1)) 407 | SEDFLAGS="${SEDFLAGS}s,@${A}@,${VAR},g;" 408 | done 409 | SEDFLAGS="${SEDFLAGS}'" 410 | for A in . config.mk ; do # SUBDIRS 411 | if [ -f "${VPATH}/${A}.acr" ]; then 412 | SD_TARGET=${A} 413 | else 414 | if [ -d "${VPATH}/${A}" ]; then 415 | SD_TARGET=${A}/Makefile 416 | mkdir -p ${A} 417 | else 418 | echo "ERROR: Cannot find ${VPATH}/${A}.acr" >&2 419 | exit 1 420 | fi 421 | fi 422 | ocho "creating ${SD_TARGET}" 423 | [ "${VPATH}" != '.' ] && mkdir -p $(echo ${A} | sed -e "s,/`basename ${A}`$,,g") 424 | cat ${VPATH}/${SD_TARGET}.acr | \ 425 | eval sed -e "s,@VPATH@,${VPATH}/${A},g" ${SEDFLAGS} > ${SD_TARGET}.tmp 426 | 427 | for A in ${ENVWORDS}; do 428 | VALUE=`eval echo "$"${A}` 429 | if [ "$VALUE" = 0 ]; then ## FALSE 430 | MARK="##${A}##" 431 | if [ -n "`grep \"${MARK}\" ${SD_TARGET}.tmp`" ]; then 432 | mv ${SD_TARGET}.tmp ${SD_TARGET}.tmp2 433 | cat ${SD_TARGET}.tmp2 | MARK=$MARK $AWK 'BEGIN{a=0;}{if($1==ENVIRON["MARK"]){if(a)a=0;else a=1}else{if(!a)print;}}' > ${SD_TARGET}.tmp 434 | fi 435 | fi 436 | done 437 | mv ${SD_TARGET}.tmp ${SD_TARGET} && rm -f ${SD_TARGET}.tmp2 438 | if [ ! $? = 0 ]; then echo Cannot write target file ; control_c ; fi 439 | done 440 | 441 | do_remove 442 | if [ "$QUIET" = 0 ]; then 443 | echo 444 | echo "Final report:" 445 | for A in PREFIX ; do 446 | eval VAL="\$${A}" 447 | [ -z "${VAL}" ] && VAL="\"\"" 448 | echo " - ${A} = ${VAL}" 449 | done 450 | fi 451 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /src/core_r2yara.c: -------------------------------------------------------------------------------- 1 | /* radare - LGPLv3 - Copyright 2014-2025 - pancake, jvoisin, jfrankowski */ 2 | 3 | #include 4 | #if USE_YARAX 5 | #include 6 | #define YR_MAJOR_VERSION 6 7 | #define R2YR_RULE YRX_RULE 8 | #define R2YR_RULES YRX_RULES 9 | #define R2YR_MATCH YRX_MATCH 10 | #define R2YR_COMPILER YRX_COMPILER 11 | #define R2YR_COMPILER_DESTROY yrx_compiler_destroy 12 | #define R2YR_RULES_DESTROY yrx_rules_destroy 13 | #define R2YR_RULE_STRINGS_FOREACH yrx_rule_strings_foreach 14 | #define R2YR_RESULT YRX_RESULT 15 | #define R2YR_SUCCESS YRX_SUCCESS 16 | #else 17 | #include 18 | #define R2YR_RULE YR_RULE 19 | #define R2YR_RULES YR_RULES 20 | #define R2YR_MATCH YR_MATCH 21 | #define R2YR_COMPILER YR_COMPILER 22 | #define R2YR_COMPILER_DESTROY yr_compiler_destroy 23 | #define R2YR_RULES_DESTROY yr_rules_destroy 24 | #define R2YR_RULE_STRINGS_FOREACH yr_rule_strings_foreach 25 | #endif 26 | 27 | #if R2_VERSION_NUMBER >= 50909 28 | #define R2_PRINTF(...) r_cons_printf(r2yara->core->cons, __VA_ARGS__) 29 | #else 30 | #define R2_PRINTF(...) r_cons_printf(__VA_ARGS__) 31 | #endif 32 | 33 | const char *short_help_message_yrg[] = { 34 | "Usage: yrg", "[action] [args..]", " load and run yara rules inside r2", 35 | "yrg-", "", "delete last pattern added to the yara rule", 36 | "yrg-", "*", "delete all the patterns in the current rule", 37 | "yrgs", " ([len])", "add string (optionally specify the length)", 38 | "yrgx", " ([len])", "add hexpairs of blocksize (or custom length)", 39 | "yrgf", " ([len])", "add function bytepattern signature", 40 | "yrgz", "", "add all strings referenced from current function", 41 | NULL 42 | }; 43 | 44 | const char *short_help_message[] = { 45 | "Usage: yr", "[action] [args..]", " load and run yara rules inside r2", 46 | "yr", " [file]", "add yara rules from file", 47 | "yr+", "", "add the currently generated yara rule", 48 | "yr", "", "same as yr?", 49 | "yr", "-*", "unload all the rules", 50 | "yr?", "", "show this help (same as 'yara?')", 51 | "yrg", "[?][-sxf]", "generate yara rule", 52 | "yrl", "", "list loaded rules", 53 | "yrs", "[q]", "scan the current file, suffix with 'q' for quiet mode", 54 | "yrt", " ([tagname])", "list tags from loaded rules, or list rules from given tag", 55 | "yrv", "", "show version information about r2yara and yara", 56 | NULL 57 | }; 58 | 59 | const char *long_help_message[] = { 60 | "Usage: yara", " [action] [args..]", " load and run yara rules inside r2", 61 | "yara", " add [file]", "Add yara rules from file", 62 | "yara", " clear", "Clear all rules", 63 | "yara", " help", "Show this help (same as 'yara?')", 64 | "yara", " list", "List all rules", 65 | "yara", " scan[S]", "Scan the current file, if S option is given it prints matching strings", 66 | "yara", " show [name]", "Show rules containing name", 67 | "yara", " tag [name]", "List rules with tag 'name'", 68 | "yara", " tags", "List tags from the loaded rules", 69 | "yara", " version", "Show version information about r2yara and yara", 70 | NULL 71 | }; 72 | 73 | #if R2_VERSION_NUMBER < 50809 74 | static inline char *r_str_after(char *s, char c) { 75 | if (s) { 76 | char *p = strchr (s, c); 77 | if (p) { 78 | *p++ = 0; 79 | return p; 80 | } 81 | } 82 | return NULL; 83 | } 84 | #endif 85 | typedef struct { 86 | bool initialized; 87 | bool print_strings; 88 | unsigned int flagidx; 89 | bool iova; // true 90 | RList *rules_list; 91 | RList *genstrings; 92 | ut64 map_addr; 93 | RCore *core; 94 | } R2Yara; 95 | 96 | #if R2_VERSION_NUMBER < 50909 97 | static R_TH_LOCAL R2Yara Gr2yara = { 0 }; 98 | #endif 99 | 100 | /* Because of how the rules are compiled, we are not allowed to add more 101 | * rules to a compiler once it has compiled. That's why we keep a list 102 | * of those compiled rules. 103 | */ 104 | 105 | #if USE_YARAX 106 | typedef struct { 107 | R2Yara *r2yara; 108 | const uint8_t *buf; 109 | size_t buflen; 110 | char *rule_ident; 111 | unsigned int ruleidx; 112 | } YRXScanCtx; 113 | 114 | static void yrx_match_cb(const struct YRX_MATCH *match_, void *user_data) { 115 | YRXScanCtx *ctx = (YRXScanCtx *)user_data; 116 | R2Yara *r2yara = ctx->r2yara; 117 | RCore *core = r2yara->core; 118 | RPrint *print = core->print; 119 | 120 | ut64 n = r2yara->map_addr + (ut64)match_->offset; 121 | if (!r2yara->iova) { 122 | RIOMap *map = r_io_map_get_at (core->io, n); 123 | if (map) { 124 | n -= r_io_map_begin (map) - map->delta; 125 | } 126 | } 127 | 128 | r_strf_var (flag, 256, "yara%d.%s_%u", r2yara->flagidx, ctx->rule_ident? ctx->rule_ident: "rule", ctx->ruleidx); 129 | if (r2yara->print_strings) { 130 | R2_PRINTF ("0x%08" PFMT64x ": %s : ", n, flag); 131 | #if R2_VERSION_NUMBER >= 50909 132 | if (ctx->buf && match_->offset + match_->length <= ctx->buflen) { 133 | r_print_bytes (print, ctx->buf + match_->offset, match_->length, "%02x", 0); 134 | } 135 | #else 136 | if (ctx->buf && match_->offset + match_->length <= ctx->buflen) { 137 | r_print_bytes (print, ctx->buf + match_->offset, match_->length, "%02x"); 138 | } 139 | #endif 140 | } 141 | r_flag_set (core->flags, flag, n, match_->length); 142 | ctx->ruleidx++; 143 | } 144 | 145 | static void yrx_pattern_cb(const struct YRX_PATTERN *pattern, void *user_data) { 146 | YRXScanCtx *ctx = (YRXScanCtx *)user_data; 147 | yrx_pattern_iter_matches (pattern, yrx_match_cb, ctx); 148 | } 149 | 150 | static void callback(const struct YRX_RULE *rule, void *user_data) { 151 | YRXScanCtx *ctx = (YRXScanCtx *)user_data; 152 | R2Yara *r2yara = ctx->r2yara; 153 | const uint8_t *ident = NULL; 154 | size_t ident_len = 0; 155 | if (yrx_rule_identifier (rule, &ident, &ident_len) == YRX_SUCCESS && ident && ident_len > 0) { 156 | free (ctx->rule_ident); 157 | ctx->rule_ident = (char *)malloc (ident_len + 1); 158 | if (ctx->rule_ident) { 159 | memcpy (ctx->rule_ident, ident, ident_len); 160 | ctx->rule_ident[ident_len] = '\0'; 161 | } 162 | } 163 | if (ctx->rule_ident) { 164 | R2_PRINTF ("%s\n", ctx->rule_ident); 165 | } 166 | ctx->ruleidx = 0; 167 | yrx_rule_iter_patterns (rule, yrx_pattern_cb, ctx); 168 | r2yara->flagidx++; 169 | } 170 | 171 | // --- Helpers for listing/showing/tags with YARA-X --- 172 | typedef struct { 173 | const char *filter; // optional substring filter 174 | R2Yara *r2yara; 175 | } YRXShowCtx; 176 | 177 | static void yrx_print_rule_name_cb(const struct YRX_RULE *rule, void *user_data) { 178 | YRXShowCtx *ctx = (YRXShowCtx *)user_data; 179 | R2Yara *r2yara = ctx->r2yara; 180 | const uint8_t *ident = NULL; 181 | size_t len = 0; 182 | if (yrx_rule_identifier (rule, &ident, &len) != YRX_SUCCESS || !ident || len == 0) { 183 | return; 184 | } 185 | char *s = (char *)malloc (len + 1); 186 | if (!s) { 187 | return; 188 | } 189 | memcpy (s, ident, len); 190 | s[len] = '\0'; 191 | if (!ctx->filter || r_str_casestr (s, ctx->filter)) { 192 | R2_PRINTF ("%s\n", s); 193 | } 194 | free (s); 195 | } 196 | 197 | static void yrx_add_tag_to_list_cb(const char *tag, void *user_data) { 198 | RList *tag_list = (RList *)user_data; 199 | if (!r_list_find (tag_list, tag, (RListComparator)strcmp)) { 200 | r_list_add_sorted (tag_list, strdup (tag), (RListComparator)strcmp); 201 | } 202 | } 203 | 204 | static void yrx_rule_collect_tags_cb(const struct YRX_RULE *rule, void *user_data) { 205 | yrx_rule_iter_tags (rule, yrx_add_tag_to_list_cb, user_data); 206 | } 207 | 208 | typedef struct { 209 | const char *search; 210 | R2Yara *r2yara; 211 | const struct YRX_RULE *rule; 212 | bool printed; 213 | } YRXTagCtx; 214 | 215 | static void yrx_tag_filter_cb(const char *tag, void *user_data) { 216 | YRXTagCtx *ctx = (YRXTagCtx *)user_data; 217 | if (ctx->printed) { 218 | return; 219 | } 220 | if (!ctx->search || !r_str_casestr (tag, ctx->search)) { 221 | return; 222 | } 223 | R2Yara *r2yara = ctx->r2yara; 224 | const uint8_t *ident = NULL; 225 | size_t len = 0; 226 | if (yrx_rule_identifier (ctx->rule, &ident, &len) == YRX_SUCCESS && ident && len) { 227 | char *s = (char *)malloc (len + 1); 228 | if (!s) { 229 | return; 230 | } 231 | memcpy (s, ident, len); 232 | s[len] = '\0'; 233 | R2_PRINTF ("%s\n", s); 234 | free (s); 235 | ctx->printed = true; 236 | } 237 | } 238 | 239 | static void yrx_rule_tags_filter_cb(const struct YRX_RULE *rule, void *user_data) { 240 | YRXTagCtx *ctx = (YRXTagCtx *)user_data; 241 | YRXTagCtx inner = { .search = ctx->search, .r2yara = ctx->r2yara, .rule = rule, .printed = false }; 242 | yrx_rule_iter_tags (rule, yrx_tag_filter_cb, &inner); 243 | } 244 | #elif YR_MAJOR_VERSION < 4 245 | static int callback(int message, void *msg_data, void *user_data) { 246 | R2Yara *r2yara = (R2Yara *)user_data; 247 | RCore *core = r2yara->core; 248 | RPrint *print = core->print; 249 | unsigned int ruleidx; 250 | st64 offset = 0; 251 | ut64 n = 0; 252 | 253 | R2YR_RULE *rule = msg_data; 254 | 255 | if (message == CALLBACK_MSG_RULE_MATCHING) { 256 | YR_STRING *string; 257 | R2_PRINTF ("%s\n", rule->identifier); 258 | ruleidx = 0; 259 | yr_rule_strings_foreach (rule, string) { 260 | R2YR_MATCH *match; 261 | 262 | yr_string_matches_foreach (string, match) { 263 | n = match->base + match->offset; 264 | // Find virtual address if needed 265 | if (r2yara->iova) { 266 | RIOMap *map = r_io_map_get_paddr (core->io, n); 267 | if (map) { 268 | offset = r_io_map_begin (map) - map->delta; 269 | } 270 | } 271 | r_strf_var (flag, 256, "%s%d.%s_%d", "yara", flagidx, rule->identifier, ruleidx); 272 | if (r2yara->print_strings) { 273 | r_cons_printf ("0x%08" PFMT64x ": %s : ", n + offset, flag); 274 | r_print_bytes (print, match->data, match->data_length, "%02x"); 275 | } 276 | r_flag_set (core->flags, flag, n + offset, match->data_length); 277 | ruleidx++; 278 | } 279 | } 280 | flagidx++; 281 | } 282 | return CALLBACK_CONTINUE; 283 | } 284 | 285 | static void compiler_callback(int error_level, const char *file_name, 286 | int line_number, const char *message, void *user_data) { 287 | // TODO depending on error_level. use R_LOG_WARN, ERROR or INFO 288 | R_LOG_INFO ("file: %s line_number: %d: %s", file_name, line_number, message); 289 | return; 290 | } 291 | #else 292 | static int callback(YR_SCAN_CONTEXT *context, int message, void *msg_data, void *user_data) { 293 | R2Yara *r2yara = (R2Yara *)user_data; 294 | RCore *core = r2yara->core; 295 | RPrint *print = core->print; 296 | ut64 n = 0; 297 | ut64 map_addr = r2yara->map_addr; 298 | R2YR_RULE *rule = msg_data; 299 | 300 | #if USE_YARAX 301 | #else 302 | if (message == CALLBACK_MSG_RULE_MATCHING) { 303 | YR_STRING *string; 304 | R2_PRINTF ("%s\n", rule->identifier); 305 | unsigned int ruleidx = 0; 306 | yr_rule_strings_foreach (rule, string) { 307 | YR_MATCH *match; 308 | yr_string_matches_foreach (context, string, match) { 309 | n = map_addr + match->base + match->offset; 310 | // Find virtual address if needed 311 | if (!r2yara->iova) { 312 | RIOMap *map = r_io_map_get_at (core->io, n); 313 | if (map) { 314 | n -= r_io_map_begin (map) - map->delta; 315 | } 316 | #if 0 317 | RIOMap *map = r_io_map_get_paddr (core->io, n); 318 | if (map) { 319 | // offset = r_io_map_begin (map) - map->delta; 320 | n -= r_io_map_begin (map) + map->delta; 321 | // n = r_io_map_begin (map) - map->delta; 322 | } 323 | #endif 324 | } 325 | r_strf_var (flag, 256, "yara%d.%s_%d", r2yara->flagidx, rule->identifier, ruleidx); 326 | if (r2yara->print_strings) { 327 | R2_PRINTF ("0x%08" PFMT64x ": %s : ", n, flag); 328 | #if R2_VERSION_NUMBER >= 50909 329 | r_print_bytes (print, match->data, match->data_length, "%02x", 0); 330 | #else 331 | r_print_bytes (print, match->data, match->data_length, "%02x"); 332 | #endif 333 | } 334 | r_flag_set (core->flags, flag, n, match->data_length); 335 | ruleidx++; 336 | } 337 | } 338 | r2yara->flagidx++; 339 | } 340 | #endif 341 | return CALLBACK_CONTINUE; 342 | } 343 | 344 | static void compiler_callback(int error_level, const char *file_name, 345 | int line_number, const struct R2YR_RULE *rule, const char *message, void *user_data) { 346 | // TODO depending on error_level. use R_LOG_WARN, ERROR or INFO 347 | R_LOG_INFO ("file: %s line_number: %d %s", file_name, line_number, message); 348 | return; 349 | } 350 | #endif 351 | 352 | static bool yr_scan(R2Yara *r2yara, void *to_scan, size_t to_scan_size) { 353 | RListIter *rules_it; 354 | R2YR_RULES *rules; 355 | #if USE_YARAX 356 | YRX_SCANNER *scanner = NULL; 357 | YRXScanCtx ctx = { .r2yara = r2yara, .buf = (const uint8_t *)to_scan, .buflen = to_scan_size, .rule_ident = NULL, .ruleidx = 0 }; 358 | r_list_foreach (r2yara->rules_list, rules_it, rules) { 359 | YRX_RESULT res = yrx_scanner_create (rules, &scanner); 360 | if (res == YRX_SUCCESS) { 361 | yrx_scanner_on_matching_rule (scanner, callback, &ctx); 362 | res = yrx_scanner_scan (scanner, to_scan, to_scan_size); 363 | if (res != YRX_SUCCESS) { 364 | // handle error, but continue 365 | } 366 | } 367 | if (scanner) { 368 | yrx_scanner_destroy (scanner); 369 | scanner = NULL; 370 | } 371 | } 372 | free (ctx.rule_ident); 373 | #else 374 | r_list_foreach (r2yara->rules_list, rules_it, rules) { 375 | if (yr_rules_scan_mem (rules, to_scan, to_scan_size, 0, callback, (void *)r2yara, 0) != 0) { 376 | // handle error 377 | } 378 | } 379 | #endif 380 | return true; 381 | } 382 | 383 | static bool yr_vscan(R2Yara *r2yara, ut64 from, int to_scan_size) { 384 | R_LOG_DEBUG ("-> 0x%" PFMT64x " + %d\n", from, to_scan_size); 385 | RCore *core = r2yara->core; 386 | if (to_scan_size < 1) { 387 | R_LOG_ERROR ("Invalid file size"); 388 | return false; 389 | } 390 | void *to_scan = malloc (to_scan_size); 391 | if (!to_scan) { 392 | R_LOG_ERROR ("Something went wrong during memory allocation"); 393 | return false; 394 | } 395 | int result = r_io_read_at (core->io, from, to_scan, to_scan_size); 396 | if (!result) { 397 | R_LOG_ERROR ("Something went wrong during r_io_read_at"); 398 | free (to_scan); 399 | return false; 400 | } 401 | bool res = yr_scan (r2yara, to_scan, to_scan_size); 402 | free (to_scan); 403 | return res; 404 | } 405 | 406 | static bool yr_pscan(R2Yara *r2yara) { 407 | RCore *core = r2yara->core; 408 | const size_t to_scan_size = r_io_size (core->io); 409 | if (to_scan_size < 1) { 410 | R_LOG_ERROR ("Invalid file size"); 411 | return false; 412 | } 413 | void *to_scan = malloc (to_scan_size); 414 | if (!to_scan) { 415 | R_LOG_ERROR ("Something went wrong during memory allocation"); 416 | return false; 417 | } 418 | int result = r_io_pread_at (core->io, 0L, to_scan, to_scan_size); 419 | if (!result) { 420 | R_LOG_ERROR ("Something went wrong during r_io_read_at"); 421 | free (to_scan); 422 | return false; 423 | } 424 | bool res = yr_scan (r2yara, to_scan, to_scan_size); 425 | free (to_scan); 426 | return res; 427 | } 428 | 429 | static int cmd_yara_scan(R2Yara *r2yara, const char *R_NULLABLE option) { 430 | RCore *core = r2yara->core; 431 | 432 | const char *yara_in = r_config_get (core->config, "yara.in"); 433 | RList *ranges = r_core_get_boundaries_prot (core, 0, yara_in, NULL); 434 | RListIter *iter; 435 | RIOMap *range; 436 | r_flag_space_push (core->flags, "yara"); 437 | r2yara->iova = r_config_get_b (core->config, "yara.va"); 438 | #if 0 439 | if (r2yara->iova) { 440 | r2yara->iova = r_config_get_b (core->config, "io.va"); 441 | } 442 | #endif 443 | r2yara->print_strings = true; 444 | if (option != NULL) { 445 | if (*option == 'q') { 446 | r2yara->print_strings = false; 447 | } else { 448 | R_LOG_ERROR ("Invalid option"); 449 | return false; 450 | } 451 | } 452 | r2yara->map_addr = 0; 453 | if (!r_list_empty (ranges)) { 454 | r_list_foreach (ranges, iter, range) { 455 | ut64 begin = r_io_map_begin (range); 456 | ut64 end = r_io_map_end (range); 457 | ut64 size = end - begin; 458 | r2yara->map_addr = begin; 459 | yr_vscan (r2yara, begin, (int)size); 460 | } 461 | return true; 462 | } 463 | return yr_pscan (r2yara); 464 | } 465 | 466 | static int cmd_yara_show(R2Yara *r2yara, const char *name) { 467 | /* List loaded rules containing name */ 468 | RListIter *rules_it; 469 | R2YR_RULES *rules; 470 | R2YR_RULE *rule; 471 | 472 | r_list_foreach (r2yara->rules_list, rules_it, rules) { 473 | #if USE_YARAX 474 | YRXShowCtx ctx = (YRXShowCtx){ .filter = name, .r2yara = r2yara }; 475 | yrx_rules_iter (rules, yrx_print_rule_name_cb, &ctx); 476 | #else 477 | yr_rules_foreach (rules, rule) { 478 | if (r_str_casestr (rule->identifier, name)) { 479 | R2_PRINTF ("%s\n", rule->identifier); 480 | } 481 | } 482 | #endif 483 | } 484 | return true; 485 | } 486 | 487 | static int cmd_yara_tags(R2Yara *r2yara) { 488 | /* List tags from all the different loaded rules */ 489 | RListIter *rules_it; 490 | RListIter *tags_it; 491 | R2YR_RULES *rules; 492 | R2YR_RULE *rule; 493 | const char *tag_name; 494 | RList *tag_list = r_list_new (); 495 | tag_list->free = free; 496 | 497 | r_list_foreach (r2yara->rules_list, rules_it, rules) { 498 | #if USE_YARAX 499 | yrx_rules_iter (rules, yrx_rule_collect_tags_cb, tag_list); 500 | #else 501 | yr_rules_foreach (rules, rule) { 502 | yr_rule_tags_foreach (rule, tag_name) { 503 | if (!r_list_find (tag_list, tag_name, (RListComparator)strcmp)) { 504 | r_list_add_sorted (tag_list, 505 | strdup (tag_name), (RListComparator)strcmp); 506 | } 507 | } 508 | } 509 | #endif 510 | } 511 | 512 | R2_PRINTF ("[YARA tags]\n"); 513 | r_list_foreach (tag_list, tags_it, tag_name) { 514 | R2_PRINTF ("%s\n", tag_name); 515 | } 516 | 517 | r_list_free (tag_list); 518 | 519 | return true; 520 | } 521 | 522 | static int cmd_yara_tag(R2Yara *r2yara, const char *search_tag) { 523 | /* List rules with tag search_tag */ 524 | RListIter *rules_it; 525 | R2YR_RULES *rules; 526 | R2YR_RULE *rule; 527 | const char *tag_name; 528 | 529 | #if USE_YARAX 530 | r_list_foreach (r2yara->rules_list, rules_it, rules) { 531 | YRXTagCtx ctx = { .search = search_tag, .r2yara = r2yara, .rule = NULL, .printed = false }; 532 | yrx_rules_iter (rules, yrx_rule_tags_filter_cb, &ctx); 533 | } 534 | #else 535 | r_list_foreach (r2yara->rules_list, rules_it, rules) { 536 | yr_rules_foreach (rules, rule) { 537 | yr_rule_tags_foreach (rule, tag_name) { 538 | if (search_tag && r_str_casestr (tag_name, search_tag)) { 539 | R2_PRINTF ("%s\n", rule->identifier); 540 | break; 541 | } 542 | } 543 | } 544 | } 545 | #endif 546 | 547 | return true; 548 | } 549 | 550 | static int cmd_yara_list(R2Yara *r2yara) { 551 | #if USE_YARAX 552 | /* List all loaded rules */ 553 | RListIter *rules_it; 554 | R2YR_RULES *rules; 555 | r_list_foreach (r2yara->rules_list, rules_it, rules) { 556 | YRXShowCtx ctx = { .filter = NULL, .r2yara = r2yara }; 557 | yrx_rules_iter (rules, yrx_print_rule_name_cb, &ctx); 558 | } 559 | #else 560 | /* List all loaded rules */ 561 | RListIter *rules_it; 562 | R2YR_RULES *rules; 563 | R2YR_RULE *rule; 564 | r_list_foreach (r2yara->rules_list, rules_it, rules) { 565 | yr_rules_foreach (rules, rule) { 566 | R2_PRINTF ("%s\n", rule->identifier); 567 | } 568 | } 569 | #endif 570 | return 0; 571 | } 572 | 573 | static int cmd_yara_clear(R2Yara *r2yara) { 574 | /* Clears all loaded rules */ 575 | r_list_free (r2yara->rules_list); 576 | r2yara->rules_list = r_list_newf ((RListFree)R2YR_RULES_DESTROY); 577 | R_LOG_INFO ("Rules cleared"); 578 | return 0; 579 | } 580 | 581 | static void logerr(R2YR_COMPILER *compiler, const char *R_NULLABLE arg) { 582 | #if USE_YARAX 583 | const char *le = yrx_last_error (); 584 | if (R_STR_ISNOTEMPTY (arg) && le && *le) { 585 | R_LOG_ERROR ("%s: %s", arg, le); 586 | } else if (le && *le) { 587 | R_LOG_ERROR ("%s", le); 588 | } else if (R_STR_ISNOTEMPTY (arg)) { 589 | R_LOG_ERROR ("%s", arg); 590 | } else { 591 | R_LOG_ERROR ("unknown error"); 592 | } 593 | #else 594 | char buf[64]; 595 | const char *errmsg = yr_compiler_get_error_message (compiler, buf, sizeof (buf)); 596 | if (R_STR_ISNOTEMPTY (arg)) { 597 | R_LOG_ERROR ("%s %s", errmsg, arg); 598 | } else { 599 | R_LOG_ERROR ("%s", errmsg); 600 | } 601 | #endif 602 | } 603 | 604 | static int cmd_yara_add_file(R2Yara *r2yara, const char *rules_path) { 605 | R2YR_COMPILER *compiler = NULL; 606 | R2YR_RULES *rules = NULL; 607 | 608 | if (!rules_path) { 609 | R_LOG_INFO ("Please tell me what am I supposed to load"); 610 | return false; 611 | } 612 | 613 | FILE *rules_file = r_sandbox_fopen (rules_path, "r"); 614 | if (!rules_file) { 615 | R_LOG_ERROR ("Unable to open %s", rules_path); 616 | return false; 617 | } 618 | 619 | #if USE_YARAX 620 | // Compile with YARA-X from source string 621 | char *rules_src = (char *)r_file_slurp (rules_path, NULL); 622 | fclose (rules_file); 623 | rules_file = NULL; 624 | if (!rules_src) { 625 | R_LOG_ERROR ("Unable to read %s", rules_path); 626 | return false; 627 | } 628 | YRX_RESULT yres = yrx_compile (rules_src, &rules); 629 | free (rules_src); 630 | if (yres != YRX_SUCCESS) { 631 | logerr (NULL, rules_path); 632 | return false; 633 | } 634 | #else 635 | if (yr_compiler_create (&compiler) != ERROR_SUCCESS) { 636 | logerr (compiler, NULL); 637 | fclose (rules_file); 638 | return false; 639 | } 640 | int result = yr_compiler_add_file (compiler, rules_file, NULL, rules_path); 641 | fclose (rules_file); 642 | rules_file = NULL; 643 | if (result > 0) { 644 | logerr (compiler, rules_path); 645 | R2YR_COMPILER_DESTROY (compiler); 646 | return false; 647 | } 648 | if (yr_compiler_get_rules (compiler, &rules) != ERROR_SUCCESS) { 649 | logerr (compiler, NULL); 650 | R2YR_COMPILER_DESTROY (compiler); 651 | return false; 652 | } 653 | R2YR_COMPILER_DESTROY (compiler); 654 | #endif 655 | 656 | r_list_append (r2yara->rules_list, rules); 657 | return true; 658 | } 659 | 660 | static RStrBuf *get_current_rule(R2Yara *r2yara) { 661 | RStrBuf *sb = r_strbuf_new (""); 662 | RConfig *cfg = r2yara->core->config; 663 | const char *name = r_config_get (cfg, "yara.rule"); 664 | const char *tags = r_config_get (cfg, "yara.tags"); 665 | const char *auth = r_config_get (cfg, "yara.author"); 666 | const char *desc = r_config_get (cfg, "yara.description"); 667 | const char *date = r_config_get (cfg, "yara.date"); 668 | const char *vers = r_config_get (cfg, "yara.version"); 669 | const int amount = r_config_get_i (cfg, "yara.amount"); 670 | r_strbuf_appendf (sb, "rule %s : %s {\n", name, tags); 671 | r_strbuf_appendf (sb, " meta:\n"); 672 | r_strbuf_appendf (sb, " author = \"%s\"\n", auth); 673 | r_strbuf_appendf (sb, " description = \"%s\"\n", desc); 674 | r_strbuf_appendf (sb, " date = \"%s\"\n", date); 675 | r_strbuf_appendf (sb, " version = \"%s\"\n", vers); 676 | if (r_list_empty (r2yara->genstrings)) { 677 | R_LOG_WARN ("See 'yrg?' to find out which subcommands use to append patterns to the rule"); 678 | } else { 679 | r_strbuf_append (sb, " strings:\n"); 680 | RListIter *iter; 681 | const char *s; 682 | r_list_foreach (r2yara->genstrings, iter, s) { 683 | r_strbuf_appendf (sb, " $ = %s\n", s); 684 | } 685 | r_strbuf_append (sb, " condition:\n"); 686 | if (amount > 1) { 687 | r_strbuf_appendf (sb, " %d of them\n", amount); 688 | } else { 689 | r_strbuf_append (sb, " all of them\n"); 690 | } 691 | } 692 | r_strbuf_append (sb, "}\n"); 693 | return sb; 694 | } 695 | 696 | static void cmd_yara_gen_show(R2Yara *r2yara) { 697 | R2_PRINTF ("%s", r_strbuf_tostring (get_current_rule (r2yara))); 698 | } 699 | 700 | static void cmd_yara_add_current(R2Yara *r2yara) { 701 | R2YR_COMPILER *compiler = NULL; 702 | R2YR_RULES *yr_rules = NULL; 703 | 704 | if (r_list_empty (r2yara->genstrings)) { 705 | R_LOG_WARN ("Empty pattern, see 'yrg?' to find out which subcommands use to append patterns to the rule"); 706 | return; 707 | } 708 | #if USE_YARAX 709 | { 710 | const char *src = r_strbuf_tostring (get_current_rule (r2yara)); 711 | if (yrx_compile (src, &yr_rules) != YRX_SUCCESS) { 712 | logerr (NULL, NULL); 713 | goto err_exit; 714 | } 715 | } 716 | #else 717 | if (yr_compiler_create (&compiler) != ERROR_SUCCESS) { 718 | logerr (compiler, NULL); 719 | goto err_exit; 720 | } 721 | if (yr_compiler_add_string (compiler, r_strbuf_tostring (get_current_rule (r2yara)), NULL) > 0) { 722 | logerr (compiler, NULL); 723 | goto err_exit; 724 | } 725 | if (yr_compiler_get_rules (compiler, &yr_rules) != ERROR_SUCCESS) { 726 | logerr (compiler, NULL); 727 | goto err_exit; 728 | } 729 | #endif 730 | 731 | r_list_append (r2yara->rules_list, yr_rules); 732 | R_LOG_INFO ("Rule successfully added"); 733 | 734 | err_exit: 735 | #if !USE_YARAX 736 | if (compiler != NULL) { 737 | R2YR_COMPILER_DESTROY (compiler); 738 | } 739 | #else 740 | return; 741 | #endif 742 | } 743 | 744 | static char *yarastring(const char *s) { 745 | RStrBuf *sb = r_strbuf_new ("\""); 746 | char *a = strdup (s); 747 | r_str_trim (a); 748 | a = r_str_replace_all (a, "\n", "\\n"); 749 | r_strbuf_append (sb, a); 750 | r_strbuf_append (sb, "\""); 751 | free (a); 752 | return r_strbuf_drain (sb); 753 | ; 754 | } 755 | 756 | static int cmd_yara_gen(R2Yara *r2yara, const char *input) { 757 | const char arg0 = input? *input: 0; 758 | switch (arg0) { 759 | case 0: 760 | cmd_yara_gen_show (r2yara); 761 | break; 762 | case '?': 763 | r_core_cmd_help (r2yara->core, short_help_message_yrg); 764 | break; 765 | case 'z': 766 | { 767 | char *s = r_core_cmd_str (r2yara->core, "axff~str.~[3]~$$"); 768 | if (!s) { 769 | break; 770 | } 771 | r_str_trim (s); 772 | RList *words = r_str_split_list (s, "\n", 0); 773 | words->free = free; 774 | RListIter *iter; 775 | char *word; 776 | r_list_foreach (words, iter, word) { 777 | char *z = r_core_cmd_strf (r2yara->core, "psz @ %s", word); 778 | r_list_append (r2yara->genstrings, yarastring (z)); 779 | free (z); 780 | } 781 | r_list_free (words); 782 | free (s); 783 | } 784 | break; 785 | case 'f': 786 | { 787 | char *b = r_core_cmd_str (r2yara->core, "zj $$~{.bytes}"); 788 | if (!b) { 789 | break; 790 | } 791 | char *m = r_core_cmd_str (r2yara->core, "zj $$~{.mask}"); 792 | if (!m) { 793 | free (b); 794 | break; 795 | } 796 | 797 | r_str_trim (b); 798 | r_str_trim (m); 799 | size_t blen = strlen (b); 800 | if (blen != strlen (m)) { 801 | R_LOG_WARN ("Mismatch"); 802 | free (b); 803 | free (m); 804 | break; 805 | } 806 | if (blen % 2) { 807 | R_LOG_WARN ("Uneven pattern"); 808 | free (b); 809 | free (m); 810 | break; 811 | } 812 | if (blen == 0) { 813 | R_LOG_WARN ("No byte pattern"); 814 | free (b); 815 | free (m); 816 | break; 817 | } 818 | R_LOG_DEBUG ("-> %s\n", b); 819 | R_LOG_DEBUG ("=> %s\n", m); 820 | RStrBuf *sb = r_strbuf_new ("{"); 821 | int i; 822 | for (i = 0; b[i]; i += 2) { 823 | if (r_str_startswith (m + i, "ff")) { 824 | r_strbuf_appendf (sb, " %c%c", b[i], b[i + 1]); 825 | } else { 826 | r_strbuf_append (sb, " ??"); 827 | } 828 | } 829 | r_strbuf_append (sb, " }"); 830 | char *s = r_strbuf_drain (sb); 831 | r_list_append (r2yara->genstrings, s); 832 | free (b); 833 | free (m); 834 | } 835 | break; 836 | case 's': 837 | { 838 | char *s; 839 | if (input[1]) { 840 | int len = (int)r_num_math (r2yara->core->num, input + 1); 841 | s = r_core_cmd_strf (r2yara->core, "psz %d", len); 842 | } else { 843 | s = r_core_cmd_str (r2yara->core, "psz"); 844 | } 845 | if (!s) { 846 | break; 847 | } 848 | r_list_append (r2yara->genstrings, yarastring (s)); 849 | free (s); 850 | } 851 | break; 852 | case '-': 853 | if (input && input[1] == '*') { 854 | r_list_free (r2yara->genstrings); 855 | r2yara->genstrings = r_list_newf (free); 856 | } else { 857 | free (r_list_pop (r2yara->genstrings)); 858 | } 859 | break; 860 | case 'x': 861 | { 862 | char *s; 863 | if (input[1]) { 864 | int len = r_num_math (r2yara->core->num, input + 1); 865 | s = r_core_cmd_strf (r2yara->core, "pcy %d", len); 866 | } else { 867 | s = r_core_cmd_str (r2yara->core, "pcy"); 868 | } 869 | if (!s) { 870 | break; 871 | } 872 | r_str_trim (s); 873 | r_list_append (r2yara->genstrings, s); 874 | } 875 | break; 876 | } 877 | return 0; 878 | } 879 | 880 | static bool cmd_yara_add(R2Yara *r2yara, const char *input) { 881 | /* Add a rule with user input */ 882 | // R2YR_COMPILER* compiler = NULL; 883 | int i; 884 | if (!input) { 885 | R_LOG_ERROR ("Missing argument"); 886 | return false; 887 | } 888 | 889 | for (i = 0; input[i]; i++) { 890 | if (input[i] != ' ') { 891 | return cmd_yara_add_file (r2yara, input + i); 892 | } 893 | } 894 | return false; 895 | } 896 | 897 | static int cmd_yara_version(R2Yara *r2yara) { 898 | R2_PRINTF ("r2 %s\n", R2_VERSION); 899 | #if USE_YARAX 900 | R2_PRINTF ("yarax git\n"); 901 | #else 902 | R2_PRINTF ("yara %s\n", YR_VERSION); 903 | #endif 904 | R2_PRINTF ("r2yara %s\n", R2Y_VERSION); 905 | return 0; 906 | } 907 | 908 | // TODO: deprecate the "yara" command, unless we expose "yara" and "yarac" commands as the original tools from the r2 shell 909 | static int cmd_yara_process(R2Yara *r2yara, const char *input) { 910 | char *inp = strdup (input); 911 | char *arg = r_str_after (inp, ' '); 912 | if (arg) { 913 | arg = (char *)r_str_trim_head_ro (arg); 914 | } 915 | int res = -1; 916 | if (r_str_startswith (input, "add")) { 917 | res = cmd_yara_add (r2yara, arg); 918 | } else if (r_str_startswith (inp, "clear")) { 919 | res = cmd_yara_clear (r2yara); 920 | } else if (r_str_startswith (inp, "list")) { 921 | res = cmd_yara_list (r2yara); 922 | } else if (r_str_startswith (inp, "scanS") || r_str_startswith (inp, "scan S")) { 923 | res = cmd_yara_scan (r2yara, "q"); 924 | } else if (r_str_startswith (inp, "scan")) { 925 | res = cmd_yara_scan (r2yara, arg); 926 | } else if (r_str_startswith (inp, "show")) { 927 | res = cmd_yara_show (r2yara, arg); 928 | } else if (r_str_startswith (inp, "tags")) { 929 | res = cmd_yara_tags (r2yara); 930 | } else if (r_str_startswith (input, "tag ")) { 931 | res = cmd_yara_tag (r2yara, arg); 932 | } else if (r_str_startswith (input, "ver")) { 933 | res = cmd_yara_version (r2yara); 934 | } else { 935 | r_core_cmd_help (r2yara->core, long_help_message); 936 | } 937 | free (inp); 938 | return res; 939 | } 940 | 941 | static int cmd_yr(R2Yara *r2yara, const char *input) { 942 | char *inp = strdup (input); 943 | char *arg = r_str_after (inp, ' '); 944 | int res = -1; 945 | if (arg) { 946 | arg = (char *)r_str_trim_head_ro (arg); 947 | } 948 | switch (*input) { 949 | case '?': // "yr?" 950 | case 0: 951 | r_core_cmd_help (r2yara->core, short_help_message); 952 | break; 953 | case 'l': 954 | cmd_yara_list (r2yara); 955 | break; 956 | case '/': // "yr/" <- imho makes more sense 957 | case 's': // "yrs" 958 | if (input[1] == 'q') { 959 | res = cmd_yara_scan (r2yara, "q"); 960 | } else { 961 | res = cmd_yara_scan (r2yara, arg); 962 | } 963 | break; 964 | case 'g': // "yrg" 965 | cmd_yara_gen (r2yara, input + 1); 966 | break; 967 | case '+': // "yr+"" 968 | cmd_yara_add_current (r2yara); 969 | break; 970 | case ' ': 971 | cmd_yara_add (r2yara, arg); 972 | break; 973 | case '-': 974 | cmd_yara_clear (r2yara); 975 | break; 976 | case 't': // "yrt" 977 | if (input[1]) { 978 | if (input[1] == '?') { 979 | r_core_cmd_help_contains (r2yara->core, short_help_message, "yrt"); 980 | } else { 981 | cmd_yara_tag (r2yara, arg); 982 | } 983 | } else { 984 | cmd_yara_tags (r2yara); 985 | } 986 | break; 987 | case 'v': // "yrv" 988 | res = cmd_yara_version (r2yara); 989 | break; 990 | } 991 | free (inp); 992 | return res; 993 | } 994 | 995 | static int cmd_yara_load_default_rules(R2Yara *r2yara) { 996 | RListIter *iter = NULL; 997 | R2YR_COMPILER *compiler = NULL; 998 | R2YR_RULES *yr_rules = NULL; 999 | char *filename; 1000 | char *rules = NULL; 1001 | #if R2_VERSION_NUMBER < 50709 1002 | char *y3_rule_dir = r_str_newf ("%s%s%s", r_str_home (R2_HOME_PLUGINS), R_SYS_DIR, "rules-yara3"); 1003 | #else 1004 | char *y3_rule_dir = r_xdg_datadir ("plugins/rules-yara3"); 1005 | #endif 1006 | RList *list = r_sys_dir (y3_rule_dir); 1007 | 1008 | #if USE_YARAX 1009 | if (yrx_compiler_create (0, &compiler) != YRX_SUCCESS) { 1010 | logerr (compiler, NULL); 1011 | goto err_exit; 1012 | } 1013 | #else 1014 | if (yr_compiler_create (&compiler) != ERROR_SUCCESS) { 1015 | logerr (compiler, NULL); 1016 | goto err_exit; 1017 | } 1018 | yr_compiler_set_callback (compiler, compiler_callback, NULL); 1019 | #endif 1020 | 1021 | r_list_foreach (list, iter, filename) { 1022 | if (filename[0] == '.') { 1023 | // skip '.', '..' and hidden files 1024 | continue; 1025 | } 1026 | char *rulepath = r_str_newf ("%s%s%s", y3_rule_dir, R_SYS_DIR, filename); 1027 | if (r_str_endswith (filename, ".gz")) { 1028 | rules = (char *)r_file_gzslurp (rulepath, NULL, true); 1029 | } else { 1030 | rules = (char *)r_file_slurp (rulepath, NULL); 1031 | } 1032 | if (rules != NULL) { 1033 | #if USE_YARAX 1034 | if (yrx_compiler_add_source (compiler, rules) != YRX_SUCCESS) { 1035 | logerr (compiler, NULL); 1036 | } 1037 | #else 1038 | if (yr_compiler_add_string (compiler, rules, rulepath) > 0) { 1039 | logerr (compiler, NULL); 1040 | } 1041 | #endif 1042 | R_FREE (rules); 1043 | } else { 1044 | R_LOG_ERROR ("cannot load %s", rulepath); 1045 | } 1046 | free (rulepath); 1047 | } 1048 | r_list_free (list); 1049 | list = NULL; 1050 | 1051 | #if USE_YARAX 1052 | yr_rules = yrx_compiler_build (compiler); 1053 | if (!yr_rules) { 1054 | logerr (compiler, NULL); 1055 | goto err_exit; 1056 | } 1057 | #else 1058 | if (yr_compiler_get_rules (compiler, &yr_rules) != ERROR_SUCCESS) { 1059 | logerr (compiler, NULL); 1060 | goto err_exit; 1061 | } 1062 | #endif 1063 | 1064 | r_list_append (r2yara->rules_list, yr_rules); 1065 | 1066 | if (compiler) { 1067 | R2YR_COMPILER_DESTROY (compiler); 1068 | } 1069 | return true; 1070 | 1071 | err_exit: 1072 | free (y3_rule_dir); 1073 | if (compiler) { 1074 | R2YR_COMPILER_DESTROY (compiler); 1075 | } 1076 | r_list_free (list); 1077 | free (rules); 1078 | return false; 1079 | } 1080 | 1081 | // Move to r_sys_time_ymd? 1082 | static char *yyyymmdd(void) { 1083 | time_t current_time; 1084 | char *ds = calloc (16, 1); 1085 | time (¤t_time); 1086 | struct tm *time_info = localtime (¤t_time); 1087 | strftime (ds, 16, "%Y-%m-%d", time_info); 1088 | return ds; 1089 | } 1090 | 1091 | static bool yara_in_callback(void *user, void *data) { 1092 | RCore *core = (RCore *)user; 1093 | RConfigNode *node = (RConfigNode *)data; 1094 | if (*node->value == '?') { 1095 | #if R2_VERSION_NUMBER >= 50909 1096 | r_cons_printf (core->cons, 1097 | #else 1098 | r_cons_printf ( 1099 | #endif 1100 | "range search between .from/.to boundaries\n" 1101 | "flag find boundaries in ranges defined by flags larger than 1 byte\n" 1102 | "flag:[glob] find boundaries in flags matching given glob and larger than 1 byte\n" 1103 | "block search in the current block\n" 1104 | "io.map search in current map\n" 1105 | "io.maps search in all maps\n" 1106 | "io.maps.[rwx] search in all r-w-x io maps\n" 1107 | "bin.segment search in current mapped segment\n" 1108 | "bin.segments search in all mapped segments\n" 1109 | "bin.segments.[rwx] search in all r-w-x segments\n" 1110 | "bin.section search in current mapped section\n" 1111 | "bin.sections search in all mapped sections\n" 1112 | "bin.sections.[rwx] search in all r-w-x sections\n" 1113 | "dbg.stack search in the stack\n" 1114 | "dbg.heap search in the heap\n" 1115 | "dbg.map search in current memory map\n" 1116 | "dbg.maps search in all memory maps\n" 1117 | "dbg.maps.[rwx] search in all executable marked memory maps\n" 1118 | "anal.fcn search in the current function\n" 1119 | "anal.bb search in the current basic-block\n"); 1120 | return false; 1121 | } 1122 | return true; 1123 | } 1124 | 1125 | static void setup_config(R2Yara *r2yara) { 1126 | RConfig *cfg = r2yara->core->config; 1127 | RConfigNode *node = NULL; 1128 | r_config_lock (cfg, false); 1129 | char *me = r_sys_whoami (); 1130 | node = r_config_set (cfg, "yara.author", me); 1131 | r_config_node_desc (node, "Author of the YARA rule"); 1132 | free (me); 1133 | node = r_config_set (cfg, "yara.description", "My first yara rule"); 1134 | r_config_node_desc (node, "YARA rule description"); 1135 | char *ymd = yyyymmdd (); 1136 | node = r_config_set (cfg, "yara.date", ymd); 1137 | r_config_node_desc (node, "YARA rule creation date"); 1138 | free (ymd); 1139 | node = r_config_set (cfg, "yara.version", "0.1"); 1140 | r_config_node_desc (node, "YARA rule version"); 1141 | node = r_config_set (cfg, "yara.rule", "rulename"); 1142 | r_config_node_desc (node, "YARA rule name"); 1143 | node = r_config_set (cfg, "yara.tags", "test"); 1144 | r_config_node_desc (node, "YARA rule tags"); 1145 | node = r_config_set_i (cfg, "yara.amount", 0); 1146 | r_config_node_desc (node, "Amount of strings to match (0 means all of them)"); 1147 | node = r_config_set_b (cfg, "yara.va", true); 1148 | r_config_node_desc (node, "Show results in virtual or physical addresses, overrides io.va"); 1149 | node = r_config_set_cb (cfg, "yara.in", "io.map", yara_in_callback); 1150 | r_config_node_desc (node, "Where to scan for matches (see yara.in=? for help)"); 1151 | r_config_lock (cfg, true); 1152 | } 1153 | 1154 | #if R2_VERSION_NUMBER >= 50909 1155 | static bool cmd_yara_init(RCorePluginSession *cps) { 1156 | RCore *core = cps->core; 1157 | R2Yara *r2yara = R_NEW0 (R2Yara); 1158 | r2yara->iova = true; 1159 | r2yara->core = core; 1160 | r2yara->rules_list = r_list_newf ((RListFree)R2YR_RULES_DESTROY); 1161 | r2yara->genstrings = r_list_newf (free); 1162 | #if !USE_YARAX 1163 | yr_initialize (); 1164 | #endif 1165 | setup_config (r2yara); 1166 | 1167 | cmd_yara_load_default_rules (r2yara); 1168 | r2yara->initialized = true; 1169 | r2yara->flagidx = 0; 1170 | cps->data = r2yara; 1171 | return true; 1172 | } 1173 | #else 1174 | static int cmd_yara_init(void *user, const char *cmd) { 1175 | RCmd *rcmd = (RCmd *)user; 1176 | RCore *core = (RCore *)rcmd->data; 1177 | 1178 | R2Yara *r2yara = &Gr2yara; 1179 | memset (r2yara, 0, sizeof (R2Yara)); 1180 | r2yara->iova = true; 1181 | r2yara->core = core; 1182 | r2yara->rules_list = r_list_newf ((RListFree)R2YR_RULES_DESTROY); 1183 | r2yara->genstrings = r_list_newf (free); 1184 | #if !USE_YARAX 1185 | yr_initialize (); 1186 | #endif 1187 | setup_config (r2yara); 1188 | 1189 | cmd_yara_load_default_rules (r2yara); 1190 | r2yara->initialized = true; 1191 | r2yara->flagidx = 0; 1192 | return true; 1193 | } 1194 | #endif 1195 | 1196 | static bool yaracall(R2Yara *r2yara, const char *input) { 1197 | if (r_str_startswith (input, "yr")) { 1198 | cmd_yr (r2yara, input + 2); 1199 | return true; 1200 | } 1201 | if (!r_str_startswith (input, "yara")) { 1202 | return false; 1203 | } 1204 | #if R2_VERSION_NUMBER < 50909 1205 | if (!r2yara->initialized) { 1206 | if (!cmd_yara_init (r2yara, NULL)) { 1207 | return false; 1208 | } 1209 | } 1210 | #endif 1211 | const char *args = input[4]? input + 5: input + 4; 1212 | cmd_yara_process (r2yara, args); 1213 | return true; 1214 | } 1215 | 1216 | #if R2_VERSION_NUMBER >= 50909 1217 | static bool cmd_yara_call(RCorePluginSession *cps, const char *input) { 1218 | R2Yara *r2yara = cps->data; 1219 | return yaracall (r2yara, input); 1220 | } 1221 | #else 1222 | static int cmd_yara_call(void *user, const char *input) { 1223 | RCmd *rcmd = (RCmd *)user; 1224 | RCore *core = (RCore *)rcmd->data; 1225 | R2Yara *r2yara = &Gr2yara; 1226 | r2yara->core = core; 1227 | return yaracall (r2yara, input); 1228 | } 1229 | #endif 1230 | 1231 | #if R2_VERSION_NUMBER >= 50909 1232 | static bool cmd_yara_fini(RCorePluginSession *cps) { 1233 | // RCore* core = cps->core; 1234 | R2Yara *r2yara = cps->data; 1235 | if (r2yara->initialized) { 1236 | r_list_free (r2yara->rules_list); 1237 | r_list_free (r2yara->genstrings); 1238 | #if !USE_YARAX 1239 | yr_finalize (); 1240 | #endif 1241 | r2yara->initialized = false; 1242 | } 1243 | free (cps->data); 1244 | return true; 1245 | } 1246 | #else 1247 | static int cmd_yara_fini(void *user, const char *cmd) { 1248 | RCmd *rcmd = (RCmd *)user; 1249 | RCore *core = (RCore *)rcmd->data; 1250 | R2Yara *r2yara = &Gr2yara; 1251 | if (r2yara->initialized) { 1252 | r_list_free (r2yara->rules_list); 1253 | r_list_free (r2yara->genstrings); 1254 | #if !USE_YARAX 1255 | yr_finalize (); 1256 | #endif 1257 | r2yara->initialized = false; 1258 | } 1259 | return true; 1260 | } 1261 | #endif 1262 | 1263 | RCorePlugin r_core_plugin_yara = { 1264 | #if R2_VERSION_NUMBER < 50809 1265 | .name = "yara", 1266 | .desc = "YARA integration", 1267 | .license = "LGPL", 1268 | .version = R2Y_VERSION, 1269 | #else 1270 | .meta = { 1271 | .name = "yara", 1272 | .desc = "YARA integration", 1273 | .license = "LGPL", 1274 | .version = R2Y_VERSION, 1275 | }, 1276 | #endif 1277 | #if R2_VERSION_NUMBER >= 50909 1278 | .call = cmd_yara_call, 1279 | .init = cmd_yara_init, 1280 | .fini = cmd_yara_fini 1281 | #else 1282 | .call = cmd_yara_call, 1283 | .init = cmd_yara_init, 1284 | .fini = cmd_yara_fini 1285 | #endif 1286 | }; 1287 | 1288 | #ifndef CORELIB 1289 | RLibStruct radare_plugin = { 1290 | .type = R_LIB_TYPE_CORE, 1291 | .data = &r_core_plugin_yara, 1292 | #if R2_VERSION_NUMBER >= 50909 1293 | .abiversion = R2_ABIVERSION, 1294 | #endif 1295 | .version = R2_VERSION 1296 | }; 1297 | #endif 1298 | --------------------------------------------------------------------------------