|
| 1 | +## |
| 2 | +# WARNING: Metasploit no longer maintains or accepts meterpreter scripts. |
| 3 | +# If you'd like to improve this script, please try to port it as a post |
| 4 | +# module instead. Thank you. |
| 5 | +## |
| 6 | + |
| 7 | + |
| 8 | +# |
| 9 | +# Meterpreter script for setting up a route from within a |
| 10 | +# Meterpreter session, without having to background the |
| 11 | +# current session. |
| 12 | + |
| 13 | +# Default options |
| 14 | +session = client |
| 15 | +subnet = nil |
| 16 | +netmask = "255.255.255.0" |
| 17 | +print_only = false |
| 18 | +remove_route = false |
| 19 | +remove_all_routes = false |
| 20 | + |
| 21 | +# Options parsing |
| 22 | +@@exec_opts = Rex::Parser::Arguments.new( |
| 23 | + "-h" => [false, "Help and usage"], |
| 24 | + "-s" => [true, "Subnet (IPv4, for example, 10.10.10.0)"], |
| 25 | + "-n" => [true, "Netmask (IPv4, for example, 255.255.255.0"], |
| 26 | + "-p" => [false, "Print active routing table. All other options are ignored"], |
| 27 | + "-d" => [false, "Delete the named route instead of adding it"], |
| 28 | + "-D" => [false, "Delete all routes (does not require a subnet)"] |
| 29 | +) |
| 30 | + |
| 31 | +@@exec_opts.parse(args) { |opt, idx, val| |
| 32 | + v = val.to_s.strip |
| 33 | + case opt |
| 34 | + when "-h" |
| 35 | + usage |
| 36 | + raise Rex::Script::Completed |
| 37 | + when "-s" |
| 38 | + if v =~ /[0-9\x2e]+\x2f[0-9]{1,2}/ |
| 39 | + subnet,cidr = v.split("\x2f") |
| 40 | + netmask = Rex::Socket.addr_ctoa(cidr.to_i) |
| 41 | + else |
| 42 | + subnet = v |
| 43 | + end |
| 44 | + when "-n" |
| 45 | + if (0..32) === v.to_i |
| 46 | + netmask = Rex::Socket.addr_ctoa(v.to_i) |
| 47 | + else |
| 48 | + netmask = v |
| 49 | + end |
| 50 | + when "-p" |
| 51 | + print_only = true |
| 52 | + when "-d" |
| 53 | + remove_route = true |
| 54 | + when "-D" |
| 55 | + remove_all_routes = true |
| 56 | + end |
| 57 | +} |
| 58 | + |
| 59 | +def delete_all_routes |
| 60 | + if Rex::Socket::SwitchBoard.routes.size > 0 |
| 61 | + routes = [] |
| 62 | + Rex::Socket::SwitchBoard.each do |route| |
| 63 | + routes << {:subnet => route.subnet, :netmask => route.netmask} |
| 64 | + end |
| 65 | + routes.each {|route_opts| delete_route(route_opts)} |
| 66 | + |
| 67 | + print_status "Deleted all routes" |
| 68 | + else |
| 69 | + print_status "No routes have been added yet" |
| 70 | + end |
| 71 | + raise Rex::Script::Completed |
| 72 | +end |
| 73 | + |
| 74 | +# Identical functionality to command_dispatcher/core.rb, and |
| 75 | +# nearly identical code |
| 76 | +def print_routes |
| 77 | + if Rex::Socket::SwitchBoard.routes.size > 0 |
| 78 | + tbl = Msf::Ui::Console::Table.new( |
| 79 | + Msf::Ui::Console::Table::Style::Default, |
| 80 | + 'Header' => "Active Routing Table", |
| 81 | + 'Prefix' => "\n", |
| 82 | + 'Postfix' => "\n", |
| 83 | + 'Columns' => |
| 84 | + [ |
| 85 | + 'Subnet', |
| 86 | + 'Netmask', |
| 87 | + 'Gateway', |
| 88 | + ], |
| 89 | + 'ColProps' => |
| 90 | + { |
| 91 | + 'Subnet' => { 'MaxWidth' => 17 }, |
| 92 | + 'Netmask' => { 'MaxWidth' => 17 }, |
| 93 | + }) |
| 94 | + ret = [] |
| 95 | + |
| 96 | + Rex::Socket::SwitchBoard.each { |route| |
| 97 | + if (route.comm.kind_of?(Msf::Session)) |
| 98 | + gw = "Session #{route.comm.sid}" |
| 99 | + else |
| 100 | + gw = route.comm.name.split(/::/)[-1] |
| 101 | + end |
| 102 | + tbl << [ route.subnet, route.netmask, gw ] |
| 103 | + } |
| 104 | + print tbl.to_s |
| 105 | + else |
| 106 | + print_status "No routes have been added yet" |
| 107 | + end |
| 108 | + raise Rex::Script::Completed |
| 109 | +end |
| 110 | + |
| 111 | +# Yet another IP validator. I'm sure there's some Rex |
| 112 | +# function that can just do this. |
| 113 | +def check_ip(ip=nil) |
| 114 | + return false if(ip.nil? || ip.strip.empty?) |
| 115 | + begin |
| 116 | + rw = Rex::Socket::RangeWalker.new(ip.strip) |
| 117 | + (rw.valid? && rw.length == 1) ? true : false |
| 118 | + rescue |
| 119 | + false |
| 120 | + end |
| 121 | +end |
| 122 | + |
| 123 | +# Adds a route to the framework instance |
| 124 | +def add_route(opts={}) |
| 125 | + subnet = opts[:subnet] |
| 126 | + netmask = opts[:netmask] || "255.255.255.0" # Default class C |
| 127 | + Rex::Socket::SwitchBoard.add_route(subnet, netmask, session) |
| 128 | +end |
| 129 | + |
| 130 | +# Removes a route to the framework instance |
| 131 | +def delete_route(opts={}) |
| 132 | + subnet = opts[:subnet] |
| 133 | + netmask = opts[:netmask] || "255.255.255.0" # Default class C |
| 134 | + Rex::Socket::SwitchBoard.remove_route(subnet, netmask, session) |
| 135 | +end |
| 136 | + |
| 137 | + |
| 138 | +# Defines usage |
| 139 | +def usage() |
| 140 | + print_status "Usage: run autoroute [-r] -s subnet -n netmask" |
| 141 | + print_status "Examples:" |
| 142 | + print_status " run autoroute -s 10.1.1.0 -n 255.255.255.0 # Add a route to 10.10.10.1/255.255.255.0" |
| 143 | + print_status " run autoroute -s 10.10.10.1 # Netmask defaults to 255.255.255.0" |
| 144 | + print_status " run autoroute -s 10.10.10.1/24 # CIDR notation is also okay" |
| 145 | + print_status " run autoroute -p # Print active routing table" |
| 146 | + print_status " run autoroute -d -s 10.10.10.1 # Deletes the 10.10.10.1/255.255.255.0 route" |
| 147 | + print_status "Use the \"route\" and \"ipconfig\" Meterpreter commands to learn about available routes" |
| 148 | + print_error "Deprecation warning: This script has been replaced by the post/windows/manage/autoroute module" |
| 149 | +end |
| 150 | + |
| 151 | +# Validates the command options |
| 152 | +def validate_cmd(subnet=nil,netmask=nil) |
| 153 | + if subnet.nil? |
| 154 | + print_error "Missing -s (subnet) option" |
| 155 | + return false |
| 156 | + end |
| 157 | + |
| 158 | + unless(check_ip(subnet)) |
| 159 | + print_error "Subnet invalid (must be IPv4)" |
| 160 | + usage |
| 161 | + return false |
| 162 | + end |
| 163 | + |
| 164 | + if(netmask and !(Rex::Socket.addr_atoc(netmask))) |
| 165 | + print_error "Netmask invalid (must define contiguous IP addressing)" |
| 166 | + usage |
| 167 | + return false |
| 168 | + end |
| 169 | + |
| 170 | + if(netmask and !check_ip(netmask)) |
| 171 | + print_error "Netmask invalid" |
| 172 | + return usage |
| 173 | + end |
| 174 | + true |
| 175 | +end |
| 176 | + |
| 177 | +if print_only |
| 178 | + print_routes() |
| 179 | + raise Rex::Script::Completed |
| 180 | +end |
| 181 | + |
| 182 | +if remove_all_routes |
| 183 | + delete_all_routes() |
| 184 | + raise Rex::Script::Completed |
| 185 | +end |
| 186 | + |
| 187 | +raise Rex::Script::Completed unless validate_cmd(subnet,netmask) |
| 188 | + |
| 189 | +if remove_route |
| 190 | + print_status("Deleting route to %s/%s..." % [subnet,netmask]) |
| 191 | + route_result = delete_route(:subnet => subnet, :netmask => netmask) |
| 192 | +else |
| 193 | + print_status("Adding a route to %s/%s..." % [subnet,netmask]) |
| 194 | + route_result = add_route(:subnet => subnet, :netmask => netmask) |
| 195 | +end |
| 196 | + |
| 197 | +if route_result |
| 198 | + print_good "%s route to %s/%s via %s" % [ |
| 199 | + (remove_route ? "Deleted" : "Added"), |
| 200 | + subnet,netmask,client.sock.peerhost |
| 201 | + ] |
| 202 | +else |
| 203 | + print_error "Could not %s route" % [(remove_route ? "delete" : "add")] |
| 204 | +end |
| 205 | + |
| 206 | +if Rex::Socket::SwitchBoard.routes.size > 0 |
| 207 | + print_status "Use the -p option to list all active routes" |
| 208 | +end |
| 209 | + |
0 commit comments