Add maximum size for process memory chunk (#1393)

Co-authored-by: Victor M. Alvarez <[email protected]>
This commit is contained in:
secDre4mer
2021-10-28 16:38:04 +02:00
committed by GitHub
co-authored by Victor M. Alvarez
parent f5893ea78b
commit 605b2edf07
10 changed files with 210 additions and 90 deletions
+1 -1
View File
@@ -80,4 +80,4 @@ jobs:
${{ runner.os }}-${{ env.cache-name }}-development
- uses: actions/checkout@v2
- name: Build and run tests
run: bazel test @jansson//... //tests/...
run: bazel test --test_output=errors @jansson//... //tests/...
+2
View File
@@ -85,3 +85,5 @@ windows/*/packages/
.dirstamp
.idea/
tests/mapper
+17 -6
View File
@@ -157,12 +157,13 @@ static bool negate = false;
static bool print_count_only = false;
static bool fail_on_warnings = false;
static bool rules_are_compiled = false;
static long total_count = 0;
static long limit = 0;
static long timeout = 1000000;
static long stack_size = DEFAULT_STACK_SIZE;
static long threads = YR_MAX_THREADS;
static long max_strings_per_rule = DEFAULT_MAX_STRINGS_PER_RULE;
static int total_count = 0;
static int limit = 0;
static int timeout = 1000000;
static int stack_size = DEFAULT_STACK_SIZE;
static int threads = YR_MAX_THREADS;
static int max_strings_per_rule = DEFAULT_MAX_STRINGS_PER_RULE;
static int max_process_memory_chunk = DEFAULT_MAX_PROCESS_MEMORY_CHUNK;
#define USAGE_STRING \
"Usage: yara [OPTION]... [NAMESPACE:]RULES_FILE... FILE | DIR | PID"
@@ -307,6 +308,14 @@ args_option_t options[] = {
_T("set maximum stack size (default=16384)"),
_T("SLOTS")),
OPT_INTEGER(
0,
_T("max-process-memory-chunk"),
&max_process_memory_chunk,
_T("set maximum chunk size while reading process memory")
_T(" (default=1073741824)"),
_T("NUMBER")),
OPT_STRING_MULTI(
't',
_T("tag"),
@@ -1359,6 +1368,8 @@ int _tmain(int argc, const char_t** argv)
yr_set_configuration(YR_CONFIG_STACK_SIZE, &stack_size);
yr_set_configuration(YR_CONFIG_MAX_STRINGS_PER_RULE, &max_strings_per_rule);
yr_set_configuration(
YR_CONFIG_MAX_PROCESS_MEMORY_CHUNK, &max_process_memory_chunk);
// Try to load the rules file as a binary file containing
// compiled rules first
+5 -3
View File
@@ -72,14 +72,16 @@ typedef enum _YR_CONFIG_NAME
YR_CONFIG_STACK_SIZE,
YR_CONFIG_MAX_STRINGS_PER_RULE,
YR_CONFIG_MAX_MATCH_DATA,
YR_CONFIG_MAX_PROCESS_MEMORY_CHUNK,
YR_CONFIG_LAST // End-of-enum marker, not a configuration
} YR_CONFIG_NAME;
#define DEFAULT_STACK_SIZE 16384
#define DEFAULT_MAX_STRINGS_PER_RULE 10000
#define DEFAULT_MAX_MATCH_DATA 512
#define DEFAULT_STACK_SIZE 16384
#define DEFAULT_MAX_STRINGS_PER_RULE 10000
#define DEFAULT_MAX_MATCH_DATA 512
#define DEFAULT_MAX_PROCESS_MEMORY_CHUNK 1073741824
YR_API int yr_initialize(void);
+16 -3
View File
@@ -235,6 +235,7 @@ YR_API int yr_initialize(void)
uint32_t def_stack_size = DEFAULT_STACK_SIZE;
uint32_t def_max_strings_per_rule = DEFAULT_MAX_STRINGS_PER_RULE;
uint32_t def_max_match_data = DEFAULT_MAX_MATCH_DATA;
uint64_t def_max_process_memory_chunk = DEFAULT_MAX_PROCESS_MEMORY_CHUNK;
init_count++;
@@ -295,6 +296,9 @@ YR_API int yr_initialize(void)
FAIL_ON_ERROR(yr_set_configuration(
YR_CONFIG_MAX_STRINGS_PER_RULE, &def_max_strings_per_rule));
FAIL_ON_ERROR(yr_set_configuration(
YR_CONFIG_MAX_PROCESS_MEMORY_CHUNK, &def_max_process_memory_chunk));
FAIL_ON_ERROR(
yr_set_configuration(YR_CONFIG_MAX_MATCH_DATA, &def_max_match_data));
@@ -363,9 +367,10 @@ YR_API int yr_finalize(void)
// Args:
// name: Any of the values defined by the YR_CONFIG_NAME enum. Possible values
// are:
// YR_CONFIG_STACK_SIZE data type: uint32_t
// YR_CONFIG_MAX_STRINGS_PER_RULE data type: uint32_t
// YR_CONFIG_MAX_MATCH_DATA data type: uint32_t
// YR_CONFIG_STACK_SIZE data type: uint32_t
// YR_CONFIG_MAX_STRINGS_PER_RULE data type: uint32_t
// YR_CONFIG_MAX_MATCH_DATA data type: uint32_t
// YR_CONFIG_MAX_PROCESS_MEMORY_CHUNK data type: uint64_t
//
// src: Pointer to the value being set for the option.
//
@@ -386,6 +391,10 @@ YR_API int yr_set_configuration(YR_CONFIG_NAME name, void *src)
yr_cfgs[name].ui32 = *(uint32_t *) src;
break;
case YR_CONFIG_MAX_PROCESS_MEMORY_CHUNK:
yr_cfgs[name].ui64 = *(uint64_t *) src;
break;
default:
return ERROR_INTERNAL_FATAL_ERROR;
}
@@ -406,6 +415,10 @@ YR_API int yr_get_configuration(YR_CONFIG_NAME name, void *dest)
*(uint32_t *) dest = yr_cfgs[name].ui32;
break;
case YR_CONFIG_MAX_PROCESS_MEMORY_CHUNK:
*(uint64_t *) dest = yr_cfgs[name].ui64;
break;
default:
return ERROR_INTERNAL_FATAL_ERROR;
}
+28 -12
View File
@@ -36,17 +36,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sys/wait.h>
#include <unistd.h>
#include <yara/error.h>
#include <yara/libyara.h>
#include <yara/mem.h>
#include <yara/proc.h>
typedef struct _YR_PROC_INFO
{
int pid;
struct ptrace_vm_entry vm_entry;
} YR_PROC_INFO;
int _yr_process_attach(int pid, YR_PROC_ITERATOR_CTX* context)
{
int status;
@@ -56,6 +55,8 @@ int _yr_process_attach(int pid, YR_PROC_ITERATOR_CTX* context)
if (proc_info == NULL)
return ERROR_INSUFFICIENT_MEMORY;
memset(proc_info, 0, sizeof(YR_PROC_INFO));
context->proc_info = proc_info;
proc_info->pid = pid;
@@ -79,7 +80,6 @@ int _yr_process_attach(int pid, YR_PROC_ITERATOR_CTX* context)
return ERROR_SUCCESS;
}
int _yr_process_detach(YR_PROC_ITERATOR_CTX* context)
{
YR_PROC_INFO* proc_info = (YR_PROC_INFO*) context->proc_info;
@@ -90,7 +90,6 @@ int _yr_process_detach(YR_PROC_ITERATOR_CTX* context)
return ERROR_SUCCESS;
}
YR_API const uint8_t* yr_process_fetch_memory_block_data(YR_MEMORY_BLOCK* block)
{
YR_PROC_ITERATOR_CTX* context = (YR_PROC_ITERATOR_CTX*) block->context;
@@ -128,7 +127,6 @@ YR_API const uint8_t* yr_process_fetch_memory_block_data(YR_MEMORY_BLOCK* block)
return context->buffer;
}
YR_API YR_MEMORY_BLOCK* yr_process_get_next_memory_block(
YR_MEMORY_BLOCK_ITERATOR* iterator)
{
@@ -142,20 +140,38 @@ YR_API YR_MEMORY_BLOCK* yr_process_get_next_memory_block(
iterator->last_error = ERROR_SUCCESS;
if (ptrace(PT_VM_ENTRY, proc_info->pid, (char*) (&proc_info->vm_entry), 0) ==
-1)
uint64_t current_begin = context->current_block.base +
context->current_block.size;
uint64_t max_process_memory_chunk;
yr_get_configuration(
YR_CONFIG_MAX_PROCESS_MEMORY_CHUNK, (void*) &max_process_memory_chunk);
if (proc_info->vm_entry.pve_end <= current_begin)
{
return NULL;
if (ptrace(
PT_VM_ENTRY, proc_info->pid, (char*) (&proc_info->vm_entry), 0) ==
-1)
{
return NULL;
}
else
{
current_begin = proc_info->vm_entry.pve_start;
}
}
context->current_block.base = proc_info->vm_entry.pve_start;
context->current_block.size = proc_info->vm_entry.pve_end -
proc_info->vm_entry.pve_start + 1;
context->current_block.base = current_begin;
context->current_block.size = yr_min(
proc_info->vm_entry.pve_end - current_begin + 1,
max_process_memory_chunk);
assert(context->current_block.size > 0);
return &context->current_block;
}
YR_API YR_MEMORY_BLOCK* yr_process_get_first_memory_block(
YR_MEMORY_BLOCK_ITERATOR* iterator)
{
+75 -35
View File
@@ -40,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <unistd.h>
#include <yara/error.h>
#include <yara/globals.h>
#include <yara/libyara.h>
#include <yara/mem.h>
#include <yara/proc.h>
@@ -49,12 +50,13 @@ typedef struct _YR_PROC_INFO
int mem_fd;
int pagemap_fd;
FILE* maps;
uint64_t map_offset;
uint64_t next_block_end;
int page_size;
char map_path[PATH_MAX];
uint64_t map_dmaj;
uint64_t map_dmin;
uint64_t map_ino;
uint64_t map_offset;
} YR_PROC_INFO;
static int page_size = -1;
@@ -78,6 +80,7 @@ int _yr_process_attach(int pid, YR_PROC_ITERATOR_CTX* context)
proc_info->maps = NULL;
proc_info->mem_fd = -1;
proc_info->pagemap_fd = -1;
proc_info->next_block_end = 0;
snprintf(buffer, sizeof(buffer), "/proc/%u/maps", pid);
proc_info->maps = fopen(buffer, "r");
@@ -303,54 +306,89 @@ _exit:;
YR_API YR_MEMORY_BLOCK* yr_process_get_next_memory_block(
YR_MEMORY_BLOCK_ITERATOR* iterator)
{
YR_MEMORY_BLOCK* result = NULL;
YR_PROC_ITERATOR_CTX* context = (YR_PROC_ITERATOR_CTX*) iterator->context;
YR_PROC_INFO* proc_info = (YR_PROC_INFO*) context->proc_info;
char buffer[PATH_MAX];
char perm[5];
uint64_t begin, end;
int n, len;
while (fgets(buffer, sizeof(buffer), proc_info->maps) != NULL)
uint64_t current_begin = context->current_block.base +
context->current_block.size;
uint64_t max_process_memory_chunk;
yr_get_configuration(
YR_CONFIG_MAX_PROCESS_MEMORY_CHUNK, (void*) &max_process_memory_chunk);
if (proc_info->next_block_end <= current_begin)
{
// If we haven't read the whole line, skip over the rest.
if (strrchr(buffer, '\n') == NULL)
int n, path_start;
while (fgets(buffer, sizeof(buffer), proc_info->maps) != NULL)
{
int c;
do
// If we haven't read the whole line, skip over the rest.
if (strrchr(buffer, '\n') == NULL)
{
c = fgetc(proc_info->maps);
} while (c >= 0 && c != '\n');
int c;
do
{
c = fgetc(proc_info->maps);
} while (c >= 0 && c != '\n');
}
// Each row in /proc/$PID/maps describes a region of contiguous virtual
// memory in a process or thread. Each row has the following fields:
//
// address perms offset dev inode pathname
// 08048000-08056000 r-xp 00000000 03:0c 64593 /usr/sbin/gpm
//
n = sscanf(
buffer,
"%" SCNx64 "-%" SCNx64 " %4s "
"%" SCNx64 " %" SCNx64 ":%" SCNx64 " %" SCNu64 " %n",
&begin,
&end,
perm,
&(proc_info->map_offset),
&(proc_info->map_dmaj),
&(proc_info->map_dmin),
&(proc_info->map_ino),
&path_start);
// If the row was parsed correctly sscan must return 7.
if (n == 7)
{
// path_start contains the offset within buffer where the path starts,
// the path should start with /.
if (buffer[path_start] == '/')
strncpy(
proc_info->map_path,
buffer + path_start,
sizeof(proc_info->map_path) - 1);
else
proc_info->map_path[0] = '\0';
break;
}
}
n = sscanf(
buffer,
"%" SCNx64 "-%" SCNx64 " %4s "
"%" SCNx64 " %" SCNx64 ":%" SCNx64 " %" SCNu64 " %n",
&begin,
&end,
perm,
&(proc_info->map_offset),
&(proc_info->map_dmaj),
&(proc_info->map_dmin),
&(proc_info->map_ino),
&len);
if (n == 7)
{
if (buffer[len] == '/')
strncpy(
proc_info->map_path, buffer + len, sizeof(proc_info->map_path) - 1);
else
proc_info->map_path[0] = '\0';
break;
current_begin = begin;
proc_info->next_block_end = end;
}
else
{
YR_DEBUG_FPRINTF(2, stderr, "+ %s() = NULL\n", __FUNCTION__);
return NULL;
}
}
if (n == 7)
{
context->current_block.base = begin;
context->current_block.size = end - begin;
result = &context->current_block;
}
context->current_block.base = current_begin;
context->current_block.size = yr_min(
proc_info->next_block_end - current_begin, max_process_memory_chunk);
assert(context->current_block.size > 0);
iterator->last_error = ERROR_SUCCESS;
@@ -363,7 +401,7 @@ YR_API YR_MEMORY_BLOCK* yr_process_get_next_memory_block(
context->current_block.base,
context->current_block.size);
return result;
return &context->current_block;
}
YR_API YR_MEMORY_BLOCK* yr_process_get_first_memory_block(
@@ -381,6 +419,8 @@ YR_API YR_MEMORY_BLOCK* yr_process_get_first_memory_block(
goto _exit;
}
proc_info->next_block_end = 0;
result = yr_process_get_next_memory_block(iterator);
_exit:
+19 -10
View File
@@ -34,16 +34,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <mach/vm_region.h>
#include <mach/vm_statistics.h>
#include <yara/error.h>
#include <yara/libyara.h>
#include <yara/mem.h>
#include <yara/proc.h>
typedef struct _YR_PROC_INFO
{
task_t task;
} YR_PROC_INFO;
int _yr_process_attach(int pid, YR_PROC_ITERATOR_CTX* context)
{
YR_PROC_INFO* proc_info = (YR_PROC_INFO*) yr_malloc(sizeof(YR_PROC_INFO));
@@ -64,7 +63,6 @@ int _yr_process_attach(int pid, YR_PROC_ITERATOR_CTX* context)
return ERROR_SUCCESS;
}
int _yr_process_detach(YR_PROC_ITERATOR_CTX* context)
{
YR_PROC_INFO* proc_info = context->proc_info;
@@ -75,7 +73,6 @@ int _yr_process_detach(YR_PROC_ITERATOR_CTX* context)
return ERROR_SUCCESS;
}
YR_API const uint8_t* yr_process_fetch_memory_block_data(YR_MEMORY_BLOCK* block)
{
YR_PROC_ITERATOR_CTX* context = (YR_PROC_ITERATOR_CTX*) block->context;
@@ -113,7 +110,6 @@ YR_API const uint8_t* yr_process_fetch_memory_block_data(YR_MEMORY_BLOCK* block)
return context->buffer;
}
YR_API YR_MEMORY_BLOCK* yr_process_get_next_memory_block(
YR_MEMORY_BLOCK_ITERATOR* iterator)
{
@@ -126,8 +122,13 @@ YR_API YR_MEMORY_BLOCK* yr_process_get_next_memory_block(
vm_region_basic_info_data_64_t info;
vm_size_t size = 0;
vm_address_t address = (vm_address_t) context->current_block.base +
context->current_block.size;
uint64_t current_begin = (vm_address_t) context->current_block.base +
context->current_block.size;
vm_address_t address = current_begin;
uint64_t max_process_memory_chunk;
yr_get_configuration(
YR_CONFIG_MAX_PROCESS_MEMORY_CHUNK, (void*) &max_process_memory_chunk);
iterator->last_error = ERROR_SUCCESS;
@@ -146,18 +147,26 @@ YR_API YR_MEMORY_BLOCK* yr_process_get_next_memory_block(
if (kr == KERN_SUCCESS)
{
context->current_block.base = address;
context->current_block.size = size;
size_t chunk_size = size - (size_t) (current_begin - address);
if (((uint64_t) chunk_size) > max_process_memory_chunk)
{
chunk_size = (size_t) max_process_memory_chunk;
}
context->current_block.base = (size_t) current_begin;
context->current_block.size = chunk_size;
return &context->current_block;
}
current_begin = address;
} while (kr != KERN_INVALID_ADDRESS);
return NULL;
}
YR_API YR_MEMORY_BLOCK* yr_process_get_first_memory_block(
YR_MEMORY_BLOCK_ITERATOR* iterator)
{
+28 -10
View File
@@ -42,6 +42,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// clang-format on
#include <yara/error.h>
#include <yara/libyara.h>
#include <yara/mem.h>
#include <yara/proc.h>
@@ -63,6 +64,8 @@ int _yr_process_attach(int pid, YR_PROC_ITERATOR_CTX* context)
if (proc_info == NULL)
return ERROR_INSUFFICIENT_MEMORY;
memset(proc_info, 0, sizeof(YR_PROC_INFO));
proc_info->pid = pid;
if (ptrace(PT_ATTACH, pid, NULL, 0) == -1)
{
@@ -149,19 +152,34 @@ YR_API YR_MEMORY_BLOCK* yr_process_get_next_memory_block(
iterator->last_error = ERROR_SUCCESS;
if (sysctl(mib, 3, &proc_info->vm_entry, &len, NULL, 0) < 0)
return NULL;
uint64_t current_begin = context->current_block.base +
context->current_block.size;
// no more blocks
if (proc_info->old_end == proc_info->vm_entry.kve_end)
return NULL;
uint64_t max_process_memory_chunk;
proc_info->old_end = proc_info->vm_entry.kve_end;
context->current_block.base = proc_info->vm_entry.kve_start;
context->current_block.size = proc_info->vm_entry.kve_end -
proc_info->vm_entry.kve_start;
yr_get_configuration(
YR_CONFIG_MAX_PROCESS_MEMORY_CHUNK, (void*) &max_process_memory_chunk);
proc_info->vm_entry.kve_start = proc_info->vm_entry.kve_start + 1;
if (proc_info->old_end <= current_begin)
{
if (sysctl(mib, 3, &proc_info->vm_entry, &len, NULL, 0) < 0)
return NULL;
// no more blocks
if (proc_info->old_end == proc_info->vm_entry.kve_end)
return NULL;
current_begin = proc_info->vm_entry.kve_start;
proc_info->old_end = proc_info->vm_entry.kve_end;
proc_info->vm_entry.kve_start = proc_info->vm_entry.kve_start + 1;
}
context->current_block.base = current_begin;
context->current_block.size = yr_min(
proc_info->old_end - current_begin, max_process_memory_chunk);
assert(context->current_block.size > 0);
return &context->current_block;
}
+19 -10
View File
@@ -31,10 +31,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <windows.h>
#include <yara/error.h>
#include <yara/libyara.h>
#include <yara/mem.h>
#include <yara/proc.h>
typedef struct _YR_PROC_INFO
{
HANDLE hProcess;
@@ -82,7 +82,6 @@ int _yr_process_attach(int pid, YR_PROC_ITERATOR_CTX* context)
return ERROR_SUCCESS;
}
int _yr_process_detach(YR_PROC_ITERATOR_CTX* context)
{
YR_PROC_INFO* proc_info = (YR_PROC_INFO*) context->proc_info;
@@ -91,7 +90,6 @@ int _yr_process_detach(YR_PROC_ITERATOR_CTX* context)
return ERROR_SUCCESS;
}
YR_API const uint8_t* yr_process_fetch_memory_block_data(YR_MEMORY_BLOCK* block)
{
SIZE_T read;
@@ -130,7 +128,6 @@ YR_API const uint8_t* yr_process_fetch_memory_block_data(YR_MEMORY_BLOCK* block)
return context->buffer;
}
YR_API YR_MEMORY_BLOCK* yr_process_get_next_memory_block(
YR_MEMORY_BLOCK_ITERATOR* iterator)
{
@@ -138,8 +135,12 @@ YR_API YR_MEMORY_BLOCK* yr_process_get_next_memory_block(
YR_PROC_INFO* proc_info = (YR_PROC_INFO*) context->proc_info;
MEMORY_BASIC_INFORMATION mbi;
PVOID address = (PVOID)(
context->current_block.base + context->current_block.size);
void* address =
(void*) (context->current_block.base + context->current_block.size);
uint64_t max_process_memory_chunk;
yr_get_configuration(
YR_CONFIG_MAX_PROCESS_MEMORY_CHUNK, (void*) &max_process_memory_chunk);
iterator->last_error = ERROR_SUCCESS;
@@ -153,19 +154,27 @@ YR_API YR_MEMORY_BLOCK* yr_process_get_next_memory_block(
if (mbi.State == MEM_COMMIT && ((mbi.Protect & PAGE_NOACCESS) == 0))
{
context->current_block.base = (size_t) mbi.BaseAddress;
context->current_block.size = mbi.RegionSize;
size_t chuck_size =
mbi.RegionSize -
(size_t) (((uint8_t*) address) - ((uint8_t*) mbi.BaseAddress));
if (((uint64_t) chuck_size) > max_process_memory_chunk)
{
chuck_size = (size_t) max_process_memory_chunk;
}
context->current_block.base = (size_t) address;
context->current_block.size = chuck_size;
return &context->current_block;
}
address = (uint8_t*) address + mbi.RegionSize;
address = (uint8_t*) mbi.BaseAddress + mbi.RegionSize;
}
return NULL;
}
YR_API YR_MEMORY_BLOCK* yr_process_get_first_memory_block(
YR_MEMORY_BLOCK_ITERATOR* iterator)
{