metasploit-framework/lib/msf/core/exploit/wdbrpc.rb

248 lines
5.2 KiB
Ruby

# -*- coding: binary -*-
require 'msf/core'
module Msf
###
#
# This module exposes methods for manipulating the WDRPC service
#
###
module Exploit::Remote::WDBRPC
# WDB_TARGET_CONNECT2
def wdbrpc_request_connect2(ip)
ip += "\x00"
while(ip.length % 4 != 0)
ip << "\x00"
end
data = [
0x00000002,
0x00000000,
0x00000000,
0x00000001,
ip.length
].pack("N*") + ip
wdbrpc_request(0x7a, data)
end
# WDB_TARGET_CONNECT
def wdbrpc_request_connect(ip)
data = [ 0x00000002, 0x00000000, 0x00000000 ].pack("N*")
wdbrpc_request(1, data)
end
# WDB_TARGET_DISCONNECT
def wdbrpc_request_disconnect
data = [ 0x00000002, 0x00000000, 0x00000000 ].pack("N*")
wdbrpc_request(2, data)
end
def wdbrpc_request_regread(regset=0, offset=0, length=512, params=0)
data = [ regset ].pack("N")
# WDB_CTX
data << [
0, # WDB_CTX_SYSTEM (3 for task)
0, # SYSTEM (or set for task)
].pack("N*")
# WDB_MEM_REGION
data << [
offset, # baseAddress
length, # numberOfBytes
params, # params
].pack("N*")
wdbrpc_request(40, data)
end
def wdbrpc_request_memread(offset=0, length=512, params=0)
# WDB_MEM_REGION
data = [
offset, # baseAddress
length, # numberOfBytes
params, # params
].pack("N*")
wdbrpc_request(10, data)
end
def wdbrpc_request_memwrite(offset=0, buff='', params=0)
# Make sure its DWORD aligned
while(buff.length % 4 != 0)
buff << "\x00"
end
# WDB_MEM_XFER
data = [
buff.length,
offset, # target
buff.length
].pack("N*") + buff
wdbrpc_request(11, data)
end
def wdbrpc_request_memscan(offset=0, depth=1024, buff='', params=0)
# Make sure its DWORD aligned
while(buff.length % 4 != 0)
buff << "\x00"
end
# WDB_MEM_REGION
data = [
offset, # baseAddress
depth, # numberOfBytes
params, # params
].pack("N*")
# WDB_MEM_XFER
data << [
buff.length,
0,
buff.length
].pack("N*") + buff
wdbrpc_request(11, data)
end
def wdbrpc_request_context_kill(ctx_type, ctx)
# WDB_CTX
data = [
ctx_type, # WDB_CTX_SYSTEM (3 for task)
ctx, # SYSTEM (or set for task)
].pack("N*")
# options
data << [ 0 ] .pack("N")
wdbrpc_request(31, data)
end
def wdbrpc_parse_connect_reply(buff)
info = {}
head = buff.slice!(0,36)
info[:agent_ver] = wdbrpc_decode_str(buff)
info[:agent_mtu] = wdbrpc_decode_int(buff)
info[:agent_mod] = wdbrpc_decode_int(buff)
info[:rt_type] = wdbrpc_decode_int(buff)
info[:rt_vers] = wdbrpc_decode_str(buff)
info[:rt_cpu_type] = wdbrpc_decode_int(buff)
info[:rt_has_fpp] = wdbrpc_decode_bool(buff)
info[:rt_has_wp] = wdbrpc_decode_bool(buff)
info[:rt_page_size] = wdbrpc_decode_int(buff)
info[:rt_endian] = wdbrpc_decode_int(buff)
info[:rt_bsp_name] = wdbrpc_decode_str(buff)
info[:rt_bootline] = wdbrpc_decode_str(buff)
info[:rt_membase] = wdbrpc_decode_int(buff)
info[:rt_memsize] = wdbrpc_decode_int(buff)
info[:rt_region_count] = wdbrpc_decode_int(buff)
info[:rt_regions] = wdbrpc_decode_arr(buff, :int)
info[:rt_hostpool_base] = wdbrpc_decode_int(buff)
info[:rt_hostpool_size] = wdbrpc_decode_int(buff)
info
end
def wdbrpc_request(procedure, data)
pkt =
[
0x00000000, # XID (ignored by checksum and length)
0x00000000,
0x00000002,
0x55555555, # Program
0x00000001, # Version
procedure, # Procedure
0x00000000,
0x00000000,
0x00000000,
0x00000000
].pack("N*")
pkt +=
[
0x00000000, # Checksum
0x00000000, # Packet Size
wdbrpc_request_seqno
].pack("N*")
pkt += data
# Length excludes the XID
pkt[44, 4] = [ pkt.length - 4].pack("N")
# Set the checksum flag and calculate the checksum
pkt[42, 2] = [ wdbrpc_checksum(pkt) ].pack("n")
pkt[40, 2] = [0xffff].pack("n")
# Set the RPC XID
pkt[ 0, 4] = [ rand(0x100000000) ].pack("N")
pkt
end
def wdbrpc_request_seqno
@wdbrpc_seqno ||= 0
@wdbrpc_seqno += 1
end
def wdbrpc_checksum(data)
sum = 0
data.unpack("n*").each {|c| sum += c }
sum = (sum & 0xffff) + (sum >> 16)
(~sum)
end
def wdbrpc_decode_str(data)
return if data.length < 4
slen = data.slice!(0,4).unpack("N")[0]
return "" if slen == 0
while (slen % 4 != 0)
slen += 1
end
data.slice!(0,slen).to_s.split("\x00")[0]
end
def wdbrpc_decode_int(data)
return if data.length < 4
data.slice!(0,4).unpack("N")[0]
end
def wdbrpc_decode_arr(data, dtype)
return if data.length < 4
res = []
alen = data.slice!(0,4).unpack("N")[0]
return res if alen == 0
1.upto(alen) do |idx|
case dtype
when :int
res << wdbrpc_decode_int(data)
when :str
res << wdbrpc_decode_str(data)
when :bool
res << wdbrpc_decode_bool(data)
end
end
res
end
def wdbrpc_decode_bool(data)
return if data.length < 4
(data.slice!(0,4).unpack("N")[0] == 0) ? false : true
end
end
end