mirror of
https://github.com/radareorg/r2yara.git
synced 2026-11-07 06:36:02 -10:00
Initial import of radare2-extras/r2yara
This commit is contained in:
1 parent
55a2bc1241
commit
c26da9d069
10 files changed
+1375
No files matched your search
@@ -0,0 +1,9 @@
|
||||
include config.mk
|
||||
|
||||
mrproper: clean
|
||||
rm -f config.mk
|
||||
|
||||
RULESDIR=$(R2PM_USRPLUGIN_DIR)/rules-yara3
|
||||
|
||||
all clean user-install install symstall user-uninstall uninstall:
|
||||
$(MAKE) -C src $<
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
r2 and yara, better together!
|
||||
|
||||
## License and Author
|
||||
|
||||
LGPLv3 - Copyright 2014-2023 - pancake, jvoisin, jfrankowski
|
||||
|
||||
## Installation
|
||||
|
||||
After running this command:
|
||||
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Look for the 'acr' tool here: https://github.com/radare/acr
|
||||
# Clone last version of ACR from here:
|
||||
# git clone https://github.com/radare/acr
|
||||
#
|
||||
# -- pancake
|
||||
|
||||
r2pm -h >/dev/null 2>&1
|
||||
if [ $? = 0 ]; then
|
||||
echo "Installing the last version of 'acr'..."
|
||||
r2pm -i acr > /dev/null
|
||||
r2pm -r acr -h > /dev/null 2>&1
|
||||
if [ $? = 0 ]; then
|
||||
echo "Running 'acr -p'..."
|
||||
r2pm -r acr -p
|
||||
else
|
||||
echo "Cannot find 'acr' in PATH"
|
||||
fi
|
||||
else
|
||||
echo "Running acr..."
|
||||
acr -p
|
||||
fi
|
||||
exit 0
|
||||
V=`./configure -qV | cut -d - -f -1`
|
||||
meson rewrite kwargs set project / version "$V"
|
||||
if [ -n "$1" ]; then
|
||||
echo "./configure $*"
|
||||
./configure $*
|
||||
fi
|
||||
|
||||
[ -z "$EDITOR" ] && EDITOR=vim
|
||||
$EDITOR README.md
|
||||
@@ -0,0 +1,24 @@
|
||||
PWD=$(shell pwd)
|
||||
VERSION=@VERSION@
|
||||
DESTDIR=
|
||||
PREFIX=@PREFIX@
|
||||
HOST_OS=@HOST_OS@
|
||||
LIBDIR=@LIBDIR@
|
||||
INSTALL_LIB=@INSTALL_LIB@
|
||||
|
||||
R2PM_USRPLUGIN_DIR=$(shell r2 -H R2_USER_PLUGINS)
|
||||
LIBEXT=$(shell r2 -H R2_LIBEXT)
|
||||
#LIBYARA_CFLAGS=@LIBYARA_CFLAGS@
|
||||
#LIBYARA_LDFLAGS=@LIBYARA_LDFLAGS@
|
||||
LIBYARA_CFLAGS=
|
||||
LIBYARA_LDFLAGS=-lyara
|
||||
R2_CFLAGS=@R2_CFLAGS@
|
||||
R2_LDFLAGS=@R2_LDFLAGS@
|
||||
YR_CFLAGS=@YR_CFLAGS@
|
||||
YR_LDFLAGS=@YR_LDFLAGS@
|
||||
|
||||
CFLAGS+=${R2_CFLAGS} ${LIBYARA_CFLAGS} ${YR_CFLAGS}
|
||||
LDFLAGS+=${R2_LDFLAGS} ${LIBYARA_LDFLAGS} ${YR_LDFLAGS}
|
||||
CFLAGS+=-I. -fPIC
|
||||
LDFLAGS+=-shared
|
||||
CFLAGS+=-DR2Y_VERSION=\"$(VERSION)\"
|
||||
@@ -0,0 +1,465 @@
|
||||
#!/bin/sh
|
||||
# This script was automatically generated by ACR v2.1.2
|
||||
# @author: pancake <nopcode.org>
|
||||
# @url: http://www.nopcode.org
|
||||
# @repo: git clone https://github.com/radare/acr
|
||||
|
||||
[ -z "${AWK}" ] && AWK=awk
|
||||
do_remove() {
|
||||
if [ "${ACR_RMFILES}" ]; then
|
||||
printf "cleaning temporally files... "
|
||||
rm -f ${ACR_RMFILES}
|
||||
echo "done"
|
||||
fi
|
||||
}
|
||||
control_c() {
|
||||
printf "\n\n^C control-c : script execution interrupted.\n"
|
||||
do_remove
|
||||
exit 1
|
||||
}
|
||||
trap control_c 2
|
||||
split_host() {
|
||||
S="$"
|
||||
while : ; do
|
||||
ENVWORDS="${ENVWORDS} $1_CPU $1_OS"
|
||||
STR=`eval "echo ${S}$1"`
|
||||
SPLIT_CPU="`echo "$STR" | cut -d - -f 1`"
|
||||
SPLIT_OS="`echo "$STR" | $AWK -F - '{
|
||||
if ($2=="unknown"){
|
||||
if (NF<3) { print $2; } else { print $3; }
|
||||
} else {
|
||||
if ($2=="linux") { print $2; } else
|
||||
if (NF<3) { print $2; } else { print $3; }
|
||||
}
|
||||
}'`"
|
||||
eval "$1_CPU=\"$SPLIT_CPU\""
|
||||
eval "$1_OS=\"$SPLIT_OS\""
|
||||
shift
|
||||
[ -z "$1" ] && break
|
||||
done
|
||||
}
|
||||
|
||||
QUIET=0
|
||||
be_quiet() {
|
||||
QUIET=1
|
||||
}
|
||||
|
||||
VPATH=`dirname ${0}`
|
||||
if [ "${VPATH}" = "." ]; then
|
||||
WODIS=current
|
||||
else
|
||||
if [ "${VPATH}" = "${PWD}" ]; then
|
||||
VPATH=.
|
||||
WODIS=current
|
||||
else
|
||||
WODIS=crosspath
|
||||
CURDIR=$PWD
|
||||
cd $VPATH
|
||||
VPATH="${PWD}/"
|
||||
cd $CURDIR
|
||||
fi
|
||||
fi
|
||||
|
||||
guess_os() {
|
||||
if [ -e "${VPATH}/config.guess" ]; then
|
||||
sh ${VPATH}/config.guess
|
||||
return
|
||||
fi
|
||||
CPU="`uname -m|sed -e 's, ,,g'|cut -d - -f 1`"
|
||||
OS="`uname -s|tr A-Z a-z`"
|
||||
uname -r | grep -qE "(Microsoft|WSL)" 2>/dev/null && OS="wsl"
|
||||
GNU="`uname --help 2>&1 | grep gnu`"
|
||||
[ "${GNU}" ] && OS="${OS}-gnu"
|
||||
[ "${CPU}" = ppc ] && CPU="powerpc"
|
||||
echo "${CPU}-unknown-${OS}"
|
||||
}
|
||||
|
||||
SEARCHPATH="/usr /usr/local /usr/pkg /sw"
|
||||
|
||||
: ${PREFIX:=/usr/local}
|
||||
CROSSBUILD=0
|
||||
BUILD=`guess_os`
|
||||
HOST="${BUILD}"
|
||||
TARGET="${HOST}"
|
||||
ETCDIR="/etc"
|
||||
SYSCONFDIR=""
|
||||
DESCRIPTION="yara plugin for radare2"
|
||||
|
||||
create_environ() {
|
||||
: ${EPREFIX:="${PREFIX}"}
|
||||
: ${SPREFIX:="${PREFIX}"}
|
||||
: ${BINDIR:="${SPREFIX}/bin"}
|
||||
: ${SBINDIR:="${PREFIX}/sbin"}
|
||||
: ${ETCDIR:="${SPREFIX}/etc"}
|
||||
: ${LIBDIR:="${SPREFIX}/lib"}
|
||||
: ${PKGCFG_LIBDIR:='${exec_prefix}/lib'}
|
||||
: ${PKGCFG_INCDIR:='${prefix}/include'}
|
||||
: ${LIBEXECDIR:="${SPREFIX}/libexec"}
|
||||
: ${INCLUDEDIR:="${SPREFIX}/include"}
|
||||
: ${DATADIR:="${SPREFIX}/share"}
|
||||
: ${INFODIR:="${DATADIR}/info"}
|
||||
: ${MANDIR:="${DATADIR}/man"}
|
||||
: ${DOCDIR:="${DATADIR}/doc/r2yara"}
|
||||
: ${LOCALSTATEDIR:="${SPREFIX}/var"}
|
||||
for A in `echo ${PATH} | sed -e 's,:, ,g'` ; do
|
||||
[ -e "$A"/ginstall ] && : ${INSTALL:="$A"/ginstall} && break
|
||||
[ -e "$A"/install ] && : ${INSTALL:="$A"/install} && break
|
||||
done
|
||||
: ${INSTALL_DIR:=${INSTALL} -d}
|
||||
: ${INSTALL_DATA:=${INSTALL} -m 644}
|
||||
: ${INSTALL_SCRIPT:=${INSTALL} -m 755}
|
||||
: ${INSTALL_PROGRAM:=${INSTALL} -m 755}
|
||||
: ${INSTALL_PROGRAM_STRIP:=${INSTALL} -m 755 -s}
|
||||
: ${INSTALL_MAN:=${INSTALL} -m 444}
|
||||
: ${INSTALL_LIB:=${INSTALL} -m 755 -c}
|
||||
PKGNAME='r2yara' ; VERSION='1.1.0' ; VERSION_MAJOR=1; VERSION_MINOR=1; VERSION_PATCH=0; VERSION_NUMBER=10100; CONTACT_MAIL="[email protected]" ; CONTACT_NAME="jfrankowski" ; CONTACT="jfrankowski <[email protected]>" ;
|
||||
}
|
||||
|
||||
show_usage() {
|
||||
cat <<EOF2
|
||||
'configure' configures r2yara-1.1.0 to adapt to many kinds of systems.
|
||||
|
||||
Usage: ./configure [OPTION]... [VAR=VALUE]...
|
||||
|
||||
To assign environment variables (e.g., CC, CFLAGS...), specify them as
|
||||
VAR=VALUE. See below for descriptions of some of the useful variables.
|
||||
|
||||
Defaults for the options are specified in brackets.
|
||||
|
||||
Configuration:
|
||||
-h, --help display this help and exit
|
||||
-r, --report show what libs/programs require to work
|
||||
-q, --quiet be quiet, less verbose (see ./configure -qV)
|
||||
-V, --version display version information and exit
|
||||
|
||||
Installation directories:
|
||||
--exec-prefix=EPREFIX install arch-dependent files in EPREFIX [PREFIX]
|
||||
--prefix=PREFIX install arch-independent files in PREFIX [/usr/local]
|
||||
--sandbox=SPREFIX sandbox prefix directory: SPREFIX [PREFIX]
|
||||
|
||||
Fine tuning of the installation directories:
|
||||
--bindir=DIR user executables [EPREFIX/bin]
|
||||
--datadir=DIR read-only architecture-independent data [PREFIX/share]
|
||||
--docdir=DIR documentation directory [DATADIR/doc/r2yara]
|
||||
--includedir=DIR C header files [PREFIX/include]
|
||||
--infodir=DIR info documentation [DATADIR/info]
|
||||
--libexecdir=DIR program executables [EPREFIX/libexec]
|
||||
--libdir=DIR object code libraries [EPREFIX/lib]
|
||||
--libpath=DIR set rpath/libname-path to linker
|
||||
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
||||
--mandir=DIR man documentation [DATADIR/man]
|
||||
--sbindir=DIR system admin executables [EPREFIX/sbin]
|
||||
--etcdir=DIR same as --sysconfdir (/etc)
|
||||
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
||||
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
||||
|
||||
System types:
|
||||
--build=BUILD configure for building on BUILD [guessed]
|
||||
--host=HOST cross-compile to build programs to run on HOST [BUILD]
|
||||
--target=TARGET configure for building compilers for TARGET [HOST]
|
||||
EOF2
|
||||
|
||||
printf "
|
||||
Some influential environment variables:
|
||||
CC C compiler command
|
||||
CFLAGS C compiler flags
|
||||
LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
|
||||
nonstandard directory <lib dir>
|
||||
CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have
|
||||
headers in a nonstandard directory <include dir>
|
||||
CPP C preprocessor
|
||||
"
|
||||
printf "
|
||||
Report bugs to: jfrankowski <[email protected]>"
|
||||
echo ""
|
||||
exit 0
|
||||
}
|
||||
|
||||
take_environ() {
|
||||
: ${SH:=/bin/sh}
|
||||
: ${CPP:=cpp}
|
||||
: ${CC:=gcc}
|
||||
: ${PREFIX:=/usr/local/}
|
||||
}
|
||||
|
||||
ochof() {
|
||||
[ "$QUIET" = 1 ] && return
|
||||
printf "$*"
|
||||
}
|
||||
|
||||
ocho() {
|
||||
[ "$QUIET" = 1 ] && return
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
show_version() {
|
||||
if [ "$QUIET" = 1 ]; then
|
||||
echo "1.1.0"
|
||||
exit 0
|
||||
fi
|
||||
echo "r2yara-1.1.0 configuration script done with acr v2.1.2.
|
||||
The 'Free Software Foundation' message is only for autodetection.
|
||||
Originally written by pancake <nopcode.org>."
|
||||
exit 0
|
||||
}
|
||||
|
||||
parse_options() {
|
||||
flag=`echo $1| cut -d = -f 1`
|
||||
value=`echo $1| $AWK 'BEGIN{FS="=";}{print $2}'`
|
||||
flag2=`echo $flag|cut -f2- -d -| sed -e 's,-,_,g' -e 's,^_,,g'|tr '[a-z]' '[A-Z]'`
|
||||
|
||||
if [ "${TARGET_OS}" = "darwin" ]; then
|
||||
LIBPATH=-Wl,-install_name,
|
||||
else
|
||||
LIBPATH=-Wl,-R
|
||||
fi
|
||||
|
||||
case $flag in
|
||||
-h|--help|--hel|--h|--he|-help)
|
||||
show_usage ; ;;
|
||||
-qV|-quiet-version|--quiet-version)
|
||||
be_quiet
|
||||
show_version ; ;;
|
||||
-q|-quiet|--quiet)
|
||||
be_quiet ; ;;
|
||||
-V|-version|--version)
|
||||
show_version ; ;;
|
||||
-r|--r|--report)
|
||||
echo "PKGNAME: r2yara"
|
||||
echo "VERSION: 1.1.0"
|
||||
echo "AUTHOR: jfrankowski"
|
||||
echo "EMAIL: [email protected]"
|
||||
echo "DESCRIPTION: yara plugin for radare2"
|
||||
echo "LANGS: c"
|
||||
echo "REQUIRED: libyara"
|
||||
echo "PKGCONFIG: yara r_core"
|
||||
exit 0
|
||||
;;
|
||||
--cache-file)
|
||||
# ignored: acr have no cache
|
||||
;;
|
||||
--build)
|
||||
BUILD="$value"; split_host BUILD ; ;;
|
||||
--host)
|
||||
CROSSBUILD=1 # XXX
|
||||
HOST="$value"; split_host HOST ; ;;
|
||||
--target)
|
||||
TARGET="$value"; split_host TARGET ; ;;
|
||||
--prefix)
|
||||
PREFIX="$value"; ;;
|
||||
--exec-prefix)
|
||||
EPREFIX="$value"; ;;
|
||||
--sandbox|--sprefix)
|
||||
SPREFIX="$value"; ;;
|
||||
--bindir)
|
||||
BINDIR="$value"; ;;
|
||||
--sbindir)
|
||||
SBINDIR="$value"; ;;
|
||||
--libexecdir)
|
||||
LIBEXECDIR="$value"; ;;
|
||||
--docdir)
|
||||
DOCDIR="$value"; ;;
|
||||
--datadir)
|
||||
DATADIR="$value"; ;;
|
||||
--sysconfdir)
|
||||
SYSCONFDIR="$value"
|
||||
ETCDIR="$value"; ;;
|
||||
--etcdir)
|
||||
SYSCONFDIR="$value"
|
||||
ETCDIR="$value"; ;;
|
||||
--sharedstatedir)
|
||||
SHAREDSTATEDIR="$value"; ;;
|
||||
--localstatedir)
|
||||
LOCALSTATEDIR="$value"; ;;
|
||||
--libdir)
|
||||
LIBDIR="$value"
|
||||
PKGCFG_LIBDIR="$value"; ;;
|
||||
--libpath)
|
||||
LDFLAGS="${LDFLAGS} ${LIBPATH}$value"; ;;
|
||||
--includedir)
|
||||
PKGCFG_INCDIR="$value"
|
||||
INCLUDEDIR="$value"; CFLAGS="${CFLAGS} -I$value"; ;;
|
||||
--infodir)
|
||||
INFODIR="$value"; ;;
|
||||
--mandir)
|
||||
MANDIR="$value"; ;;
|
||||
|
||||
*) if [ "$value" ]; then eval "`echo $flag2=$value`" ;
|
||||
else echo ; echo "WARNING: Unknown flag '$flag'." >&2 ; echo ; fi ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# MAIN #
|
||||
take_environ
|
||||
split_host BUILD HOST TARGET
|
||||
[ -z "$ACRHOOK" ] && ACRHOOK=./configure.hook
|
||||
[ -e "$ACRHOOK" ] && . ${ACRHOOK}
|
||||
|
||||
while : ; do
|
||||
[ -z "$1" ] && break
|
||||
parse_options "$1"
|
||||
shift
|
||||
done
|
||||
|
||||
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 HAVE_LIB_YARA YR_CFLAGS YR_LDFLAGS HAVE_PKGCFG_YARA R2_CFLAGS R2_LDFLAGS HAVE_PKGCFG_R_CORE"
|
||||
|
||||
create_environ
|
||||
|
||||
ocho "checking build system type... ${BUILD}"
|
||||
ocho "checking host system type... ${HOST}"
|
||||
ocho "checking target system type... ${TARGET}"
|
||||
[ "${CROSSBUILD}" = 1 ] && echo "using crosscompilation mode."
|
||||
|
||||
#split_host BUILD HOST TARGET
|
||||
[ -n "${prefix}" ] && PREFIX="${prefix}"
|
||||
ocho "checking for working directories... ${WODIS}"
|
||||
ocho "using prefix '${PREFIX}'"
|
||||
ACR_RMFILES=" test.c a.out a.exe"
|
||||
|
||||
ochof "checking for pkg-config... "
|
||||
if [ -n "$PKGCONFIG" ]; then
|
||||
if [ -x "$PKGCONFIG" ]; then
|
||||
_HAVE_PKGCONFIG="${PKGCONFIG}"
|
||||
else
|
||||
ocho "PKGCONFIG env is not executable"
|
||||
PKGCONFIG=""
|
||||
fi
|
||||
else
|
||||
IFS=:
|
||||
for A in ${PATH} ; do
|
||||
if [ -x "${A}/pkg-config" ]; then
|
||||
PKGCONFIG="${A}/pkg-config"
|
||||
elif [ -x "${A}/pkgconf" ]; then
|
||||
PKGCONFIG="${A}/pkgconf"
|
||||
else
|
||||
continue
|
||||
fi
|
||||
break
|
||||
done
|
||||
unset IFS
|
||||
fi
|
||||
if [ -n "${PKGCONFIG}" ]; then
|
||||
ocho ${PKGCONFIG}
|
||||
else
|
||||
echo "Cannot find pkg-config or pkgconf in PATH" >&2
|
||||
exit 1
|
||||
ocho no; fi
|
||||
COMPILER=CC
|
||||
ochof "checking for c compiler... "
|
||||
HAVE_LANG_C=1
|
||||
if [ "${CROSSBUILD}" = 1 ]; then
|
||||
(command -v ${HOST}-${CC} >/dev/null 2>&1)
|
||||
if [ $? = 0 ]; then CC="${HOST}-${CC}"; fi
|
||||
fi
|
||||
echo "int main(int argc, char **argv){return 0;}" > test.c
|
||||
(exec ${CC} -o a.out ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} test.c >/dev/null 2>&1)
|
||||
if [ $? = 0 ]; then echo ${CC}; else
|
||||
echo no ; HAVE_LANG_C=0
|
||||
do_remove
|
||||
echo "ERROR: ${CC} cannot create executables" >&2 ;
|
||||
exit 1 ; fi
|
||||
check_library() {
|
||||
VAR=$1
|
||||
S="$"
|
||||
_REQUIRED=$3
|
||||
_CHKLIB_NAME=$2
|
||||
_CHKLIB_LIBS=$(echo "-l${_CHKLIB_NAME}" | sed 's,+, -l,g')
|
||||
ochof "checking for lib${_CHKLIB_NAME} ... "
|
||||
echo "int main(int ac, char **av){return 0;}" > test.c
|
||||
eval ${S}${COMPILER} ${CFLAGS} ${CPPFLAGS} ${CXXFLAGS} ${LDFLAGS} ${_CHKLIB_LIBS} test.c >/dev/null 2>&1
|
||||
if [ $? = 0 ]; then
|
||||
eval ${VAR}=1
|
||||
echo yes
|
||||
else
|
||||
eval ${VAR}=0
|
||||
echo no
|
||||
if [ "${_REQUIRED}" = 1 ]; then
|
||||
echo "this library is required."
|
||||
do_remove
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
check_library HAVE_LIB_YARA yara 1
|
||||
if [ -z "${PKGCONFIG}" ]; then pkg-config --version >/dev/null 2>&1 ; if [ 0 = 0 ]; then PKGCONFIG=pkg-config ; else PKGCONFIG=pkgconf ; fi; fi
|
||||
type ${PKGCONFIG} > /dev/null 2>&1 || echo "ERROR: Cannot find valid PKGCONFIG, pkg-config or pkgconf in PATH"
|
||||
echo 'Using PKGCONFIG: '${PKGCONFIG}
|
||||
printf 'checking pkg-config flags for yara... '
|
||||
tmp=`${PKGCONFIG} --cflags yara 2>/dev/null`
|
||||
if [ $? != 0 ]; then echo no ; HAVE_PKGCFG_YARA=0;
|
||||
YR_CFLAGS='';YR_LDFLAGS='';
|
||||
echo 'This package is required'
|
||||
exit 1
|
||||
else
|
||||
YR_CFLAGS=$tmp;
|
||||
tmp=`${PKGCONFIG} --libs yara 2>/dev/null`
|
||||
if [ $? = 0 ]; then
|
||||
echo yes; HAVE_PKGCFG_YARA=1;
|
||||
YR_LDFLAGS=$tmp; fi; fi
|
||||
if [ -z "${PKGCONFIG}" ]; then pkg-config --version >/dev/null 2>&1 ; if [ 0 = 0 ]; then PKGCONFIG=pkg-config ; else PKGCONFIG=pkgconf ; fi; fi
|
||||
printf 'checking pkg-config flags for r_core... '
|
||||
tmp=`${PKGCONFIG} --cflags r_core 2>/dev/null`
|
||||
if [ $? != 0 ]; then echo no ; HAVE_PKGCFG_R_CORE=0;
|
||||
R2_CFLAGS='';R2_LDFLAGS='';
|
||||
echo 'This package is required'
|
||||
exit 1
|
||||
else
|
||||
R2_CFLAGS=$tmp;
|
||||
tmp=`${PKGCONFIG} --libs r_core 2>/dev/null`
|
||||
if [ $? = 0 ]; then
|
||||
echo yes; HAVE_PKGCFG_R_CORE=1;
|
||||
R2_LDFLAGS=$tmp; fi; fi
|
||||
SEDFLAGS=" -e '"
|
||||
COUNT=0
|
||||
for A in ${ENVWORDS} ; do
|
||||
[ "${A}" = VPATH ] && continue
|
||||
[ "${A}" = srcdir ] && continue
|
||||
eval "VAR=\$${A}"
|
||||
VAR="`echo ${VAR} | sed -e 's/\,/\\\,/g'`"
|
||||
[ $COUNT = 10 ] && COUNT=0 && SEDFLAGS="${SEDFLAGS}' -e '"
|
||||
COUNT=$(($COUNT+1))
|
||||
SEDFLAGS="${SEDFLAGS}s,@${A}@,${VAR},g;"
|
||||
done
|
||||
SEDFLAGS="${SEDFLAGS}'"
|
||||
for A in . config.mk ; do # SUBDIRS
|
||||
if [ -f "${VPATH}/${A}.acr" ]; then
|
||||
SD_TARGET=${A}
|
||||
else
|
||||
if [ -d "${VPATH}/${A}" ]; then
|
||||
SD_TARGET=${A}/Makefile
|
||||
mkdir -p ${A}
|
||||
else
|
||||
echo "ERROR: Cannot find ${VPATH}/${A}.acr" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
ocho "creating ${SD_TARGET}"
|
||||
[ "${VPATH}" != '.' ] && mkdir -p $(echo ${A} | sed -e "s,/`basename ${A}`$,,g")
|
||||
cat ${VPATH}/${SD_TARGET}.acr | \
|
||||
eval sed -e "s,@VPATH@,${VPATH}/${A},g" ${SEDFLAGS} > ${SD_TARGET}.tmp
|
||||
|
||||
for A in ${ENVWORDS}; do
|
||||
VALUE=`eval echo "$"${A}`
|
||||
if [ "$VALUE" = 0 ]; then ## FALSE
|
||||
MARK="##${A}##"
|
||||
if [ -n "`grep \"${MARK}\" ${SD_TARGET}.tmp`" ]; then
|
||||
mv ${SD_TARGET}.tmp ${SD_TARGET}.tmp2
|
||||
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
|
||||
fi
|
||||
fi
|
||||
done
|
||||
mv ${SD_TARGET}.tmp ${SD_TARGET} && rm -f ${SD_TARGET}.tmp2
|
||||
if [ ! $? = 0 ]; then echo Cannot write target file ; control_c ; fi
|
||||
done
|
||||
|
||||
do_remove
|
||||
if [ "$QUIET" = 0 ]; then
|
||||
echo
|
||||
echo "Final report:"
|
||||
for A in PREFIX ; do
|
||||
eval VAL="\$${A}"
|
||||
[ -z "${VAL}" ] && VAL="\"\""
|
||||
echo " - ${A} = ${VAL}"
|
||||
done
|
||||
fi
|
||||
@@ -0,0 +1,15 @@
|
||||
PKGNAME r2yara
|
||||
VERSION 1.1.0
|
||||
DESCRIPTION yara plugin for radare2 ;
|
||||
CONTACT jfrankowski ; [email protected]
|
||||
|
||||
REPORT PREFIX ;
|
||||
USE_PKGCONFIG!
|
||||
|
||||
LANG_C!
|
||||
|
||||
CHKLIB! yara
|
||||
PKGCFG! YR_CFLAGS YR_LDFLAGS yara
|
||||
PKGCFG! R2_CFLAGS R2_LDFLAGS r_core
|
||||
|
||||
SUBDIRS . config.mk ;
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
Copyright (c) 2014, Colin Childs <[email protected]>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
* Neither the names of the copyright owners nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
rule BLOWFISH_Constants : crypto {
|
||||
meta:
|
||||
author = "phoul (@phoul)"
|
||||
description = "Look for Blowfish constants"
|
||||
date = "2014-01"
|
||||
version = "0.1"
|
||||
strings:
|
||||
$c0 = { D1310BA6 }
|
||||
$c1 = { A60B31D1 }
|
||||
$c2 = { 98DFB5AC }
|
||||
$c3 = { ACB5DF98 }
|
||||
$c4 = { 2FFD72DB }
|
||||
$c5 = { DB72FD2F }
|
||||
$c6 = { D01ADFB7 }
|
||||
$c7 = { B7DF1AD0 }
|
||||
$c8 = { 4B7A70E9 }
|
||||
$c9 = { E9707A4B }
|
||||
$c10 = { F64C261C }
|
||||
$c11 = { 1C264CF6 }
|
||||
condition:
|
||||
6 of them
|
||||
}
|
||||
rule MD5_Constants : crypto {
|
||||
meta:
|
||||
author = "phoul (@phoul)"
|
||||
description = "Look for MD5 constants"
|
||||
date = "2014-01"
|
||||
version = "0.2"
|
||||
strings:
|
||||
// Init constants
|
||||
$c0 = { 67452301 }
|
||||
$c1 = { efcdab89 }
|
||||
$c2 = { 98badcfe }
|
||||
$c3 = { 10325476 }
|
||||
$c4 = { 01234567 }
|
||||
$c5 = { 89ABCDEF }
|
||||
$c6 = { FEDCBA98 }
|
||||
$c7 = { 76543210 }
|
||||
// Round 2
|
||||
$c8 = { F4D50d87 }
|
||||
$c9 = { 78A46AD7 }
|
||||
condition:
|
||||
5 of them
|
||||
}
|
||||
rule RC6_Constants : crypto {
|
||||
meta:
|
||||
author = "chort (@chort0)"
|
||||
description = "Look for RC6 magic constants in binary"
|
||||
reference = "https://twitter.com/mikko/status/417620511397400576"
|
||||
reference2 = "https://twitter.com/dyngnosis/status/418105168517804033"
|
||||
date = "2013-12"
|
||||
version = "0.2"
|
||||
strings:
|
||||
$c1 = { B7E15163 }
|
||||
$c2 = { 9E3779B9 }
|
||||
$c3 = { 6351E1B7 }
|
||||
$c4 = { B979379E }
|
||||
condition:
|
||||
2 of them
|
||||
}rule RIPEMD160_Constants : crypto {
|
||||
meta:
|
||||
author = "phoul (@phoul)"
|
||||
description = "Look for RIPEMD-160 constants"
|
||||
date = "2014-01"
|
||||
version = "0.1"
|
||||
strings:
|
||||
$c0 = { 67452301 }
|
||||
$c1 = { EFCDAB89 }
|
||||
$c2 = { 98BADCFE }
|
||||
$c3 = { 10325476 }
|
||||
$c4 = { C3D2E1F0 }
|
||||
$c5 = { 01234567 }
|
||||
$c6 = { 89ABCDEF }
|
||||
$c7 = { FEDCBA98 }
|
||||
$c8 = { 76543210 }
|
||||
$c9 = { F0E1D2C3 }
|
||||
condition:
|
||||
5 of them
|
||||
}
|
||||
rule SHA1_Constants : crypto {
|
||||
meta:
|
||||
author = "phoul (@phoul)"
|
||||
description = "Look for SHA1 constants"
|
||||
date = "2014-01"
|
||||
version = "0.1"
|
||||
strings:
|
||||
$c0 = { 67452301 }
|
||||
$c1 = { EFCDAB89 }
|
||||
$c2 = { 98BADCFE }
|
||||
$c3 = { 10325476 }
|
||||
$c4 = { C3D2E1F0 }
|
||||
$c5 = { 01234567 }
|
||||
$c6 = { 89ABCDEF }
|
||||
$c7 = { FEDCBA98 }
|
||||
$c8 = { 76543210 }
|
||||
$c9 = { F0E1D2C3 }
|
||||
condition:
|
||||
5 of them
|
||||
}
|
||||
rule SHA256_Constants : crypto {
|
||||
meta:
|
||||
author = "phoul (@phoul)"
|
||||
description = "Look for SHA224/SHA256 constants"
|
||||
date = "2014-01"
|
||||
version = "0.1"
|
||||
strings:
|
||||
$c0 = { 428a2f98 }
|
||||
$c1 = { 982F8A42 }
|
||||
$c2 = { 71374491 }
|
||||
$c3 = { 91443771 }
|
||||
$c4 = { B5C0FBCF }
|
||||
$c5 = { CFFBC0B5 }
|
||||
$c6 = { E9B5DBA5 }
|
||||
$c7 = { A5DBB5E9 }
|
||||
// Exclude
|
||||
$e0 = { D728AE22 }
|
||||
$e1 = { 22AE28D7 }
|
||||
condition:
|
||||
4 of ($c0,$c1,$c2,$c3,$c4,$c5,$c6,$c7) and not ($e0 or $e1)
|
||||
}
|
||||
rule SHA512_Constants : crypto {
|
||||
meta:
|
||||
author = "phoul (@phoul)"
|
||||
description = "Look for SHA384/SHA512 constants"
|
||||
date = "2014-01"
|
||||
version = "0.1"
|
||||
strings:
|
||||
$c0 = { 428a2f98 }
|
||||
$c1 = { 982F8A42 }
|
||||
$c2 = { 71374491 }
|
||||
$c3 = { 91443771 }
|
||||
$c4 = { B5C0FBCF }
|
||||
$c5 = { CFFBC0B5 }
|
||||
$c6 = { E9B5DBA5 }
|
||||
$c7 = { A5DBB5E9 }
|
||||
$c8 = { D728AE22 }
|
||||
$c9 = { 22AE28D7 }
|
||||
condition:
|
||||
5 of them
|
||||
}
|
||||
rule WHIRLPOOL_Constants : crypto {
|
||||
meta:
|
||||
author = "phoul (@phoul)"
|
||||
description = "Look for WhirlPool constants"
|
||||
date = "2014-02"
|
||||
version = "0.1"
|
||||
strings:
|
||||
$c0 = { 18186018c07830d8 }
|
||||
$c1 = { d83078c018601818 }
|
||||
$c2 = { 23238c2305af4626 }
|
||||
$c3 = { 2646af05238c2323 }
|
||||
condition:
|
||||
2 of them
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
rule HelloWorld : foo {
|
||||
meta:
|
||||
author = "pancake"
|
||||
description = "hello world"
|
||||
date = "2023-10"
|
||||
version = "0.1"
|
||||
strings:
|
||||
$ = "lib"
|
||||
condition:
|
||||
all of them
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
include ../config.mk
|
||||
|
||||
MOD=core_yara
|
||||
|
||||
all: $(MOD).$(LIBEXT)
|
||||
|
||||
$(MOD).$(LIBEXT): ${MOD}.o
|
||||
$(CC) -g ${MOD}.o ${CFLAGS} ${LDFLAGS} -o ${MOD}.${LIBEXT}
|
||||
|
||||
clean:
|
||||
rm -f ${MOD}.o ${MOD}.${LIBEXT}
|
||||
|
||||
mrproper: clean
|
||||
rm -f Makefile
|
||||
|
||||
RULESDIR=$(R2PM_USRPLUGIN_DIR)/rules-yara3
|
||||
|
||||
user-install install:
|
||||
${INSTALL_LIB} ${MOD}.${LIBEXT} $(R2PM_USRPLUGIN_DIR)/${MOD}.${LIBEXT}
|
||||
mkdir -p $(RULESDIR)
|
||||
cp -rf *.gz $(RULESDIR)
|
||||
|
||||
symstall:
|
||||
ln -fs ${PWD}/${MOD}.${LIBEXT} $(R2PM_USRPLUGIN_DIR)/$(MOD).$(LIBEXT)
|
||||
rm -rf $(R2PM_USRPLUGIN_DIR)/yara
|
||||
mkdir -p $(RULESDIR)
|
||||
for a in *.gz ; do ln -fs $(PWD)/$$a $(RULESDIR)/$$a ; done
|
||||
|
||||
user-uninstall uninstall:
|
||||
rm -f ${R2PM_USRPLUGIN_DIR}/$(MOD).$(LIBEXT)
|
||||
rm -rf $(RULESDIR)
|
||||
rm -rf ${R2PM_USRPLUGIN_DIR}/yara
|
||||
+595
@@ -0,0 +1,595 @@
|
||||
|
||||
|
||||
/* radare - LGPLv3 - Copyright 2014-2023 - pancake, jvoisin, jfrankowski */
|
||||
|
||||
#include <r_core.h>
|
||||
#include <yara.h>
|
||||
|
||||
// TODO: remove globals!
|
||||
static R_TH_LOCAL bool initialized = false;
|
||||
static R_TH_LOCAL bool print_strings = false;
|
||||
static R_TH_LOCAL unsigned int flagidx = 0;
|
||||
static R_TH_LOCAL bool io_va = true;
|
||||
static R_TH_LOCAL RList* rules_list = NULL;
|
||||
|
||||
#if YR_MAJOR_VERSION < 4
|
||||
static int callback(int message, void* rule, void* data);
|
||||
#else
|
||||
static int callback(YR_SCAN_CONTEXT* context, int message, void* rule, void* data);
|
||||
#endif
|
||||
static int cmd_yara_add(const RCore* core, const char* input);
|
||||
static int cmd_yara_add_file(const char* rules_path);
|
||||
static int cmd_yara_call(void *user, const char *input);
|
||||
static int cmd_yara_clear();
|
||||
static int cmd_yara_init(void *user, const char *cmd);
|
||||
static int cmd_yara_help(const RCore* core);
|
||||
static int cmd_yara_process(const RCore* core, const char* input);
|
||||
static int cmd_yara_scan(const RCore* core, const char* option);
|
||||
static int cmd_yara_load_default_rules(const RCore* core);
|
||||
|
||||
static const char yara_rule_template[] = "rule RULE_NAME {\n strings:\n\n condition:\n}";
|
||||
|
||||
/* Because of how the rules are compiled, we are not allowed to add more
|
||||
* rules to a compiler once it has compiled. That's why we keep a list
|
||||
* of those compiled rules.
|
||||
*/
|
||||
|
||||
#if YR_MAJOR_VERSION < 4
|
||||
static int callback (int message, void *msg_data, void *user_data) {
|
||||
RCore *core = (RCore *) user_data;
|
||||
RPrint *print = core->print;
|
||||
unsigned int ruleidx;
|
||||
st64 offset = 0;
|
||||
ut64 n = 0;
|
||||
|
||||
YR_RULE* rule = msg_data;
|
||||
|
||||
if (message == CALLBACK_MSG_RULE_MATCHING) {
|
||||
YR_STRING* string;
|
||||
r_cons_printf ("%s\n", rule->identifier);
|
||||
ruleidx = 0;
|
||||
yr_rule_strings_foreach (rule, string) {
|
||||
YR_MATCH* match;
|
||||
|
||||
yr_string_matches_foreach (string, match) {
|
||||
n = match->base + match->offset;
|
||||
// Find virtual address if needed
|
||||
if (io_va) {
|
||||
RIOMap *map = r_io_map_get_paddr (core->io, n);
|
||||
if (map) {
|
||||
offset = r_io_map_begin (map) - map->delta;
|
||||
}
|
||||
}
|
||||
|
||||
r_strf_var (flag, 256, "%s%d_%s_%d", "yara", flagidx, rule->identifier, ruleidx);
|
||||
if (print_strings) {
|
||||
r_cons_printf ("0x%08" PFMT64x ": %s : ", n + offset, flag);
|
||||
r_print_bytes (print, match->data, match->data_length, "%02x");
|
||||
}
|
||||
r_flag_set (core->flags, flag, n + offset, match->data_length);
|
||||
ruleidx++;
|
||||
}
|
||||
}
|
||||
flagidx++;
|
||||
}
|
||||
return CALLBACK_CONTINUE;
|
||||
}
|
||||
|
||||
static void compiler_callback(int error_level, const char* file_name,
|
||||
int line_number, const char* message, void* user_data) {
|
||||
// TODO depending on error_level. use R_LOG_WARN, ERROR or INFO
|
||||
eprintf ("file: %s line_number: %d.\n%s", file_name, line_number, message);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
static int callback (YR_SCAN_CONTEXT* context, int message, void *msg_data, void *user_data) {
|
||||
RCore *core = (RCore *) user_data;
|
||||
RPrint *print = core->print;
|
||||
unsigned int ruleidx;
|
||||
st64 offset = 0;
|
||||
ut64 n = 0;
|
||||
|
||||
YR_RULE* rule = msg_data;
|
||||
|
||||
if (message == CALLBACK_MSG_RULE_MATCHING) {
|
||||
YR_STRING* string;
|
||||
r_cons_printf ("%s\n", rule->identifier);
|
||||
ruleidx = 0;
|
||||
yr_rule_strings_foreach (rule, string) {
|
||||
YR_MATCH* match;
|
||||
yr_string_matches_foreach (context, string, match) {
|
||||
n = match->base + match->offset;
|
||||
// Find virtual address if needed
|
||||
if (io_va) {
|
||||
RIOMap *map = r_io_map_get_paddr (core->io, n);
|
||||
if (map) {
|
||||
offset = r_io_map_begin (map) - map->delta;
|
||||
}
|
||||
}
|
||||
|
||||
r_strf_var (flag, 256, "%s%d_%s_%d", "yara", flagidx, rule->identifier, ruleidx);
|
||||
if (print_strings) {
|
||||
r_cons_printf ("0x%08" PFMT64x ": %s : ", n + offset, flag);
|
||||
r_print_bytes (print, match->data, match->data_length, "%02x");
|
||||
}
|
||||
r_flag_set (core->flags, flag, n + offset, match->data_length);
|
||||
ruleidx++;
|
||||
}
|
||||
}
|
||||
flagidx++;
|
||||
|
||||
}
|
||||
return CALLBACK_CONTINUE;
|
||||
}
|
||||
|
||||
static void compiler_callback(int error_level, const char* file_name,
|
||||
int line_number, const struct YR_RULE *rule, const char* message, void* user_data) {
|
||||
// TODO depending on error_level. use R_LOG_WARN, ERROR or INFO
|
||||
eprintf ("file: %s line_number: %d.\n%s", file_name, line_number, message);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int cmd_yara_scan(const RCore* core, R_NULLABLE const char* option) {
|
||||
RListIter* rules_it;
|
||||
YR_RULES* rules;
|
||||
void* to_scan;
|
||||
|
||||
r_flag_space_push (core->flags, "yara");
|
||||
const unsigned int to_scan_size = r_io_size (core->io);
|
||||
io_va = r_config_get_b (core->config, "io.va");
|
||||
|
||||
if (to_scan_size < 1) {
|
||||
R_LOG_ERROR ("Invalid file size");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (option != NULL) {
|
||||
if (*option == '\0') {
|
||||
print_strings = false;
|
||||
} else if (*option == 'S') {
|
||||
print_strings = true;
|
||||
} else {
|
||||
print_strings = false;
|
||||
R_LOG_ERROR ("Invalid option");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
to_scan = malloc (to_scan_size);
|
||||
if (!to_scan) {
|
||||
R_LOG_ERROR ("Something went wrong during memory allocation");
|
||||
return false;
|
||||
}
|
||||
|
||||
int result = r_io_pread_at (core->io, 0L, to_scan, to_scan_size);
|
||||
if (!result) {
|
||||
R_LOG_ERROR ("Something went wrong during r_io_read_at");
|
||||
free (to_scan);
|
||||
return false;
|
||||
}
|
||||
r_list_foreach (rules_list, rules_it, rules) {
|
||||
yr_rules_scan_mem (rules, to_scan, to_scan_size, 0, callback, (void *)core, 0);
|
||||
}
|
||||
free (to_scan);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int cmd_yara_show(const char * name) {
|
||||
/* List loaded rules containing name */
|
||||
RListIter* rules_it;
|
||||
YR_RULES* rules;
|
||||
YR_RULE* rule;
|
||||
|
||||
r_list_foreach (rules_list, rules_it, rules) {
|
||||
yr_rules_foreach (rules, rule) {
|
||||
if (r_str_casestr (rule->identifier, name)) {
|
||||
r_cons_printf ("%s\n", rule->identifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int cmd_yara_tags() {
|
||||
/* List tags from all the different loaded rules */
|
||||
RListIter* rules_it;
|
||||
RListIter *tags_it;
|
||||
YR_RULES* rules;
|
||||
YR_RULE* rule;
|
||||
const char* tag_name;
|
||||
RList *tag_list = r_list_new();
|
||||
tag_list->free = free;
|
||||
|
||||
r_list_foreach (rules_list, rules_it, rules) {
|
||||
yr_rules_foreach(rules, rule) {
|
||||
yr_rule_tags_foreach(rule, tag_name) {
|
||||
if (! r_list_find (tag_list, tag_name, (RListComparator)strcmp)) {
|
||||
r_list_add_sorted (tag_list,
|
||||
strdup (tag_name), (RListComparator)strcmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r_cons_printf ("[YARA tags]\n");
|
||||
r_list_foreach (tag_list, tags_it, tag_name) {
|
||||
r_cons_printf ("%s\n", tag_name);
|
||||
}
|
||||
|
||||
r_list_free (tag_list);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int cmd_yara_tag(const char * search_tag) {
|
||||
/* List rules with tag search_tag */
|
||||
RListIter* rules_it;
|
||||
YR_RULES* rules;
|
||||
YR_RULE* rule;
|
||||
const char* tag_name;
|
||||
|
||||
r_list_foreach (rules_list, rules_it, rules) {
|
||||
yr_rules_foreach (rules, rule) {
|
||||
yr_rule_tags_foreach(rule, tag_name) {
|
||||
R_LOG_WARN ("Invalid option");
|
||||
if (r_str_casestr (tag_name, search_tag)) {
|
||||
r_cons_printf ("%s\n", rule->identifier);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int cmd_yara_list() {
|
||||
/* List all loaded rules */
|
||||
RListIter* rules_it;
|
||||
YR_RULES* rules;
|
||||
YR_RULE* rule;
|
||||
|
||||
r_list_foreach (rules_list, rules_it, rules) {
|
||||
yr_rules_foreach (rules, rule) {
|
||||
r_cons_printf ("%s\n", rule->identifier);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int cmd_yara_clear() {
|
||||
/* Clears all loaded rules */
|
||||
r_list_free (rules_list);
|
||||
rules_list = r_list_newf ((RListFree) yr_rules_destroy);
|
||||
R_LOG_INFO ("Rules cleared");
|
||||
return true;
|
||||
}
|
||||
|
||||
static void logerr(YR_COMPILER* compiler, R_NULLABLE const char *arg) {
|
||||
char buf[64];
|
||||
const char *errmsg = yr_compiler_get_error_message (compiler, buf, sizeof (buf));
|
||||
if (arg) {
|
||||
R_LOG_ERROR ("%s %s", errmsg, arg);
|
||||
} else {
|
||||
R_LOG_ERROR ("%s", errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
static int cmd_yara_add(const RCore* core, const char* input) {
|
||||
if (!input) {
|
||||
R_LOG_ERROR ("Missing argument");
|
||||
return false;
|
||||
}
|
||||
/* Add a rule with user input */
|
||||
YR_COMPILER* compiler = NULL;
|
||||
int result, i, continue_edit;
|
||||
|
||||
for (i = 0; input[i]; i++) {
|
||||
if (input[i] != ' ') {
|
||||
return cmd_yara_add_file (input + i);
|
||||
}
|
||||
}
|
||||
|
||||
if (yr_compiler_create (&compiler) != ERROR_SUCCESS) {
|
||||
logerr (compiler, NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
char *old_template = strdup (yara_rule_template);
|
||||
char *modified_template = NULL;
|
||||
do {
|
||||
char *modified_template = r_core_editor (core, NULL, old_template);
|
||||
R_FREE (old_template);
|
||||
if (!modified_template) {
|
||||
R_LOG_ERROR ("Something bad happened with the temp file");
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
result = yr_compiler_add_string (compiler, modified_template, NULL);
|
||||
if (result > 0) {
|
||||
logerr (compiler, NULL);
|
||||
continue_edit = r_cons_yesno ('y', "Do you want to continue editing the rule? [y]/n\n");
|
||||
if (!continue_edit) {
|
||||
goto err_exit;
|
||||
}
|
||||
old_template = modified_template;
|
||||
modified_template = NULL;
|
||||
}
|
||||
} while (result > 0);
|
||||
|
||||
free (modified_template);
|
||||
if (compiler != NULL) {
|
||||
yr_compiler_destroy (compiler);
|
||||
}
|
||||
R_LOG_INFO ("Rule successfully added");
|
||||
return true;
|
||||
|
||||
err_exit:
|
||||
if (compiler != NULL) {
|
||||
yr_compiler_destroy (compiler);
|
||||
}
|
||||
free (modified_template);
|
||||
free (old_template);
|
||||
return false;
|
||||
}
|
||||
|
||||
static int cmd_yara_add_file(const char* rules_path) {
|
||||
YR_COMPILER* compiler = NULL;
|
||||
YR_RULES* rules;
|
||||
|
||||
if (!rules_path) {
|
||||
R_LOG_INFO ("Please tell me what am I supposed to load");
|
||||
return false;
|
||||
}
|
||||
|
||||
FILE* rules_file = r_sandbox_fopen (rules_path, "r");
|
||||
if (!rules_file) {
|
||||
R_LOG_ERROR ("Unable to open %s", rules_path);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (yr_compiler_create (&compiler) != ERROR_SUCCESS) {
|
||||
logerr (compiler, NULL);
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
int result = yr_compiler_add_file (compiler, rules_file, NULL, rules_path);
|
||||
fclose (rules_file);
|
||||
rules_file = NULL;
|
||||
if (result > 0) {
|
||||
logerr (compiler, rules_path);
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
if (yr_compiler_get_rules (compiler, &rules) != ERROR_SUCCESS) {
|
||||
logerr (compiler, NULL);
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
r_list_append (rules_list, rules);
|
||||
|
||||
yr_compiler_destroy (compiler);
|
||||
return true;
|
||||
|
||||
err_exit:
|
||||
if (compiler) {
|
||||
yr_compiler_destroy (compiler);
|
||||
}
|
||||
if (rules_file) {
|
||||
fclose (rules_file);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *short_help_message[] = {
|
||||
"Usage: yr", "[action] [args..]", " load and run yara rules inside r2",
|
||||
"yr", " [file]", "add yara rules from file",
|
||||
"yr", "-*", "unload all the rules",
|
||||
"yr", "?", "show this help (same as 'yara?')",
|
||||
"yr", "", "list loaded rules",
|
||||
"yr", "s[S]", "scan the current file, if S option is given it prints matching strings",
|
||||
"yr", "t", "list tags from the loaded rules",
|
||||
"yr", "t [tagname]", "list rules with given tag",
|
||||
"yr", "v", "show version information about r2yara and yara",
|
||||
NULL
|
||||
};
|
||||
|
||||
const char *long_help_message[] = {
|
||||
"Usage: yara", " [action] [args..]", " load and run yara rules inside r2",
|
||||
"yara", " add [file]", "Add yara rules from file, or open $EDITOR with yara rule template",
|
||||
"yara", " clear", "Clear all rules",
|
||||
"yara", " help", "Show this help (same as 'yara?')",
|
||||
"yara", " list", "List all rules",
|
||||
"yara", " scan[S]", "Scan the current file, if S option is given it prints matching strings",
|
||||
"yara", " show [name]", "Show rules containing name",
|
||||
"yara", " tag [name]", "List rules with tag 'name'",
|
||||
"yara", " tags", "List tags from the loaded rules",
|
||||
"yara", " version", "Show version information about r2yara and yara",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int cmd_yara_process(const RCore* core, const char* input) {
|
||||
char *inp = strdup (input);
|
||||
char *arg = r_str_after (inp, ' ');
|
||||
if (arg) {
|
||||
arg = (char *)r_str_trim_head_ro (arg);
|
||||
}
|
||||
int res = -1;
|
||||
if (r_str_startswith (input, "add")) {
|
||||
res = cmd_yara_add (core, arg);
|
||||
} else if (r_str_startswith (inp, "clear")) {
|
||||
res = cmd_yara_clear ();
|
||||
} else if (r_str_startswith (inp, "list")) {
|
||||
res = cmd_yara_list ();
|
||||
} else if (r_str_startswith (inp, "scanS") || r_str_startswith (inp, "scan S")) {
|
||||
res = cmd_yara_scan (core, "S");
|
||||
} else if (r_str_startswith (inp, "scan")) {
|
||||
res = cmd_yara_scan (core, arg);
|
||||
} else if (r_str_startswith (inp, "show")) {
|
||||
res = cmd_yara_show (arg);
|
||||
} else if (r_str_startswith (inp, "tags")) {
|
||||
res = cmd_yara_tags ();
|
||||
} else if (r_str_startswith (input, "tag ")) {
|
||||
res = cmd_yara_tag (arg);
|
||||
} else if (r_str_startswith (input, "ver")) {
|
||||
r_cons_printf ("r2 %s\n", R2_VERSION);
|
||||
r_cons_printf ("yara %s\n", YR_VERSION);
|
||||
r_cons_printf ("r2yara %s\n", R2Y_VERSION);
|
||||
res = 0;
|
||||
} else {
|
||||
r_core_cmd_help (core, long_help_message);
|
||||
}
|
||||
free (inp);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int cmd_yr(RCore *core, const char *input) {
|
||||
char *inp = strdup (input);
|
||||
char *arg = r_str_after (inp, ' ');
|
||||
int res = -1;
|
||||
if (arg) {
|
||||
arg = (char *)r_str_trim_head_ro (arg);
|
||||
}
|
||||
switch (*input) {
|
||||
case '?': // "yr?"
|
||||
r_core_cmd_help (core, short_help_message);
|
||||
break;
|
||||
case '/': // "yr/" <- imho makes more sense
|
||||
case 's': // "yrs"
|
||||
res = cmd_yara_scan (core, arg);
|
||||
break;
|
||||
case '+':
|
||||
case ' ':
|
||||
cmd_yara_add (core, arg);
|
||||
break;
|
||||
case '-':
|
||||
cmd_yara_clear ();
|
||||
break;
|
||||
case 't': // "yrs"
|
||||
if (input[1]) {
|
||||
cmd_yara_tag (arg);
|
||||
} else {
|
||||
cmd_yara_tags ();
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
cmd_yara_list ();
|
||||
break;
|
||||
}
|
||||
free (inp);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int cmd_yara_call(void *user, const char *input) {
|
||||
RCore* core = (RCore*) user;
|
||||
if (r_str_startswith (input, "yr")) {
|
||||
cmd_yr (core, input + 2);
|
||||
return true;
|
||||
}
|
||||
if (!r_str_startswith (input, "yara")) {
|
||||
return false;
|
||||
}
|
||||
if (!initialized && !cmd_yara_init (core, NULL)) {
|
||||
return false;
|
||||
}
|
||||
const char *args = input[4]? input + 5: input + 4;
|
||||
cmd_yara_process (core, args);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int cmd_yara_load_default_rules(const RCore* core) {
|
||||
RListIter* iter = NULL;
|
||||
YR_COMPILER* compiler = NULL;
|
||||
YR_RULES* yr_rules;
|
||||
char* filename, *complete_path;
|
||||
char* rules = NULL;
|
||||
#if R2_VERSION_NUMBER < 50709
|
||||
char* y3_rule_dir = r_str_newf ("%s%s%s", r_str_home (R2_HOME_PLUGINS), R_SYS_DIR, "rules-yara3");
|
||||
#else
|
||||
char* y3_rule_dir = r_xdg_datadir ("plugins/rules-yara3");
|
||||
#endif
|
||||
RList* list = r_sys_dir (y3_rule_dir);
|
||||
|
||||
if (yr_compiler_create (&compiler) != ERROR_SUCCESS) {
|
||||
logerr (compiler, NULL);
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
yr_compiler_set_callback (compiler, compiler_callback, NULL);
|
||||
|
||||
r_list_foreach (list, iter, filename) {
|
||||
if (filename[0] != '.') { // skip '.', '..' and hidden files
|
||||
complete_path = r_str_newf ("%s%s%s", y3_rule_dir, R_SYS_DIR, filename);
|
||||
rules = (char*)r_file_gzslurp (complete_path, NULL, true);
|
||||
R_FREE (complete_path);
|
||||
if (yr_compiler_add_string (compiler, rules, NULL) > 0) {
|
||||
logerr (compiler, NULL);
|
||||
}
|
||||
R_FREE (rules);
|
||||
}
|
||||
}
|
||||
r_list_free (list);
|
||||
|
||||
if (yr_compiler_get_rules (compiler, &yr_rules) != ERROR_SUCCESS) {
|
||||
logerr (compiler, NULL);
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
r_list_append (rules_list, yr_rules);
|
||||
|
||||
if (compiler) {
|
||||
yr_compiler_destroy (compiler);
|
||||
}
|
||||
return true;
|
||||
|
||||
err_exit:
|
||||
free (y3_rule_dir);
|
||||
if (compiler) {
|
||||
yr_compiler_destroy (compiler);
|
||||
}
|
||||
r_list_free (list);
|
||||
free (rules);
|
||||
return false;
|
||||
}
|
||||
|
||||
static int cmd_yara_init(void *user, const char *cmd) {
|
||||
RCore* core = (RCore *)user;
|
||||
rules_list = r_list_newf ((RListFree) yr_rules_destroy);
|
||||
yr_initialize ();
|
||||
cmd_yara_load_default_rules (core);
|
||||
initialized = true;
|
||||
flagidx = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int cmd_yara_fini() {
|
||||
if (initialized) {
|
||||
r_list_free (rules_list);
|
||||
yr_finalize ();
|
||||
initialized = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
RCorePlugin r_core_plugin_yara = {
|
||||
.meta = {
|
||||
.name = "yara",
|
||||
.desc = "YARA integration",
|
||||
.license = "LGPL",
|
||||
.version = "0.1.2",
|
||||
},
|
||||
.call = cmd_yara_call,
|
||||
.init = cmd_yara_init,
|
||||
.fini = cmd_yara_fini
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_CORE,
|
||||
.data = &r_core_plugin_yara,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
Reference in new issue
Block a user