1
mirror of https://github.com/rapid7/metasploit-framework synced 2024-11-12 11:52:01 +01:00

Networkpug improvements

git-svn-id: file:///home/svn/framework3/trunk@10484 4d416f70-5f16-0410-b530-b9f4589650da
This commit is contained in:
pks 2010-09-26 05:58:48 +00:00
parent 1392ef78d7
commit 784e355d93
2 changed files with 71 additions and 44 deletions

View File

@ -132,7 +132,7 @@ NetworkPug *allocate_networkpug(char *interface)
* Needs to be active for cleanup to proceed.
*/
void free_networkpug(NetworkPug *np, int close_channel)
void free_networkpug(NetworkPug *np, int close_channel, int destroy_channel)
{
int cont;
@ -175,9 +175,14 @@ void free_networkpug(NetworkPug *np, int close_channel)
if(close_channel == TRUE) {
// Tell the remote side we've shut down for now.
channel_close(np->channel, np->remote, NULL, 0, NULL);
}
if(destroy_channel == TRUE) {
// the channel handler code will destroy it.
// if we destroy it, it will end up double freeing
// and calling abort :~(
channel_destroy(np->channel, NULL);
}
channel_destroy(np->channel, NULL); // channel_destroy does not look at packet it seems
}
if(np->interface) {
@ -234,13 +239,24 @@ DWORD networkpug_channel_write(Channel *channel, Packet *request,
DWORD networkpug_channel_close(Channel *channel, Packet *request, LPVOID context)
{
int result = ERROR_SUCCESS;
NetworkPug *np;
dprintf("[%s] Channel shutdown requested. context = %p", __FUNCTION__, context);
dprintf("[%s] pugs is at %p, and pugs[MAX_PUGS] is %p", __FUNCTION__, pugs, pugs + MAX_PUGS);
lock_acquire(pug_lock);
free_networkpug((NetworkPug *)(context), FALSE);
np = (NetworkPug *)(context);
dprintf("[%s] closed channel successfully", __FUNCTION__);
if(np->active) {
dprintf("[%s] Channel shutdown requested. context = %p", __FUNCTION__, context);
dprintf("[%s] pugs is at %p, and pugs[MAX_PUGS] is %p", __FUNCTION__, pugs, pugs + MAX_PUGS);
free_networkpug((NetworkPug *)(context), FALSE, FALSE);
dprintf("[%s] closed channel successfully", __FUNCTION__);
} else {
dprintf("[%s] Already closed down context %p", __FUNCTION__, context);
}
lock_release(pug_lock);
return result;
}
@ -342,7 +358,7 @@ DWORD request_networkpug_start(Remote *remote, Packet *packet)
if(result != ERROR_SUCCESS) {
np->active = 1;
free_networkpug(np, FALSE);
free_networkpug(np, FALSE, TRUE);
}
lock_release(pug_lock);
@ -379,7 +395,7 @@ DWORD request_networkpug_stop(Remote *remote, Packet *packet)
}
dprintf("[%s] calling free_networkpug", __FUNCTION__);
free_networkpug(np, TRUE);
free_networkpug(np, TRUE, FALSE);
result = ERROR_SUCCESS;
} while(0);

View File

@ -20,9 +20,18 @@ class Console::CommandDispatcher::NetworkPug
)
def initialize(shell)
@thread_stuff = nil
@tapdev = nil
@channel = nil
super
end
attr_accessor :thread_stuff
attr_accessor :tapdev
attr_accessor :channel
#
# List of supported commands.
#
@ -64,44 +73,47 @@ class Console::CommandDispatcher::NetworkPug
return nil, nil, nil
end
def proxy_packets(tapdev, channel)
def proxy_packets()
while 1
# Ghetto :\
sd = Rex::ThreadSafe.select([ channel.lsock, tapdev ], nil, nil)
sd = Rex::ThreadSafe.select([ @channel.lsock, @tapdev ], nil, nil)
sd[0].each { |s|
if(s == channel.lsock) # Packet from remote host to local TAP dev
len = channel.lsock.read(2)
if(s == @channel.lsock) # Packet from remote host to local TAP dev
len = @channel.lsock.read(2)
len = len.unpack('n')[0]
# print_line("Got #{len} bytes from remote host's network")
#print_line("Got #{len} bytes from remote host's network")
if(len > 1514 or len == 0)
tapdev.close()
@tapdev.close()
print_line("length is invalid .. #{len} ?, de-synchronized ? ")
end
packet = channel.lsock.read(len)
packet = @channel.lsock.read(len)
# print_line("remote from remote host:\n" + Rex::Text.hexify(packet))
print_line("packet from remote host:\n" + Rex::Text.hexify(packet))
tapdev.syswrite(packet)
@tapdev.syswrite(packet)
elsif(s == tapdev)
elsif(s == @tapdev)
# Packet from tapdev to remote host network
packet = tapdev.sysread(1514)
packet = @tapdev.sysread(1514)
# print_line("packet to remote host:\n" + Rex::Text.hexify(packet))
print_line("packet to remote host:\n" + Rex::Text.hexify(packet))
channel.write(packet)
@channel.write(packet)
end
} if(sd)
if(not sd)
print_line("hmmm. ")
end
end
end
def cmd_networkpug_start(*args)
# PKS - I suck at ruby ;\
@ -114,7 +126,6 @@ class Console::CommandDispatcher::NetworkPug
end
@@options.parse(args) { |opt, idx, val|
# print_line("before: #{opt} #{idx} #{val} || virtual nic: #{virtual_nic}, filter: #{filter}, interface: #{interface}")
case opt
when "-v"
@ -142,9 +153,9 @@ class Console::CommandDispatcher::NetworkPug
return
end
tapdev, tapname, mac = setup_tapdev
@tapdev, tapname, mac = setup_tapdev
if(tapdev == nil)
if(@tapdev == nil)
print_status("Failed to create tapdev")
return
end
@ -152,35 +163,25 @@ class Console::CommandDispatcher::NetworkPug
# PKS, we should implement multiple filter strings and let the
# remote host build it properly.
# not (our conn) and (virtual nic filter) and (custom filter)
# print_line("before virtual, filter is #{filter}")
if(filter == nil and virtual_nic == true)
filter = "ether host #{mac}"
elsif(filter != nil and virtual_nic == true)
filter += " and ether host #{mac}"
print_line("Adjusted filter is #{filter}")
#print_line("Adjusted filter is #{filter}")
end
# print_line("after virtual, filter is #{filter}")
print_line("#{tapname} created with a hwaddr of #{mac}, ctrl-c when done")
begin
response, channel = client.networkpug.networkpug_start(interface, filter)
response, @channel = client.networkpug.networkpug_start(interface, filter)
if(not channel)
print_line("No channel? bailing")
return
end
if(@channel)
@thread_stuff = ::Thread.new {
proxy_packets()
}
print_line("Forwarding packets between #{tapname} and remote host")
proxy_packets(tapdev, channel)
ensure
tapdev.close()
print_line("don't forget to networkpug_stop remote host as well")
print_line("Packet slinger for #{interface} has a thread structure of #{@thread_stuff}")
end
return true
@ -191,8 +192,18 @@ class Console::CommandDispatcher::NetworkPug
if (interface == nil)
print_error("Usage: networkpug_stop [interface]")
return
end
if(@thread_stuff)
::Thread.kill(@thread_stuff)
::Thread.join(@thread_stuff)
@thread_stuff = nil
@channel.close
@tapdev.close
end
client.networkpug.networkpug_stop(interface)
print_status("Packet slinging stopped on #{interface}")
return true