diff --git a/c/meterpreter/source/extensions/stdapi/server/sys/process/memory.c b/c/meterpreter/source/extensions/stdapi/server/sys/process/memory.c
index 4d2eef43..e592dd4c 100644
--- a/c/meterpreter/source/extensions/stdapi/server/sys/process/memory.c
+++ b/c/meterpreter/source/extensions/stdapi/server/sys/process/memory.c
@@ -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
///
/// 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.
///
-/// The packet to insert the needle goup into
+/// The packet to insert the needle group into
/// ERROR_SUCCESS on success, else non-zero
-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;
-}
-
-///
-/// Compile a regular expression in-place.
-///
-/// A pointer to a regular expression needle struct.
-/// ERROR_SUCCESS on success, ERROR_INVALID_PARAMETER when provided with a null pointer or the regular expression failed to compile
-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;
-}
-
-///
-/// Sets up a regular expression needle from a TLV.
-///
-/// - Pointer to the needle TLV received from the server containing the needle buffer
-/// - The compiled needle
-/// ERROR_SUCCESS on success, non-zero on failure
-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, ®ex_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)®ex_needles[needle_enum_index].compiled_regex, (unsigned char*)®ex_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)®ex_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(®ex_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;
diff --git a/c/meterpreter/source/tiny-regex-c/re.c b/c/meterpreter/source/tiny-regex-c/re.c
index b5fd887c..4c13e11a 100644
--- a/c/meterpreter/source/tiny-regex-c/re.c
+++ b/c/meterpreter/source/tiny-regex-c/re.c
@@ -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 = ®ex_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)
diff --git a/c/meterpreter/source/tiny-regex-c/re.h b/c/meterpreter/source/tiny-regex-c/re.h
index 45b8cdf1..28956d26 100644
--- a/c/meterpreter/source/tiny-regex-c/re.h
+++ b/c/meterpreter/source/tiny-regex-c/re.h
@@ -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
}