[Forensics-changes] [yara] 343/368: Improve mem block iterators (#471)

Hilko Bengen bengen at moszumanska.debian.org
Sat Jul 1 10:30:56 UTC 2017


This is an automated email from the git hooks/post-receive script.

bengen pushed a commit to annotated tag v3.5.0
in repository yara.

commit 3b6e21e9ca066e5c29f8dff942680cf5715feae0
Author: Victor M. Alvarez <plusvic at gmail.com>
Date:   Mon Jun 27 15:00:15 2016 +0200

    Improve mem block iterators (#471)
    
    * Improve process memory iterators (Linux & Mac OS X)
    
    * Fix some issues in previous commit
    
    * Improve process memory iterators (Windows)
    
    * Fix issues with previous commit
---
 libyara/exec.c               |   4 +-
 libyara/include/yara/proc.h  |   4 +-
 libyara/include/yara/types.h |  54 ++--
 libyara/modules/elf.c        |   4 +-
 libyara/modules/hash.c       |  16 +-
 libyara/modules/magic.c      |  22 +-
 libyara/modules/math.c       |  20 +-
 libyara/modules/pe.c         |   4 +-
 libyara/proc.c               | 592 ++++++++++++++++++-------------------------
 libyara/rules.c              |  37 ++-
 10 files changed, 318 insertions(+), 439 deletions(-)

diff --git a/libyara/exec.c b/libyara/exec.c
index c312fd8..b0a79b6 100644
--- a/libyara/exec.c
+++ b/libyara/exec.c
@@ -112,7 +112,7 @@ typedef union _STACK_ITEM {
 
 
 #define function_read(type, endianess) \
-    int64_t read_##type##_##endianess(YR_BLOCK_ITERATOR* iterator, size_t offset) \
+    int64_t read_##type##_##endianess(YR_MEMORY_BLOCK_ITERATOR* iterator, size_t offset) \
     { \
       YR_MEMORY_BLOCK* block = iterator->first(iterator); \
       while (block != NULL) \
@@ -122,7 +122,7 @@ typedef union _STACK_ITEM {
             offset <= block->base + block->size - sizeof(type)) \
         { \
           type result; \
-          uint8_t* data = iterator->fetch_data(iterator); \
+          uint8_t* data = block->fetch_data(block); \
           if (data == NULL) \
             return UNDEFINED; \
           result = *(type *)(data + offset - block->base); \
diff --git a/libyara/include/yara/proc.h b/libyara/include/yara/proc.h
index 7ce7c5f..644bce8 100644
--- a/libyara/include/yara/proc.h
+++ b/libyara/include/yara/proc.h
@@ -34,9 +34,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 int yr_process_open_iterator(
     int pid,
-    YR_BLOCK_ITERATOR* iterator);
+    YR_MEMORY_BLOCK_ITERATOR* iterator);
 
 int yr_process_close_iterator(
-    YR_BLOCK_ITERATOR* iterator);
+    YR_MEMORY_BLOCK_ITERATOR* iterator);
 
 #endif
diff --git a/libyara/include/yara/types.h b/libyara/include/yara/types.h
index 2f1b874..bdacaa9 100644
--- a/libyara/include/yara/types.h
+++ b/libyara/include/yara/types.h
@@ -382,55 +382,39 @@ typedef struct _YR_RULES {
 } YR_RULES;
 
 
-// memory block iteration types
-typedef struct _YR_MEMORY_BLOCK
-{
-  size_t size;
-  size_t base;
-
-  struct _YR_MEMORY_BLOCK* next;
 
-} YR_MEMORY_BLOCK;
-
-
-typedef struct _YR_BLOCK_ITERATOR YR_BLOCK_ITERATOR;
+struct _YR_MEMORY_BLOCK;
+struct _YR_MEMORY_BLOCK_ITERATOR;
 
 
-typedef YR_MEMORY_BLOCK* (*YR_BLOCK_ITERATOR_MOVE)(
-    YR_BLOCK_ITERATOR* self);
+typedef uint8_t* (*YR_MEMORY_BLOCK_FETCH_DATA_FUNC)(
+    struct _YR_MEMORY_BLOCK* self);
 
 
-typedef uint8_t* (*YR_BLOCK_ITERATOR_FETCH)(
-    YR_BLOCK_ITERATOR* self);
+typedef struct _YR_MEMORY_BLOCK* (*YR_MEMORY_BLOCK_ITERATOR_FUNC)(
+    struct _YR_MEMORY_BLOCK_ITERATOR* self);
 
 
-struct _YR_BLOCK_ITERATOR
+typedef struct _YR_MEMORY_BLOCK
 {
-  void* context;
-
-  YR_BLOCK_ITERATOR_MOVE  first;
-  YR_BLOCK_ITERATOR_MOVE  next;
-  YR_BLOCK_ITERATOR_FETCH fetch_data;
+  size_t size;
+  size_t base;
 
-};
+  void* context;
 
-// a memory block in context with its data
-typedef struct _YR_BLOCK_CONTEXT
-{
-  uint8_t* data;
-  YR_MEMORY_BLOCK* block;
+  YR_MEMORY_BLOCK_FETCH_DATA_FUNC fetch_data;
 
-} YR_BLOCK_CONTEXT;
+} YR_MEMORY_BLOCK;
 
 
-typedef struct _YR_PROCESS_CONTEXT
+typedef struct _YR_MEMORY_BLOCK_ITERATOR
 {
-  uint8_t* data;
-  void* process_context;
-  YR_MEMORY_BLOCK* blocks;
-  YR_MEMORY_BLOCK* current;
+  void* context;
+
+  YR_MEMORY_BLOCK_ITERATOR_FUNC  first;
+  YR_MEMORY_BLOCK_ITERATOR_FUNC  next;
 
-} YR_PROCESS_CONTEXT;
+} YR_MEMORY_BLOCK_ITERATOR;
 
 
 typedef int (*YR_CALLBACK_FUNC)(
@@ -449,7 +433,7 @@ typedef struct _YR_SCAN_CONTEXT
 
   void* user_data;
 
-  YR_BLOCK_ITERATOR*  iterator;
+  YR_MEMORY_BLOCK_ITERATOR*  iterator;
   YR_HASH_TABLE*  objects_table;
   YR_CALLBACK_FUNC  callback;
 
diff --git a/libyara/modules/elf.c b/libyara/modules/elf.c
index bc0e6af..ed4ccd1 100644
--- a/libyara/modules/elf.c
+++ b/libyara/modules/elf.c
@@ -324,7 +324,7 @@ int module_load(
     size_t module_data_size)
 {
   YR_MEMORY_BLOCK* block;
-  YR_BLOCK_ITERATOR* iterator = context->iterator;
+  YR_MEMORY_BLOCK_ITERATOR* iterator = context->iterator;
 
   elf32_header_t* elf_header32;
   elf64_header_t* elf_header64;
@@ -384,7 +384,7 @@ int module_load(
 
   foreach_memory_block(iterator, block)
   {
-    uint8_t* block_data = iterator->fetch_data(iterator);
+    uint8_t* block_data = block->fetch_data(block);
 
     if (block_data == NULL)
       continue;
diff --git a/libyara/modules/hash.c b/libyara/modules/hash.c
index 0571371..63d4219 100644
--- a/libyara/modules/hash.c
+++ b/libyara/modules/hash.c
@@ -135,7 +135,7 @@ define_function(data_md5)
 
   YR_SCAN_CONTEXT* context = scan_context();
   YR_MEMORY_BLOCK* block = first_memory_block(context);
-  YR_BLOCK_ITERATOR* iterator = context->iterator;
+  YR_MEMORY_BLOCK_ITERATOR* iterator = context->iterator;
 
   int64_t offset = integer_argument(1);   // offset where to start
   int64_t length = integer_argument(2);   // length of bytes we want hash on
@@ -154,7 +154,7 @@ define_function(data_md5)
     if (offset >= block->base &&
         offset < block->base + block->size)
     {
-      uint8_t* block_data = iterator->fetch_data(iterator);
+      uint8_t* block_data = block->fetch_data(block);
 
       if (block_data != NULL)
       {
@@ -210,7 +210,7 @@ define_function(data_sha1)
 
   YR_SCAN_CONTEXT* context = scan_context();
   YR_MEMORY_BLOCK* block = first_memory_block(context);
-  YR_BLOCK_ITERATOR* iterator = context->iterator;
+  YR_MEMORY_BLOCK_ITERATOR* iterator = context->iterator;
 
   SHA1_Init(&sha_context);
 
@@ -225,7 +225,7 @@ define_function(data_sha1)
     if (offset >= block->base &&
         offset < block->base + block->size)
     {
-      uint8_t* block_data = iterator->fetch_data(iterator);
+      uint8_t* block_data = block->fetch_data(block);
 
       if (block_data != NULL)
       {
@@ -281,7 +281,7 @@ define_function(data_sha256)
 
   YR_SCAN_CONTEXT* context = scan_context();
   YR_MEMORY_BLOCK* block = first_memory_block(context);
-  YR_BLOCK_ITERATOR* iterator = context->iterator;
+  YR_MEMORY_BLOCK_ITERATOR* iterator = context->iterator;
 
   SHA256_Init(&sha256_context);
 
@@ -296,7 +296,7 @@ define_function(data_sha256)
     if (offset >= block->base &&
         offset < block->base + block->size)
     {
-      uint8_t* block_data = iterator->fetch_data(iterator);
+      uint8_t* block_data = block->fetch_data(block);
 
       if (block_data != NULL)
       {
@@ -344,7 +344,7 @@ define_function(data_checksum32)
 
   YR_SCAN_CONTEXT* context = scan_context();
   YR_MEMORY_BLOCK* block = first_memory_block(context);
-  YR_BLOCK_ITERATOR* iterator = context->iterator;
+  YR_MEMORY_BLOCK_ITERATOR* iterator = context->iterator;
 
   uint32_t checksum = 0;
   int past_first_block = FALSE;
@@ -359,7 +359,7 @@ define_function(data_checksum32)
     if (offset >= block->base &&
         offset < block->base + block->size)
     {
-      uint8_t* block_data = iterator->fetch_data(iterator);
+      uint8_t* block_data = block->fetch_data(block);
 
       if (block_data != NULL)
       {
diff --git a/libyara/modules/magic.c b/libyara/modules/magic.c
index 1e81941..f7beb23 100644
--- a/libyara/modules/magic.c
+++ b/libyara/modules/magic.c
@@ -48,7 +48,9 @@ define_function(magic_mime_type)
 {
   YR_MEMORY_BLOCK* block;
   YR_SCAN_CONTEXT* context = scan_context();
-  YR_BLOCK_ITERATOR* iterator = context->iterator;
+  YR_MEMORY_BLOCK_ITERATOR* iterator = context->iterator;
+
+  uint8_t* block_data;
 
   if (context->flags & SCAN_FLAGS_PROCESS_MEMORY)
     return_string(UNDEFINED);
@@ -56,15 +58,15 @@ define_function(magic_mime_type)
   if (cached_mime_types[context->tidx] == NULL)
   {
     block = first_memory_block(context);
+    block_data = block->fetch_data(block);
 
-    magic_setflags(magic_cookie[context->tidx], MAGIC_MIME_TYPE);
-
-    uint8_t* block_data = iterator->fetch_data(iterator);
     if (block_data != NULL)
     {
+      magic_setflags(magic_cookie[context->tidx], MAGIC_MIME_TYPE);
+
       cached_mime_types[context->tidx] = magic_buffer(
+          magic_cookie[context->tidx],
           block_data,
-          context->iterator->fetch_data((context)->iterator),
           block->size);
     }
   }
@@ -80,7 +82,9 @@ define_function(magic_type)
 {
   YR_MEMORY_BLOCK* block;
   YR_SCAN_CONTEXT* context = scan_context();
-  YR_BLOCK_ITERATOR* iterator = context->iterator;
+  YR_MEMORY_BLOCK_ITERATOR* iterator = context->iterator;
+
+  uint8_t* block_data;
 
   if (context->flags & SCAN_FLAGS_PROCESS_MEMORY)
     return_string(UNDEFINED);
@@ -88,12 +92,12 @@ define_function(magic_type)
   if (cached_types[context->tidx] == NULL)
   {
     block = first_memory_block(context);
+    block_data = block->fetch_data(block);
 
-    magic_setflags(magic_cookie[context->tidx], 0);
-
-    uint8_t* block_data = iterator->fetch_data(iterator);
     if (block_data != NULL)
     {
+      magic_setflags(magic_cookie[context->tidx], 0);
+
       cached_types[context->tidx] = magic_buffer(
           magic_cookie[context->tidx],
           block_data,
diff --git a/libyara/modules/math.c b/libyara/modules/math.c
index 6eefe24..1c38b3d 100644
--- a/libyara/modules/math.c
+++ b/libyara/modules/math.c
@@ -93,7 +93,7 @@ define_function(data_entropy)
 
   YR_SCAN_CONTEXT* context = scan_context();
   YR_MEMORY_BLOCK* block = first_memory_block(context);
-  YR_BLOCK_ITERATOR* iterator = context->iterator;
+  YR_MEMORY_BLOCK_ITERATOR* iterator = context->iterator;
 
   if (offset < 0 || length < 0 || offset < block->base)
     return_float(UNDEFINED);
@@ -112,7 +112,7 @@ define_function(data_entropy)
       size_t data_len = (size_t) yr_min(
           length, (size_t) (block->size - data_offset));
 
-      uint8_t* block_data = iterator->fetch_data(iterator);
+      uint8_t* block_data = block->fetch_data(block);
 
       if (block_data == NULL)
       {
@@ -199,7 +199,7 @@ define_function(data_deviation)
 
   YR_SCAN_CONTEXT* context = scan_context();
   YR_MEMORY_BLOCK* block = first_memory_block(context);
-  YR_BLOCK_ITERATOR* iterator = context->iterator;
+  YR_MEMORY_BLOCK_ITERATOR* iterator = context->iterator;
 
   if (offset < 0 || length < 0 || offset < block->base)
     return_float(UNDEFINED);
@@ -209,7 +209,7 @@ define_function(data_deviation)
     if (offset >= block->base &&
         offset < block->base + block->size)
     {
-      uint8_t* block_data = iterator->fetch_data(iterator);
+      uint8_t* block_data = block->fetch_data(block);
 
       if (block_data == NULL)
         return_float(UNDEFINED);
@@ -272,7 +272,7 @@ define_function(data_mean)
 
   YR_SCAN_CONTEXT* context = scan_context();
   YR_MEMORY_BLOCK* block = first_memory_block(context);
-  YR_BLOCK_ITERATOR* iterator = context->iterator;
+  YR_MEMORY_BLOCK_ITERATOR* iterator = context->iterator;
 
   size_t total_len = 0;
   size_t i;
@@ -289,7 +289,7 @@ define_function(data_mean)
       size_t data_len = (size_t) yr_min(
           length, (size_t) (block->size - data_offset));
 
-      uint8_t* block_data = iterator->fetch_data(iterator);
+      uint8_t* block_data = block->fetch_data(block);
 
       if (block_data == NULL)
         return_float(UNDEFINED);
@@ -336,7 +336,7 @@ define_function(data_serial_correlation)
 
   YR_SCAN_CONTEXT* context = scan_context();
   YR_MEMORY_BLOCK* block = first_memory_block(context);
-  YR_BLOCK_ITERATOR* iterator = context->iterator;
+  YR_MEMORY_BLOCK_ITERATOR* iterator = context->iterator;
 
   double sccun = 0;
   double scclast = 0;
@@ -357,7 +357,7 @@ define_function(data_serial_correlation)
       size_t data_len = (size_t) yr_min(
           length, (size_t) (block->size - data_offset));
 
-      uint8_t* block_data = iterator->fetch_data(iterator);
+      uint8_t* block_data = block->fetch_data(block);
 
       if (block_data == NULL)
         return_float(UNDEFINED);
@@ -460,7 +460,7 @@ define_function(data_monte_carlo_pi)
 
   YR_SCAN_CONTEXT* context = scan_context();
   YR_MEMORY_BLOCK* block = first_memory_block(context);
-  YR_BLOCK_ITERATOR* iterator = context->iterator;
+  YR_MEMORY_BLOCK_ITERATOR* iterator = context->iterator;
 
   if (offset < 0 || length < 0 || offset < block->base)
     return_float(UNDEFINED);
@@ -476,7 +476,7 @@ define_function(data_monte_carlo_pi)
       size_t data_len = (size_t) yr_min(
           length, (size_t) (block->size - data_offset));
 
-      uint8_t* block_data = iterator->fetch_data(iterator);
+      uint8_t* block_data = block->fetch_data(block);
 
       if (block_data == NULL)
         return_float(UNDEFINED);
diff --git a/libyara/modules/pe.c b/libyara/modules/pe.c
index 99579f6..4f7a93c 100644
--- a/libyara/modules/pe.c
+++ b/libyara/modules/pe.c
@@ -2263,7 +2263,7 @@ int module_load(
     size_t module_data_size)
 {
   YR_MEMORY_BLOCK* block;
-  YR_BLOCK_ITERATOR* iterator = context->iterator;
+  YR_MEMORY_BLOCK_ITERATOR* iterator = context->iterator;
 
   set_integer(
       IMAGE_FILE_MACHINE_UNKNOWN, module_object,
@@ -2506,7 +2506,7 @@ int module_load(
 
   foreach_memory_block(iterator, block)
   {
-    uint8_t* block_data = iterator->fetch_data(iterator);
+    uint8_t* block_data = block->fetch_data(block);
 
     if (block_data == NULL)
       continue;
diff --git a/libyara/proc.c b/libyara/proc.c
index 44e0b78..21c21cb 100644
--- a/libyara/proc.c
+++ b/libyara/proc.c
@@ -35,17 +35,29 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <yara/error.h>
 #include <yara/proc.h>
 
+// Windows
+
+typedef struct _YR_PROC_ITERATOR_CTX
+{
+  HANDLE          hProcess;
+  uint8_t*        buffer;
+  size_t          buffer_size;
+  SYSTEM_INFO     si;
+  YR_MEMORY_BLOCK current_block;
+
+} YR_PROC_ITERATOR_CTX;
+
 
 int _yr_process_attach(
     int pid,
-    void** hProcess)
+    YR_PROC_ITERATOR_CTX* context)
 {
   TOKEN_PRIVILEGES tokenPriv;
   LUID luidDebug;
   HANDLE hToken = NULL;
 
   if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken) &&
-    LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luidDebug))
+      LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luidDebug))
   {
     tokenPriv.PrivilegeCount = 1;
     tokenPriv.Privileges[0].Luid = luidDebug;
@@ -63,109 +75,102 @@ int _yr_process_attach(
   if (hToken != NULL)
     CloseHandle(hToken);
 
-  *hProcess = OpenProcess(
+  context->hProcess = OpenProcess(
       PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
       FALSE,
       pid);
 
-  if (*hProcess == NULL)
+  if (context->hProcess == NULL)
     return ERROR_COULD_NOT_ATTACH_TO_PROCESS;
 
+  GetSystemInfo(&context->si);
+
   return ERROR_SUCCESS;
 }
 
 
 int _yr_process_detach(
-    void* hProcess)
+    YR_PROC_ITERATOR_CTX* context)
 {
-  if (hProcess != NULL)
-    CloseHandle(hProcess);
-
+  CloseHandle(context->hProcess);
   return ERROR_SUCCESS;
 }
 
 
-int _yr_process_get_blocks(
-    void* hProcess,
-    YR_MEMORY_BLOCK** head)
+uint8_t* _yr_fetch_block_data(
+    YR_MEMORY_BLOCK* block)
 {
-  PVOID address;
-  YR_MEMORY_BLOCK* new_block;
-  YR_MEMORY_BLOCK* current = NULL;
-  SYSTEM_INFO si;
-  MEMORY_BASIC_INFORMATION mbi;
+  YR_PROC_ITERATOR_CTX* context = (YR_PROC_ITERATOR_CTX*) block->context;
+  SIZE_T read;
 
-  GetSystemInfo(&si);
-  address = si.lpMinimumApplicationAddress;
+  if (context->buffer_size < block->size)
+  {
+    if (context->buffer != NULL)
+      yr_free(context->buffer);
 
-  *head = NULL;
+    context->buffer = (uint8_t*) yr_malloc(block->size);
 
-  while (address < si.lpMaximumApplicationAddress &&
-    VirtualQueryEx(hProcess, address, &mbi, sizeof(mbi)) != 0)
-  {
-    if (mbi.State == MEM_COMMIT && ((mbi.Protect & PAGE_NOACCESS) == 0))
+    if (context->buffer != NULL)
     {
-      new_block = (YR_MEMORY_BLOCK*) yr_malloc(sizeof(YR_MEMORY_BLOCK));
+      context->buffer_size = block->size;
+    }
+    else
+    {
+      context->buffer_size = 0;
+      return NULL;
+    }
+  }
 
-      if (new_block == NULL)
-        return ERROR_INSUFICIENT_MEMORY;
+  if (ReadProcessMemory(
+        context->hProcess,
+        (LPCVOID) block->base,
+        context->buffer,
+        (SIZE_T) block->size,
+        &read) == FALSE)
+    {
+      return NULL;
+    }
+
+  return context->buffer;
+}
 
-      new_block->base = (size_t) mbi.BaseAddress;
-      new_block->size = mbi.RegionSize;
-      new_block->next = NULL;
 
-      if (*head == NULL)
-        *head = new_block;
+YR_MEMORY_BLOCK* _yr_get_next_block(
+    YR_MEMORY_BLOCK_ITERATOR* iterator)
+{
+  YR_PROC_ITERATOR_CTX* context = (YR_PROC_ITERATOR_CTX*) iterator->context;
+
+  MEMORY_BASIC_INFORMATION mbi;
+  PVOID address = (PVOID) (context->current_block.base + \
+	                       context->current_block.size);
 
-      if (current != NULL)
-        current->next = new_block;
+  while (address < context->si.lpMaximumApplicationAddress &&
+    VirtualQueryEx(context->hProcess, address, &mbi, sizeof(mbi)) != 0)
+  {
+    if (mbi.State == MEM_COMMIT && ((mbi.Protect & PAGE_NOACCESS) == 0))
+    {
+      context->current_block.base = (size_t) mbi.BaseAddress;
+      context->current_block.size = mbi.RegionSize;
 
-      current = new_block;
+      return &context->current_block;
     }
 
     address = (uint8_t*) address + mbi.RegionSize;
   }
 
-  return ERROR_SUCCESS;
+  return NULL;
 }
 
 
-int _yr_process_read_block(
-    void* hProcess,
-    YR_MEMORY_BLOCK* block,
-    uint8_t** data)
+YR_MEMORY_BLOCK* _yr_get_first_block(
+    YR_MEMORY_BLOCK_ITERATOR* iterator)
 {
-  SIZE_T read;
-  uint8_t* buffer = NULL;
-  int result = ERROR_SUCCESS;
-  *data = NULL;
-
-  buffer = (uint8_t*) yr_malloc(block->size);
-
-  if (buffer == NULL)
-    return ERROR_INSUFICIENT_MEMORY;
-
-  if (ReadProcessMemory(
-      (HANDLE) hProcess,
-      (LPCVOID) block->base,
-      buffer,
-      (SIZE_T) block->size,
-      &read) == FALSE)
-  {
-    result = ERROR_COULD_NOT_READ_PROCESS_MEMORY;
-
-    if (buffer != NULL)
-    {
-      yr_free(buffer);
-      buffer = NULL;
-    }
-  }
+  YR_PROC_ITERATOR_CTX* context = (YR_PROC_ITERATOR_CTX*) iterator->context;
 
-  // TODO: compare read with block size
-  // it would be bad to assume block size bytes were read
-  *data = buffer;
+  context->current_block.base = (size_t) context->si.lpMinimumApplicationAddress;
+  context->current_block.size = 0;
 
-  return result;
+  return _yr_get_next_block(iterator);
 }
 
 #else
@@ -199,26 +204,25 @@ int _yr_process_read_block(
 #include <mach/vm_region.h>
 #include <mach/vm_statistics.h>
 
-typedef struct _YR_MACH_CONTEXT
-{
-  task_t task;
+// Mac OS X
 
-} YR_MACH_CONTEXT;
+typedef struct _YR_PROC_ITERATOR_CTX {
 
+  task_t            task;
+  uint8_t*          buffer;
+  size_t            buffer_size;
+  YR_MEMORY_BLOCK   current_block;
 
-int _yr_process_attach(
-  int pid,
-  void** context)
-{
-  YR_MACH_CONTEXT* ctx = (YR_MACH_CONTEXT*) yr_malloc(sizeof(YR_MACH_CONTEXT));
-  *context = ctx;
+} YR_PROC_ITERATOR_CTX;
 
-  if (ctx == NULL)
-    return ERROR_INSUFICIENT_MEMORY;
 
-  kern_return_t kr;
+int _yr_process_attach(
+    int pid,
+    YR_PROC_ITERATOR_CTX* context)
+{
+  kern_return_t kr = task_for_pid(mach_task_self(), pid, &context->task);
 
-  if ((kr = task_for_pid(mach_task_self(), pid, &ctx->task)) != KERN_SUCCESS)
+  if (kr != KERN_SUCCESS)
     return ERROR_COULD_NOT_ATTACH_TO_PROCESS;
 
   return ERROR_SUCCESS;
@@ -226,46 +230,71 @@ int _yr_process_attach(
 
 
 int _yr_process_detach(
-  void* context)
+    YR_PROC_ITERATOR_CTX* context)
 {
-  if (context == NULL)
-    return ERROR_SUCCESS;
+  if (context->task != MACH_PORT_NULL)
+    mach_port_deallocate(mach_task_self(), context->task);
 
-  YR_MACH_CONTEXT* ctx = (YR_MACH_CONTEXT*)context;
+  return ERROR_SUCCESS;
+}
 
-  if (ctx->task != MACH_PORT_NULL)
-    mach_port_deallocate(mach_task_self(), ctx->task);
 
-  yr_free(ctx);
+uint8_t* _yr_fetch_block_data(
+    YR_MEMORY_BLOCK* block)
+{
+  YR_PROC_ITERATOR_CTX* context = (YR_PROC_ITERATOR_CTX*) block->context;
+  vm_size_t size = block->size;
 
-  return ERROR_SUCCESS;
+  if (context->buffer_size < block->size)
+  {
+    if (context->buffer != NULL)
+      yr_free(context->buffer);
+
+    context->buffer = yr_malloc(block->size);
+
+    if (context->buffer != NULL)
+    {
+      context->buffer_size = block->size;
+    }
+    else
+    {
+      context->buffer_size = 0;
+      return NULL;
+    }
+  }
+
+  if (vm_read_overwrite(
+      context->task,
+      block->base,
+      block->size,
+      (vm_address_t) context->buffer,
+      &size) != KERN_SUCCESS)
+  {
+    return NULL;
+  }
+
+  return context->buffer;
 }
 
 
-int _yr_process_get_blocks(
-  void* context,
-  YR_MEMORY_BLOCK** head)
+YR_MEMORY_BLOCK* _yr_get_next_block(
+    YR_MEMORY_BLOCK_ITERATOR* iterator)
 {
-  YR_MACH_CONTEXT* ctx = (YR_MACH_CONTEXT*)context;
+  YR_PROC_ITERATOR_CTX* context = (YR_PROC_ITERATOR_CTX*) iterator->context;
 
   kern_return_t kr;
-  vm_size_t size = 0;
-  vm_address_t address = 0;
-  vm_region_basic_info_data_64_t info;
   mach_msg_type_number_t info_count;
   mach_port_t object;
-
-  YR_MEMORY_BLOCK* new_block;
-  YR_MEMORY_BLOCK* current = NULL;
-
-  *head = NULL;
-
+  vm_region_basic_info_data_64_t info;
+  vm_size_t size = 0;
+  vm_address_t address = context->current_block.base \
+                       + context->current_block.size;
   do
   {
     info_count = VM_REGION_BASIC_INFO_COUNT_64;
 
     kr = vm_region_64(
-        ctx->task,
+        context->task,
         &address,
         &size,
         VM_REGION_BASIC_INFO,
@@ -275,354 +304,219 @@ int _yr_process_get_blocks(
 
     if (kr == KERN_SUCCESS)
     {
-      new_block = (YR_MEMORY_BLOCK*) yr_malloc(sizeof(YR_MEMORY_BLOCK));
-
-      if (new_block == NULL)
-        return ERROR_INSUFICIENT_MEMORY;
+      context->current_block.base = address;
+      context->current_block.size = size;
 
-      new_block->base = address;
-      new_block->size = size;
-      new_block->next = NULL;
-
-      if (*head == NULL)
-        *head = new_block;
-
-      if (current != NULL)
-        current->next = new_block;
-
-      current = new_block;
-      address += size;
+      return &context->current_block;
     }
 
   } while (kr != KERN_INVALID_ADDRESS);
 
-  return ERROR_SUCCESS;
+  return NULL;
 }
 
 
-int _yr_process_read_block(
-  void* context,
-  YR_MEMORY_BLOCK* block,
-  uint8_t** data)
+YR_MEMORY_BLOCK* _yr_get_first_block(
+    YR_MEMORY_BLOCK_ITERATOR* iterator)
 {
-  YR_MACH_CONTEXT* ctx = (YR_MACH_CONTEXT*)context;
+  YR_PROC_ITERATOR_CTX* context = (YR_PROC_ITERATOR_CTX*) iterator->context;
 
-  int result = ERROR_SUCCESS;
-  uint8_t* buffer;
-  vm_size_t size = block->size;
-  *data = NULL;
+  context->current_block.base = 0;
+  context->current_block.size = 0;
 
-  buffer = (uint8_t*) yr_malloc(size);
+  return _yr_get_next_block(iterator);
+}
 
-  if (buffer == NULL)
-    return ERROR_INSUFICIENT_MEMORY;
 
-  if (vm_read_overwrite(
-      ctx->task,
-      block->base,
-      block->size,
-      (vm_address_t) buffer,
-      &size) != KERN_SUCCESS)
-  {
-    result = ERROR_COULD_NOT_READ_PROCESS_MEMORY;
+#else
 
-    if (buffer != NULL)
-    {
-      yr_free(buffer);
-      buffer = NULL;
-    }
-  }
+#include <errno.h>
 
-  // TODO: compare read with block size
-  // it would be bad to assume block size bytes were read
-  *data = buffer;
+// Linux
 
-  return result;
-}
 
-#else
+typedef struct _YR_PROC_ITERATOR_CTX {
 
-#include <errno.h>
+  int             pid;
+  int             mem_fd;
+  FILE*           maps;
+  uint8_t*        buffer;
+  size_t          buffer_size;
+  YR_MEMORY_BLOCK current_block;
 
-typedef struct _YR_PTRACE_CONTEXT
-{
-  int pid;
-  int mem_fd;
-  FILE* maps;
-  int attached;
+} YR_PROC_ITERATOR_CTX;
 
-} YR_PTRACE_CONTEXT;
 
 
 int _yr_process_attach(
-  int pid,
-  void** context)
+    int pid,
+    YR_PROC_ITERATOR_CTX* context)
 {
   char buffer[256];
 
-  YR_PTRACE_CONTEXT* ctx = (YR_PTRACE_CONTEXT*) yr_malloc(
-      sizeof(YR_PTRACE_CONTEXT));
-
-  *context = ctx;
-
-  if (ctx == NULL)
-    return ERROR_INSUFICIENT_MEMORY;
-
-  ctx->pid = pid;
-  ctx->maps = NULL;
-  ctx->mem_fd = -1;
-  ctx->attached = 0;
+  context->pid = pid;
+  context->maps = NULL;
+  context->mem_fd = -1;
 
   snprintf(buffer, sizeof(buffer), "/proc/%u/maps", pid);
-  ctx->maps = fopen(buffer, "r");
+  context->maps = fopen(buffer, "r");
 
-  if (ctx->maps == NULL)
+  if (context->maps == NULL)
     return ERROR_COULD_NOT_ATTACH_TO_PROCESS;
 
   snprintf(buffer, sizeof(buffer), "/proc/%u/mem", pid);
-  ctx->mem_fd = open(buffer, O_RDONLY);
+  context->mem_fd = open(buffer, O_RDONLY);
 
-  if (ctx->mem_fd == -1)
-    return ERROR_COULD_NOT_ATTACH_TO_PROCESS;
+  if (context->mem_fd == -1)
+  {
+    fclose(context->maps);
+    context->maps = NULL;
 
-  if (ptrace(PTRACE_ATTACH, pid, NULL, 0) != -1)
-    ctx->attached = 1;
-  else
     return ERROR_COULD_NOT_ATTACH_TO_PROCESS;
+  }
 
-  wait(NULL);
-
-  return ERROR_SUCCESS;
-}
-
-
-int _yr_process_detach(
-  void* context)
-{
-  if (context == NULL)
-    return ERROR_SUCCESS;
-
-  YR_PTRACE_CONTEXT* ctx = (YR_PTRACE_CONTEXT*)context;
-
-  if(ctx->attached)
-    ptrace(PTRACE_DETACH, ctx->pid, NULL, 0);
-
-  if (ctx->mem_fd != -1)
-    close(ctx->mem_fd);
+  if (ptrace(PTRACE_ATTACH, pid, NULL, 0) == -1)
+  {
+    fclose(context->maps);
+    context->maps = NULL;
 
-  if (ctx->maps != NULL)
-    fclose(ctx->maps);
+    close(context->mem_fd);
+    context->mem_fd = -1;
 
-  yr_free(ctx);
+    return ERROR_COULD_NOT_ATTACH_TO_PROCESS;
+  }
 
   return ERROR_SUCCESS;
 }
 
 
-int _yr_process_get_blocks(
-  void* context,
-  YR_MEMORY_BLOCK** head)
+int _yr_process_detach(
+    YR_PROC_ITERATOR_CTX* context)
 {
-  char buffer[256];
-  size_t begin, end;
-
-  YR_MEMORY_BLOCK* new_block;
-  YR_MEMORY_BLOCK* current = NULL;
-
-  YR_PTRACE_CONTEXT* ctx = (YR_PTRACE_CONTEXT*) context;
-
-  *head = NULL;
-
-  while (fgets(buffer, sizeof(buffer), ctx->maps) != NULL)
-  {
-    sscanf(buffer, "%zx-%zx", &begin, &end);
-
-    new_block = (YR_MEMORY_BLOCK*) yr_malloc(sizeof(YR_MEMORY_BLOCK));
-
-    if (new_block == NULL)
-      return ERROR_INSUFICIENT_MEMORY;
-
-    new_block->base = begin;
-    new_block->size = end - begin;
-    new_block->next = NULL;
-
-    if (*head == NULL)
-      *head = new_block;
-
-    if (current != NULL)
-      current->next = new_block;
-
-    current = new_block;
-  }
+  fclose(context->maps);
+  close(context->mem_fd);
+  ptrace(PTRACE_DETACH, context->pid, NULL, 0);
 
   return ERROR_SUCCESS;
 }
 
 
-int _yr_process_read_block(
-  void* context,
-  YR_MEMORY_BLOCK* block,
-  uint8_t** data)
+uint8_t* _yr_fetch_block_data(
+    YR_MEMORY_BLOCK* block)
 {
-  uint8_t* buffer = NULL;
-  int result = ERROR_SUCCESS;
-  *data = NULL;
-
-  YR_PTRACE_CONTEXT* ctx = (YR_PTRACE_CONTEXT*)context;
+  YR_PROC_ITERATOR_CTX* context = (YR_PROC_ITERATOR_CTX*) block->context;
 
-  buffer = (uint8_t*) yr_malloc(block->size);
-
-  if (buffer == NULL)
-    return ERROR_INSUFICIENT_MEMORY;
-
-  if (pread(ctx->mem_fd, buffer, block->size, block->base) == -1)
+  if (context->buffer_size < block->size)
   {
-    result = ERROR_COULD_NOT_READ_PROCESS_MEMORY;
+    if (context->buffer != NULL)
+      yr_free(context->buffer);
 
-    if (buffer != NULL)
+    context->buffer = yr_malloc(block->size);
+
+    if (context->buffer != NULL)
+    {
+      context->buffer_size = block->size;
+    }
+    else
     {
-      yr_free(buffer);
-      buffer = NULL;
+      context->buffer_size = 0;
+      return NULL;
     }
   }
 
-  *data = buffer;
-
-  return result;
-}
-
-#endif
-#endif
-
-// process iterator abstraction
-
-static void _yr_free_context_data(
-    YR_PROCESS_CONTEXT* context)
-{
-  if (context->data != NULL)
+  if (pread(context->mem_fd,
+            context->buffer,
+            block->size,
+            block->base) == -1)
   {
-    yr_free(context->data);
-    context->data = NULL;
+    return NULL;
   }
-}
 
-
-static YR_MEMORY_BLOCK* _yr_get_first_block(
-    YR_BLOCK_ITERATOR* iterator)
-{
-  YR_PROCESS_CONTEXT* ctx = (YR_PROCESS_CONTEXT*)iterator->context;
-
-  _yr_free_context_data(ctx);
-  ctx->current = ctx->blocks;
-
-  return ctx->current;
+  return context->buffer;
 }
 
 
-static YR_MEMORY_BLOCK* _yr_get_next_block(
-    YR_BLOCK_ITERATOR* iterator)
+YR_MEMORY_BLOCK* _yr_get_next_block(
+    YR_MEMORY_BLOCK_ITERATOR* iterator)
 {
-  YR_PROCESS_CONTEXT* ctx = (YR_PROCESS_CONTEXT*)iterator->context;
+  YR_PROC_ITERATOR_CTX* context = (YR_PROC_ITERATOR_CTX*) iterator->context;
 
-  _yr_free_context_data(ctx);
+  char buffer[256];
+  size_t begin, end;
 
-  if (ctx->current == NULL)
-    return NULL;
+  if (fgets(buffer, sizeof(buffer), context->maps) != NULL)
+  {
+    sscanf(buffer, "%zx-%zx", &begin, &end);
 
-  ctx->current = ctx->current->next;
+    context->current_block.base = begin;
+    context->current_block.size = end - begin;
+
+    return &context->current_block;
+  }
 
-  return ctx->current;
+  return NULL;
 }
 
 
-static uint8_t* _yr_fetch_block_data(
-    YR_BLOCK_ITERATOR* iterator)
+YR_MEMORY_BLOCK* _yr_get_first_block(
+    YR_MEMORY_BLOCK_ITERATOR* iterator)
 {
-  YR_PROCESS_CONTEXT* ctx = (YR_PROCESS_CONTEXT*)iterator->context;
+  YR_PROC_ITERATOR_CTX* context = (YR_PROC_ITERATOR_CTX*) iterator->context;
 
-  if (ctx->current == NULL)
+  if (fseek(context->maps, 0, SEEK_SET) != 0)
     return NULL;
 
-  // reuse cached data if available
-  if (ctx->data != NULL)
-    return ctx->data;
-
-  _yr_free_context_data(ctx);
+  return _yr_get_next_block(iterator);
+}
 
-  _yr_process_read_block(
-      ctx->process_context,
-      ctx->current,
-      &ctx->data);
 
-  // TODO should this return error code?
-  // On one hand it's useful, on the other failure
-  // is expected in cases when the section isn't
-  // readable and that's not a reason to exit
+#endif
+#endif
 
-  return ctx->data;
-}
 
 
 int yr_process_open_iterator(
     int pid,
-    YR_BLOCK_ITERATOR* iterator)
+    YR_MEMORY_BLOCK_ITERATOR* iterator)
 {
-  YR_PROCESS_CONTEXT* context = (YR_PROCESS_CONTEXT*) yr_malloc(
-      sizeof(YR_PROCESS_CONTEXT));
+  YR_PROC_ITERATOR_CTX* context = (YR_PROC_ITERATOR_CTX*) \
+      yr_malloc(sizeof(YR_PROC_ITERATOR_CTX));
 
   if (context == NULL)
     return ERROR_INSUFICIENT_MEMORY;
 
-  context->blocks = NULL;
-  context->current = NULL;
-  context->data = NULL;
-  context->process_context = NULL;
-
   iterator->context = context;
   iterator->first = _yr_get_first_block;
   iterator->next = _yr_get_next_block;
-  iterator->fetch_data = _yr_fetch_block_data;
 
-  int result = _yr_process_attach(
-      pid,
-      &context->process_context);
+  context->buffer = NULL;
+  context->buffer_size = 0;
 
-  if (result == ERROR_SUCCESS)
-    result = _yr_process_get_blocks(
-        context->process_context,
-        &context->blocks);
+  context->current_block.base = 0;
+  context->current_block.size = 0;
+  context->current_block.context = context;
+  context->current_block.fetch_data = _yr_fetch_block_data;
 
-  return result;
+  return _yr_process_attach(pid, context);
 }
 
 
 int yr_process_close_iterator(
-    YR_BLOCK_ITERATOR* iterator)
+    YR_MEMORY_BLOCK_ITERATOR* iterator)
 {
-  YR_PROCESS_CONTEXT* ctx = (YR_PROCESS_CONTEXT*) iterator->context;
-
-  if (ctx == NULL)
-    return ERROR_SUCCESS;
+  YR_PROC_ITERATOR_CTX* context = (YR_PROC_ITERATOR_CTX*) iterator->context;
 
-  // NOTE: detach must free allocated process context
-  _yr_process_detach(ctx->process_context);
+  if (context != NULL)
+  {
+    _yr_process_detach(context);
 
-  _yr_free_context_data(ctx);
+    if (context->buffer != NULL)
+      yr_free(context->buffer);
 
-  YR_MEMORY_BLOCK* current = ctx->blocks;
-  YR_MEMORY_BLOCK* next;
+    yr_free(context);
 
-  // free blocks list
-  while(current != NULL)
-  {
-    next = current->next;
-    yr_free(current);
-    current = next;
+    iterator->context = NULL;
   }
 
-  // free the context
-  yr_free(iterator->context);
-  iterator->context = NULL;
-
   return ERROR_SUCCESS;
 }
diff --git a/libyara/rules.c b/libyara/rules.c
index 449eb18..490c472 100644
--- a/libyara/rules.c
+++ b/libyara/rules.c
@@ -330,7 +330,7 @@ int _yr_rules_scan_mem_block(
 
 YR_API int yr_rules_scan_mem_blocks(
     YR_RULES* rules,
-    YR_BLOCK_ITERATOR* iterator,
+    YR_MEMORY_BLOCK_ITERATOR* iterator,
     int flags,
     YR_CALLBACK_FUNC callback,
     void* user_data,
@@ -425,7 +425,7 @@ YR_API int yr_rules_scan_mem_blocks(
 
   while (block != NULL)
   {
-    uint8_t* data = iterator->fetch_data(iterator);
+    uint8_t* data = block->fetch_data(block);
 
     // fetch may fail
     if (data == NULL)
@@ -536,26 +536,25 @@ _exit:
 }
 
 
+
 static YR_MEMORY_BLOCK* _yr_get_first_block(
-    YR_BLOCK_ITERATOR* iterator)
+    YR_MEMORY_BLOCK_ITERATOR* iterator)
 {
-  YR_BLOCK_CONTEXT* ctx = (YR_BLOCK_CONTEXT*) iterator->context;
-  return ctx->block;
+  return (YR_MEMORY_BLOCK*) iterator->context;
 }
 
 
 static YR_MEMORY_BLOCK* _yr_get_next_block(
-    YR_BLOCK_ITERATOR* iterator)
+    YR_MEMORY_BLOCK_ITERATOR* iterator)
 {
   return NULL;
 }
 
 
 static uint8_t* _yr_fetch_block_data(
-    YR_BLOCK_ITERATOR* iterator)
+    YR_MEMORY_BLOCK* block)
 {
-  YR_BLOCK_CONTEXT* ctx = (YR_BLOCK_CONTEXT*) iterator->context;
-  return ctx->data;
+  return (uint8_t*) block->context;
 }
 
 
@@ -569,20 +568,16 @@ YR_API int yr_rules_scan_mem(
     int timeout)
 {
   YR_MEMORY_BLOCK block;
-  YR_BLOCK_CONTEXT context;
-  YR_BLOCK_ITERATOR iterator;
+  YR_MEMORY_BLOCK_ITERATOR iterator;
 
   block.size = buffer_size;
   block.base = 0;
-  block.next = NULL;
-
-  context.block = █
-  context.data = buffer;
+  block.fetch_data = _yr_fetch_block_data;
+  block.context = buffer;
 
-  iterator.context = &context;
+  iterator.context = █
   iterator.first = _yr_get_first_block;
   iterator.next = _yr_get_next_block;
-  iterator.fetch_data = _yr_fetch_block_data;
 
   return yr_rules_scan_mem_blocks(
       rules,
@@ -662,13 +657,14 @@ YR_API int yr_rules_scan_proc(
     void* user_data,
     int timeout)
 {
-  YR_BLOCK_ITERATOR iterator;
+  YR_MEMORY_BLOCK_ITERATOR iterator;
 
   int result = yr_process_open_iterator(
       pid,
       &iterator);
 
-  if (result == ERROR_SUCCESS)
+  if (result == ERROR_SUCCESS) 
+  {
     result = yr_rules_scan_mem_blocks(
         rules,
         &iterator,
@@ -677,7 +673,8 @@ YR_API int yr_rules_scan_proc(
         user_data,
         timeout);
 
-  yr_process_close_iterator(&iterator);
+    yr_process_close_iterator(&iterator);
+  }
 
   return result;
 }

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/forensics/yara.git



More information about the forensics-changes mailing list