I'd like to create a dummy script (with the prospect of writing a real life script) that invokes for example the Python interactive interpreter from within a Scala process and lets the user fully interact with the subprocess; i.e. the stdin/stdout/stderr of the child process should be connected to those of the parent (Scala) process. I've tried using the following to no avail:
#!/usr/bin/env scala -savecompiled
import sys.process._
stringToProcess("python").run(BasicIO.standard(connectInput = true)).exitValue
however, while it does seem to successfully run a python subprocess, the only interaction I get to have with it is Ctrl-C:
~$ ./scalashelltest.scala
foo
^CTraceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyboardInterrupt
If press Ctrl-C immediately, I don't even get that output:
~$ ./scalashelltest.scala
^C~$
Any idea why this is happening and how to make it work as expected?
You aren't giving python a (pseudo-)tty. You are just giving it stdin (and possibly stdout).
So python is operating in a non-interactive mode.
Running python with the -i flag will force it to use prompts even without a tty but the more correct fix is likely to find a scala/java library which can create a (pseudo-)tty and run an application in it.
Related
I am currently helping my university's cyber security program by creating a simple Capture the Flag style python script to be used for the final exam. I created the script and everything is working great when run natively on Windows. The issue that I am having is that since the course is dealing with ethical hacking, many of the students will be accessing the Windows machine via a reverse shell or meterpreter on their local Kali linux machine. When I try to run the script through the meterpreter or reverse shell, I am having an EOF error as soon as my script asks for input, without waitingfor a user to type.
I tried to recreate a simple script in order to demonstrate the issue:
test.py:
print "This is a test"
answer = raw_input("Type anything")
print answer
When I run the command through the meterpreter or reverse shell, the output is as follows
> test.py
This is a test
Type anythingTraceback (most recent call last):
File "test.py", line 2, in <module>
answer = raw_input("Type anything")
EOFError: EOF when reading a line
I have tried this with both input and raw_input and both have the same EOFError. I've tried searching through similar posts, but none seem to address the issue.
My belief is that the reverse shell or meterpreter are causing the issue, but I can not find any information on how to remotely execute a python script on the target machine while using the meterpreter or reverse shell.
I appreciate any help or insight, as I am honestly quite stumped!
I'm new to subprocesses in python, I need to spawn a number of independent subprocesses, keep them alive and pass commands into them. At first sight, subprocess library is what I'm looking for.
I've read the documenations for it and as I'm understanding to pass any command into the subprocess, I'd have to specify the input.
I need to run commands via windows command line, hence the toy example below is good enough that if I have it working, I'm pretty much done. Running code below via IDLE opens a new cmd window, printing a list of cwd files, however I can't write to it as stdin is not specified (would be writing to it using p.stdin.write('DIR') with 'DIR' being an example command).
from subprocess import Popen, PIPE
p = Popen(['cmd', '/K', 'DIR'])
Therefore I specify the stdin as PIPE, as per documentations.
from subprocess import Popen, PIPE
p = Popen(['cmd', '/K', 'DIR'], stdin=PIPE)
However, running the second snippet of code instantly terminates the opened cmd window. Is that the expected behavior? As far as I could find in the documentations, only p.kill() or p.terminate() end the child process. If so, what are the possible workarounds? If not, what am I doing incorrectly, what other libraries should I be using? Thanks!
I have a python script called speech.pyw. I don't want it showing up on the screen when run so I used that extension.
How can I check using another python script whether or not this script is running? If it isn't running, this script should launch it.
Off the top of my head, there are at least two ways to do this:
You could make the script create an empty file in a specific location, and the other script could check for that. Note that you might have to manually remove the file if the script exits uncleanly.
You could list all running processes, and check if the first one is among those processes. This is somewhat more brittle and platform-dependant.
An alternative hybrid strategy would be for the script to create the specific file and write it's PID (process id) to it. The runner script could read that file, and if the specified PID either wasn't running or was not the script, it could delete the file. This is also somewhat platform-dependant.
!/usr/bin/env python2
import psutil
import sys
processName="wastetime.py"
def check_if_script_is_running(script_name):
script_name_lower = script_name.lower()
for proc in psutil.process_iter():
try:
for element in proc.cmdline():
if element.lower() == script_name_lower:
return True
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
pass
return False;
print(check_if_script_is_running(processName))
sys.stdin.readline()
I'm trying to run bash.exe (Bash on Ubuntu for Windows) as a build command for Sublime Text. However, bash.exe has a bug and does not support outputting its stdout to any pipe.
Question is this: how can I run a cmd line (i.e. "bash.exe -c ls") and capture the output without ever making bash.exe output into pipes on windows?
I'm open to using any languages or environment on Windows to make this tool.
Edit
I ran
bashTest = subprocess.Popen(["bash.exe", "-c", "ls"]), stdout=subproccess.PIPE)
Which yielded:
bashTest.communicate()[0] b'E\x00r\x00r\x00o\x00r\x00:\x00\x000\x00x\x008\x000\x000\x007\x000\x000\x005\x007\x00\r\x00\r\x00\n\x00'
This is currently not possible. There's a github issue about it which was closed as a known limitation. If you want to increase awareness of it, I see 2 related User Voice ideas: Allow Windows programs to spawn Bash and Allow native Win32 applications to launch Linux tools/commands.
There are ways you could hack around it, however. One way would be to write a script which loops forever in a bash.exe console. When the script gets a signal, it runs Linux commands with the output piped to a file then signals that it is complete. Here's some pseudo code:
Linux:
while true
while not exists /mnt/c/dobuild
sleep 1
end
gcc foo.c > /mnt/c/build.log
rm /mnt/c/dobuild
end
Windows:
touch C:\dobuild
while exists C:\dobuild
sleep 1
end
cat C:\build.log
This does require keeping a bash.exe console always open with the script running, which is not ideal.
Another potential workaround, which was already mentioned, is to use ReadConsoleOutput.
You need to use the option shell=True in Popen() to have pipes work.
like this example dont need to split this command.
>>> import subprocess as sp
>>> cmd = 'echo "test" | cat'
>>> process = sp.Popen(cmd,stdout=sp.PIPE,shell=True)
>>> output = process.communicate()[0]
>>> print output
test
Your only realistic option, if you can't wait for a fix, would be to use ReadConsoleOutput and/or the related functions.
I have a number of bash/bind tools that I've written to simplify my command-line existence, and have recently wanted to make one of these tools interactive. If I try to read from stdin in one of these scripts, execution locks up at the point of reading. My example here is in python, but I have seen the exact same behavior when the invoked script is written in ruby:
~> cat tmp.py
import sys
sys.stdout.write(">>>")
sys.stdout.flush()
foo = sys.stdin.readline()
print "foo: %s" % foo,
~> python tmp.py
>>>yodeling yoda
foo: yodeling yoda
So the script works. When I invoke it, I can give it input and it prints what I fed it.
~> bind -x '"\eh":"echo yodeling yoda"'
[output deleted]
~> [Alt-H]
yodeling yoda
bind works as expected. The bound keystroke invokes the command. I use this stuff all the time, but until now, I've only invoked scripts that required no stdin reads.
Let's bind [Alt-H] to the script:
~> bind -x '"\eh":"python tmp.py"'
[output deleted]
Now we're configured to have the script read from stdin while invoked by the bound keystroke. Hitting [Alt-H] starts the script but nothing typed is echoed back. Even hitting [Crl-D] doesn't end it. The only way to get out is to hit [Crl-C], killing the process in the readline. (sys.stdin.read() suffers the same fate.)
~> [Alt-H]
>>>Traceback (most recent call last):
File "tmp.py", line 7, in <module>
foo = sys.stdin.readline()
KeyboardInterrupt
As I mentioned at the top, I see the same issue with ruby, so I know it's nothing to do with the language I'm using. (I've omitted the script.)
~> bind -x '"\eh":"ruby tmp.rb"'
[Output deleted]
~> [Alt-H]
>>>tmp.rb:3:in `gets': Interrupt
from tmp.rb:3
I've looked through the Bash Reference Manual entry on bind, and it says nothing about a restriction on input. Any thoughts?
EDIT:
If I cat /proc/[PID]/fd/0 while the process is stuck, I see the script's input being displayed. (Oddly enough, a fair number of characters - seemingly at random - fail to appear here. This symptom only appears after I've given a few hundred bytes of input.)
Found this, a description of how and when a terminal switches between cooked and raw modes. Calling stty cooked and stty echo at the beginning of prompting, then stty sane or stty raw afterward triggers a new cascade of problems; mostly relating to how bound characters are handled, but suffice it to say that it destroys most alt bindings (and more) until return has been hit a couple times.
In the end, the best answer proved to be cooking the tty and manually turning on echo, then reverting the tty settings back to where they were when I started:
def _get_terminal_settings():
proc = subprocess.Popen(['/bin/stty', '-g'], stdout=subprocess.PIPE)
settings = proc.communicate()[0]
os.system('stty cooked echo')
return settings
def _set_terminal_settings(settings):
os.system('stty %s' % settings)
...
...
settings = _get_terminal_settings()
user_input = sys.stdin.readline()
_set_terminal_settings(settings)
...
...
You should be able to do this in any language you choose.
If you're curious about why this insanity is required, I would encourage you to read the link I added (under EDIT), above. The article doesn't cover anywhere enough detail, but you'll at least understand more than I did when I started.
Hmm, my guess is that what's happening is the python script is running and waiting for input from stdin when you press [Alt-H],but that it's stdin scope is not the same as the stdin scope of the calling script. When you type in something, it goes to the Bash scripts stdin, not the pythons. Perhaps look up a way to "reverse pipe" or forward the stdin from the bash shell to the stdin of a called script?
Edit:
Okay, I researched it a bit, and it looks like pipes might work. Here's a really informative link:
bash - redirect specific output from 2nd script back to stdin of 1st program?