-
Notifications
You must be signed in to change notification settings - Fork 675
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Windows Memory Search support using regex #686
Add Windows Memory Search support using regex #686
Conversation
Looks like there's multiple warnings/errors on the mingw build |
regex_t* compiled_needle; | ||
}; | ||
|
||
#define NEEDLES_MAX (size_t)5 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this limit enforced in Metasploit/mettle somewhere? It seems a bit arbitrary 👀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's being used in Mettle: https://github.com/rapid7/mettle/blob/a2f3c756ea84f07b80d64ff815cfec2b2e6d27e3/mettle/src/stdapi/sys/memory.c#L15 👍
c/meterpreter/source/extensions/stdapi/server/sys/process/memory.c
Outdated
Show resolved
Hide resolved
if (buffer == NULL) { dprintf("[MEM SEARCH] Could not allocate memory buffer"); result = ERROR_OUTOFMEMORY; goto done; } | ||
|
||
// The maximum length of data that we can read into a buffer at a time from a memory region. | ||
const size_t current_max_size = megabytes_64; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this an arbitrary value, or does it come from somewhere as a recommended value, i.e. Microsoft docs etc?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its an arbitrary value. Microsoft doesn't mention any recommended values here, and I thought 64 MB was a suitable value. I'm not opposed to reducing this value 🚀
c/meterpreter/source/extensions/stdapi/server/sys/process/memory.c
Outdated
Show resolved
Hide resolved
c/meterpreter/source/extensions/stdapi/server/sys/process/memory.c
Outdated
Show resolved
Hide resolved
217c51f
to
e588bad
Compare
5c0c8b7
to
e3dc185
Compare
…'ing CHAR, correctly free compiled needle and associated buffer
… contain static-size arrays
e3dc185
to
92d04de
Compare
static HMODULE hKernel32 = NULL; | ||
static HMODULE hNTDLL = NULL; | ||
|
||
static GETPROCADDRESS fGetProcAddress = NULL; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do these need to be global statics? I think the windows dispatcher is threaded for process handling, so I wonder if this approach would introduce quirks versus just using local variables on the stack 👀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sync'd up with @sjanusz-r7 and this pattern is from:
metasploit-payloads/c/meterpreter/source/extensions/extapi/clipboard.c
Lines 123 to 136 in 1731613
static PCLOSECLIPBOARD pCloseClipboard = NULL; | |
static PCLOSEHANDLE pCloseHandle = NULL; | |
static PCREATEFILEA pCreateFileA = NULL; | |
static PDRAGQUERYFILEA pDragQueryFileA = NULL; | |
static PEMPTYCLIPBOARD pEmptyClipboard = NULL; | |
static PENUMCLIPBOARDFORMATS pEnumClipboardFormats = NULL; | |
static PGETCLIPBOARDDATA pGetClipboardData = NULL; | |
static PGETFILESIZEEX pGetFileSizeEx = NULL; | |
static PGLOBALALLOC pGlobalAlloc = NULL; | |
static PGLOBALFREE pGlobalFree = NULL; | |
static PGLOBALLOCK pGlobalLock = NULL; | |
static PGLOBALUNLOCK pGlobalUnlock = NULL; | |
static POPENCLIPBOARD pOpenClipboard = NULL; | |
static PSETCLIPBOARDDATA pSetClipboardData = NULL; |
This PR adds in the ability to search Windows process memory for needles. These needles are searched for using regex, provided by the tiny-regex-c library. This library has been modified to match an arbitrary length of bytes (null-bytes included). This was necessary so that we do not treat null-bytes as the end of a string/buffer, and continue trying to match the regular expression.
Example Usage
I went through the following steps:
data
directory into the VM as a share with write permissions.cp -rf ./output/* /z/meterpreter && ~/Desktop/met.exe
to copy the debug dll files to Framework. met.exe is a symlink to a Framework-generated Meterpreter payload.setg MeterpreterDebugBuild true
sessions -i -1
irb
Now we can define our memory search function that we will use for testing:
Then we can use regex to search for needles:
When searching for multiple needles, call:
The changes in the tiny-regex-c library allow us to match null-bytes as well, meaning we can match wide characters:
To make sure the command is stable, you can run the following in
irb
for a single needle:or with multiple needles:
This should result in no memory usage increases for Meterpreter and the session should remain stable.
Debugging
When wanting to debug the new
re.c
file, we can first:This will also
typedef CHAR
which initially conflicted with theenum CHAR
; this has been renamed toCHAR_RE
.Then define a buffer, format it using
sprintf
and callOutputDebugStringA
, mimicking whatdprintf
was doing.You will need to use the DebugView program to view debug logs.
Dr. Memory
I also ran the generated executable with Dr. Memory using
drmemory -- ~/Desktop/met.exe
:This points at issues not related to the added memory search functionality and occurred before the memory search function was called.
Diagram
To help future travellers or potentially myself, below is a diagram of the memory search buffer implementation: