Move defs to top of file, remove pointer-to-pointer, make RegexNeedle contain static-size arrays

This commit is contained in:
sjanusz-r7 2023-12-08 18:32:47 +00:00
parent 72b39289d0
commit 8f51ee7e6d
3 changed files with 155 additions and 255 deletions

View File

@ -2,6 +2,89 @@
#include "common_metapi.h"
#include "../tiny-regex-c/re.h"
#ifndef __kernel_entry
#define __kernel_entry
#endif
typedef __kernel_entry NTSTATUS(WINAPI* NTQUERYINFORMATIONPROCESS) (HANDLE ProcessHandle, DWORD ProcessInformationClass, LPVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength);
typedef SIZE_T(WINAPI* VIRTUALQUERYEX) (HANDLE hProcess, LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength);
typedef BOOL(WINAPI* CLOSEHANDLE) (HANDLE hObject);
typedef HANDLE(WINAPI* OPENPROCESS) (DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId);
typedef FARPROC(WINAPI* GETPROCADDRESS) (HMODULE hModule, LPCSTR lpProcName);
// http://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FMemory%20Management%2FVirtual%20Memory%2FNtReadVirtualMemory.html
// https://ntdoc.m417z.com/ntreadvirtualmemory
typedef NTSTATUS(NTAPI* NTREADVIRTUALMEMORY) (HANDLE ProcessHandle, LPCVOID BaseAddress, LPVOID Buffer, SIZE_T NumberOfBytesToRead, PSIZE_T NumberOfBytesRead);
// http://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FMemory%20Management%2FVirtual%20Memory%2FMEMORY_INFORMATION_CLASS.html
typedef enum _MEMORY_INFORMATION_CLASS {
MemoryBasicInformation
} MEMORY_INFORMATION_CLASS, * PMEMORY_INFORMATION_CLASS;
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING;
typedef UNICODE_STRING* PUNICODE_STRING;
typedef const UNICODE_STRING* PCUNICODE_STRING;
// https://learn.microsoft.com/en-us/windows/win32/api/ntdef/ns-ntdef-_object_attributes
typedef struct _OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES;
typedef struct _RTL_USER_PROCESS_PARAMETERS {
BYTE Reserved1[16];
PVOID Reserved2[10];
UNICODE_STRING ImagePathName;
UNICODE_STRING CommandLine;
} RTL_USER_PROCESS_PARAMETERS, * PRTL_USER_PROCESS_PARAMETERS;
typedef
VOID
(NTAPI* PPS_POST_PROCESS_INIT_ROUTINE) (
VOID
);
typedef struct _PEB {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[1];
PVOID Reserved3[2];
PPEB_LDR_DATA Ldr;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
BYTE Reserved4[104];
PVOID Reserved5[52];
PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
BYTE Reserved6[128];
PVOID Reserved7[1];
ULONG SessionId;
} PEB, * PPEB;
typedef struct _PROCESS_BASIC_INFORMATION {
PVOID Reserved1;
PPEB PebBaseAddress;
PVOID Reserved2[2];
ULONG_PTR UniqueProcessId;
PVOID Reserved3;
} PROCESS_BASIC_INFORMATION;
typedef PROCESS_BASIC_INFORMATION* PPROCESS_BASIC_INFORMATION;
typedef enum _PROCESSINFOCLASS {
ProcessBasicInformation = 0,
ProcessWow64Information = 26
} PROCESSINFOCLASS;
/*!
* @brief Allocates memory in the context of the supplied process.
* @remark The
@ -341,89 +424,6 @@ DWORD request_sys_process_memory_unlock(Remote *remote, Packet *packet)
return ERROR_SUCCESS;
}
#ifndef __kernel_entry
#define __kernel_entry
#endif
typedef __kernel_entry NTSTATUS(WINAPI* NTQUERYINFORMATIONPROCESS) (HANDLE ProcessHandle, DWORD ProcessInformationClass, LPVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength);
typedef SIZE_T(WINAPI* VIRTUALQUERYEX) (HANDLE hProcess, LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength);
typedef BOOL(WINAPI* CLOSEHANDLE) (HANDLE hObject);
typedef HANDLE(WINAPI* OPENPROCESS) (DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId);
typedef FARPROC(WINAPI* GETPROCADDRESS) (HMODULE hModule, LPCSTR lpProcName);
// http://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FMemory%20Management%2FVirtual%20Memory%2FNtReadVirtualMemory.html
// https://ntdoc.m417z.com/ntreadvirtualmemory
typedef NTSTATUS(NTAPI* NTREADVIRTUALMEMORY) (HANDLE ProcessHandle, LPCVOID BaseAddress, LPVOID Buffer, SIZE_T NumberOfBytesToRead, PSIZE_T NumberOfBytesRead);
// http://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FMemory%20Management%2FVirtual%20Memory%2FMEMORY_INFORMATION_CLASS.html
typedef enum _MEMORY_INFORMATION_CLASS {
MemoryBasicInformation
} MEMORY_INFORMATION_CLASS, * PMEMORY_INFORMATION_CLASS;
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING;
typedef UNICODE_STRING* PUNICODE_STRING;
typedef const UNICODE_STRING* PCUNICODE_STRING;
// https://learn.microsoft.com/en-us/windows/win32/api/ntdef/ns-ntdef-_object_attributes
typedef struct _OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES;
typedef struct _RTL_USER_PROCESS_PARAMETERS {
BYTE Reserved1[16];
PVOID Reserved2[10];
UNICODE_STRING ImagePathName;
UNICODE_STRING CommandLine;
} RTL_USER_PROCESS_PARAMETERS, * PRTL_USER_PROCESS_PARAMETERS;
typedef
VOID
(NTAPI* PPS_POST_PROCESS_INIT_ROUTINE) (
VOID
);
typedef struct _PEB {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[1];
PVOID Reserved3[2];
PPEB_LDR_DATA Ldr;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
BYTE Reserved4[104];
PVOID Reserved5[52];
PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
BYTE Reserved6[128];
PVOID Reserved7[1];
ULONG SessionId;
} PEB, * PPEB;
typedef struct _PROCESS_BASIC_INFORMATION {
PVOID Reserved1;
PPEB PebBaseAddress;
PVOID Reserved2[2];
ULONG_PTR UniqueProcessId;
PVOID Reserved3;
} PROCESS_BASIC_INFORMATION;
typedef PROCESS_BASIC_INFORMATION* PPROCESS_BASIC_INFORMATION;
typedef enum _PROCESSINFOCLASS {
ProcessBasicInformation = 0,
ProcessWow64Information = 26
} PROCESSINFOCLASS;
BOOL can_read_memory(DWORD memory_protect)
{
const int page_execute_read = 0x20;
@ -437,14 +437,10 @@ BOOL can_read_memory(DWORD memory_protect)
memory_protect == page_readwrite;
}
// In order to be able to regex null-butes, we need to store the length explicitly, so that null-bytes aren't being treated as the end of a string.
struct regex_needle
{
char* raw_needle_buffer;
size_t length;
regex_t* compiled_needle;
unsigned char* char_buf;
};
typedef struct {
re_t compiled_regex[MAX_REGEXP_OBJECTS];
unsigned char buffer[MAX_CHAR_CLASS_LEN]; // Used for character strings when "[]" is used.
} RegexNeedle;
#define NEEDLES_MAX (size_t)5
#define MEMORY_BUFFER_SIZE (size_t)(64 * 1024 * 1024)
@ -452,116 +448,25 @@ struct regex_needle
/// <summary>
/// Add the needle results to a packet. This automatically inserts each result into a new group. Returns ERROR_SUCCESS on success, or 1 on failure.
/// </summary>
/// <param name="out">The packet to insert the needle goup into</param>
/// <param name="packet">The packet to insert the needle group into</param>
/// <returns>ERROR_SUCCESS on success, else non-zero</returns>
NTSTATUS add_needle_results_to_packet(Packet** out, const char* memory_buffer_ptr, size_t match_length, size_t match_address, size_t memory_base_address, size_t memory_region_size)
NTSTATUS add_needle_results_to_packet(Packet* packet, const unsigned char* memory_buffer_ptr, size_t match_length, size_t match_address, size_t memory_base_address, size_t memory_region_size)
{
if (out == NULL || memory_buffer_ptr == NULL) { return ERROR_INVALID_PARAMETER; }
if (packet == NULL || memory_buffer_ptr == NULL) { return ERROR_INVALID_PARAMETER; }
dprintf("[MEM SEARCH] Creating results group");
Packet* search_results = met_api->packet.create_group();
if (search_results == NULL) { dprintf("[MEM SEARCH] Could not create search result group"); return ERROR_OUTOFMEMORY; }
dprintf("[MEM SEARCH] Adding results to packet group");
dprintf("[MEM SEARCH] Adding Match bytes");
// Note: This raw data needs to be read from the buffer we copied. Trying to read it from mem.BaseAddress directly will make us crash.
met_api->packet.add_tlv_raw(search_results, TLV_TYPE_MEMORY_SEARCH_MATCH_STR, (LPVOID)memory_buffer_ptr, (DWORD)match_length + 1);
dprintf("[MEM SEARCH] Adding Match address");
met_api->packet.add_tlv_qword(search_results, TLV_TYPE_MEMORY_SEARCH_MATCH_ADDR, match_address);
dprintf("[MEM SEARCH] Adding Region base address");
met_api->packet.add_tlv_qword(search_results, TLV_TYPE_MEMORY_SEARCH_START_ADDR, memory_base_address);
dprintf("[MEM SEARCH] Adding Region size");
met_api->packet.add_tlv_qword(search_results, TLV_TYPE_MEMORY_SEARCH_SECT_LEN, memory_region_size);
dprintf("[MEM SEARCH] Adding Match Length");
met_api->packet.add_tlv_uint(search_results, TLV_TYPE_MEMORY_SEARCH_MATCH_LEN, (UINT)match_length);
dprintf("[MEM SEARCH] Adding Group");
met_api->packet.add_group(*out, TLV_TYPE_MEMORY_SEARCH_RESULTS, search_results);
return ERROR_SUCCESS;
}
/// <summary>
/// Compile a regular expression in-place.
/// </summary>
/// <param name="in_out">A pointer to a regular expression needle struct.</param>
/// <returns>ERROR_SUCCESS on success, ERROR_INVALID_PARAMETER when provided with a null pointer or the regular expression failed to compile</returns>
NTSTATUS re_compile_inplace(struct regex_needle** in_out)
{
if (in_out == NULL) { return ERROR_INVALID_PARAMETER; }
const int compile_result = re_compile((*in_out)->raw_needle_buffer, (*in_out)->length, MAX_REGEXP_OBJECTS, MAX_CHAR_CLASS_LEN, &(*in_out)->compiled_needle, &(*in_out)->char_buf);
if (compile_result != ERROR_SUCCESS) { return ERROR_INVALID_PARAMETER; }
return ERROR_SUCCESS;
}
/// <summary>
/// Sets up a regular expression needle from a TLV.
/// </summary>
/// <param name="needle_buffer_tlv">- Pointer to the needle TLV received from the server containing the needle buffer</param>
/// <param name="out">- The compiled needle</param>
/// <returns>ERROR_SUCCESS on success, non-zero on failure</returns>
NTSTATUS setup_needle_from_tlv(const Tlv* needle_buffer_tlv, struct regex_needle** out)
{
// The header contains a null-terminator which we do not need.
dprintf("[MEM SEARCH] Getting needle length");
const size_t needle_length = needle_buffer_tlv->header.length - 1;
if (needle_length == 0) { dprintf("[MEM SEARCH] Got a needle length of 0"); return ERROR_INVALID_PARAMETER; }
(*out)->length = needle_length;
dprintf("[MEM SEARCH] Allocating memory for needle buffer");
(*out)->raw_needle_buffer = (char*)malloc(needle_length * sizeof(char));
if ((*out)->raw_needle_buffer == NULL) { dprintf("[MEM SEARCH] Could not allocate memory for raw needle buffer"); return ERROR_OUTOFMEMORY; }
dprintf("[MEM SEARCH] Copying TLV buffer to needle");
memcpy((*out)->raw_needle_buffer, (char*)needle_buffer_tlv->buffer, needle_length);
dprintf("[MEM SEARCH] Allocating memory for a compiled needle");
(*out)->compiled_needle = (regex_t*)malloc(MAX_REGEXP_OBJECTS * sizeof(struct regex_t));
if ((*out)->compiled_needle == NULL) { dprintf("[MEM SEARCH] Unable to malloc memory for a compiled needle"); return ERROR_OUTOFMEMORY; }
dprintf("[MEM SEARCH] Allocating memory for a char buffer");
(*out)->char_buf = (unsigned char*)malloc(MAX_CHAR_CLASS_LEN * sizeof(unsigned char));
if ((*out)->char_buf == NULL) { dprintf("[MEM SEARCH] Unable to malloc memory for a char buffer"); return ERROR_OUTOFMEMORY; }
dprintf("[MEM SEARCH] Compiling needle: %.*s", needle_length, (char*)needle_buffer_tlv->buffer);
const NTSTATUS compile_result = re_compile_inplace(&(*out));
if (compile_result != ERROR_SUCCESS)
{ dprintf("[MEM SEARCH] Failed to compile needle"); return ERROR_INVALID_PARAMETER; }
return ERROR_SUCCESS;
}
NTSTATUS cleanup_needle(struct regex_needle** in)
{
if (in == NULL || *in == NULL) { return ERROR_INVALID_PARAMETER; }
if ((*in)->raw_needle_buffer != NULL)
{
dprintf("[MEM SEARCH] Freeing needle buffer");
free((*in)->raw_needle_buffer);
}
if ((*in)->char_buf != NULL)
{
dprintf("[MEM SEARCH] Freeing char buf");
free((*in)->char_buf);
}
if ((*in)->compiled_needle != NULL)
{
dprintf("[MEM SEARCH] Freeing compiled needle");
free((*in)->compiled_needle);
}
dprintf("[MEM SEARCH] Freeing regex needle.");
free((*in));
met_api->packet.add_group(packet, TLV_TYPE_MEMORY_SEARCH_RESULTS, search_results);
return ERROR_SUCCESS;
}
@ -575,7 +480,7 @@ static CLOSEHANDLE fCloseHandle = NULL;
static VIRTUALQUERYEX fVirtualQueryEx = NULL;
static NTREADVIRTUALMEMORY fNtReadVirtualMemory = NULL;
BOOL setup_handles()
NTSTATUS setup_handles()
{
if ((hKernel32 = GetModuleHandleA("kernel32.dll")) == NULL) { dprintf("[MEM SEARCH] Could not get kernel32.dll handle"); return ERROR_INVALID_HANDLE; }
@ -606,29 +511,24 @@ DWORD request_sys_process_memory_search(Remote* remote, Packet* packet)
{
Packet* response = met_api->packet.create_response(packet);
DWORD result = ERROR_SUCCESS;
char* buffer = NULL;
unsigned char* memory_buffer = NULL;
size_t needle_enum_index = 0;
HANDLE process_handle = NULL;
struct regex_needle* regex_needles[NEEDLES_MAX];
RegexNeedle regex_needles[NEEDLES_MAX] = { NULL };
dprintf("[MEM SEARCH] Getting PID");
const DWORD pid = met_api->packet.get_tlv_value_uint(packet, TLV_TYPE_PID);
if (pid == 0) { result = ERROR_INVALID_PARAMETER; goto done; }
dprintf("[MEM SEARCH] Searching PID: %lu", pid);
Tlv needle_buffer_tlv = { 0 };
while (needle_enum_index < NEEDLES_MAX && met_api->packet.enum_tlv(packet, (DWORD)needle_enum_index, TLV_TYPE_MEMORY_SEARCH_NEEDLE, &needle_buffer_tlv) == ERROR_SUCCESS)
Tlv needle_tlv = { 0 };
while (needle_enum_index < NEEDLES_MAX && met_api->packet.enum_tlv(packet, (DWORD)needle_enum_index, TLV_TYPE_MEMORY_SEARCH_NEEDLE, &needle_tlv) == ERROR_SUCCESS)
{
dprintf("[MEM SEARCH] Allocating %u bytes of memory for regex needle", sizeof(struct regex_needle));
regex_needles[needle_enum_index] = (struct regex_needle*)malloc(sizeof(struct regex_needle));
if (regex_needles[needle_enum_index] == NULL) { dprintf("[MEM SEARCH] Could not allocate memory for regex needle"); result = ERROR_OUTOFMEMORY; goto done; }
dprintf("[MEM SEARCH] Setting up needle from TLV");
const NTSTATUS needle_setup_result = setup_needle_from_tlv(&needle_buffer_tlv, &regex_needles[needle_enum_index]);
if (needle_setup_result != ERROR_SUCCESS)
dprintf("[MEM SEARCH] Compiling needle regex from TLV");
const int result = re_compile(needle_tlv.buffer, needle_tlv.header.length - 1, (re_t)&regex_needles[needle_enum_index].compiled_regex, (unsigned char*)&regex_needles[needle_enum_index].buffer);
if (result != ERROR_SUCCESS)
{
dprintf("[MEM SEARCH] Failed to setup needle from TLV packet");
result = needle_setup_result;
dprintf("[MEM SEARCH] Failed to setup compile needle regex from TLV packet");
goto done;
}
@ -642,8 +542,11 @@ DWORD request_sys_process_memory_search(Remote* remote, Packet* packet)
const size_t current_max_match_length = max_match_length;
dprintf("[MEM SEARCH] Getting handles & proc addresses");
const NTSTATUS setup_handles_result = setup_handles();
if (setup_handles_result != ERROR_SUCCESS) { dprintf("[MEM SEARCH] Could not set up all necessary handles & proc addresses"); result = setup_handles_result; goto done; }
if ((result = setup_handles()) != ERROR_SUCCESS)
{
dprintf("[MEM SEARCH] Could not set up all necessary handles & proc addresses");
goto done;
}
const DWORD process_vm_read = 0x0010;
const DWORD process_query_information = 0x0400;
@ -655,8 +558,8 @@ DWORD request_sys_process_memory_search(Remote* remote, Packet* packet)
MEMORY_BASIC_INFORMATION mem = { 0 };
dprintf("[MEM SEARCH] Allocating buffer for storing process memory");
buffer = (char*)malloc(MEMORY_BUFFER_SIZE);
if (buffer == NULL) { dprintf("[MEM SEARCH] Could not allocate memory buffer"); result = ERROR_OUTOFMEMORY; goto done; }
memory_buffer = (unsigned char*)malloc(MEMORY_BUFFER_SIZE * sizeof(unsigned char));
if (memory_buffer == NULL) { dprintf("[MEM SEARCH] Could not allocate memory buffer"); result = ERROR_OUTOFMEMORY; goto done; }
for (size_t current_ptr = 0; fVirtualQueryEx(process_handle, (LPCVOID)current_ptr, &mem, sizeof(mem)); current_ptr += mem.RegionSize)
{
@ -670,15 +573,19 @@ DWORD request_sys_process_memory_search(Remote* remote, Packet* packet)
while (mem.RegionSize > memory_region_offset)
{
const size_t leftover_bytes = mem.RegionSize - memory_region_offset;
const size_t bytes_to_read = min(leftover_bytes, MEMORY_BUFFER_SIZE);
const size_t bytes_to_read = min(leftover_bytes, MEMORY_BUFFER_SIZE * sizeof(unsigned char));
dprintf("[MEM SEARCH] Leftover Bytes count: %llu", leftover_bytes);
dprintf("[MEM SEARCH] Bytes to read: %llu", bytes_to_read);
size_t bytes_read = 0;
const size_t read_address = (size_t)mem.BaseAddress + memory_region_offset;
// Note: This will read up to a maximum of bytes_to_read OR to the end of the memory region if the end of it has been reached.
const NTSTATUS read_virtual_memory_status = fNtReadVirtualMemory(process_handle, (LPCVOID)read_address, buffer, bytes_to_read, &bytes_read);
if (read_virtual_memory_status != ERROR_SUCCESS) { dprintf("[MEM SEARCH] Failed to read some virtual memory for process, skipping %u bytes", bytes_to_read); memory_region_offset += bytes_to_read; continue; }
if (fNtReadVirtualMemory(process_handle, (LPCVOID)read_address, memory_buffer, bytes_to_read, &bytes_read) != ERROR_SUCCESS)
{
dprintf("[MEM SEARCH] Failed to read some virtual memory for process, skipping %u bytes", bytes_to_read);
memory_region_offset += bytes_to_read;
continue;
}
dprintf("[MEM SEARCH] Read %llu bytes", bytes_read);
// Note: Increment the offset so that we aren't stuck in an infinite loop, trying to read zero bytes from the same pointer.
@ -692,10 +599,10 @@ DWORD request_sys_process_memory_search(Remote* remote, Packet* packet)
do
{
const char* current_buffer_ptr = buffer + current_buffer_offset;
const unsigned char* current_buffer_ptr = memory_buffer + current_buffer_offset;
const size_t bytes_to_regex = bytes_read - current_buffer_offset;
result = re_matchp(regex_needles[current_needle_index]->compiled_needle, current_buffer_ptr, bytes_to_regex, &match_length);
result = re_matchp((re_t)&regex_needles[current_needle_index].compiled_regex, current_buffer_ptr, bytes_to_regex, &match_length);
if (result != -1)
{
@ -712,9 +619,11 @@ DWORD request_sys_process_memory_search(Remote* remote, Packet* packet)
// TODO: Add a workaround for match length to the regex itself, allowing the regex engine to stop matching once an upper limit has been reached.
const size_t current_match_length = min(max_match_length, match_length);
const char* memory_buffer_ptr = buffer + current_buffer_offset + result;
const NTSTATUS add_needles_result = add_needle_results_to_packet(&response, memory_buffer_ptr, current_match_length, match_address, (size_t)mem.BaseAddress, mem.RegionSize);
if (add_needles_result != ERROR_SUCCESS) { dprintf("[MEM SEARCH] Adding search results to packet was not successful"); }
const unsigned char* memory_buffer_ptr = memory_buffer + current_buffer_offset + result;
if (add_needle_results_to_packet(response, memory_buffer_ptr, current_match_length, match_address, (size_t)mem.BaseAddress, mem.RegionSize) != ERROR_SUCCESS)
{
dprintf("[MEM SEARCH] Adding search results to packet was not successful");
}
current_buffer_offset += (result + current_match_length);
}
@ -731,16 +640,9 @@ DWORD request_sys_process_memory_search(Remote* remote, Packet* packet)
done:
dprintf("[MEM SEARCH] Memory Search complete.");
if (buffer != NULL) { dprintf("[MEM SEARCH] Freeing process memory buffer."); free(buffer); }
if (memory_buffer != NULL) { dprintf("[MEM SEARCH] Freeing process memory buffer."); free(memory_buffer); }
if (process_handle != NULL) { dprintf("[MEM SEARCH] Closing process handle."); fCloseHandle(process_handle); }
dprintf("[MEM SEARCH] Cleaning up needles");
for (size_t i = 0; i < needle_enum_index; i++)
{
const NTSTATUS cleanup_result = cleanup_needle(&regex_needles[i]);
if (cleanup_result == ERROR_INVALID_PARAMETER) { dprintf("[MEM SEARCH] Could not clean up needle"); }
}
dprintf("[MEM SEARCH] Transmitting response");
met_api->packet.transmit_response(result, remote, response);
return ERROR_SUCCESS;

View File

@ -62,7 +62,7 @@ int re_matchp(re_t pattern, const char* text, size_t text_length, size_t* matchl
return ((matchpattern(&pattern[1], text, text_length, 0, matchlength)) ? 0 : -1);
}
size_t idx = -1;
int idx = -1;
do
{
@ -70,18 +70,16 @@ int re_matchp(re_t pattern, const char* text, size_t text_length, size_t* matchl
if (matchpattern(pattern, text, text_length, idx, matchlength))
{
return (int)idx;
return idx;
}
}
while (idx < text_length);
while ((size_t)idx < text_length);
return -1;
}
int re_compile(const char* pattern, size_t pattern_length, size_t max_regex_objects, size_t max_char_class_len, re_t* out_compiled, unsigned char** out_ccl)
int re_compile(const char* pattern, size_t pattern_length, re_t compiled_regex, unsigned char* regex_char_buffer)
{
if (out_compiled == NULL || out_ccl == NULL) { return 1; }
int ccl_bufidx = 1;
char c; /* current char in pattern */
@ -95,13 +93,13 @@ int re_compile(const char* pattern, size_t pattern_length, size_t max_regex_obje
switch (c)
{
/* Meta-characters: */
case '^': { (*out_compiled)[j].type = BEGIN; } break;
case '$': { (*out_compiled)[j].type = END; } break;
case '.': { (*out_compiled)[j].type = DOT; } break;
case '*': { (*out_compiled)[j].type = STAR; } break;
case '+': { (*out_compiled)[j].type = PLUS; } break;
case '?': { (*out_compiled)[j].type = QUESTIONMARK; } break;
/* case '|': { re_compiled[j].type = BRANCH; } break; <-- not working properly */
case '^': { compiled_regex[j].type = BEGIN; } break;
case '$': { compiled_regex[j].type = END; } break;
case '.': { compiled_regex[j].type = DOT; } break;
case '*': { compiled_regex[j].type = STAR; } break;
case '+': { compiled_regex[j].type = PLUS; } break;
case '?': { compiled_regex[j].type = QUESTIONMARK; } break;
/* case '|': { compiled_regex[j].type = BRANCH; } break; <-- not working properly */
/* Escaped character-classes (\s \w ...): */
case '\\':
@ -114,25 +112,25 @@ int re_compile(const char* pattern, size_t pattern_length, size_t max_regex_obje
switch (pattern[i])
{
/* Meta-character: */
case 'd': { (*out_compiled)[j].type = DIGIT; } break;
case 'D': { (*out_compiled)[j].type = NOT_DIGIT; } break;
case 'w': { (*out_compiled)[j].type = ALPHA; } break;
case 'W': { (*out_compiled)[j].type = NOT_ALPHA; } break;
case 's': { (*out_compiled)[j].type = WHITESPACE; } break;
case 'S': { (*out_compiled)[j].type = NOT_WHITESPACE; } break;
case 'd': { compiled_regex[j].type = DIGIT; } break;
case 'D': { compiled_regex[j].type = NOT_DIGIT; } break;
case 'w': { compiled_regex[j].type = ALPHA; } break;
case 'W': { compiled_regex[j].type = NOT_ALPHA; } break;
case 's': { compiled_regex[j].type = WHITESPACE; } break;
case 'S': { compiled_regex[j].type = NOT_WHITESPACE; } break;
/* Escaped character, e.g. '.' or '$' */
default:
{
(*out_compiled)[j].type = CHAR_RE;
(*out_compiled)[j].u.ch = pattern[i];
compiled_regex[j].type = CHAR_RE;
compiled_regex[j].u.ch = pattern[i];
} break;
}
}
else
{
(*out_compiled)[j].type = CHAR_RE;
(*out_compiled)[j].u.ch = pattern[i];
compiled_regex[j].type = CHAR_RE;
compiled_regex[j].u.ch = pattern[i];
}
} break;
@ -145,7 +143,7 @@ int re_compile(const char* pattern, size_t pattern_length, size_t max_regex_obje
/* Look-ahead to determine if negated */
if (pattern[i + 1] == '^')
{
(*out_compiled)[j].type = INV_CHAR_CLASS;
compiled_regex[j].type = INV_CHAR_CLASS;
i += 1; /* Increment i to avoid including '^' in the char-buffer */
if (i + 1 == (int)pattern_length) /* incomplete pattern, missing non-zero char after '^' */
{
@ -154,7 +152,7 @@ int re_compile(const char* pattern, size_t pattern_length, size_t max_regex_obje
}
else
{
(*out_compiled)[j].type = CHAR_CLASS;
compiled_regex[j].type = CHAR_CLASS;
}
/* Copy characters inside [..] to buffer */
@ -172,14 +170,14 @@ int re_compile(const char* pattern, size_t pattern_length, size_t max_regex_obje
{
return 1;
}
(*out_ccl)[ccl_bufidx++] = pattern[i++];
regex_char_buffer[ccl_bufidx++] = pattern[i++];
}
else if (ccl_bufidx >= MAX_CHAR_CLASS_LEN)
{
//fputs("exceeded internal buffer!\n", stderr);
return 1;
}
(*out_ccl)[ccl_bufidx++] = pattern[i];
regex_char_buffer[ccl_bufidx++] = pattern[i];
}
if (ccl_bufidx >= MAX_CHAR_CLASS_LEN)
{
@ -188,15 +186,15 @@ int re_compile(const char* pattern, size_t pattern_length, size_t max_regex_obje
return 1;
}
/* Null-terminate string end */
(*out_ccl)[ccl_bufidx++] = 0;
(*out_compiled)[j].u.ccl = &(*out_ccl)[buf_begin];
regex_char_buffer[ccl_bufidx++] = 0;
compiled_regex[j].u.ccl = &regex_char_buffer[buf_begin];
} break;
/* Other characters: */
default:
{
(*out_compiled)[j].type = CHAR_RE;
(*out_compiled)[j].u.ch = c;
compiled_regex[j].type = CHAR_RE;
compiled_regex[j].u.ch = c;
} break;
}
@ -204,7 +202,7 @@ int re_compile(const char* pattern, size_t pattern_length, size_t max_regex_obje
j += 1;
}
/* 'UNUSED' is a sentinel used to indicate end-of-pattern */
(*out_compiled)[j].type = UNUSED;
compiled_regex[j].type = UNUSED;
return 0; // ERROR_SUCCESS
}
@ -364,7 +362,7 @@ static int matchstar(regex_t p, regex_t* pattern, const char* text, size_t text_
const char* prepoint = text;
while ((text_offset < text_length) && matchone(p, text[text_offset]))
{
text_offset++;
text_offset++;
(*matchlength)++;
}
while (&text[text_offset] >= prepoint)
@ -383,7 +381,7 @@ static int matchplus(regex_t p, regex_t* pattern, const char* text, size_t text_
const char* prepoint = text;
while ((text_offset < text_length) && matchone(p, text[text_offset]))
{
text_offset++;
text_offset++;
(*matchlength)++;
}
while (text > prepoint)

View File

@ -62,7 +62,7 @@ typedef struct regex_t* re_t;
int re_matchp(re_t pattern, const char* text, size_t text_length, size_t* matchlength);
/* Compile a regular expression in-place, allowing for multiple needles to be compiled without the usage of a static buffer. Returns ERROR_SUCCESS (0) on success, else 1. */
int re_compile(const char* pattern, size_t pattern_length, size_t max_regex_objects, size_t max_char_class_len, re_t* out_compiled, unsigned char** out_ccl);
int re_compile(const char* pattern, size_t pattern_length, re_t compiled_regex, unsigned char* regex_char_buffer);
#ifdef __cplusplus
}