-
Notifications
You must be signed in to change notification settings - Fork 143
Change thread creation to support x86->x64 #76
Conversation
The create thread functionality would work in all cases except where the thread was being created in an x64 process from an x86 process. This commit adds support for this by reusing the wow64 injection code in this case.
Test PASSED. |
Sweet. Should this fall back on APC technique for Win2k3? |
NB Should |
Yeah it should fall back on apc, I was thinking about that just as I was And yes I agree, I used a post module in my testing as well as the script. |
OK, I'm having second thoughts about doing the APC technique for this. In the case of migration I can understand the need for it. However, for the general case of "create me a new thread over there", the semantics doesn't seem to fit. The APC thread technique reuses an existing thread in the target application, and returning that to the caller as a "new" thread handle implies:
I don't think this is the case with APC. If you hijack enough threads in the target, then the target would just stop functioning, right? My gut feeling is that for the case of general thread creation the APC thread thing doesn't belong. Thoughts? |
TBH I dont know enough about the technique to comment! |
Sounds like a separate issue to me, probably worth talking about that and working on it separately. |
Yeah, maybe a method like |
Behind the scenes the RTL approach is already being used. The APC thread creation is a thread reuser not a thread creator, which is basically my problem with baking this approach in here. |
|
||
DWORD inject_via_remotethread( Remote * remote, Packet * response, HANDLE hProcess, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter ); | ||
DWORD inject_via_remotethread_wow64(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter, HANDLE * pThread); |
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 doesn't this have the same signature as inject_via_remotethread
?
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.
My understanding is that it is called by inject_via_remotethread when it detects its in a wow64 environment. Its not exposed as remote method call.
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.
Ben's right. It's used internally and doesn't interact with packets at all.
Bump? This is good to go and works nicely in all but x64 2003 (where it doesn't currently work anyway!). It'd be great to see this land soon. |
Boom:
|
Everything seems functional, apart from x64 -> x64 process injection, but this doesn't appear to be related to the thread creation. I suspect a 64 bit PTR is being returned with the high bits set and this isn't getting back to the ruby correctly. It doesn't work with the original meterpreter binaries either. The address returned is : 0xF7FF0000
|
Ditto multi_meter_inject:
|
Pants. Nice catch. I'll look into this one. Thanks for testing mate. |
https://github.com/rapid7/meterpreter/blob/master/source/extensions/stdapi/server/sys/process/memory.c#L30 |
Yeah mate, the |
DWORD was being used, resulting in x64 being unhappy thanks to pointer truncation. This fixes the problem.
Updated. Here's x86 to x86
Here's x64 to x86:
x86 to x64:
And finally, the biggie, x64 to x64:
Proof of the sessions:
Session 1 was the one I used to launch the others, and I migrated between x86 and x64 to do the injections. This is a x64 Windows 7 with all patches. Adjusted in the MSF side over here: rapid7/metasploit-framework#3416 Thanks again @Meatballs1 ! |
Test PASSED. |
This still not working for me on x64 -> x64. It is allocating and memprotecting fine but - request_sys_process_thread_create is taking a TLV_TYPE_ENTRY_POINT which is uint again! P.S. you probably want to test this on 2012 or Win8.1 as 7 doesn't tend to exercise the full memory address space |
Dammit! I feel stupid for missing that. I'll fix it up and submit later |
The goal is to avoid pointer truncation where possible so this commit changes parameter types to qword where it makes the most sense. This includes all handles (event, process, thread, registry), addresses and generic parameters.
OK, I think I might finally have it: Session 2 is the one I used to inject. It started as x86 where I created the 3 and 4. I then migrated to an x64 process and created 5 and 6.
Let's hope this is it! I have also updated a few other things including:
|
In case it's not clear, this was tested on Windows 2012. So hopefully that covers off the ASLR bit :) @Meatballs1 would be awesome if you could confirm when you get the chance dude. Cheers! |
Test PASSED. |
Cool will do when I get a chance :) |
Also fixes a number of PTR truncation issues...
These are the binaries generated for rapid7/meterpreter#76 , against commit 2776adb8b91d9967983033c0e770c46a10a68002 These bins are need to make rapid7#3416 actually functional
This lands rapid7#3416 again as well, but now with the bins from rapid7/meterpreter#76 Sorry for the mixup.
The create thread functionality would work in all cases except where the thread was being created in an x64 process from an x86 process. This commit adds support for this by reusing the wow64 injection code in this case.
To see this in action, the best thing to do is create a session on a 64-bit machine with a 32-bit meterpreter. Then do something like this:
This demonstrates the use case, though there are many cases where this could possibly apply.
Verification