mirror of
https://github.com/VirusTotal/yara.git
synced 2026-10-11 22:49:58 +00:00
Integrate tlshc library, calculate telfhash and import hash in ELF module (#1624)
* Add simple_str string implementation * Integrate tlshc library, calculate telfhash and import hash in the ELF module. * Hide usage of MD5 into #ifdef crypto
This commit is contained in:
@@ -6,6 +6,8 @@ YARA_CONFIG_OPTS = [
|
||||
"-DHAVE_STDBOOL_H=1",
|
||||
# "-DHAVE__MKGMTIME=1",
|
||||
"-DHAVE_TIMEGM=1",
|
||||
"-DBUCKETS_128=1", # Defining TLSH function
|
||||
"-DCHECKSUM_1B=1", # Defining TLSH function
|
||||
]
|
||||
|
||||
YARA_COPTS = YARA_CONFIG_OPTS + [
|
||||
@@ -126,6 +128,7 @@ def yara_library(
|
||||
"libyara/include/yara/dex.h",
|
||||
"libyara/include/yara/dotnet.h",
|
||||
"libyara/include/yara/elf.h",
|
||||
"libyara/include/yara/elf_utils.h",
|
||||
"libyara/include/yara/endian.h",
|
||||
"libyara/include/yara/error.h",
|
||||
"libyara/include/yara/exec.h",
|
||||
@@ -152,6 +155,7 @@ def yara_library(
|
||||
"libyara/include/yara/rules.h",
|
||||
"libyara/include/yara/scan.h",
|
||||
"libyara/include/yara/scanner.h",
|
||||
"libyara/include/yara/simple_str.h",
|
||||
"libyara/include/yara/sizedstr.h",
|
||||
"libyara/include/yara/stack.h",
|
||||
"libyara/include/yara/stopwatch.h",
|
||||
@@ -161,6 +165,7 @@ def yara_library(
|
||||
"libyara/include/yara/types.h",
|
||||
"libyara/include/yara/unaligned.h",
|
||||
"libyara/include/yara/utils.h",
|
||||
"libyara/include/tlshc/tlsh.h",
|
||||
"libyara/lexer.c",
|
||||
"libyara/libyara.c",
|
||||
"libyara/mem.c",
|
||||
@@ -182,12 +187,18 @@ def yara_library(
|
||||
"libyara/rules.c",
|
||||
"libyara/scan.c",
|
||||
"libyara/scanner.c",
|
||||
"libyara/simple_str.c",
|
||||
"libyara/sizedstr.c",
|
||||
"libyara/stack.c",
|
||||
"libyara/stopwatch.c",
|
||||
"libyara/stream.c",
|
||||
"libyara/strutils.c",
|
||||
"libyara/threading.c",
|
||||
"libyara/tlshc/tlsh.c",
|
||||
"libyara/tlshc/tlsh_impl.c",
|
||||
"libyara/tlshc/tlsh_impl.h",
|
||||
"libyara/tlshc/tlsh_util.c",
|
||||
"libyara/tlshc/tlsh_util.h",
|
||||
],
|
||||
hdrs = [
|
||||
"libyara/include/yara.h",
|
||||
|
||||
@@ -367,6 +367,9 @@ AS_IF(
|
||||
[test x$proc_interface != xnone],[AC_DEFINE([HAVE_SCAN_PROC_IMPL],[1])],
|
||||
[test x$proc_interface = xnone],[AC_DEFINE([HAVE_SCAN_PROC_IMPL],[0])])
|
||||
|
||||
# Configure TLSH function
|
||||
CFLAGS="$CFLAGS -DBUCKETS_128=1 -DCHECKSUM_1B=1"
|
||||
|
||||
AC_SUBST([PC_REQUIRES_PRIVATE])
|
||||
AC_SUBST([PC_LIBS_PRIVATE])
|
||||
|
||||
|
||||
@@ -371,6 +371,17 @@ Reference
|
||||
|
||||
The section index which the symbol is associated with.
|
||||
|
||||
.. c:function:: telfhash()
|
||||
|
||||
Function returning Telfhash - TLSH hash of the ELF export and import symbols.
|
||||
|
||||
*Example: elf.telfhash() == "t166a00284751084526486df8b5df5b2fccb3f511dbc188c37156f5e714a11bc5d71014d"*
|
||||
|
||||
.. c:function:: import_md5()
|
||||
|
||||
Function returning Import Hash - MD5 hash of the ELF imported symbols.
|
||||
|
||||
*Example: elf.import_md5() == "c3eca50cbb03400a6e91b9fe48da0c0c"*
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -157,6 +157,7 @@ yarainclude_HEADERS = \
|
||||
include/yara/rules.h \
|
||||
include/yara/scan.h \
|
||||
include/yara/scanner.h \
|
||||
include/yara/simple_str.h \
|
||||
include/yara/sizedstr.h \
|
||||
include/yara/stack.h \
|
||||
include/yara/stopwatch.h \
|
||||
@@ -226,11 +227,15 @@ libyara_la_SOURCES = \
|
||||
rules.c \
|
||||
scan.c \
|
||||
scanner.c \
|
||||
simple_str.c \
|
||||
sizedstr.c \
|
||||
stack.c \
|
||||
stopwatch.c \
|
||||
strutils.c \
|
||||
stream.c \
|
||||
tlshc/tlsh.c \
|
||||
tlshc/tlsh_impl.c \
|
||||
tlshc/tlsh_util.c \
|
||||
threading.c
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
#ifndef __TLSH_TLSH_H__
|
||||
#define __TLSH_TLSH_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#define TLSH_OPTION_CONSERVATIVE 2
|
||||
#define TLSH_OPTION_KEEP_BUCKET 4
|
||||
#define TLSH_OPTION_PRIVATE 8
|
||||
#define TLSH_OPTION_THREADED 16
|
||||
|
||||
// Define TLSH_STRING_LEN_REQ, which is the string length of "T1" + the hex
|
||||
// value of the Tlsh hash. BUCKETS_256 & CHECKSUM_3B are compiler switches
|
||||
// defined in CMakeLists.txt
|
||||
#if defined BUCKETS_256
|
||||
#define TLSH_STRING_LEN_REQ 136
|
||||
// changed the minimum data length to 256 for version 3.3
|
||||
#define MIN_DATA_LENGTH 50
|
||||
// added the -force option for version 3.5
|
||||
// added the -conservatibe option for version 3.17
|
||||
#define MIN_CONSERVATIVE_DATA_LENGTH 256
|
||||
#endif
|
||||
|
||||
#if defined BUCKETS_128
|
||||
#define TLSH_STRING_LEN_REQ 72
|
||||
// changed the minimum data length to 256 for version 3.3
|
||||
#define MIN_DATA_LENGTH 50
|
||||
// added the -force option for version 3.5
|
||||
// added the -conservatibe option for version 3.17
|
||||
#define MIN_CONSERVATIVE_DATA_LENGTH 256
|
||||
#endif
|
||||
|
||||
#if defined BUCKETS_48
|
||||
// No 3 Byte checksum option for 48 Bucket min hash
|
||||
#define TLSH_STRING_LEN 30
|
||||
// changed the minimum data length to 256 for version 3.3
|
||||
#define MIN_DATA_LENGTH 10
|
||||
// added the -force option for version 3.5
|
||||
#define MIN_CONSERVATIVE_DATA_LENGTH 10
|
||||
#endif
|
||||
|
||||
#define TLSH_STRING_BUFFER_LEN (TLSH_STRING_LEN_REQ + 1)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct TlshImpl TlshImpl;
|
||||
|
||||
typedef struct {
|
||||
TlshImpl* impl;
|
||||
} Tlsh;
|
||||
|
||||
Tlsh* tlsh_new();
|
||||
void tlsh_free(Tlsh* tlsh);
|
||||
void tlsh_reset(Tlsh* tlsh);
|
||||
int tlsh_update(Tlsh* tlsh, const unsigned char* data, unsigned int len);
|
||||
int tlsh_final(Tlsh* tlsh, const unsigned char* data, unsigned int len, int tlsh_option);
|
||||
const char* tlsh_get_hash(Tlsh* tlsh, bool showvers);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __TLSH_TLSH_H__
|
||||
@@ -152,6 +152,11 @@ typedef uint64_t elf64_xword_t;
|
||||
#define ELF_STT_COMMON 5 // Symbol is a common data object
|
||||
#define ELF_STT_TLS 6 // Symbol is thread-local data object
|
||||
|
||||
#define ELF_STV_DEFAULT 0 // Visibility by binding
|
||||
#define ELF_STV_INTERNAL 1 // Reserved
|
||||
#define ELF_STV_HIDDEN 2 // Not visible to other components
|
||||
#define ELF_STV_PROTECTED 3 // Visible in other but cannot be preempted.
|
||||
|
||||
#define ELF_STB_LOCAL 0 // Local symbol
|
||||
#define ELF_STB_GLOBAL 1 // Global symbol
|
||||
#define ELF_STB_WEAK 2 // Weak symbol
|
||||
@@ -162,6 +167,10 @@ typedef uint64_t elf64_xword_t;
|
||||
|
||||
#define ELF_PN_XNUM 0xffff
|
||||
|
||||
#define ELF_SHN_UNDEF 0 // Missing, undefined section index
|
||||
#define ELF_SHN_ABS 0xFFF1 // Absolute references, not affected by relocs
|
||||
#define ELF_SHN_COMMON 0xFFF2 // Symbols relative to this are common
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
typedef struct
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef YR_ELF_UTILS_H
|
||||
#define YR_ELF_UTILS_H
|
||||
|
||||
#include <yara/elf.h>
|
||||
|
||||
typedef struct _ELF_SYMBOL
|
||||
{
|
||||
char *name;
|
||||
int value;
|
||||
int size;
|
||||
int type;
|
||||
int bind;
|
||||
int shndx;
|
||||
int visibility;
|
||||
|
||||
struct _ELF_SYMBOL *next; // Next symbol in the list
|
||||
} ELF_SYMBOL;
|
||||
|
||||
// Linked list of symbols
|
||||
typedef struct _ELF_SYMBOL_LIST
|
||||
{
|
||||
int count;
|
||||
ELF_SYMBOL *symbols;
|
||||
} ELF_SYMBOL_LIST;
|
||||
|
||||
typedef struct _ELF
|
||||
{
|
||||
ELF_SYMBOL_LIST *symtab;
|
||||
ELF_SYMBOL_LIST *dynsym;
|
||||
char *telfhash;
|
||||
char *import_hash;
|
||||
} ELF;
|
||||
|
||||
#endif //YR_ELF_UTILS_H
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef _SIMPLESTR_H
|
||||
#define _SIMPLESTR_H
|
||||
|
||||
#include <yara/types.h>
|
||||
|
||||
/* Simple dynamic string implementation for more readable/maintainable code
|
||||
Can be further optimized */
|
||||
typedef struct _SIMPLE_STR
|
||||
{
|
||||
uint32_t len;
|
||||
uint32_t cap;
|
||||
char* str;
|
||||
} SIMPLE_STR, *PSIMPLE_STR;
|
||||
|
||||
SIMPLE_STR* sstr_new(const char* s);
|
||||
SIMPLE_STR* sstr_newf(const char* fmt, ...);
|
||||
void sstr_free(SIMPLE_STR* ss);
|
||||
bool sstr_appendf(SIMPLE_STR* ss, const char* fmt, ...);
|
||||
char* sstr_move(SIMPLE_STR* ss);
|
||||
|
||||
#endif
|
||||
+399
-16
@@ -28,18 +28,253 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <tlshc/tlsh.h>
|
||||
#include <yara/elf.h>
|
||||
#include <yara/elf_utils.h>
|
||||
#include <yara/endian.h>
|
||||
#include <yara/mem.h>
|
||||
#include <yara/modules.h>
|
||||
#include <yara/simple_str.h>
|
||||
#include <yara/utils.h>
|
||||
|
||||
#include "../crypto.h"
|
||||
|
||||
#define MODULE_NAME elf
|
||||
|
||||
#define CLASS_DATA(c, d) ((c << 8) | d)
|
||||
|
||||
static int sort_strcmp(const void* a, const void* b)
|
||||
{
|
||||
return strcmp(*(const char**) a, *(const char**) b);
|
||||
}
|
||||
|
||||
define_function(telfhash)
|
||||
{
|
||||
YR_OBJECT* obj = module();
|
||||
ELF* elf = (ELF*) obj->data;
|
||||
if (elf == NULL)
|
||||
return_string(YR_UNDEFINED);
|
||||
|
||||
if (elf->telfhash)
|
||||
return_string(elf->telfhash);
|
||||
|
||||
/* We prefer dynsym if possible */
|
||||
ELF_SYMBOL_LIST* list = elf->dynsym ? elf->dynsym : elf->symtab;
|
||||
if (!list)
|
||||
return_string(YR_UNDEFINED);
|
||||
|
||||
/* exclusions are based on the original implementation
|
||||
https://github.com/trendmicro/telfhash/blob/master/telfhash/telfhash.py */
|
||||
char* exclude_strings[] = {
|
||||
"__libc_start_main",
|
||||
"main",
|
||||
"abort",
|
||||
"cachectl",
|
||||
"cacheflush",
|
||||
"puts",
|
||||
"atol",
|
||||
"malloc_trim"};
|
||||
|
||||
SIMPLE_STR* sstr = NULL;
|
||||
|
||||
int symbol_count = 0;
|
||||
char** clean_names = yr_malloc(list->count * sizeof(*clean_names));
|
||||
if (!clean_names)
|
||||
return_string(YR_UNDEFINED);
|
||||
|
||||
for (ELF_SYMBOL* i = list->symbols; i != NULL; i = i->next)
|
||||
{
|
||||
char* name = i->name;
|
||||
|
||||
if (!name)
|
||||
continue;
|
||||
|
||||
/* Use only global code symbols */
|
||||
if (i->bind != ELF_STB_GLOBAL || i->type != ELF_STT_FUNC ||
|
||||
i->visibility != ELF_STV_DEFAULT)
|
||||
continue;
|
||||
|
||||
/* ignore:
|
||||
x86-64 specific functions
|
||||
string functions (str.* and mem.*), gcc changes them depending on arch
|
||||
symbols starting with . or _ */
|
||||
bool is_bad_prefix = name[0] == '.' || name[0] == '_';
|
||||
bool is_x86_64 = name[0] == '.' || name[0] == '_';
|
||||
bool is_mem_or_str = strncmp(name, "str", 3) == 0 ||
|
||||
strncmp(name, "mem", 3) == 0;
|
||||
|
||||
if (is_bad_prefix || is_x86_64 || is_mem_or_str)
|
||||
continue;
|
||||
|
||||
/* Exclude any symbols that match the excluded ones */
|
||||
bool is_excluded = false;
|
||||
for (int i = 0; i < sizeof(exclude_strings) / sizeof(*exclude_strings); i++)
|
||||
{
|
||||
if (strcmp(name, exclude_strings[i]) == 0)
|
||||
{
|
||||
is_excluded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_excluded)
|
||||
continue;
|
||||
|
||||
clean_names[symbol_count] = yr_malloc(strlen(name) + 1);
|
||||
if (!clean_names[symbol_count])
|
||||
goto cleanup;
|
||||
|
||||
/* Convert it to lowercase */
|
||||
int j;
|
||||
for (j = 0; name[j]; j++) clean_names[symbol_count][j] = tolower(name[j]);
|
||||
|
||||
clean_names[symbol_count][j] = '\0';
|
||||
|
||||
symbol_count++;
|
||||
}
|
||||
|
||||
if (!symbol_count)
|
||||
goto cleanup;
|
||||
|
||||
/* Now we have all the valid symbols, sort them, concat them */
|
||||
qsort(clean_names, symbol_count, sizeof(*clean_names), &sort_strcmp);
|
||||
|
||||
sstr = sstr_newf("%s", clean_names[0]);
|
||||
if (!sstr)
|
||||
goto cleanup;
|
||||
|
||||
/* We've already written first symbol, start at 1 */
|
||||
for (int i = 1; i < symbol_count; ++i)
|
||||
{
|
||||
if (!sstr_appendf(sstr, ",%s", clean_names[i]))
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
Tlsh* tlsh = tlsh_new();
|
||||
if (!tlsh)
|
||||
goto cleanup;
|
||||
|
||||
tlsh_final(tlsh, (const unsigned char*) sstr->str, sstr->len, 0);
|
||||
|
||||
const char* telfhash = tlsh_get_hash(tlsh, true);
|
||||
elf->telfhash = yr_strdup(telfhash); // cache it
|
||||
if (!elf->telfhash)
|
||||
goto cleanup;
|
||||
|
||||
for (int i = 0; i < symbol_count; ++i) yr_free(clean_names[i]);
|
||||
yr_free(clean_names);
|
||||
sstr_free(sstr);
|
||||
tlsh_free(tlsh);
|
||||
|
||||
return_string(elf->telfhash);
|
||||
|
||||
cleanup:
|
||||
for (int i = 0; i < symbol_count; ++i) yr_free(clean_names[i]);
|
||||
yr_free(clean_names);
|
||||
sstr_free(sstr);
|
||||
|
||||
return_string(YR_UNDEFINED);
|
||||
}
|
||||
|
||||
#if defined(HAVE_LIBCRYPTO) || defined(HAVE_WINCRYPT_H) || \
|
||||
defined(HAVE_COMMONCRYPTO_COMMONCRYPTO_H)
|
||||
|
||||
define_function(import_md5)
|
||||
{
|
||||
YR_OBJECT* obj = module();
|
||||
ELF* elf = (ELF*) obj->data;
|
||||
if (elf == NULL)
|
||||
return_string(YR_UNDEFINED);
|
||||
|
||||
if (elf->import_hash)
|
||||
return_string(elf->import_hash);
|
||||
|
||||
ELF_SYMBOL_LIST* list = elf->dynsym ? elf->dynsym : elf->symtab;
|
||||
if (!list)
|
||||
return_string(YR_UNDEFINED);
|
||||
|
||||
SIMPLE_STR* sstr = NULL;
|
||||
|
||||
int symbol_count = 0;
|
||||
char** clean_names = yr_malloc(list->count * sizeof(*clean_names));
|
||||
if (!clean_names)
|
||||
return_string(YR_UNDEFINED);
|
||||
|
||||
for (ELF_SYMBOL* i = list->symbols; i != NULL; i = i->next)
|
||||
{
|
||||
char* name = i->name;
|
||||
|
||||
if (!name)
|
||||
continue;
|
||||
|
||||
if (i->shndx != ELF_SHN_UNDEF)
|
||||
continue;
|
||||
|
||||
// skip empty names
|
||||
if (strlen(i->name) == 0)
|
||||
continue;
|
||||
|
||||
clean_names[symbol_count] = yr_malloc(strlen(name) + 1);
|
||||
if (!clean_names[symbol_count])
|
||||
goto cleanup;
|
||||
|
||||
/* Convert it to lowercase */
|
||||
int j;
|
||||
for (j = 0; name[j]; j++) clean_names[symbol_count][j] = tolower(name[j]);
|
||||
|
||||
clean_names[symbol_count][j] = '\0';
|
||||
|
||||
symbol_count++;
|
||||
}
|
||||
|
||||
if (!symbol_count)
|
||||
goto cleanup;
|
||||
|
||||
/* Now we have all the valid symbols, sort them, concat them */
|
||||
qsort(clean_names, symbol_count, sizeof(*clean_names), &sort_strcmp);
|
||||
|
||||
sstr = sstr_newf("%s", clean_names[0]);
|
||||
if (!sstr)
|
||||
goto cleanup;
|
||||
|
||||
/* We've already written first symbol, start at 1 */
|
||||
for (int i = 1; i < symbol_count; ++i)
|
||||
{
|
||||
if (!sstr_appendf(sstr, ",%s", clean_names[i]))
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
unsigned char hash[YR_MD5_LEN];
|
||||
|
||||
yr_md5_ctx ctx;
|
||||
yr_md5_init(&ctx);
|
||||
yr_md5_update(&ctx, sstr->str, sstr->len);
|
||||
yr_md5_final(hash, &ctx);
|
||||
|
||||
elf->import_hash = yr_malloc(YR_MD5_LEN * 2 + 1);
|
||||
if (!elf->import_hash)
|
||||
goto cleanup;
|
||||
|
||||
for (int i = 0; i < YR_MD5_LEN; ++i)
|
||||
sprintf(elf->import_hash + (i * 2), "%02x", hash[i]);
|
||||
|
||||
for (int i = 0; i < symbol_count; ++i) yr_free(clean_names[i]);
|
||||
yr_free(clean_names);
|
||||
sstr_free(sstr);
|
||||
|
||||
return_string(elf->import_hash);
|
||||
|
||||
cleanup:
|
||||
for (int i = 0; i < symbol_count; ++i) yr_free(clean_names[i]);
|
||||
yr_free(clean_names);
|
||||
sstr_free(sstr);
|
||||
|
||||
return_string(YR_UNDEFINED);
|
||||
}
|
||||
|
||||
#endif // defined(HAVE_LIBCRYPTO) || defined(HAVE_WINCRYPT_H)
|
||||
|
||||
int get_elf_class_data(const uint8_t* buffer, size_t buffer_length)
|
||||
{
|
||||
elf_ident_t* elf_ident;
|
||||
@@ -207,7 +442,8 @@ static const char* str_table_entry(
|
||||
}
|
||||
|
||||
#define PARSE_ELF_HEADER(bits, bo) \
|
||||
void parse_elf_header_##bits##_##bo( \
|
||||
int parse_elf_header_##bits##_##bo( \
|
||||
ELF* elf_data, \
|
||||
elf##bits##_header_t* elf, \
|
||||
uint64_t base_address, \
|
||||
size_t elf_size, \
|
||||
@@ -228,6 +464,8 @@ static const char* str_table_entry(
|
||||
uint##bits##_t dyn_sym_table_size = 0; \
|
||||
uint##bits##_t dyn_sym_str_table_size = 0; \
|
||||
\
|
||||
elf_data->symtab = elf_data->dynsym = NULL; \
|
||||
\
|
||||
elf##bits##_section_header_t* section_table; \
|
||||
elf##bits##_section_header_t* section; \
|
||||
elf##bits##_program_header_t* segment; \
|
||||
@@ -340,7 +578,7 @@ static const char* str_table_entry(
|
||||
{ \
|
||||
dyn_sym_table = elf_raw + yr_##bo##bits##toh(section->offset); \
|
||||
dyn_sym_str_table = elf_raw + \
|
||||
yr_##bo##bits##toh(dynstr_section->offset); \
|
||||
yr_##bo##bits##toh(dynstr_section->offset); \
|
||||
dyn_sym_table_size = yr_##bo##bits##toh(section->size); \
|
||||
dyn_sym_str_table_size = yr_##bo##bits##toh(dynstr_section->size); \
|
||||
} \
|
||||
@@ -351,57 +589,148 @@ static const char* str_table_entry(
|
||||
is_valid_ptr(elf, elf_size, sym_table, sym_table_size)) \
|
||||
{ \
|
||||
elf##bits##_sym_t* sym = (elf##bits##_sym_t*) sym_table; \
|
||||
elf_data->symtab = (ELF_SYMBOL_LIST*) yr_malloc( \
|
||||
sizeof(ELF_SYMBOL_LIST)); \
|
||||
\
|
||||
if (elf_data->symtab == NULL) \
|
||||
return ERROR_INSUFFICIENT_MEMORY; \
|
||||
\
|
||||
ELF_SYMBOL** symbol = &(elf_data->symtab->symbols); \
|
||||
*symbol = NULL; \
|
||||
\
|
||||
for (j = 0; j < sym_table_size / sizeof(elf##bits##_sym_t); \
|
||||
j++, sym++) \
|
||||
{ \
|
||||
*symbol = (ELF_SYMBOL*) yr_malloc(sizeof(ELF_SYMBOL)); \
|
||||
if (*symbol == NULL) \
|
||||
return ERROR_INSUFFICIENT_MEMORY; \
|
||||
\
|
||||
(*symbol)->name = NULL; \
|
||||
(*symbol)->next = NULL; \
|
||||
\
|
||||
const char* sym_name = str_table_entry( \
|
||||
sym_str_table, \
|
||||
sym_str_table + sym_str_table_size, \
|
||||
yr_##bo##32toh(sym->name)); \
|
||||
\
|
||||
if (sym_name) \
|
||||
{ \
|
||||
set_string(sym_name, elf_obj, "symtab[%i].name", j); \
|
||||
(*symbol)->name = (char*) yr_malloc(strlen(sym_name) + 1); \
|
||||
if ((*symbol)->name == NULL) \
|
||||
return ERROR_INSUFFICIENT_MEMORY; \
|
||||
\
|
||||
set_integer(sym->info >> 4, elf_obj, "symtab[%i].bind", j); \
|
||||
set_integer(sym->info & 0xf, elf_obj, "symtab[%i].type", j); \
|
||||
set_integer( \
|
||||
yr_##bo##16toh(sym->shndx), elf_obj, "symtab[%i].shndx", j); \
|
||||
strcpy((*symbol)->name, sym_name); \
|
||||
} \
|
||||
\
|
||||
int bind = sym->info >> 4; \
|
||||
(*symbol)->bind = bind; \
|
||||
set_integer(bind, elf_obj, "symtab[%i].bind", j); \
|
||||
\
|
||||
int type = sym->info & 0xf; \
|
||||
(*symbol)->type = type; \
|
||||
set_integer(type, elf_obj, "symtab[%i].type", j); \
|
||||
\
|
||||
int shndx = yr_##bo##16toh(sym->shndx); \
|
||||
(*symbol)->shndx = shndx; \
|
||||
set_integer(shndx, elf_obj, "symtab[%i].shndx", j); \
|
||||
\
|
||||
int value = yr_##bo##bits##toh(sym->value); \
|
||||
(*symbol)->value = value; \
|
||||
set_integer( \
|
||||
yr_##bo##bits##toh(sym->value), elf_obj, "symtab[%i].value", j); \
|
||||
\
|
||||
int size = yr_##bo##bits##toh(sym->size); \
|
||||
(*symbol)->size = size; \
|
||||
set_integer( \
|
||||
yr_##bo##bits##toh(sym->size), elf_obj, "symtab[%i].size", j); \
|
||||
\
|
||||
int other = yr_##bo##bits##toh(sym->other); \
|
||||
(*symbol)->visibility = other & 0x3; \
|
||||
\
|
||||
symbol = &((*symbol)->next); \
|
||||
} \
|
||||
\
|
||||
elf_data->symtab->count = j; \
|
||||
set_integer(j, elf_obj, "symtab_entries"); \
|
||||
} \
|
||||
\
|
||||
if (is_valid_ptr(elf, elf_size, dyn_sym_str_table, dyn_sym_str_table_size) && \
|
||||
if (is_valid_ptr( \
|
||||
elf, elf_size, dyn_sym_str_table, dyn_sym_str_table_size) && \
|
||||
is_valid_ptr(elf, elf_size, dyn_sym_table, dyn_sym_table_size)) \
|
||||
{ \
|
||||
elf##bits##_sym_t* dynsym = (elf##bits##_sym_t*) dyn_sym_table; \
|
||||
\
|
||||
elf_data->dynsym = (ELF_SYMBOL_LIST*) yr_malloc( \
|
||||
sizeof(ELF_SYMBOL_LIST)); \
|
||||
\
|
||||
if (elf_data->dynsym == NULL) \
|
||||
return ERROR_INSUFFICIENT_MEMORY; \
|
||||
\
|
||||
ELF_SYMBOL** symbol = &(elf_data->dynsym->symbols); \
|
||||
*symbol = NULL; \
|
||||
\
|
||||
for (m = 0; m < dyn_sym_table_size / sizeof(elf##bits##_sym_t); \
|
||||
m++, dynsym++) \
|
||||
{ \
|
||||
*symbol = (ELF_SYMBOL*) yr_malloc(sizeof(ELF_SYMBOL)); \
|
||||
if (*symbol == NULL) \
|
||||
return ERROR_INSUFFICIENT_MEMORY; \
|
||||
\
|
||||
(*symbol)->name = NULL; \
|
||||
(*symbol)->next = NULL; \
|
||||
\
|
||||
const char* dynsym_name = str_table_entry( \
|
||||
dyn_sym_str_table, \
|
||||
dyn_sym_str_table + dyn_sym_str_table_size, \
|
||||
yr_##bo##32toh(dynsym->name)); \
|
||||
\
|
||||
if (dynsym_name) \
|
||||
{ \
|
||||
set_string(dynsym_name, elf_obj, "dynsym[%i].name", m); \
|
||||
(*symbol)->name = (char*) yr_malloc(strlen(dynsym_name) + 1); \
|
||||
if ((*symbol)->name == NULL) \
|
||||
return ERROR_INSUFFICIENT_MEMORY; \
|
||||
\
|
||||
strcpy((*symbol)->name, dynsym_name); \
|
||||
} \
|
||||
\
|
||||
int bind = dynsym->info >> 4; \
|
||||
(*symbol)->bind = bind; \
|
||||
set_integer(dynsym->info >> 4, elf_obj, "dynsym[%i].bind", m); \
|
||||
\
|
||||
int type = dynsym->info & 0xf; \
|
||||
(*symbol)->type = type; \
|
||||
set_integer(dynsym->info & 0xf, elf_obj, "dynsym[%i].type", m); \
|
||||
\
|
||||
int shndx = yr_##bo##16toh(dynsym->shndx); \
|
||||
(*symbol)->shndx = shndx; \
|
||||
set_integer( \
|
||||
yr_##bo##16toh(dynsym->shndx), elf_obj, "dynsym[%i].shndx", m); \
|
||||
\
|
||||
int value = yr_##bo##bits##toh(dynsym->value); \
|
||||
(*symbol)->value = value; \
|
||||
set_integer( \
|
||||
yr_##bo##bits##toh(dynsym->value), elf_obj, "dynsym[%i].value", m); \
|
||||
yr_##bo##bits##toh(dynsym->value), \
|
||||
elf_obj, \
|
||||
"dynsym[%i].value", \
|
||||
m); \
|
||||
\
|
||||
int size = yr_##bo##bits##toh(dynsym->size); \
|
||||
(*symbol)->size = size; \
|
||||
set_integer( \
|
||||
yr_##bo##bits##toh(dynsym->size), elf_obj, "dynsym[%i].size", m); \
|
||||
yr_##bo##bits##toh(dynsym->size), \
|
||||
elf_obj, \
|
||||
"dynsym[%i].size", \
|
||||
m); \
|
||||
\
|
||||
int other = yr_##bo##bits##toh(dynsym->other); \
|
||||
(*symbol)->visibility = other & 0x3; \
|
||||
\
|
||||
symbol = &((*symbol)->next); \
|
||||
} \
|
||||
\
|
||||
elf_data->dynsym->count = m; \
|
||||
set_integer(m, elf_obj, "dynsym_entries"); \
|
||||
} \
|
||||
} \
|
||||
@@ -476,6 +805,7 @@ static const char* str_table_entry(
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
return ERROR_SUCCESS; \
|
||||
}
|
||||
|
||||
ELF_RVA_TO_OFFSET(32, le);
|
||||
@@ -646,6 +976,13 @@ begin_declarations
|
||||
declare_integer("shndx");
|
||||
end_struct_array("dynsym")
|
||||
|
||||
declare_function("telfhash", "", "s", telfhash);
|
||||
|
||||
#if defined(HAVE_LIBCRYPTO) || defined(HAVE_WINCRYPT_H) || \
|
||||
defined(HAVE_COMMONCRYPTO_COMMONCRYPTO_H)
|
||||
declare_function("import_md5", "", "s", import_md5);
|
||||
#endif // defined(HAVE_LIBCRYPTO) || defined(HAVE_WINCRYPT_H)
|
||||
|
||||
end_declarations
|
||||
|
||||
|
||||
@@ -771,6 +1108,8 @@ int module_load(
|
||||
set_integer(ELF_PF_W, module_object, "PF_W");
|
||||
set_integer(ELF_PF_R, module_object, "PF_R");
|
||||
|
||||
uint64_t parse_result = ERROR_SUCCESS;
|
||||
|
||||
foreach_memory_block(iterator, block)
|
||||
{
|
||||
const uint8_t* block_data = block->fetch_data(block);
|
||||
@@ -778,6 +1117,11 @@ int module_load(
|
||||
if (block_data == NULL)
|
||||
continue;
|
||||
|
||||
ELF* elf = (ELF*) yr_calloc(1, sizeof(ELF));
|
||||
if (elf == NULL)
|
||||
return ERROR_INSUFFICIENT_MEMORY;
|
||||
|
||||
module_object->data = elf;
|
||||
switch (get_elf_class_data(block_data, block->size))
|
||||
{
|
||||
case CLASS_DATA(ELF_CLASS_32, ELF_DATA_2LSB):
|
||||
@@ -789,7 +1133,8 @@ int module_load(
|
||||
if (!(context->flags & SCAN_FLAGS_PROCESS_MEMORY) ||
|
||||
yr_le16toh(elf_header32->type) == ELF_ET_EXEC)
|
||||
{
|
||||
parse_elf_header_32_le(
|
||||
parse_result = parse_elf_header_32_le(
|
||||
elf,
|
||||
elf_header32,
|
||||
block->base,
|
||||
block->size,
|
||||
@@ -809,7 +1154,8 @@ int module_load(
|
||||
if (!(context->flags & SCAN_FLAGS_PROCESS_MEMORY) ||
|
||||
yr_be16toh(elf_header32->type) == ELF_ET_EXEC)
|
||||
{
|
||||
parse_elf_header_32_be(
|
||||
parse_result = parse_elf_header_32_be(
|
||||
elf,
|
||||
elf_header32,
|
||||
block->base,
|
||||
block->size,
|
||||
@@ -829,7 +1175,8 @@ int module_load(
|
||||
if (!(context->flags & SCAN_FLAGS_PROCESS_MEMORY) ||
|
||||
yr_le16toh(elf_header64->type) == ELF_ET_EXEC)
|
||||
{
|
||||
parse_elf_header_64_le(
|
||||
parse_result = parse_elf_header_64_le(
|
||||
elf,
|
||||
elf_header64,
|
||||
block->base,
|
||||
block->size,
|
||||
@@ -849,7 +1196,8 @@ int module_load(
|
||||
if (!(context->flags & SCAN_FLAGS_PROCESS_MEMORY) ||
|
||||
yr_be16toh(elf_header64->type) == ELF_ET_EXEC)
|
||||
{
|
||||
parse_elf_header_64_be(
|
||||
parse_result = parse_elf_header_64_be(
|
||||
elf,
|
||||
elf_header64,
|
||||
block->base,
|
||||
block->size,
|
||||
@@ -862,11 +1210,46 @@ int module_load(
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
return parse_result;
|
||||
}
|
||||
|
||||
|
||||
int module_unload(YR_OBJECT* module_object)
|
||||
{
|
||||
ELF* elf = (ELF*) module_object->data;
|
||||
if (elf == NULL)
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
if (elf->symtab != NULL)
|
||||
{
|
||||
ELF_SYMBOL *act = NULL, *next = NULL;
|
||||
for (act = elf->symtab->symbols; act != NULL; act = next)
|
||||
{
|
||||
next = act->next;
|
||||
if (act->name != NULL)
|
||||
yr_free(act->name);
|
||||
yr_free(act);
|
||||
}
|
||||
yr_free(elf->symtab);
|
||||
}
|
||||
|
||||
if (elf->dynsym != NULL)
|
||||
{
|
||||
ELF_SYMBOL *act = NULL, *next = NULL;
|
||||
for (act = elf->dynsym->symbols; act != NULL; act = next)
|
||||
{
|
||||
next = act->next;
|
||||
if (act->name != NULL)
|
||||
yr_free(act->name);
|
||||
yr_free(act);
|
||||
}
|
||||
yr_free(elf->dynsym);
|
||||
}
|
||||
|
||||
yr_free(elf->telfhash);
|
||||
yr_free(elf->import_hash);
|
||||
yr_free(elf);
|
||||
|
||||
module_object->data = NULL;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <yara/mem.h>
|
||||
#include <yara/simple_str.h>
|
||||
#include <yara/types.h>
|
||||
|
||||
static bool sstr_vappendf(SIMPLE_STR* ss, const char* fmt, va_list va)
|
||||
{
|
||||
va_list va2;
|
||||
// Create copy because list will get consumed when getting the final length
|
||||
va_copy(va2, va);
|
||||
|
||||
int size = vsnprintf(NULL, 0, fmt, va);
|
||||
if (size < 0)
|
||||
return false;
|
||||
|
||||
if (ss->cap < ss->len + size + 1)
|
||||
{
|
||||
uint32_t new_size = (ss->len + size) * 2 + 64;
|
||||
char* tmp = yr_realloc(ss->str, new_size);
|
||||
if (!tmp)
|
||||
return false;
|
||||
|
||||
ss->str = tmp;
|
||||
ss->cap = new_size;
|
||||
}
|
||||
|
||||
ss->len += vsnprintf(ss->str + ss->len, ss->cap, fmt, va2);
|
||||
|
||||
va_end(va2);
|
||||
return true;
|
||||
}
|
||||
|
||||
SIMPLE_STR* sstr_new(const char* s)
|
||||
{
|
||||
SIMPLE_STR* ss = yr_calloc(1, sizeof(SIMPLE_STR));
|
||||
if (!ss)
|
||||
return NULL;
|
||||
|
||||
if (s)
|
||||
{
|
||||
uint32_t slen = strlen(s);
|
||||
ss->str = yr_malloc(slen + 1);
|
||||
if (!ss->str)
|
||||
{
|
||||
yr_free(ss);
|
||||
return NULL;
|
||||
}
|
||||
ss->len = slen;
|
||||
ss->cap = slen;
|
||||
memcpy(ss->str, s, slen + 1);
|
||||
}
|
||||
|
||||
return ss;
|
||||
}
|
||||
|
||||
SIMPLE_STR* sstr_newf(const char* fmt, ...)
|
||||
{
|
||||
SIMPLE_STR* ss = sstr_new(NULL);
|
||||
if (!ss)
|
||||
return NULL;
|
||||
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
bool ret = sstr_vappendf(ss, fmt, va);
|
||||
va_end(va);
|
||||
|
||||
if (ret)
|
||||
return ss;
|
||||
|
||||
sstr_free(ss);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void sstr_free(SIMPLE_STR* ss)
|
||||
{
|
||||
if (ss)
|
||||
{
|
||||
yr_free(ss->str);
|
||||
yr_free(ss);
|
||||
}
|
||||
}
|
||||
|
||||
bool sstr_appendf(SIMPLE_STR* ss, const char* fmt, ...)
|
||||
{
|
||||
va_list vlist;
|
||||
va_start(vlist, fmt);
|
||||
bool ret = sstr_vappendf(ss, fmt, vlist);
|
||||
va_end(vlist);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
char* sstr_move(SIMPLE_STR* ss)
|
||||
{
|
||||
char* ret = ss->str;
|
||||
ss->str = NULL;
|
||||
ss->len = 0;
|
||||
ss->cap = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
#include "tlsh_impl.h"
|
||||
#include <stdlib.h>
|
||||
#include <tlshc/tlsh.h>
|
||||
|
||||
Tlsh* tlsh_new()
|
||||
{
|
||||
Tlsh* tlsh = malloc(sizeof(Tlsh));
|
||||
if (!tlsh)
|
||||
return NULL;
|
||||
|
||||
tlsh->impl = tlsh_impl_new();
|
||||
if (!tlsh->impl) {
|
||||
free(tlsh);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return tlsh;
|
||||
}
|
||||
|
||||
void tlsh_free(Tlsh* tlsh)
|
||||
{
|
||||
if (tlsh) {
|
||||
tlsh_impl_free(tlsh->impl);
|
||||
free(tlsh);
|
||||
}
|
||||
}
|
||||
|
||||
int tlsh_update(Tlsh* tlsh, const unsigned char* data, unsigned int len)
|
||||
{
|
||||
int tlsh_option = 0;
|
||||
if (tlsh->impl) {
|
||||
int res = tlsh_impl_update(tlsh->impl, data, len, tlsh_option);
|
||||
if (res) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tlsh_reset(Tlsh* tlsh)
|
||||
{
|
||||
if (tlsh->impl)
|
||||
tlsh_impl_reset(tlsh->impl);
|
||||
}
|
||||
|
||||
int tlsh_final(Tlsh* tlsh, const unsigned char* data, unsigned int len, int tlsh_option)
|
||||
{
|
||||
if (tlsh->impl) {
|
||||
if ((data != NULL) && (len > 0)) {
|
||||
int res = tlsh_impl_update(tlsh->impl, data, len, tlsh_option);
|
||||
if (res) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
tlsh_impl_final(tlsh->impl, tlsh_option);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* tlsh_get_hash(Tlsh* tlsh, bool showvers)
|
||||
{
|
||||
if (tlsh->impl)
|
||||
return tlsh_impl_hash(tlsh->impl, showvers);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
@@ -0,0 +1,988 @@
|
||||
#include "tlsh_util.h"
|
||||
#include "tlsh_impl.h"
|
||||
#include <tlshc/tlsh.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define RANGE_LVALUE 256
|
||||
#define RANGE_QRATIO 16
|
||||
|
||||
static void
|
||||
find_quartile(unsigned int *q1, unsigned int *q2, unsigned int *q3, const unsigned int *a_bucket);
|
||||
static unsigned int partition(unsigned int *buf, unsigned int left, unsigned int right);
|
||||
static void tlsh_impl_fast_update5(
|
||||
TlshImpl *impl, const unsigned char *data, unsigned int len, int tlsh_option);
|
||||
|
||||
// Pearson's sample random table
|
||||
static unsigned char v_table[256] = {
|
||||
1, 87, 49, 12, 176, 178, 102, 166, 121, 193, 6, 84, 249, 230, 44, 163, 14, 197, 213,
|
||||
181, 161, 85, 218, 80, 64, 239, 24, 226, 236, 142, 38, 200, 110, 177, 104, 103, 141, 253,
|
||||
255, 50, 77, 101, 81, 18, 45, 96, 31, 222, 25, 107, 190, 70, 86, 237, 240, 34, 72,
|
||||
242, 20, 214, 244, 227, 149, 235, 97, 234, 57, 22, 60, 250, 82, 175, 208, 5, 127, 199,
|
||||
111, 62, 135, 248, 174, 169, 211, 58, 66, 154, 106, 195, 245, 171, 17, 187, 182, 179, 0,
|
||||
243, 132, 56, 148, 75, 128, 133, 158, 100, 130, 126, 91, 13, 153, 246, 216, 219, 119, 68,
|
||||
223, 78, 83, 88, 201, 99, 122, 11, 92, 32, 136, 114, 52, 10, 138, 30, 48, 183, 156,
|
||||
35, 61, 26, 143, 74, 251, 94, 129, 162, 63, 152, 170, 7, 115, 167, 241, 206, 3, 150,
|
||||
55, 59, 151, 220, 90, 53, 23, 131, 125, 173, 15, 238, 79, 95, 89, 16, 105, 137, 225,
|
||||
224, 217, 160, 37, 123, 118, 73, 2, 157, 46, 116, 9, 145, 134, 228, 207, 212, 202, 215,
|
||||
69, 229, 27, 188, 67, 124, 168, 252, 42, 4, 29, 108, 21, 247, 19, 205, 39, 203, 233,
|
||||
40, 186, 147, 198, 192, 155, 33, 164, 191, 98, 204, 165, 180, 117, 76, 140, 36, 210, 172,
|
||||
41, 54, 159, 8, 185, 232, 113, 196, 231, 47, 146, 120, 51, 65, 28, 144, 254, 221, 93,
|
||||
189, 194, 139, 112, 43, 71, 109, 184, 209};
|
||||
|
||||
static unsigned char v_table48[256] = {
|
||||
1, 39, 1, 12, 32, 34, 6, 22, 25, 1, 6, 36, 48, 38, 44, 19, 14, 5, 21, 37, 17, 37, 26, 32,
|
||||
16, 47, 24, 34, 44, 46, 38, 8, 14, 33, 8, 7, 45, 48, 48, 2, 29, 5, 33, 18, 45, 0, 31, 30,
|
||||
25, 11, 46, 22, 38, 45, 48, 34, 24, 48, 20, 22, 48, 35, 5, 43, 1, 42, 9, 22, 12, 48, 34, 31,
|
||||
16, 5, 31, 7, 15, 14, 39, 48, 30, 25, 19, 10, 18, 10, 10, 3, 48, 27, 17, 43, 38, 35, 0, 48,
|
||||
36, 8, 4, 27, 32, 37, 14, 4, 34, 30, 43, 13, 9, 48, 24, 27, 23, 20, 31, 30, 35, 40, 9, 3,
|
||||
26, 11, 44, 32, 40, 18, 4, 10, 42, 30, 0, 39, 12, 35, 13, 26, 47, 26, 48, 46, 33, 18, 15, 8,
|
||||
26, 7, 19, 23, 48, 14, 3, 6, 7, 11, 7, 28, 42, 5, 23, 35, 29, 29, 15, 46, 31, 47, 41, 16,
|
||||
9, 41, 33, 32, 25, 16, 37, 27, 22, 25, 2, 13, 46, 20, 9, 1, 38, 36, 15, 20, 10, 23, 21, 37,
|
||||
27, 44, 19, 28, 24, 48, 42, 4, 29, 12, 21, 48, 19, 13, 39, 11, 41, 40, 42, 3, 6, 0, 11, 33,
|
||||
20, 47, 2, 12, 21, 36, 21, 28, 44, 36, 18, 28, 41, 6, 15, 8, 41, 40, 17, 4, 39, 47, 2, 24,
|
||||
3, 17, 28, 0, 48, 29, 45, 45, 2, 43, 16, 43, 23, 13, 40, 17,
|
||||
};
|
||||
|
||||
// Pearson's algorithm
|
||||
static unsigned char
|
||||
b_mapping(unsigned char salt, unsigned char i, unsigned char j, unsigned char k)
|
||||
{
|
||||
unsigned char h = 0;
|
||||
|
||||
h = v_table[h ^ salt];
|
||||
h = v_table[h ^ i];
|
||||
h = v_table[h ^ j];
|
||||
h = v_table[h ^ k];
|
||||
return h;
|
||||
}
|
||||
|
||||
#if defined BUCKETS_48
|
||||
#define fast_b_mapping(ms, i, j, k) (v_table48[v_table[v_table[ms ^ i] ^ j] ^ k])
|
||||
#else
|
||||
#define fast_b_mapping(ms, i, j, k) (v_table[v_table[v_table[ms ^ i] ^ j] ^ k])
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if SLIDING_WND_SIZE == 5
|
||||
#define SLIDING_WND_SIZE_M1 4
|
||||
#elif SLIDING_WND_SIZE == 4
|
||||
#define SLIDING_WND_SIZE_M1 3
|
||||
#elif SLIDING_WND_SIZE == 6
|
||||
#define SLIDING_WND_SIZE_M1 5
|
||||
#elif SLIDING_WND_SIZE == 7
|
||||
#define SLIDING_WND_SIZE_M1 6
|
||||
#elif SLIDING_WND_SIZE == 8
|
||||
#define SLIDING_WND_SIZE_M1 7
|
||||
#endif
|
||||
|
||||
#define RNG_SIZE SLIDING_WND_SIZE
|
||||
#define RNG_IDX(i) ((i + RNG_SIZE) % RNG_SIZE)
|
||||
|
||||
TlshImpl *tlsh_impl_new()
|
||||
{
|
||||
TlshImpl *impl = calloc(1, sizeof(TlshImpl));
|
||||
if (!impl)
|
||||
return NULL;
|
||||
|
||||
return impl;
|
||||
}
|
||||
void tlsh_impl_free(TlshImpl *impl)
|
||||
{
|
||||
if (impl) {
|
||||
free(impl->a_bucket);
|
||||
free(impl->lsh_code);
|
||||
free(impl);
|
||||
}
|
||||
}
|
||||
|
||||
void tlsh_impl_reset(TlshImpl *impl)
|
||||
{
|
||||
free(impl->a_bucket);
|
||||
impl->a_bucket = NULL;
|
||||
memset(impl->slide_window, 0, sizeof impl->slide_window);
|
||||
free(impl->lsh_code);
|
||||
impl->lsh_code = NULL;
|
||||
memset(&impl->lsh_bin, 0, sizeof impl->lsh_bin);
|
||||
impl->data_len = 0;
|
||||
impl->lsh_code_valid = false;
|
||||
}
|
||||
|
||||
int tlsh_impl_update(TlshImpl *impl, const unsigned char *data, unsigned int len, int tlsh_option)
|
||||
{
|
||||
if (impl->lsh_code_valid) {
|
||||
fprintf(stderr, "call to update() on a tlsh that is already valid\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned int fed_len = impl->data_len;
|
||||
|
||||
if (impl->a_bucket == NULL) {
|
||||
impl->a_bucket = malloc(BUCKETS * sizeof(unsigned int)); // TODO error handling
|
||||
if (!impl->a_bucket) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(impl->a_bucket, 0, sizeof(int) * BUCKETS);
|
||||
}
|
||||
|
||||
#if SLIDING_WND_SIZE == 5
|
||||
if (TLSH_CHECKSUM_LEN == 1) {
|
||||
tlsh_impl_fast_update5(impl, data, len, tlsh_option);
|
||||
#ifndef CHECKSUM_0B
|
||||
if ((tlsh_option & TLSH_OPTION_THREADED) || (tlsh_option & TLSH_OPTION_PRIVATE)) {
|
||||
impl->lsh_bin.checksum[0] = 0;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
int j = (int)(impl->data_len % RNG_SIZE);
|
||||
|
||||
for (unsigned int i = 0; i < len; i++, fed_len++, j = RNG_IDX(j + 1)) {
|
||||
impl->slide_window[j] = data[i];
|
||||
|
||||
if (fed_len >= SLIDING_WND_SIZE_M1) {
|
||||
// only calculate when input >= 5 bytes
|
||||
int j_1 = RNG_IDX(j - 1);
|
||||
int j_2 = RNG_IDX(j - 2);
|
||||
int j_3 = RNG_IDX(j - 3);
|
||||
#if SLIDING_WND_SIZE >= 5
|
||||
int j_4 = RNG_IDX(j - 4);
|
||||
#endif
|
||||
#if SLIDING_WND_SIZE >= 6
|
||||
int j_5 = RNG_IDX(j - 5);
|
||||
#endif
|
||||
#if SLIDING_WND_SIZE >= 7
|
||||
int j_6 = RNG_IDX(j - 6);
|
||||
#endif
|
||||
#if SLIDING_WND_SIZE >= 8
|
||||
int j_7 = RNG_IDX(j - 7);
|
||||
#endif
|
||||
|
||||
#ifndef CHECKSUM_0B
|
||||
for (int k = 0; k < TLSH_CHECKSUM_LEN; k++) {
|
||||
if (k == 0) {
|
||||
// b_mapping(0, ... )
|
||||
impl->lsh_bin.checksum[k] = fast_b_mapping(
|
||||
1,
|
||||
impl->slide_window[j],
|
||||
impl->slide_window[j_1],
|
||||
impl->lsh_bin.checksum[k]);
|
||||
} else {
|
||||
// use calculated 1 byte checksums to expand the total checksum to 3
|
||||
// bytes
|
||||
impl->lsh_bin.checksum[k] = b_mapping(
|
||||
impl->lsh_bin.checksum[k - 1],
|
||||
impl->slide_window[j],
|
||||
impl->slide_window[j_1],
|
||||
impl->lsh_bin.checksum[k]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned char r;
|
||||
// b_mapping(2, ... )
|
||||
r = fast_b_mapping(
|
||||
49, impl->slide_window[j], impl->slide_window[j_1], impl->slide_window[j_2]);
|
||||
impl->a_bucket[r]++;
|
||||
// b_mapping(3, ... )
|
||||
r = fast_b_mapping(
|
||||
12, impl->slide_window[j], impl->slide_window[j_1], impl->slide_window[j_3]);
|
||||
impl->a_bucket[r]++;
|
||||
// b_mapping(5, ... )
|
||||
r = fast_b_mapping(
|
||||
178, impl->slide_window[j], impl->slide_window[j_2], impl->slide_window[j_3]);
|
||||
impl->a_bucket[r]++;
|
||||
#if SLIDING_WND_SIZE >= 5
|
||||
// b_mapping(7, ... )
|
||||
r = fast_b_mapping(
|
||||
166, impl->slide_window[j], impl->slide_window[j_2], impl->slide_window[j_4]);
|
||||
impl->a_bucket[r]++;
|
||||
// b_mapping(11, ... )
|
||||
r = fast_b_mapping(
|
||||
84, impl->slide_window[j], impl->slide_window[j_1], impl->slide_window[j_4]);
|
||||
impl->a_bucket[r]++;
|
||||
// b_mapping(13, ... )
|
||||
r = fast_b_mapping(
|
||||
230, impl->slide_window[j], impl->slide_window[j_3], impl->slide_window[j_4]);
|
||||
impl->a_bucket[r]++;
|
||||
#endif
|
||||
#if SLIDING_WND_SIZE >= 6
|
||||
// b_mapping(17, ... )
|
||||
r = fast_b_mapping(
|
||||
197, this->slide_window[j], this->slide_window[j_1], this->slide_window[j_5]);
|
||||
this->a_bucket[r]++;
|
||||
// b_mapping(19, ... )
|
||||
r = fast_b_mapping(
|
||||
181, this->slide_window[j], this->slide_window[j_2], this->slide_window[j_5]);
|
||||
this->a_bucket[r]++;
|
||||
// b_mapping(23, ... )
|
||||
r = fast_b_mapping(
|
||||
80, this->slide_window[j], this->slide_window[j_3], this->slide_window[j_5]);
|
||||
this->a_bucket[r]++;
|
||||
// b_mapping(29, ... )
|
||||
r = fast_b_mapping(
|
||||
142, this->slide_window[j], this->slide_window[j_4], this->slide_window[j_5]);
|
||||
this->a_bucket[r]++;
|
||||
#endif
|
||||
#if SLIDING_WND_SIZE >= 7
|
||||
// b_mapping(31, ... )
|
||||
r = fast_b_mapping(
|
||||
200, this->slide_window[j], this->slide_window[j_1], this->slide_window[j_6]);
|
||||
this->a_bucket[r]++;
|
||||
// b_mapping(37, ... )
|
||||
r = fast_b_mapping(
|
||||
253, this->slide_window[j], this->slide_window[j_2], this->slide_window[j_6]);
|
||||
this->a_bucket[r]++;
|
||||
// b_mapping(41, ... )
|
||||
r = fast_b_mapping(
|
||||
101, this->slide_window[j], this->slide_window[j_3], this->slide_window[j_6]);
|
||||
this->a_bucket[r]++;
|
||||
// b_mapping(43, ... )
|
||||
r = fast_b_mapping(
|
||||
18, this->slide_window[j], this->slide_window[j_4], this->slide_window[j_6]);
|
||||
this->a_bucket[r]++;
|
||||
// b_mapping(47, ... )
|
||||
r = fast_b_mapping(
|
||||
222, this->slide_window[j], this->slide_window[j_5], this->slide_window[j_6]);
|
||||
this->a_bucket[r]++;
|
||||
#endif
|
||||
#if SLIDING_WND_SIZE >= 8
|
||||
// b_mapping(53, ... )
|
||||
r = fast_b_mapping(
|
||||
237, this->slide_window[j], this->slide_window[j_1], this->slide_window[j_7]);
|
||||
this->a_bucket[r]++;
|
||||
// b_mapping(59, ... )
|
||||
r = fast_b_mapping(
|
||||
214, this->slide_window[j], this->slide_window[j_2], this->slide_window[j_7]);
|
||||
this->a_bucket[r]++;
|
||||
// b_mapping(61, ... )
|
||||
r = fast_b_mapping(
|
||||
227, this->slide_window[j], this->slide_window[j_3], this->slide_window[j_7]);
|
||||
this->a_bucket[r]++;
|
||||
// b_mapping(67, ... )
|
||||
r = fast_b_mapping(
|
||||
22, this->slide_window[j], this->slide_window[j_4], this->slide_window[j_7]);
|
||||
this->a_bucket[r]++;
|
||||
// b_mapping(71, ... )
|
||||
r = fast_b_mapping(
|
||||
175, this->slide_window[j], this->slide_window[j_5], this->slide_window[j_7]);
|
||||
this->a_bucket[r]++;
|
||||
// b_mapping(73, ... )
|
||||
r = fast_b_mapping(
|
||||
5, this->slide_window[j], this->slide_window[j_6], this->slide_window[j_7]);
|
||||
this->a_bucket[r]++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
impl->data_len += len;
|
||||
#ifndef CHECKSUM_0B
|
||||
if ((tlsh_option & TLSH_OPTION_THREADED) || (tlsh_option & TLSH_OPTION_PRIVATE)) {
|
||||
for (int k = 0; k < TLSH_CHECKSUM_LEN; k++) {
|
||||
impl->lsh_bin.checksum[k] = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// update for the case when SLIDING_WND_SIZE==5
|
||||
// have different optimized functions for
|
||||
// default TLSH
|
||||
// threaded TLSH
|
||||
// private TLSH
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
static void raw_fast_update5(
|
||||
// inputs
|
||||
const unsigned char *data,
|
||||
unsigned int len,
|
||||
unsigned int fed_len,
|
||||
// outputs
|
||||
unsigned int *a_bucket,
|
||||
unsigned char *ret_checksum,
|
||||
unsigned char *slide_window);
|
||||
|
||||
static void raw_fast_update5_private(
|
||||
// inputs
|
||||
const unsigned char *data,
|
||||
unsigned int len,
|
||||
unsigned int fed_len,
|
||||
// outputs
|
||||
unsigned int *a_bucket,
|
||||
unsigned char *slide_window);
|
||||
|
||||
static void
|
||||
tlsh_impl_fast_update5(TlshImpl *impl, const unsigned char *data, unsigned int len, int tlsh_option)
|
||||
{
|
||||
if (tlsh_option & TLSH_OPTION_PRIVATE) {
|
||||
raw_fast_update5_private(data, len, impl->data_len, impl->a_bucket, impl->slide_window);
|
||||
impl->data_len += len;
|
||||
impl->lsh_bin.checksum[0] = 0;
|
||||
} else {
|
||||
raw_fast_update5(
|
||||
data,
|
||||
len,
|
||||
impl->data_len,
|
||||
impl->a_bucket,
|
||||
&(impl->lsh_bin.checksum[0]),
|
||||
impl->slide_window);
|
||||
impl->data_len += len;
|
||||
}
|
||||
}
|
||||
|
||||
static void raw_fast_update5(
|
||||
// inputs
|
||||
const unsigned char *data,
|
||||
unsigned int len,
|
||||
unsigned int fed_len,
|
||||
// outputs
|
||||
unsigned int *a_bucket,
|
||||
unsigned char *ret_checksum,
|
||||
unsigned char *slide_window)
|
||||
{
|
||||
int j = (int)(fed_len % RNG_SIZE);
|
||||
unsigned char checksum = *ret_checksum;
|
||||
|
||||
unsigned int start_i = 0;
|
||||
if (fed_len < SLIDING_WND_SIZE_M1) {
|
||||
int extra = SLIDING_WND_SIZE_M1 - fed_len;
|
||||
start_i = extra;
|
||||
j = (j + extra) % RNG_SIZE;
|
||||
}
|
||||
for (unsigned int i = start_i; i < len;) {
|
||||
// only calculate when input >= 5 bytes
|
||||
if ((i >= 4) && (i + 5 < len)) {
|
||||
unsigned char a0 = data[i - 4];
|
||||
unsigned char a1 = data[i - 3];
|
||||
unsigned char a2 = data[i - 2];
|
||||
unsigned char a3 = data[i - 1];
|
||||
unsigned char a4 = data[i];
|
||||
unsigned char a5 = data[i + 1];
|
||||
unsigned char a6 = data[i + 2];
|
||||
unsigned char a7 = data[i + 3];
|
||||
unsigned char a8 = data[i + 4];
|
||||
|
||||
checksum = fast_b_mapping(1, a4, a3, checksum);
|
||||
a_bucket[fast_b_mapping(49, a4, a3, a2)]++;
|
||||
a_bucket[fast_b_mapping(12, a4, a3, a1)]++;
|
||||
a_bucket[fast_b_mapping(178, a4, a2, a1)]++;
|
||||
a_bucket[fast_b_mapping(166, a4, a2, a0)]++;
|
||||
a_bucket[fast_b_mapping(84, a4, a3, a0)]++;
|
||||
a_bucket[fast_b_mapping(230, a4, a1, a0)]++;
|
||||
|
||||
checksum = fast_b_mapping(1, a5, a4, checksum);
|
||||
a_bucket[fast_b_mapping(49, a5, a4, a3)]++;
|
||||
a_bucket[fast_b_mapping(12, a5, a4, a2)]++;
|
||||
a_bucket[fast_b_mapping(178, a5, a3, a2)]++;
|
||||
a_bucket[fast_b_mapping(166, a5, a3, a1)]++;
|
||||
a_bucket[fast_b_mapping(84, a5, a4, a1)]++;
|
||||
a_bucket[fast_b_mapping(230, a5, a2, a1)]++;
|
||||
|
||||
checksum = fast_b_mapping(1, a6, a5, checksum);
|
||||
a_bucket[fast_b_mapping(49, a6, a5, a4)]++;
|
||||
a_bucket[fast_b_mapping(12, a6, a5, a3)]++;
|
||||
a_bucket[fast_b_mapping(178, a6, a4, a3)]++;
|
||||
a_bucket[fast_b_mapping(166, a6, a4, a2)]++;
|
||||
a_bucket[fast_b_mapping(84, a6, a5, a2)]++;
|
||||
a_bucket[fast_b_mapping(230, a6, a3, a2)]++;
|
||||
|
||||
checksum = fast_b_mapping(1, a7, a6, checksum);
|
||||
a_bucket[fast_b_mapping(49, a7, a6, a5)]++;
|
||||
a_bucket[fast_b_mapping(12, a7, a6, a4)]++;
|
||||
a_bucket[fast_b_mapping(178, a7, a5, a4)]++;
|
||||
a_bucket[fast_b_mapping(166, a7, a5, a3)]++;
|
||||
a_bucket[fast_b_mapping(84, a7, a6, a3)]++;
|
||||
a_bucket[fast_b_mapping(230, a7, a4, a3)]++;
|
||||
|
||||
checksum = fast_b_mapping(1, a8, a7, checksum);
|
||||
a_bucket[fast_b_mapping(49, a8, a7, a6)]++;
|
||||
a_bucket[fast_b_mapping(12, a8, a7, a5)]++;
|
||||
a_bucket[fast_b_mapping(178, a8, a6, a5)]++;
|
||||
a_bucket[fast_b_mapping(166, a8, a6, a4)]++;
|
||||
a_bucket[fast_b_mapping(84, a8, a7, a4)]++;
|
||||
a_bucket[fast_b_mapping(230, a8, a5, a4)]++;
|
||||
|
||||
i = i + 5;
|
||||
j = RNG_IDX(j + 5);
|
||||
} else {
|
||||
slide_window[j] = data[i];
|
||||
int j_1 = RNG_IDX(j - 1);
|
||||
if (i >= 1) {
|
||||
slide_window[j_1] = data[i - 1];
|
||||
}
|
||||
int j_2 = RNG_IDX(j - 2);
|
||||
if (i >= 2) {
|
||||
slide_window[j_2] = data[i - 2];
|
||||
}
|
||||
int j_3 = RNG_IDX(j - 3);
|
||||
if (i >= 3) {
|
||||
slide_window[j_3] = data[i - 3];
|
||||
}
|
||||
int j_4 = RNG_IDX(j - 4);
|
||||
if (i >= 4) {
|
||||
slide_window[j_4] = data[i - 4];
|
||||
}
|
||||
|
||||
checksum = fast_b_mapping(1, slide_window[j], slide_window[j_1], checksum);
|
||||
a_bucket[fast_b_mapping(49, slide_window[j], slide_window[j_1], slide_window[j_2])]++;
|
||||
a_bucket[fast_b_mapping(12, slide_window[j], slide_window[j_1], slide_window[j_3])]++;
|
||||
a_bucket[fast_b_mapping(178, slide_window[j], slide_window[j_2], slide_window[j_3])]++;
|
||||
a_bucket[fast_b_mapping(166, slide_window[j], slide_window[j_2], slide_window[j_4])]++;
|
||||
a_bucket[fast_b_mapping(84, slide_window[j], slide_window[j_1], slide_window[j_4])]++;
|
||||
a_bucket[fast_b_mapping(230, slide_window[j], slide_window[j_3], slide_window[j_4])]++;
|
||||
i++;
|
||||
j = RNG_IDX(j + 1);
|
||||
}
|
||||
}
|
||||
*ret_checksum = checksum;
|
||||
}
|
||||
|
||||
static void raw_fast_update5_private(
|
||||
// inputs
|
||||
const unsigned char *data,
|
||||
unsigned int len,
|
||||
unsigned int fed_len,
|
||||
// outputs
|
||||
unsigned int *a_bucket,
|
||||
unsigned char *slide_window)
|
||||
{
|
||||
int j = (int)(fed_len % RNG_SIZE);
|
||||
|
||||
unsigned int start_i = 0;
|
||||
if (fed_len < SLIDING_WND_SIZE_M1) {
|
||||
int extra = SLIDING_WND_SIZE_M1 - fed_len;
|
||||
start_i = extra;
|
||||
j = (j + extra) % RNG_SIZE;
|
||||
}
|
||||
for (unsigned int i = start_i; i < len;) {
|
||||
// only calculate when input >= 5 bytes
|
||||
if ((i >= 4) && (i + 5 < len)) {
|
||||
unsigned char a0 = data[i - 4];
|
||||
unsigned char a1 = data[i - 3];
|
||||
unsigned char a2 = data[i - 2];
|
||||
unsigned char a3 = data[i - 1];
|
||||
unsigned char a4 = data[i];
|
||||
unsigned char a5 = data[i + 1];
|
||||
unsigned char a6 = data[i + 2];
|
||||
unsigned char a7 = data[i + 3];
|
||||
unsigned char a8 = data[i + 4];
|
||||
|
||||
a_bucket[fast_b_mapping(49, a4, a3, a2)]++;
|
||||
a_bucket[fast_b_mapping(12, a4, a3, a1)]++;
|
||||
a_bucket[fast_b_mapping(178, a4, a2, a1)]++;
|
||||
a_bucket[fast_b_mapping(166, a4, a2, a0)]++;
|
||||
a_bucket[fast_b_mapping(84, a4, a3, a0)]++;
|
||||
a_bucket[fast_b_mapping(230, a4, a1, a0)]++;
|
||||
|
||||
a_bucket[fast_b_mapping(49, a5, a4, a3)]++;
|
||||
a_bucket[fast_b_mapping(12, a5, a4, a2)]++;
|
||||
a_bucket[fast_b_mapping(178, a5, a3, a2)]++;
|
||||
a_bucket[fast_b_mapping(166, a5, a3, a1)]++;
|
||||
a_bucket[fast_b_mapping(84, a5, a4, a1)]++;
|
||||
a_bucket[fast_b_mapping(230, a5, a2, a1)]++;
|
||||
|
||||
a_bucket[fast_b_mapping(49, a6, a5, a4)]++;
|
||||
a_bucket[fast_b_mapping(12, a6, a5, a3)]++;
|
||||
a_bucket[fast_b_mapping(178, a6, a4, a3)]++;
|
||||
a_bucket[fast_b_mapping(166, a6, a4, a2)]++;
|
||||
a_bucket[fast_b_mapping(84, a6, a5, a2)]++;
|
||||
a_bucket[fast_b_mapping(230, a6, a3, a2)]++;
|
||||
|
||||
a_bucket[fast_b_mapping(49, a7, a6, a5)]++;
|
||||
a_bucket[fast_b_mapping(12, a7, a6, a4)]++;
|
||||
a_bucket[fast_b_mapping(178, a7, a5, a4)]++;
|
||||
a_bucket[fast_b_mapping(166, a7, a5, a3)]++;
|
||||
a_bucket[fast_b_mapping(84, a7, a6, a3)]++;
|
||||
a_bucket[fast_b_mapping(230, a7, a4, a3)]++;
|
||||
|
||||
a_bucket[fast_b_mapping(49, a8, a7, a6)]++;
|
||||
a_bucket[fast_b_mapping(12, a8, a7, a5)]++;
|
||||
a_bucket[fast_b_mapping(178, a8, a6, a5)]++;
|
||||
a_bucket[fast_b_mapping(166, a8, a6, a4)]++;
|
||||
a_bucket[fast_b_mapping(84, a8, a7, a4)]++;
|
||||
a_bucket[fast_b_mapping(230, a8, a5, a4)]++;
|
||||
|
||||
i = i + 5;
|
||||
j = RNG_IDX(j + 5);
|
||||
} else {
|
||||
slide_window[j] = data[i];
|
||||
int j_1 = RNG_IDX(j - 1);
|
||||
if (i >= 1) {
|
||||
slide_window[j_1] = data[i - 1];
|
||||
}
|
||||
int j_2 = RNG_IDX(j - 2);
|
||||
if (i >= 2) {
|
||||
slide_window[j_2] = data[i - 2];
|
||||
}
|
||||
int j_3 = RNG_IDX(j - 3);
|
||||
if (i >= 3) {
|
||||
slide_window[j_3] = data[i - 3];
|
||||
}
|
||||
int j_4 = RNG_IDX(j - 4);
|
||||
if (i >= 4) {
|
||||
slide_window[j_4] = data[i - 4];
|
||||
}
|
||||
|
||||
a_bucket[fast_b_mapping(49, slide_window[j], slide_window[j_1], slide_window[j_2])]++;
|
||||
a_bucket[fast_b_mapping(12, slide_window[j], slide_window[j_1], slide_window[j_3])]++;
|
||||
a_bucket[fast_b_mapping(178, slide_window[j], slide_window[j_2], slide_window[j_3])]++;
|
||||
a_bucket[fast_b_mapping(166, slide_window[j], slide_window[j_2], slide_window[j_4])]++;
|
||||
a_bucket[fast_b_mapping(84, slide_window[j], slide_window[j_1], slide_window[j_4])]++;
|
||||
a_bucket[fast_b_mapping(230, slide_window[j], slide_window[j_3], slide_window[j_4])]++;
|
||||
i++;
|
||||
j = RNG_IDX(j + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// fc_cons_option - a bitfield
|
||||
// 0 default
|
||||
// 1 force (now the default)
|
||||
// 2 conservative
|
||||
// 4 do not delete a_bucket
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* to signal the class there is no more data to be added */
|
||||
void tlsh_impl_final(TlshImpl *this, int fc_cons_option)
|
||||
{
|
||||
if (this->lsh_code_valid) {
|
||||
fprintf(stderr, "call to final() on a tlsh that is already valid\n");
|
||||
return;
|
||||
}
|
||||
// incoming data must more than or equal to MIN_DATA_LENGTH bytes
|
||||
if (((fc_cons_option & TLSH_OPTION_CONSERVATIVE) == 0) && (this->data_len < MIN_DATA_LENGTH)) {
|
||||
// this->lsh_code be empty
|
||||
free(this->a_bucket);
|
||||
this->a_bucket = NULL;
|
||||
return;
|
||||
}
|
||||
if ((fc_cons_option & TLSH_OPTION_CONSERVATIVE) &&
|
||||
(this->data_len < MIN_CONSERVATIVE_DATA_LENGTH)) {
|
||||
// this->lsh_code be empty
|
||||
free(this->a_bucket);
|
||||
this->a_bucket = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int q1, q2, q3;
|
||||
find_quartile(&q1, &q2, &q3, this->a_bucket);
|
||||
|
||||
// issue #79 - divide by 0 if q3 == 0
|
||||
if (q3 == 0) {
|
||||
free(this->a_bucket);
|
||||
this->a_bucket = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
// buckets must be more than 50% non-zero
|
||||
int nonzero = 0;
|
||||
for (unsigned int i = 0; i < CODE_SIZE; i++) {
|
||||
for (unsigned int j = 0; j < 4; j++) {
|
||||
if (this->a_bucket[4 * i + j] > 0) {
|
||||
nonzero++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if defined BUCKETS_48
|
||||
if (nonzero < 18) {
|
||||
// printf("nonzero=%d\n", nonzero);
|
||||
delete[] this->a_bucket;
|
||||
this->a_bucket = NULL;
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (nonzero <= 4 * CODE_SIZE / 2) {
|
||||
free(this->a_bucket);
|
||||
this->a_bucket = NULL;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (unsigned int i = 0; i < CODE_SIZE; i++) {
|
||||
unsigned char h = 0;
|
||||
for (unsigned int j = 0; j < 4; j++) {
|
||||
unsigned int k = this->a_bucket[4 * i + j];
|
||||
if (q3 < k) {
|
||||
h += 3 << (j * 2); // leave the optimization j*2 = j<<1 or j*2 = j+j for
|
||||
// compiler
|
||||
} else if (q2 < k) {
|
||||
h += 2 << (j * 2);
|
||||
} else if (q1 < k) {
|
||||
h += 1 << (j * 2);
|
||||
}
|
||||
}
|
||||
this->lsh_bin.tmp_code[i] = h;
|
||||
}
|
||||
|
||||
if ((fc_cons_option & TLSH_OPTION_KEEP_BUCKET) == 0) {
|
||||
// Done with a_bucket so deallocate
|
||||
free(this->a_bucket);
|
||||
this->a_bucket = NULL;
|
||||
}
|
||||
|
||||
this->lsh_bin.lvalue = l_capturing(this->data_len);
|
||||
this->lsh_bin.Q.QR.q1ratio = (unsigned int)((float)(q1 * 100) / (float)q3) % 16;
|
||||
this->lsh_bin.Q.QR.q2ratio = (unsigned int)((float)(q2 * 100) / (float)q3) % 16;
|
||||
this->lsh_code_valid = true;
|
||||
}
|
||||
|
||||
int tlsh_impl_from_tlsh_str(TlshImpl *impl, const char *str)
|
||||
{
|
||||
// Assume that we have 128 Buckets
|
||||
int start = 0;
|
||||
if (strncmp(str, "T1", 2) == 0) {
|
||||
start = 2;
|
||||
} else {
|
||||
start = 0;
|
||||
}
|
||||
// Validate input string
|
||||
for (int ii = 0; ii < INTERNAL_TLSH_STRING_LEN; ii++) {
|
||||
int i = ii + start;
|
||||
if (!((str[i] >= '0' && str[i] <= '9') || (str[i] >= 'A' && str[i] <= 'F') ||
|
||||
(str[i] >= 'a' && str[i] <= 'f'))) {
|
||||
// printf("warning ii=%d str[%d]='%c'\n", ii, i, str[i]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
int xi = INTERNAL_TLSH_STRING_LEN + start;
|
||||
if (((str[xi] >= '0' && str[xi] <= '9') || (str[xi] >= 'A' && str[xi] <= 'F') ||
|
||||
(str[xi] >= 'a' && str[xi] <= 'f'))) {
|
||||
// printf("warning xi=%d\n", xi);
|
||||
return 1;
|
||||
}
|
||||
|
||||
tlsh_impl_reset(impl);
|
||||
|
||||
LshBinStruct tmp;
|
||||
from_hex(&str[start], INTERNAL_TLSH_STRING_LEN, (unsigned char *)&tmp);
|
||||
|
||||
// Reconstruct checksum, Qrations & lvalue
|
||||
for (int k = 0; k < TLSH_CHECKSUM_LEN; k++) {
|
||||
impl->lsh_bin.checksum[k] = swap_byte(tmp.checksum[k]);
|
||||
}
|
||||
impl->lsh_bin.lvalue = swap_byte(tmp.lvalue);
|
||||
impl->lsh_bin.Q.qb = swap_byte(tmp.Q.qb);
|
||||
for (int i = 0; i < CODE_SIZE; i++) {
|
||||
impl->lsh_bin.tmp_code[i] = (tmp.tmp_code[CODE_SIZE - 1 - i]);
|
||||
}
|
||||
impl->lsh_code_valid = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *hash2(TlshImpl *impl, char *buffer, unsigned int bufSize, bool showvers)
|
||||
{
|
||||
if (bufSize < TLSH_STRING_LEN_REQ + 1) {
|
||||
strncpy(buffer, "", bufSize);
|
||||
return buffer;
|
||||
}
|
||||
if (impl->lsh_code_valid == false) {
|
||||
strncpy(buffer, "", bufSize);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
LshBinStruct tmp;
|
||||
for (int k = 0; k < TLSH_CHECKSUM_LEN; k++) {
|
||||
tmp.checksum[k] = swap_byte(impl->lsh_bin.checksum[k]);
|
||||
}
|
||||
tmp.lvalue = swap_byte(impl->lsh_bin.lvalue);
|
||||
tmp.Q.qb = swap_byte(impl->lsh_bin.Q.qb);
|
||||
for (int i = 0; i < CODE_SIZE; i++) {
|
||||
tmp.tmp_code[i] = (impl->lsh_bin.tmp_code[CODE_SIZE - 1 - i]);
|
||||
}
|
||||
|
||||
if (showvers) {
|
||||
buffer[0] = 'T';
|
||||
buffer[1] = '0' + showvers;
|
||||
to_hex((unsigned char *)&tmp, sizeof(tmp), &buffer[2]);
|
||||
} else {
|
||||
to_hex((unsigned char *)&tmp, sizeof(tmp), buffer);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/* to get the hex-encoded hash code */
|
||||
const char *tlsh_impl_hash(TlshImpl *impl, bool showvers)
|
||||
{
|
||||
if (impl->lsh_code != NULL) {
|
||||
// lsh_code has been previously calculated, so just return it
|
||||
return impl->lsh_code;
|
||||
}
|
||||
|
||||
impl->lsh_code = (char *)malloc(TLSH_STRING_LEN_REQ + 1);
|
||||
if (!impl->lsh_code) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(impl->lsh_code, 0, TLSH_STRING_LEN_REQ + 1);
|
||||
|
||||
return hash2(impl, impl->lsh_code, TLSH_STRING_LEN_REQ + 1, showvers);
|
||||
}
|
||||
|
||||
int tlsh_impl_compare(TlshImpl *this, TlshImpl *other)
|
||||
{
|
||||
return (memcmp(&(this->lsh_bin), &(other->lsh_bin), sizeof(this->lsh_bin)));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////
|
||||
// the default for these parameters is 12
|
||||
////////////////////////////////////////////
|
||||
|
||||
static int length_mult = 12;
|
||||
static int qratio_mult = 12;
|
||||
|
||||
#ifdef TLSH_DISTANCE_PARAMETERS
|
||||
|
||||
int hist_diff1_add = 1;
|
||||
int hist_diff2_add = 2;
|
||||
int hist_diff3_add = 6;
|
||||
|
||||
void set_tlsh_distance_parameters(
|
||||
int length_mult_value,
|
||||
int qratio_mult_value,
|
||||
int hist_diff1_add_value,
|
||||
int hist_diff2_add_value,
|
||||
int hist_diff3_add_value)
|
||||
{
|
||||
if (length_mult_value != -1) {
|
||||
length_mult = length_mult_value;
|
||||
}
|
||||
if (qratio_mult_value != -1) {
|
||||
qratio_mult = qratio_mult_value;
|
||||
}
|
||||
if (hist_diff1_add_value != -1) {
|
||||
hist_diff1_add = hist_diff1_add_value;
|
||||
}
|
||||
if (hist_diff2_add_value != -1) {
|
||||
hist_diff2_add = hist_diff2_add_value;
|
||||
}
|
||||
if (hist_diff3_add_value != -1) {
|
||||
hist_diff3_add = hist_diff3_add_value;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int tlsh_impl_lvalue(TlshImpl *impl)
|
||||
{
|
||||
return (impl->lsh_bin.lvalue);
|
||||
}
|
||||
|
||||
int tlsh_impl_q1ratio(TlshImpl *impl)
|
||||
{
|
||||
return (impl->lsh_bin.Q.QR.q1ratio);
|
||||
}
|
||||
|
||||
int tlsh_impl_q2ratio(TlshImpl *impl)
|
||||
{
|
||||
return (impl->lsh_bin.Q.QR.q2ratio);
|
||||
}
|
||||
|
||||
int tlsh_impl_is_valid(TlshImpl *impl)
|
||||
{
|
||||
return (impl->lsh_code_valid);
|
||||
}
|
||||
|
||||
int tlsh_impl_checksum(TlshImpl *impl, int k)
|
||||
{
|
||||
if ((k >= TLSH_CHECKSUM_LEN) || (k < 0)) {
|
||||
return 0;
|
||||
}
|
||||
return impl->lsh_bin.checksum[k];
|
||||
}
|
||||
|
||||
int tlsh_impl_bucket_value(TlshImpl *impl, int bucket)
|
||||
{
|
||||
int idx;
|
||||
int elem;
|
||||
unsigned char bv;
|
||||
|
||||
idx = (CODE_SIZE - (bucket / 4)) - 1;
|
||||
elem = bucket % 4;
|
||||
bv = impl->lsh_bin.tmp_code[idx];
|
||||
int h1 = bv / 16;
|
||||
int h2 = bv % 16;
|
||||
int p1 = h1 / 4;
|
||||
int p2 = h1 % 4;
|
||||
int p3 = h2 / 4;
|
||||
int p4 = h2 % 4;
|
||||
if (elem == 0) {
|
||||
return (p1);
|
||||
}
|
||||
if (elem == 1) {
|
||||
return (p2);
|
||||
}
|
||||
if (elem == 2) {
|
||||
return (p3);
|
||||
}
|
||||
return (p4);
|
||||
}
|
||||
|
||||
int tlsh_impl_histogram_count(TlshImpl *impl, int bucket)
|
||||
{
|
||||
if (impl->a_bucket == NULL)
|
||||
return (-1);
|
||||
return (impl->a_bucket[EFF_BUCKETS - 1 - bucket]);
|
||||
}
|
||||
|
||||
int tlsh_impl_total_diff(TlshImpl *impl, TlshImpl *other, bool len_diff)
|
||||
{
|
||||
int diff = 0;
|
||||
|
||||
if (len_diff) {
|
||||
int ldiff = mod_diff(impl->lsh_bin.lvalue, other->lsh_bin.lvalue, RANGE_LVALUE);
|
||||
if (ldiff == 0)
|
||||
diff = 0;
|
||||
else if (ldiff == 1)
|
||||
diff = 1;
|
||||
else
|
||||
diff += ldiff * length_mult;
|
||||
}
|
||||
|
||||
int q1diff = mod_diff(impl->lsh_bin.Q.QR.q1ratio, other->lsh_bin.Q.QR.q1ratio, RANGE_QRATIO);
|
||||
if (q1diff <= 1)
|
||||
diff += q1diff;
|
||||
else
|
||||
diff += (q1diff - 1) * qratio_mult;
|
||||
|
||||
int q2diff = mod_diff(impl->lsh_bin.Q.QR.q2ratio, other->lsh_bin.Q.QR.q2ratio, RANGE_QRATIO);
|
||||
if (q2diff <= 1)
|
||||
diff += q2diff;
|
||||
else
|
||||
diff += (q2diff - 1) * qratio_mult;
|
||||
|
||||
for (int k = 0; k < TLSH_CHECKSUM_LEN; k++) {
|
||||
if (impl->lsh_bin.checksum[k] != other->lsh_bin.checksum[k]) {
|
||||
diff++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
diff += h_distance(CODE_SIZE, impl->lsh_bin.tmp_code, other->lsh_bin.tmp_code);
|
||||
|
||||
return (diff);
|
||||
}
|
||||
|
||||
#define SWAP_UINT(x, y) \
|
||||
do { \
|
||||
unsigned int int_tmp = (x); \
|
||||
(x) = (y); \
|
||||
(y) = int_tmp; \
|
||||
} while (0)
|
||||
|
||||
void find_quartile(
|
||||
unsigned int *q1, unsigned int *q2, unsigned int *q3, const unsigned int *a_bucket)
|
||||
{
|
||||
unsigned int bucket_copy[EFF_BUCKETS], short_cut_left[EFF_BUCKETS],
|
||||
short_cut_right[EFF_BUCKETS], spl = 0, spr = 0;
|
||||
unsigned int p1 = EFF_BUCKETS / 4 - 1;
|
||||
unsigned int p2 = EFF_BUCKETS / 2 - 1;
|
||||
unsigned int p3 = EFF_BUCKETS - EFF_BUCKETS / 4 - 1;
|
||||
unsigned int end = EFF_BUCKETS - 1;
|
||||
|
||||
for (unsigned int i = 0; i <= end; i++) {
|
||||
bucket_copy[i] = a_bucket[i];
|
||||
}
|
||||
|
||||
for (unsigned int l = 0, r = end;;) {
|
||||
unsigned int ret = partition(bucket_copy, l, r);
|
||||
if (ret > p2) {
|
||||
r = ret - 1;
|
||||
short_cut_right[spr] = ret;
|
||||
spr++;
|
||||
} else if (ret < p2) {
|
||||
l = ret + 1;
|
||||
short_cut_left[spl] = ret;
|
||||
spl++;
|
||||
} else {
|
||||
*q2 = bucket_copy[p2];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
short_cut_left[spl] = p2 - 1;
|
||||
short_cut_right[spr] = p2 + 1;
|
||||
|
||||
for (unsigned int i = 0, l = 0; i <= spl; i++) {
|
||||
unsigned int r = short_cut_left[i];
|
||||
if (r > p1) {
|
||||
for (;;) {
|
||||
unsigned int ret = partition(bucket_copy, l, r);
|
||||
if (ret > p1) {
|
||||
r = ret - 1;
|
||||
} else if (ret < p1) {
|
||||
l = ret + 1;
|
||||
} else {
|
||||
*q1 = bucket_copy[p1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else if (r < p1) {
|
||||
l = r;
|
||||
} else {
|
||||
*q1 = bucket_copy[p1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int i = 0, r = end; i <= spr; i++) {
|
||||
unsigned int l = short_cut_right[i];
|
||||
if (l < p3) {
|
||||
for (;;) {
|
||||
unsigned int ret = partition(bucket_copy, l, r);
|
||||
if (ret > p3) {
|
||||
r = ret - 1;
|
||||
} else if (ret < p3) {
|
||||
l = ret + 1;
|
||||
} else {
|
||||
*q3 = bucket_copy[p3];
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else if (l > p3) {
|
||||
r = l;
|
||||
} else {
|
||||
*q3 = bucket_copy[p3];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int partition(unsigned int *buf, unsigned int left, unsigned int right)
|
||||
{
|
||||
if (left == right) {
|
||||
return left;
|
||||
}
|
||||
if (left + 1 == right) {
|
||||
if (buf[left] > buf[right]) {
|
||||
SWAP_UINT(buf[left], buf[right]);
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
unsigned int ret = left, pivot = (left + right) >> 1;
|
||||
|
||||
unsigned int val = buf[pivot];
|
||||
|
||||
buf[pivot] = buf[right];
|
||||
buf[right] = val;
|
||||
|
||||
for (unsigned int i = left; i < right; i++) {
|
||||
if (buf[i] < val) {
|
||||
SWAP_UINT(buf[ret], buf[i]);
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
buf[right] = buf[ret];
|
||||
buf[ret] = val;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
#ifndef __TLSH_TLSH_IMPL_H__
|
||||
#define __TLSH_TLSH_IMPL_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#define SLIDING_WND_SIZE 5
|
||||
|
||||
#define BUCKETS 256
|
||||
#define Q_BITS 2 // 2 bits; quartile value 0, 1, 2, 3
|
||||
|
||||
// BUCKETS_256 & CHECKSUM_3B are compiler switches defined in CMakeLists.txt
|
||||
|
||||
#if defined BUCKETS_256
|
||||
#define EFF_BUCKETS 256
|
||||
#define CODE_SIZE 64 // 256 * 2 bits = 64 bytes
|
||||
#if defined CHECKSUM_3B
|
||||
#define INTERNAL_TLSH_STRING_LEN 138
|
||||
#define TLSH_CHECKSUM_LEN 3
|
||||
// defined in tlsh.h #define TLSH_STRING_LEN 138 // 2 + 3 + 64 bytes = 138
|
||||
// hexidecimal chars
|
||||
#else
|
||||
#define INTERNAL_TLSH_STRING_LEN 134
|
||||
#define TLSH_CHECKSUM_LEN 1
|
||||
// defined in tlsh.h #define TLSH_STRING_LEN 134 // 2 + 1 + 64 bytes = 134
|
||||
// hexidecimal chars
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined BUCKETS_128
|
||||
#define EFF_BUCKETS 128
|
||||
#define CODE_SIZE 32 // 128 * 2 bits = 32 bytes
|
||||
#if defined CHECKSUM_3B
|
||||
#define INTERNAL_TLSH_STRING_LEN 74
|
||||
#define TLSH_CHECKSUM_LEN 3
|
||||
// defined in tlsh.h #define TLSH_STRING_LEN 74 // 2 + 3 + 32 bytes = 74
|
||||
// hexidecimal chars
|
||||
#else
|
||||
#define INTERNAL_TLSH_STRING_LEN 70
|
||||
#define TLSH_CHECKSUM_LEN 1
|
||||
// defined in tlsh.h #define TLSH_STRING_LEN 70 // 2 + 1 + 32 bytes = 70
|
||||
// hexidecimal chars
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined BUCKETS_48
|
||||
#define INTERNAL_TLSH_STRING_LEN 33
|
||||
#define EFF_BUCKETS 48
|
||||
#define CODE_SIZE 12 // 48 * 2 bits = 12 bytes
|
||||
#define TLSH_CHECKSUM_LEN 1
|
||||
// defined in tlsh.h #define TLSH_STRING_LEN 30 // 2 + 1 + 12 bytes = 30
|
||||
// hexidecimal chars
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
unsigned char checksum[TLSH_CHECKSUM_LEN];
|
||||
unsigned char lvalue;
|
||||
union {
|
||||
unsigned char qb;
|
||||
struct {
|
||||
unsigned char q1ratio : 4;
|
||||
unsigned char q2ratio : 4;
|
||||
} QR;
|
||||
} Q;
|
||||
unsigned char tmp_code[CODE_SIZE];
|
||||
} LshBinStruct;
|
||||
|
||||
typedef struct TlshImpl {
|
||||
unsigned int *a_bucket;
|
||||
unsigned char slide_window[SLIDING_WND_SIZE];
|
||||
unsigned int data_len;
|
||||
LshBinStruct lsh_bin;
|
||||
char *lsh_code;
|
||||
bool lsh_code_valid;
|
||||
} TlshImpl;
|
||||
|
||||
TlshImpl *tlsh_impl_new();
|
||||
void tlsh_impl_free(TlshImpl *impl);
|
||||
|
||||
int tlsh_impl_update(TlshImpl *impl, const unsigned char *data, unsigned int len, int tlsh_option);
|
||||
void tlsh_impl_final(TlshImpl *impl, int fc_cons_option);
|
||||
void tlsh_impl_reset(TlshImpl *impl);
|
||||
int tlsh_impl_is_valid(TlshImpl *impl);
|
||||
int tlsh_impl_compare(TlshImpl *impl, TlshImpl *other);
|
||||
int tlsh_impl_total_diff(TlshImpl *impl, TlshImpl *other, bool len_diff);
|
||||
int tlsh_impl_lvalue(TlshImpl *impl);
|
||||
int tlsh_impl_q1ratio(TlshImpl *impl);
|
||||
int tlsh_impl_q2ratio(TlshImpl *impl);
|
||||
int tlsh_impl_checksum(TlshImpl *impl, int k);
|
||||
int tlsh_impl_bucket_value(TlshImpl *impl, int bucket);
|
||||
int tlsh_impl_histogram_count(TlshImpl *impl, int bucket);
|
||||
int tlsh_impl_from_tlsh_str(TlshImpl *impl, const char *str);
|
||||
const char *tlsh_impl_hash(TlshImpl *impl, bool showvers);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __TLSH_TLSH_IMPL_H__
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,20 @@
|
||||
#ifndef __TLSH_TLSH_UTIL_H__
|
||||
#define __TLSH_TLSH_UTIL_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// unsigned char b_mapping(unsigned char salt, unsigned char i, unsigned char j, unsigned char k);
|
||||
unsigned char l_capturing(unsigned int len);
|
||||
int mod_diff(unsigned int x, unsigned int y, unsigned int R);
|
||||
int h_distance( int len, const unsigned char x[], const unsigned char y[]);
|
||||
void to_hex( unsigned char * psrc, int len, char* pdest);
|
||||
void from_hex( const char* psrc, int len, unsigned char* pdest);
|
||||
unsigned char swap_byte( const unsigned char in );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __TLSH_TLSH_UTIL_H__
|
||||
@@ -89,7 +89,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;CUCKOO_MODULE;HASH_MODULE;DOTNET_MODULE;HAVE_LIBCRYPTO;USE_WINDOWS_PROC;YR_BUILDING_STATIC_LIB;YR_PROFILING_ENABLED</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;CUCKOO_MODULE;HASH_MODULE;DOTNET_MODULE;HAVE_LIBCRYPTO;USE_WINDOWS_PROC;YR_BUILDING_STATIC_LIB;YR_PROFILING_ENABLED;BUCKETS_128;CHECKSUM_1B</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\..\libyara;..\..\..\libyara\include;..\..\..;..\packages\YARA.Jansson.x86.1.1.0\include;..\packages\YARA.OpenSSL.x86.1.1.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<DisableSpecificWarnings>4005;4273;4090</DisableSpecificWarnings>
|
||||
<CompileAs>CompileAsC</CompileAs>
|
||||
@@ -116,7 +116,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;CUCKOO_MODULE;HASH_MODULE;DOTNET_MODULE;HAVE_LIBCRYPTO;USE_WINDOWS_PROC;YR_BUILDING_STATIC_LIBC;YR_PROFILING_ENABLED</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;CUCKOO_MODULE;HASH_MODULE;DOTNET_MODULE;HAVE_LIBCRYPTO;USE_WINDOWS_PROC;YR_BUILDING_STATIC_LIBC;YR_PROFILING_ENABLED;BUCKETS_128;CHECKSUM_1B</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\..\libyara;..\..\..\libyara\include;..\..\..;..\packages\YARA.Jansson.x64.1.1.0\include;..\packages\YARA.OpenSSL.x64.1.1.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<DisableSpecificWarnings>4005;4273;4090</DisableSpecificWarnings>
|
||||
<CompileAs>CompileAsC</CompileAs>
|
||||
@@ -143,7 +143,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;CUCKOO_MODULE;HASH_MODULE;DOTNET_MODULE;HAVE_LIBCRYPTO;USE_WINDOWS_PROC;YR_BUILDING_STATIC_LIB</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;CUCKOO_MODULE;HASH_MODULE;DOTNET_MODULE;HAVE_LIBCRYPTO;USE_WINDOWS_PROC;YR_BUILDING_STATIC_LIB;BUCKETS_128;CHECKSUM_1B</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\..\libyara;..\..\..\libyara\include;..\..\..;..\packages\YARA.Jansson.x86.1.1.0\include;..\packages\YARA.OpenSSL.x86.1.1.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<DisableSpecificWarnings>4005;4273;4090</DisableSpecificWarnings>
|
||||
<CompileAs>CompileAsC</CompileAs>
|
||||
@@ -168,7 +168,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;CUCKOO_MODULE;HASH_MODULE;DOTNET_MODULE;HAVE_LIBCRYPTO;USE_WINDOWS_PROC;YR_BUILDING_STATIC_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;CUCKOO_MODULE;HASH_MODULE;DOTNET_MODULE;HAVE_LIBCRYPTO;USE_WINDOWS_PROC;YR_BUILDING_STATIC_LIB;BUCKETS_128;CHECKSUM_1B;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\..\libyara;..\..\..\libyara\include;..\..\..;..\packages\YARA.Jansson.x64.1.1.0\include;..\packages\YARA.OpenSSL.x64.1.1.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<DisableSpecificWarnings>4005;4273;4090</DisableSpecificWarnings>
|
||||
<CompileAs>CompileAsC</CompileAs>
|
||||
@@ -195,7 +195,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='StaticRelease|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;CUCKOO_MODULE;HASH_MODULE;DOTNET_MODULE;HAVE_LIBCRYPTO;USE_WINDOWS_PROC;YR_BUILDING_STATIC_LIB;NDEBUG=1</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;CUCKOO_MODULE;HASH_MODULE;DOTNET_MODULE;HAVE_LIBCRYPTO;USE_WINDOWS_PROC;YR_BUILDING_STATIC_LIB;BUCKETS_128;CHECKSUM_1B;NDEBUG=1</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\..\libyara;..\..\..\libyara\include;..\..\..;..\packages\YARA.Jansson.x64.1.1.0\include;..\packages\YARA.OpenSSL.x64.1.1.0\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<DisableSpecificWarnings>4005;4273;4090</DisableSpecificWarnings>
|
||||
<CompileAs>CompileAsC</CompileAs>
|
||||
@@ -267,6 +267,10 @@
|
||||
<ClCompile Include="..\..\..\libyara\stream.c" />
|
||||
<ClCompile Include="..\..\..\libyara\strutils.c" />
|
||||
<ClCompile Include="..\..\..\libyara\threading.c" />
|
||||
<ClCompile Include="..\..\..\libyara\simple_str.c" />
|
||||
<ClCompile Include="..\..\..\libyara\tlshc\tlsh_util.c" />
|
||||
<ClCompile Include="..\..\..\libyara\tlshc\tlsh_impl.c" />
|
||||
<ClCompile Include="..\..\..\libyara\tlshc\tlsh.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;CUCKOO_MODULE;HASH_MODULE;DOTNET_MODULE;HAVE_LIBCRYPTO;USE_WINDOWS_PROC;YR_BUILDING_STATIC_LIB;YR_PROFILING_ENABLED</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;CUCKOO_MODULE;HASH_MODULE;DOTNET_MODULE;HAVE_LIBCRYPTO;USE_WINDOWS_PROC;YR_BUILDING_STATIC_LIB;YR_PROFILING_ENABLED;BUCKETS_128;CHECKSUM_1B</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\..\libyara;..\..\..\libyara\include;..\..\..;..\packages\YARA.Jansson.x86.1.1.0\include;..\packages\YARA.OpenSSL.x86.1.1.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<DisableSpecificWarnings>4005;4273;4090</DisableSpecificWarnings>
|
||||
<CompileAs>CompileAsC</CompileAs>
|
||||
@@ -115,7 +115,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;CUCKOO_MODULE;HASH_MODULE;DOTNET_MODULE;HAVE_LIBCRYPTO;USE_WINDOWS_PROC;YR_BUILDING_STATIC_LIBC;YR_PROFILING_ENABLED</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;CUCKOO_MODULE;HASH_MODULE;DOTNET_MODULE;HAVE_LIBCRYPTO;USE_WINDOWS_PROC;YR_BUILDING_STATIC_LIBC;YR_PROFILING_ENABLED;BUCKETS_128;CHECKSUM_1B</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\..\libyara;..\..\..\libyara\include;..\..\..;..\packages\YARA.Jansson.x64.1.1.0\include;..\packages\YARA.OpenSSL.x64.1.1.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<DisableSpecificWarnings>4005;4273;4090</DisableSpecificWarnings>
|
||||
<CompileAs>CompileAsC</CompileAs>
|
||||
@@ -142,7 +142,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;CUCKOO_MODULE;HASH_MODULE;DOTNET_MODULE;HAVE_LIBCRYPTO;USE_WINDOWS_PROC;YR_BUILDING_STATIC_LIB</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;CUCKOO_MODULE;HASH_MODULE;DOTNET_MODULE;HAVE_LIBCRYPTO;USE_WINDOWS_PROC;YR_BUILDING_STATIC_LIB;BUCKETS_128;CHECKSUM_1B</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\..\libyara;..\..\..\libyara\include;..\..\..;..\packages\YARA.Jansson.x86.1.1.0\include;..\packages\YARA.OpenSSL.x86.1.1.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<DisableSpecificWarnings>4005;4273;4090</DisableSpecificWarnings>
|
||||
<CompileAs>CompileAsC</CompileAs>
|
||||
@@ -167,7 +167,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;CUCKOO_MODULE;HASH_MODULE;DOTNET_MODULE;HAVE_LIBCRYPTO;USE_WINDOWS_PROC;YR_BUILDING_STATIC_LIB</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;CUCKOO_MODULE;HASH_MODULE;DOTNET_MODULE;HAVE_LIBCRYPTO;USE_WINDOWS_PROC;YR_BUILDING_STATIC_LIB;BUCKETS_128;CHECKSUM_1B</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\..\libyara;..\..\..\libyara\include;..\..\..;..\packages\YARA.Jansson.x64.1.1.0\include;..\packages\YARA.OpenSSL.x64.1.1.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<DisableSpecificWarnings>4005;4273;4090</DisableSpecificWarnings>
|
||||
<CompileAs>CompileAsC</CompileAs>
|
||||
@@ -194,7 +194,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='StaticRelease|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;CUCKOO_MODULE;HASH_MODULE;DOTNET_MODULE;HAVE_LIBCRYPTO;USE_WINDOWS_PROC;YR_BUILDING_STATIC_LIB;NDEBUG=1</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;CUCKOO_MODULE;HASH_MODULE;DOTNET_MODULE;HAVE_LIBCRYPTO;USE_WINDOWS_PROC;YR_BUILDING_STATIC_LIB;NDEBUG=1;BUCKETS_128;CHECKSUM_1B</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\..\libyara;..\..\..\libyara\include;..\..\..;..\packages\YARA.Jansson.x64.1.1.0\include;..\packages\YARA.OpenSSL.x64.1.1.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<DisableSpecificWarnings>4005;4273;4090</DisableSpecificWarnings>
|
||||
<CompileAs>CompileAsC</CompileAs>
|
||||
@@ -266,6 +266,10 @@
|
||||
<ClCompile Include="..\..\..\libyara\stream.c" />
|
||||
<ClCompile Include="..\..\..\libyara\strutils.c" />
|
||||
<ClCompile Include="..\..\..\libyara\threading.c" />
|
||||
<ClCompile Include="..\..\..\libyara\simple_str.c" />
|
||||
<ClCompile Include="..\..\..\libyara\tlshc\tlsh_util.c" />
|
||||
<ClCompile Include="..\..\..\libyara\tlshc\tlsh_impl.c" />
|
||||
<ClCompile Include="..\..\..\libyara\tlshc\tlsh.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
||||
Reference in New Issue
Block a user