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 }