Refactor process memory scanning variants (#776)

Implementation details are placed into separate files and a dummy
implementation stub has been added for other platforms.
This commit is contained in:
Hilko Bengen
2017-10-30 10:13:12 +01:00
committed by Victor M. Alvarez
parent 9e03c23f0f
commit c4cdf42ad8
9 changed files with 662 additions and 463 deletions
+10 -1
View File
@@ -28,12 +28,16 @@ case $host_alias in
i?86-*-mingw*) CFLAGS="$CFLAGS -D__MINGW_USE_VC2005_COMPAT" ;;
esac
proc_interface=none
case $host_os in
darwin*) CFLAGS="$CFLAGS -I/opt/local/include"
# Starting with Mac OS X 10.11 (El Capitan) the OpenSSL headers
# are in /usr/local/opt/openssl/include
CFLAGS="$CFLAGS -I/usr/local/opt/openssl/include"
LDFLAGS="$LDFLAGS -L/usr/local/opt/openssl/lib" ;;
LDFLAGS="$LDFLAGS -L/usr/local/opt/openssl/lib"
proc_interface=mach ;;
mingw*) proc_interface=windows ;;
linux*|freebsd*|openbsd*) proc_interface=linux ;;
esac
AC_C_BIGENDIAN
@@ -206,6 +210,11 @@ AM_CONDITIONAL([HASH_MODULE], [test x$build_hash_module = xtrue])
AM_CONDITIONAL([DOTNET_MODULE], [test x$build_dotnet_module = xtrue])
AM_CONDITIONAL([GCC], [test "x$GCC" = xyes])
AM_CONDITIONAL([USE_WINDOWS_PROC], [test x$proc_interface = xwindows ])
AM_CONDITIONAL([USE_LINUX_PROC], [test x$proc_interface = xlinux ])
AM_CONDITIONAL([USE_MACH_PROC], [test x$proc_interface = xmach ])
AM_CONDITIONAL([USE_NO_PROC], [test x$proc_interface = xnone ])
AC_SUBST([PC_REQUIRES_PRIVATE])
AC_SUBST([PC_LIBS_PRIVATE])
+13
View File
@@ -142,5 +142,18 @@ libyara_la_SOURCES = \
threading.h \
utils.h
if USE_WINDOWS_PROC
libyara_la_SOURCES += proc_windows.c
endif
if USE_LINUX_PROC
libyara_la_SOURCES += proc_linux.c
endif
if USE_MACH_PROC
libyara_la_SOURCES += proc_mach.c
endif
if USE_NO_PROC
libyara_la_SOURCES += proc_none.c
endif
pkgconfigdir = $(libdir)/pkgconfig
nodist_pkgconfig_DATA = yara.pc
+7
View File
@@ -32,6 +32,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <yara/types.h>
typedef struct _YR_PROC_ITERATOR_CTX {
const uint8_t* buffer;
size_t buffer_size;
YR_MEMORY_BLOCK current_block;
void* proc_info;
} YR_PROC_ITERATOR_CTX;
YR_API int yr_process_open_iterator(
int pid,
YR_MEMORY_BLOCK_ITERATOR* iterator);
+6 -462
View File
@@ -27,471 +27,12 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if defined(_WIN32) || defined(__CYGWIN__)
#include <windows.h>
#include <yara/mem.h>
#include <yara/error.h>
#include <yara/proc.h>
// Windows
typedef struct _YR_PROC_ITERATOR_CTX
{
HANDLE hProcess;
const 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,
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))
{
tokenPriv.PrivilegeCount = 1;
tokenPriv.Privileges[0].Luid = luidDebug;
tokenPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(
hToken,
FALSE,
&tokenPriv,
sizeof(tokenPriv),
NULL,
NULL);
}
if (hToken != NULL)
CloseHandle(hToken);
context->hProcess = OpenProcess(
PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
FALSE,
pid);
if (context->hProcess == NULL)
return ERROR_COULD_NOT_ATTACH_TO_PROCESS;
GetSystemInfo(&context->si);
return ERROR_SUCCESS;
}
int _yr_process_detach(
YR_PROC_ITERATOR_CTX* context)
{
CloseHandle(context->hProcess);
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;
SIZE_T read;
if (context->buffer_size < block->size)
{
if (context->buffer != NULL)
yr_free((void*) context->buffer);
context->buffer = (const uint8_t*) yr_malloc(block->size);
if (context->buffer != NULL)
{
context->buffer_size = block->size;
}
else
{
context->buffer_size = 0;
return NULL;
}
}
if (ReadProcessMemory(
context->hProcess,
(LPCVOID) block->base,
(LPVOID) context->buffer,
(SIZE_T) block->size,
&read) == FALSE)
{
return NULL;
}
return context->buffer;
}
YR_API YR_MEMORY_BLOCK* yr_process_get_next_memory_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);
while (address < context->si.lpMaximumApplicationAddress &&
VirtualQueryEx(context->hProcess, address, &mbi, sizeof(mbi)) != 0)
{
if (GetLastError() != ERROR_SUCCESS)
break;
if (mbi.State == MEM_COMMIT && ((mbi.Protect & PAGE_NOACCESS) == 0))
{
context->current_block.base = (size_t) mbi.BaseAddress;
context->current_block.size = mbi.RegionSize;
return &context->current_block;
}
address = (uint8_t*) address + mbi.RegionSize;
}
return NULL;
}
YR_API YR_MEMORY_BLOCK* yr_process_get_first_memory_block(
YR_MEMORY_BLOCK_ITERATOR* iterator)
{
YR_PROC_ITERATOR_CTX* context = (YR_PROC_ITERATOR_CTX*) iterator->context;
context->current_block.base = (size_t) context->si.lpMinimumApplicationAddress;
context->current_block.size = 0;
return yr_process_get_next_memory_block(iterator);
}
#else
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
defined(__OpenBSD__) || defined(__MACH__)
#else
#define _XOPEN_SOURCE 500
#endif
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <yara/error.h>
#include <yara/proc.h>
#include <yara/mem.h>
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
defined(__OpenBSD__) || defined(__MACH__)
#define PTRACE_ATTACH PT_ATTACH
#define PTRACE_DETACH PT_DETACH
#endif
#if defined(__MACH__)
#include <mach/mach.h>
#include <mach/mach_vm.h>
#include <mach/vm_region.h>
#include <mach/vm_statistics.h>
// Mac OS X
typedef struct _YR_PROC_ITERATOR_CTX {
task_t task;
const uint8_t* buffer;
size_t buffer_size;
YR_MEMORY_BLOCK current_block;
} YR_PROC_ITERATOR_CTX;
static 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 != KERN_SUCCESS)
return ERROR_COULD_NOT_ATTACH_TO_PROCESS;
return ERROR_SUCCESS;
}
static int _yr_process_detach(
YR_PROC_ITERATOR_CTX* context)
{
if (context->task != MACH_PORT_NULL)
mach_port_deallocate(mach_task_self(), context->task);
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;
vm_size_t size = block->size;
if (context->buffer_size < block->size)
{
if (context->buffer != NULL)
yr_free((void*) context->buffer);
context->buffer = (const uint8_t*) 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;
}
YR_API YR_MEMORY_BLOCK* yr_process_get_next_memory_block(
YR_MEMORY_BLOCK_ITERATOR* iterator)
{
YR_PROC_ITERATOR_CTX* context = (YR_PROC_ITERATOR_CTX*) iterator->context;
kern_return_t kr;
mach_msg_type_number_t info_count;
mach_port_t object;
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(
context->task,
&address,
&size,
VM_REGION_BASIC_INFO,
(vm_region_info_t) &info,
&info_count,
&object);
if (kr == KERN_SUCCESS)
{
context->current_block.base = address;
context->current_block.size = size;
return &context->current_block;
}
} while (kr != KERN_INVALID_ADDRESS);
return NULL;
}
YR_API YR_MEMORY_BLOCK* yr_process_get_first_memory_block(
YR_MEMORY_BLOCK_ITERATOR* iterator)
{
YR_PROC_ITERATOR_CTX* context = (YR_PROC_ITERATOR_CTX*) iterator->context;
context->current_block.base = 0;
context->current_block.size = 0;
return yr_process_get_next_memory_block(iterator);
}
#else
#include <errno.h>
// Linux
typedef struct _YR_PROC_ITERATOR_CTX {
int pid;
int mem_fd;
FILE* maps;
const uint8_t* buffer;
size_t buffer_size;
YR_MEMORY_BLOCK current_block;
} YR_PROC_ITERATOR_CTX;
static int _yr_process_attach(
int pid,
YR_PROC_ITERATOR_CTX* context)
{
int status;
char buffer[256];
context->pid = pid;
context->maps = NULL;
context->mem_fd = -1;
snprintf(buffer, sizeof(buffer), "/proc/%u/maps", pid);
context->maps = fopen(buffer, "r");
if (context->maps == NULL)
return ERROR_COULD_NOT_ATTACH_TO_PROCESS;
snprintf(buffer, sizeof(buffer), "/proc/%u/mem", pid);
context->mem_fd = open(buffer, O_RDONLY);
if (context->mem_fd == -1)
{
fclose(context->maps);
context->maps = NULL;
return ERROR_COULD_NOT_ATTACH_TO_PROCESS;
}
if (ptrace(PTRACE_ATTACH, pid, NULL, 0) == -1)
{
fclose(context->maps);
context->maps = NULL;
close(context->mem_fd);
context->mem_fd = -1;
return ERROR_COULD_NOT_ATTACH_TO_PROCESS;
}
status = 0;
if (waitpid(pid, &status, 0) == -1)
{
// this is a strange error state where we attached but the proc didn't
// stop. Try to detach and clean up.
ptrace(PTRACE_DETACH, context->pid, NULL, 0);
fclose(context->maps);
context->maps = NULL;
close(context->mem_fd);
context->mem_fd = -1;
return ERROR_COULD_NOT_ATTACH_TO_PROCESS;
}
return ERROR_SUCCESS;
}
static int _yr_process_detach(
YR_PROC_ITERATOR_CTX* context)
{
fclose(context->maps);
close(context->mem_fd);
ptrace(PTRACE_DETACH, context->pid, NULL, 0);
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;
if (context->buffer_size < block->size)
{
if (context->buffer != NULL)
yr_free((void*) context->buffer);
context->buffer = (const uint8_t*) yr_malloc(block->size);
if (context->buffer != NULL)
{
context->buffer_size = block->size;
}
else
{
context->buffer_size = 0;
return NULL;
}
}
if (pread(context->mem_fd,
(void *) context->buffer,
block->size,
block->base) == -1)
{
return NULL;
}
return context->buffer;
}
YR_API YR_MEMORY_BLOCK* yr_process_get_next_memory_block(
YR_MEMORY_BLOCK_ITERATOR* iterator)
{
YR_PROC_ITERATOR_CTX* context = (YR_PROC_ITERATOR_CTX*) iterator->context;
char buffer[256];
size_t begin, end;
if (fgets(buffer, sizeof(buffer), context->maps) != NULL)
{
sscanf(buffer, "%zx-%zx", &begin, &end);
context->current_block.base = begin;
context->current_block.size = end - begin;
return &context->current_block;
}
return NULL;
}
YR_API YR_MEMORY_BLOCK* yr_process_get_first_memory_block(
YR_MEMORY_BLOCK_ITERATOR* iterator)
{
YR_PROC_ITERATOR_CTX* context = (YR_PROC_ITERATOR_CTX*) iterator->context;
if (fseek(context->maps, 0, SEEK_SET) != 0)
return NULL;
return yr_process_get_next_memory_block(iterator);
}
#endif
#endif
int _yr_process_attach(int, YR_PROC_ITERATOR_CTX*);
int _yr_process_detach(YR_PROC_ITERATOR_CTX*);
YR_API int yr_process_open_iterator(
int pid,
@@ -509,11 +50,11 @@ YR_API int yr_process_open_iterator(
context->buffer = NULL;
context->buffer_size = 0;
context->current_block.base = 0;
context->current_block.size = 0;
context->current_block.context = context;
context->current_block.fetch_data = yr_process_fetch_memory_block_data;
context->proc_info = NULL;
return _yr_process_attach(pid, context);
}
@@ -531,6 +72,9 @@ YR_API int yr_process_close_iterator(
if (context->buffer != NULL)
yr_free((void*) context->buffer);
if (context->proc_info != NULL)
yr_free(context->proc_info);
yr_free(context);
iterator->context = NULL;
+215
View File
@@ -0,0 +1,215 @@
/*
Copyright (c) 2007-2017. The YARA Authors. All Rights Reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/ptrace.h>
#include <sys/wait.h>
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
defined(__OpenBSD__) || defined(__MACH__)
#else
#define PTRACE_ATTACH PT_ATTACH
#define PTRACE_DETACH PT_DETACH
#define _XOPEN_SOURCE 500
#endif
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <errno.h>
#include <yara/error.h>
#include <yara/proc.h>
#include <yara/mem.h>
typedef struct _YR_PROC_INFO {
int pid;
int mem_fd;
FILE* maps;
} YR_PROC_INFO;
int _yr_process_attach(
int pid,
YR_PROC_ITERATOR_CTX* context)
{
int status;
char buffer[256];
YR_PROC_INFO* proc_info = (YR_PROC_INFO*)yr_malloc(sizeof(YR_PROC_INFO));
if (proc_info == NULL)
return ERROR_INSUFFICIENT_MEMORY;
context->proc_info = proc_info;
proc_info->pid = pid;
proc_info->maps = NULL;
proc_info->mem_fd = -1;
snprintf(buffer, sizeof(buffer), "/proc/%u/maps", pid);
proc_info->maps = fopen(buffer, "r");
if (proc_info->maps == NULL)
{
yr_free(proc_info);
return ERROR_COULD_NOT_ATTACH_TO_PROCESS;
}
snprintf(buffer, sizeof(buffer), "/proc/%u/mem", pid);
proc_info->mem_fd = open(buffer, O_RDONLY);
if (proc_info->mem_fd == -1)
{
fclose(proc_info->maps);
proc_info->maps = NULL;
yr_free(proc_info);
return ERROR_COULD_NOT_ATTACH_TO_PROCESS;
}
if (ptrace(PTRACE_ATTACH, pid, NULL, 0) == -1)
{
fclose(proc_info->maps);
proc_info->maps = NULL;
close(proc_info->mem_fd);
proc_info->mem_fd = -1;
yr_free(proc_info);
return ERROR_COULD_NOT_ATTACH_TO_PROCESS;
}
status = 0;
if (waitpid(pid, &status, 0) == -1)
{
// this is a strange error state where we attached but the proc didn't
// stop. Try to detach and clean up.
ptrace(PTRACE_DETACH, proc_info->pid, NULL, 0);
fclose(proc_info->maps);
proc_info->maps = NULL;
close(proc_info->mem_fd);
proc_info->mem_fd = -1;
yr_free(proc_info);
return ERROR_COULD_NOT_ATTACH_TO_PROCESS;
}
return ERROR_SUCCESS;
}
int _yr_process_detach(
YR_PROC_ITERATOR_CTX* context)
{
YR_PROC_INFO* proc_info = (YR_PROC_INFO*)context->proc_info;
fclose(proc_info->maps);
close(proc_info->mem_fd);
ptrace(PTRACE_DETACH, proc_info->pid, NULL, 0);
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;
YR_PROC_INFO* proc_info = (YR_PROC_INFO*)context->proc_info;
if (context->buffer_size < block->size)
{
if (context->buffer != NULL)
yr_free((void*) context->buffer);
context->buffer = (const uint8_t*) yr_malloc(block->size);
if (context->buffer != NULL)
{
context->buffer_size = block->size;
}
else
{
context->buffer_size = 0;
return NULL;
}
}
if (pread(proc_info->mem_fd,
(void *) context->buffer,
block->size,
block->base) == -1)
{
return NULL;
}
return context->buffer;
}
YR_API YR_MEMORY_BLOCK* yr_process_get_next_memory_block(
YR_MEMORY_BLOCK_ITERATOR* iterator)
{
YR_PROC_ITERATOR_CTX* context = (YR_PROC_ITERATOR_CTX*) iterator->context;
YR_PROC_INFO* proc_info = (YR_PROC_INFO*)context->proc_info;
char buffer[256];
size_t begin, end;
if (fgets(buffer, sizeof(buffer), proc_info->maps) != NULL)
{
sscanf(buffer, "%zx-%zx", &begin, &end);
context->current_block.base = begin;
context->current_block.size = end - begin;
return &context->current_block;
}
return NULL;
}
YR_API YR_MEMORY_BLOCK* yr_process_get_first_memory_block(
YR_MEMORY_BLOCK_ITERATOR* iterator)
{
YR_PROC_ITERATOR_CTX* context = (YR_PROC_ITERATOR_CTX*) iterator->context;
YR_PROC_INFO* proc_info = (YR_PROC_INFO*)context->proc_info;
if (fseek(proc_info->maps, 0, SEEK_SET) != 0)
return NULL;
return yr_process_get_next_memory_block(iterator);
}
+167
View File
@@ -0,0 +1,167 @@
/*
Copyright (c) 2007-2017. The YARA Authors. All Rights Reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <mach/mach.h>
#include <mach/mach_vm.h>
#include <mach/vm_region.h>
#include <mach/vm_statistics.h>
#include <yara/mem.h>
#include <yara/proc.h>
#include <yara/error.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));
if (proc_info == NULL)
return ERROR_INSUFFICIENT_MEMORY;
kern_return_t kr = task_for_pid(mach_task_self(), pid, &proc_info->task);
if (kr != KERN_SUCCESS)
{
yr_free(proc_info);
return ERROR_COULD_NOT_ATTACH_TO_PROCESS;
}
context->proc_info = proc_info;
return ERROR_SUCCESS;
}
int _yr_process_detach(
YR_PROC_ITERATOR_CTX* context)
{
YR_PROC_INFO* proc_info = context->proc_info;
if (proc_info->task != MACH_PORT_NULL)
mach_port_deallocate(mach_task_self(), proc_info->task);
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;
YR_PROC_INFO* proc_info = context->proc_info;
vm_size_t size = block->size;
if (context->buffer_size < block->size)
{
if (context->buffer != NULL)
yr_free((void*) context->buffer);
context->buffer = (const uint8_t*) yr_malloc(block->size);
if (context->buffer != NULL)
{
context->buffer_size = block->size;
}
else
{
context->buffer_size = 0;
return NULL;
}
}
if (vm_read_overwrite(
proc_info->task,
block->base,
block->size,
(vm_address_t) context->buffer,
&size) != KERN_SUCCESS)
{
return NULL;
}
return context->buffer;
}
YR_API YR_MEMORY_BLOCK* yr_process_get_next_memory_block(
YR_MEMORY_BLOCK_ITERATOR* iterator)
{
YR_PROC_ITERATOR_CTX* context = (YR_PROC_ITERATOR_CTX*) iterator->context;
YR_PROC_INFO* proc_info = context->proc_info;
kern_return_t kr;
mach_msg_type_number_t info_count;
mach_port_t object;
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(
proc_info->task,
&address,
&size,
VM_REGION_BASIC_INFO,
(vm_region_info_t) &info,
&info_count,
&object);
if (kr == KERN_SUCCESS)
{
context->current_block.base = address;
context->current_block.size = size;
return &context->current_block;
}
} while (kr != KERN_INVALID_ADDRESS);
return NULL;
}
YR_API YR_MEMORY_BLOCK* yr_process_get_first_memory_block(
YR_MEMORY_BLOCK_ITERATOR* iterator)
{
YR_PROC_ITERATOR_CTX* context = (YR_PROC_ITERATOR_CTX*) iterator->context;
context->current_block.base = 0;
context->current_block.size = 0;
return yr_process_get_next_memory_block(iterator);
}
+62
View File
@@ -0,0 +1,62 @@
/*
Copyright (c) 2007-2017. The YARA Authors. All Rights Reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <yara/error.h>
#include <yara/proc.h>
int _yr_process_attach(
int pid,
YR_PROC_ITERATOR_CTX* context)
{
return ERROR_COULD_NOT_ATTACH_TO_PROCESS;
}
int _yr_process_detach(
YR_PROC_ITERATOR_CTX* context)
{
return ERROR_INVALID_ARGUMENT;
}
YR_API const uint8_t* yr_process_fetch_memory_block_data(
YR_MEMORY_BLOCK* block)
{
return ERROR_INVALID_ARGUMENT;
}
YR_API YR_MEMORY_BLOCK* yr_process_get_next_memory_block(
YR_MEMORY_BLOCK_ITERATOR* iterator)
{
return NULL;
}
YR_API YR_MEMORY_BLOCK* yr_process_get_first_memory_block(
YR_MEMORY_BLOCK_ITERATOR* iterator)
{
return NULL;
}
+181
View File
@@ -0,0 +1,181 @@
/*
Copyright (c) 2007-2017. The YARA Authors. All Rights Reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <windows.h>
#include <yara/mem.h>
#include <yara/error.h>
#include <yara/proc.h>
typedef struct _YR_PROC_INFO {
HANDLE hProcess;
SYSTEM_INFO si;
} YR_PROC_INFO;
int _yr_process_attach(
int pid,
YR_PROC_ITERATOR_CTX* context)
{
TOKEN_PRIVILEGES tokenPriv;
LUID luidDebug;
HANDLE hToken = NULL;
YR_PROC_INFO* proc_info = (YR_PROC_INFO*)yr_malloc(sizeof(YR_PROC_INFO));
if (proc_info == NULL)
return ERROR_INSUFFICIENT_MEMORY;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken) &&
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luidDebug))
{
tokenPriv.PrivilegeCount = 1;
tokenPriv.Privileges[0].Luid = luidDebug;
tokenPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(
hToken,
FALSE,
&tokenPriv,
sizeof(tokenPriv),
NULL,
NULL);
}
if (hToken != NULL)
CloseHandle(hToken);
proc_info->hProcess = OpenProcess(
PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
FALSE,
pid);
if (proc_info->hProcess == NULL)
{
yr_free(proc_info);
return ERROR_COULD_NOT_ATTACH_TO_PROCESS;
}
GetSystemInfo(&proc_info->si);
context->proc_info = proc_info;
return ERROR_SUCCESS;
}
int _yr_process_detach(
YR_PROC_ITERATOR_CTX* context)
{
YR_PROC_INFO* proc_info = (YR_PROC_INFO*)context->proc_info;
CloseHandle(proc_info->hProcess);
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;
YR_PROC_INFO* proc_info = (YR_PROC_INFO*)context->proc_info;
SIZE_T read;
if (context->buffer_size < block->size)
{
if (context->buffer != NULL)
yr_free((void*) context->buffer);
context->buffer = (const uint8_t*) yr_malloc(block->size);
if (context->buffer != NULL)
{
context->buffer_size = block->size;
}
else
{
context->buffer_size = 0;
return NULL;
}
}
if (ReadProcessMemory(
proc_info->hProcess,
(LPCVOID) block->base,
(LPVOID) context->buffer,
(SIZE_T) block->size,
&read) == FALSE)
{
return NULL;
}
return context->buffer;
}
YR_API YR_MEMORY_BLOCK* yr_process_get_next_memory_block(
YR_MEMORY_BLOCK_ITERATOR* iterator)
{
YR_PROC_ITERATOR_CTX* context = (YR_PROC_ITERATOR_CTX*) iterator->context;
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);
while (address < proc_info->si.lpMaximumApplicationAddress &&
VirtualQueryEx(proc_info->hProcess, address, &mbi, sizeof(mbi)) != 0)
{
if (GetLastError() != ERROR_SUCCESS)
break;
if (mbi.State == MEM_COMMIT && ((mbi.Protect & PAGE_NOACCESS) == 0))
{
context->current_block.base = (size_t) mbi.BaseAddress;
context->current_block.size = mbi.RegionSize;
return &context->current_block;
}
address = (uint8_t*) address + mbi.RegionSize;
}
return NULL;
}
YR_API YR_MEMORY_BLOCK* yr_process_get_first_memory_block(
YR_MEMORY_BLOCK_ITERATOR* iterator)
{
YR_PROC_ITERATOR_CTX* context = (YR_PROC_ITERATOR_CTX*) iterator->context;
YR_PROC_INFO* proc_info = (YR_PROC_INFO*)context->proc_info;
context->current_block.base = (size_t) proc_info->si.lpMinimumApplicationAddress;
context->current_block.size = 0;
return yr_process_get_next_memory_block(iterator);
}
+1
View File
@@ -210,6 +210,7 @@
<ClCompile Include="..\..\..\libyara\object.c" />
<ClCompile Include="..\..\..\libyara\parser.c" />
<ClCompile Include="..\..\..\libyara\proc.c" />
<ClCompile Include="..\..\..\libyara\proc_windows.c" />
<ClCompile Include="..\..\..\libyara\re.c" />
<ClCompile Include="..\..\..\libyara\re_grammar.c" />
<ClCompile Include="..\..\..\libyara\re_lexer.c" />