Sending variables to bash from python - python

I have tried my best to research and I have got to the point where I am using subprocess and subprocess.call to help me send my python variables to bash. I managed to get my python variables from bash output but now I need these variables to be in sync. I looked around couldn't learn how to use subprocess.call effectively. I have been using subprocess.check_output to obtain bash output into python variables flawlessly. I am having troubles understand how subprocess.call accepts arguments and how to use it properly. I tried following what I believed to be the correct format.
Here is my code. P.S I am brand new to joining this forum although I have been using it for tons of usefull information over the years. I dont know how to format my code input to look nice like how I see all over here. Regardless im sure you can forgive me as I tried the "Code" "Blockquotes" etc buttons.
###BEGINING OF CODE###
#! /usr/bin/env python2
import os,time,subprocess
#GRAB DATA
os.system('ifconfig > /tmp/ifconfig.txt;clear;cat /tmp/ifconfig.txt|grep "wlan"|cut -c 1-5 > /tmp/dev.lst;clear;')
#SET allwlan
allwlan=subprocess.check_output("cat /tmp/dev.lst", shell=True)
#SET max_index VARIABLE
max_index=subprocess.check_output("wc -l < /tmp/dev.lst", shell=True)
#SET curwlan WLAN LINE
#os.system(echo 2 > /tmp/curline.lst)
#STRIP DATA FOR curwlan
subprocess.call(['head', '-2', '/tmp/dev.lst', stdout=subprocess.PIPE, shell=True'])
#NEED#HELP#HERE# subprocess.call(['tail', '-1', > /tmp/curwlan.lst;')
#SET curwlan VARIABLE
curwlan=subprocess.check_output("cat /tmp/curwlan.lst", shell=True)
##STRIP EXCESS CHARACTERS/EMPTY LINES FROM VARIABLES##
curwlan=str(curwlan)
splitted=curwlan.split()
curwlan=splitted[0]
allwlan=allwlan[:-1]
splitted=max_index.split()
max_ index=splitted[0]
max_index=int(max_index)
##DEBUG MODE
print("Welcome, ")
print(" to debug mode. wireless adapter decting algorithm")
print
print("ALLWLAN:")
print(allwlan)
print
print("CURWLAN:")
print(curwlan)
print
print("MAX_INDEX:")
print(max_index)
print
input("PRESS ENTER TO EXIT")
####END OF CODE####*
The error in my code is under
#STRIP DATA FOR curwlan
Here is the output of that before I added the subprocess.call command.
Welcome,
to debug mode. wireless adapter decting algorithm
ALLWLAN:
wlan0
wlan3
CURWLAN:
wlan2
MAX_INDEX:
2
PRESS ENTER TO EXIT
I would love to learn how to have my python and bash parts communicate their variables together and I know I am on the right track with subprocess.call and ive been struggling for a few days now. I am trying to make my own algorithm to detect my wireless cards and be able to use each one (how ever many that may be or regardless what they may be named) as a variable for my
older scripts which now are struggling because of my constantly changing wireless card names. Thanks in advance I don't understand if what i'm asking subprocess.call to do is unrealistic or not.

You will want to avoid external processes as much as possible. Most of what you are doing is easy to do in just Python, and will be much more compact as well as more efficient if implemented natively.
Also, you are mixing the obsolete os.system() with subprocess where the latter is generally to be preferred, as also pointed out in the os.system() documentation.
subprocess.call() is only really appropriate when you don't expect any output from a command. The instance where you tried to use it, subprocess.check_output() would be the proper call to use. However, the places where you (as I understand, needlessly) ran shell commands with output to temporary files, you could have used subprocess.call(), trivially.
You need to understand when and where a shell is useful and necessary. Many places where you have shell=True would be more secure, faster, simpler, and more straightforward without a shell. Where you only run a simple hard-coded command with no redirection or globbing, switching from subprocess.whatever('command with args', shell=True) to subprocess.whatever(['command', 'with', 'args']) will instantly reduce your time and memory footprint with no ill effects. If you need redirection, pipelines, or globbing, maybe you want shell=True; but in many cases, doing those things in Python will be simple and straightforward. For example, here is how the head command could have been written without a shell:
with open('/tmp/randomfile', 'w') as outputfile:
subprocess.call(['head', '-n', '2', '/tmp/dev.lst'], stdout=outputfile)
Anyway, with these things out of the way, here is how I would do what (I think) you are attempting:
#!/usr/bin/env python2
import subprocess
allwlan = []
ifconfig = subprocess.check_output(['ifconfig'])
for line in ifconfig.split('\n'):
if "wlan" in line:
allwlan.append(line[0:5].strip())
max_index=len(allwlan)
curwlan=allwlan[1]
This was hastily thrown together, but I believe I captured at least most of what your current pretzel logic code does; though I have assumed that sprinkling the /tmp file system with random output files was not an essential feature of your script.

Thank you all for your advice. My script has come along way; Here is what this part looks like, over 1 year later,
def detmon():
try:
subprocess.call(['clear'])
item = []
items = []
the_choice = []
iwconfig = subprocess.check_output(['iwconfig'])
for line in iwconfig.split():
if "mon" in line:
items.append(line.strip(':'))
subprocess.call(['clear'])
max_index=len(items)-1
#items=items[counter]
#Print Files List
for item in items:
print(" ", items.index(item), ": ", item)
os.system('echo "\n"')
print(len(items))
try:
if len(items) >= 0:
counter = 0
allmon = []
ifconfig = subprocess.check_output(['iwconfig'])
for line in ifconfig.split():
if "mon" in line:
allmon.append(line.strip(':'))
subprocess.call(['clear'])
max_index=len(allmon)
curmon=allmon[counter]
while counter <= max_index:
curmon=allmon[counter]
subprocess.call(['airmon-ng', 'stop', curmon])
counter += 1
else:
print("No more 'mon' interfaces are found")
except:
print("No more 'mon' interfaces are found")
except KeyboardInterrupt:
pass

Related

how do i redirect fifo to stdin using python either with subprocess or with pwntools?

As an example I am trying to "imitate" the behaviour of the following sets of commands is bash:
mkfifo named_pipe
/challenge/embryoio_level103 < named_pipe &
cat > named_pipe
In Python I have tried the following commands:
import os
import subprocess as sp
os.mkfifo("named_pipe",0777) #equivalent to mkfifo in bash..
fw = open("named_pipe",'w')
#at this point the system hangs...
My idea it was to use subprocess.Popen and redirect stdout to fw...
next open named_pipe for reading and giving it as input to cat (still using Popen).
I know it is a simple (and rather stupid) example, but I can't manage to make it work..
How would you implement such simple scenario?
Hello fellow pwn college user! I just solved this level :)
open(path, flags) blocks execution. There are many similar stackoverflow Q&As, but I'll reiterate here. A pipe will not pass data until both ends are opened, which is why the process hangs (only 1 end was opened).
If you want to open without blocking, you may do so on certain operating systems (Unix works, Windows doesn't as far as I'm aware) using os.open with the flag os.O_NONBLOCK. I don't know what consequences there are, but be cautious of opening with nonblocking because you may try reading prematurely and there will be nothing to read (possibly leading to error, etc.).
Also, note that using the integer literal 0777 causes a syntax error, so I assume you mean 0o777 (max permissions), where the preceding 0o indicates octal. The default for os.mkfifo is 0o666, which is identical to 0o777 except for the execute flags, which are useless because pipes cannot be executed. Also, be aware that these permissions might not all be granted and when trying to set to 0o666, the permissions may actually be 0o644 (like in my case). I believe this is due to the umask, which can be changed and is used simply for security purposes, but more info can be found elsewhere.
For the blocking case, you can use the package multiprocessing like so:
import os
import subprocess as sp
from multiprocessing import Process
path='named_pipe'
os.mkfifo(path)
def read(): sp.run("cat", stdin=open(path, "r"))
def write(): sp.run(["echo", "hello world"], stdout=open(path, "w"))
if __name__ == "__main__":
p_read = Process(target=read)
p_write = Process(target=write)
p_read.start()
p_write.start()
p_read.join()
p_write.join()
os.remove(path)
output:
hello world

How do I determine if sys.stdin is redirected from a file vs. piped from another process?

In a simple Python script intended to be run from the shell, can I reliably determine whether sys.stdin has been redirected from an actual file vs. piped from another process?
I want to change runtime behavior depending on whether stdin is coming from a data file vs. streaming from another process via a pipe.
As expected, isatty() returns False in both cases. Here's a quick isatty() test:
# test.py
import os
import sys
print sys.stdin.isatty()
print os.isatty(sys.stdin.fileno())
Testing:
python test.py < file.txt
produces:
False
False
and:
ls -al | python test.py
produces:
False
False
Is there a pythonic method of doing this?
Unix/Linux specific is fine, though it would be nice to know if it's possible to do this in a portable manner.
Edit: Note in response to commenters: Why do I care? Well, in my case, I want to deal with time-stamped data that comes in at irregular intervals when piped from another process; when I play back pre-recorded data from a file, I'd like to replay it using a fixed or variable delays.
I agree it's probably advantageous to use a cleaner method (and I can think of several, including an intermediate script to insert delays in the playback stream) but I'm terminally curious.
You're looking for stat macros:
import os, stat
mode = os.fstat(0).st_mode
if stat.S_ISFIFO(mode):
print "stdin is piped"
elif stat.S_ISREG(mode):
print "stdin is redirected"
else:
print "stdin is terminal"

How to run and control a commandline program from python?

I have a python script which will give an output file. I need to feed this output file to a command line program. Is there any way I could call the commandline program and control it to process the file in python?
I tried to run this code
import os
import subprocess
import sys
proc = subprocess.Popen(["program.exe"], stdin=subprocess.PIPE)
proc.communicate(input=sys.argv[1]) #here the filename should be entered
proc.communicate(input=sys.argv[2]) #choice 1
proc.communicate(input=sys.argv[3]) #choice 2
is there any way I could enter the input coming from the commandline. And also though the cmd program opens the interface flickers after i run the code.
Thanks.
Note: platform is windows
Have a look at http://docs.python.org/library/subprocess.html. It's the current way to go when starting external programms. There are many examples and you have to check yourself which one fits your needs best.
You could do os.system(somestr) which lets you execute semestr as a command on the command line. However, this has been scrutinized over time for being insecure, etc (will post a link as soon as I find it).
As a result, it has been conventionally replaced with subprocess.popen
Hope this helps
depending on how much control you need, you might find it easier to use pexpect which makes parsing the output of the program rather easy and can also easily be used to talk to the programs stdin. Check out the website, they have some nice examples.
If your target program is expecting the input on STDIN, you can redirect using pipe:
python myfile.py | someprogram
As I just answered another question regarding subprocess, there is a better alternative!
Please have a look at the great library python sh, it is a full-fledged subprocess interface for Python that allows you to call any program as if it were a function, and more important, it's pleasingly pythonic.
Beside redirecting data stream with pipes, you can also process a command line such as:
mycode.py -o outputfile inputfilename.txt
You must import sys
import sys
and in you main function:
ii=1
infile=None
outfile=None
# let's process the command line
while ii < len(sys.argv):
arg = sys.argv[ii]
if arg == '-o':
ii = ii +1
outfile = sys.argv[ii]
else:
infile=arg
ii = ii +1
Of course, you can add some file checking, etc...

How to mimic passing a file using python variable

I am trying to figure out how to mimic passing a file to a program and instead of passing the file pass a python variable that has what information the program needs in it.
The syntax I need to mimic:
msfconsole < setofcommands.txt 2>/dev/null
What I would like to do:
answer = os.system('msfconsole < ' + myvariable + ' 2>/dev/null')
I also would be extremely happy if someone knew how to interact with something like msfconsole over a period of time so that when the msfconsole shell is open I could continually get python to type different commands without have to relaunch a new application for each time I wanted to type a series of commands
Thanks a lot in advance.
Instead, of os.system, you should use subprocess:
import subprocess
p=subprocess.Popen(['msfconsole'], stdin=subprocess.PIPE, stderr=subprocess.PIPE)
p.communicate(myvariable)
Note that communicate will block until termination. In general, interactive-like communication with another process just via stdin/stdout is a hard problem, since you must know how the other process delimits ends of messages.
In the case of metasploit, you should use the XMLRPC API instead of the interactive tool msfconsole.

Python - Run a simple command-line program with prompted I/O and "proxy" it, on Windows

I have a simple command-line binary program hello which outputs to STDOUT:
What is your name?
and waits for the user to input it. After receiving their input it outputs:
Hello, [name]!
and terminates.
I want to use Python to run computations on the final output of this program ("Hello, [name]!"), however before the final output I want the Python script to essentially "be" the binary program. In other words I'd like Python to forward all of the prompts to STDOUT and then accept the user's input and give it to the program. However I want to hide the final output so I can process it and show my own results to the user. I do not want to replicate the hello's behavior in the script, as this simple program is a stand-in for a more complex program that I am actually working with.
I was hoping there would be some sort of mechanic in subprocess where I would be able to do something akin to:
while process.is_running():
next_char = process.stdout.read(1)
if next_char == input_prompt_thing: # somehow check if the program is waiting for input
user_input = raw_input(buffer)
process.stdin.write(user_input)
else:
buffer += next_char
I have been playing with subprocess and essentially got as far as realizing I could use process.stdout.read(1) to read from the program before it began blocking, but I can't figure out how to break this loop before the process blocks my Python script. I am not too familiar with console I/O and it is not an area of much expertise for me, so I am starting to feel pretty lost. I appreciate any help!
You could try winpexpect (not tested):
import re
from winpexpect import winspawn
p = winspawn('hello')
prompt = "What is your name?"
p.expect(re.escape(prompt))
name = raw_input(prompt)
p.sendline(name)
p.expect("Hello, .*!")
output = p.after
# ...

Categories

Resources