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:
HoundThe
2022-06-20 12:25:33 +02:00
committed by GitHub
parent 15b8de578e
commit 19ac2efeb8
17 changed files with 4894 additions and 26 deletions
+11
View File
@@ -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",
+3
View File
@@ -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])
+11
View File
@@ -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"*
+5
View File
@@ -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
+64
View File
@@ -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__
+9
View File
@@ -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
+34
View File
@@ -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
+21
View File
@@ -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
View File
@@ -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;
}
+103
View File
@@ -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;
}
+69
View File
@@ -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 "";
}
+988
View File
@@ -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;
}
+102
View File
@@ -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
+20
View File
@@ -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__
+9 -5
View File
@@ -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" />
+9 -5
View File
@@ -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" />