0

I am having some issues getting a script to run.

This works perfectly from command line:

ssh root@ip.add.re.ss /usr/sbin/tcpdump -i eth0 -w - | /usr/sbin/tcpdump -r - -w /home/cuckoo/cuckoo/storage/analyses/1/saveit.pcap

However when I use this script: #!/usr/bin/env python

import sys
import os
import subprocess

cmd = []
remote_cmd = []
local_cmd = []
connect_cmd = []
outfile = None

try:
    connect_cmd = str.split(os.environ["RTCPDUMP_CMD"], " ")
except:
    connect_cmd = str.split("ssh root@fw", " ")

remote_cmd.extend(str.split("/usr/sbin/tcpdump -w -", " "))
local_cmd.extend(str.split("/usr/sbin/tcpdump -r -", " "))

for argument in xrange(1, len(sys.argv)):
    if sys.argv[argument] == "-w":
        outfile=sys.argv[argument+1]
        sys.argv[argument] = None
        sys.argv[argument+1] = None

    if sys.argv[argument] == "-i":
        remote_cmd.append(sys.argv[argument])
        remote_cmd.append(sys.argv[argument+1])
        sys.argv[argument] = None
        sys.argv[argument+1] = None

    if not sys.argv[argument] == None:
        if " " in sys.argv[argument]:
            local_cmd.append("'" + sys.argv[argument] + "'")
            remote_cmd.append("'" + sys.argv[argument] + "'")
        else:
            local_cmd.append(sys.argv[argument])
            remote_cmd.append(sys.argv[argument])

if not outfile == None:
    local_cmd.insert(1, "-w")
    local_cmd.insert(2, outfile)

cmd.extend(connect_cmd)
cmd.extend(remote_cmd)
cmd.append("|")
cmd.extend(local_cmd)

try:
    subprocess.call(cmd)
except KeyboardInterrupt:
    exit(0)

It spawns both tcpdump processes on the remote host and the second tcpdump fails to save due to non working path. I added a print cmd at the end and the ssh command being passed to the prompt is exactly the same (when running the script itself, cuckoo passes a ton of options when it calls the script. Also it gets the -w - before the -i eth0, but I tested that and it works from command line as well).

So I am thoroughly stumped, why is the pipe to local not working in the script but it works from prompt?

Oh, and credit for the script belongs to Michael Boman http://blog.michaelboman.org/2013/02/making-cuckoo-sniff-remotely.html

  • As a side note, calling unbound methods like `str.split` with an explicit `self` is not very readable; why not just `"ssh root@fw".split(" ")` instead of `str.split("ssh root@fw", " ")`? Also, why `split(" ")` instead of just the default `split()`? (Although really, you probably want `shlex.split` here, because one day you're going to add a quoted argument somewhere and `str.split` will do the wrong thing…) – abarnert Oct 18 '14 at 01:21
  • Yeah, to be honest I am just starting to learn python. I found this script and was trying to get it to run as it fit with the lab environment I had set up. – Garth Austin Oct 18 '14 at 20:30

1 Answers1

0

So I am thoroughly stumped, why is the pipe to local not working in the script but it works from prompt?

Because pipes are handled by the shell, and you're not running a shell.

If you look at the docs, under Replacing Older Functions with the subprocess Module, it explains how to do the same thing shell pipelines do. Here's the example:

output=`dmesg | grep hda`
# becomes
p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.
output = p2.communicate()[0]

So, in your terms:

cmd.extend(connect_cmd)
cmd.extend(remote_cmd)
try:
    remote = subprocess.Popen(cmd, stdout=subprocess.PIPE)
    local = subprocess.Popen(local_cmd, stdin=remote.stdout)
    remote.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.
    local.communicate()
except KeyboardInterrupt:
    exit(0)
abarnert
  • 354,177
  • 51
  • 601
  • 671