I have a python 3 script that accepts input from the user, this input is piped into a subprocess, where a shell has been spawned. Originally I was going to put this code together with a socket, to be able to make my own non-serious remote administration tool, however this proves too hard for my level currently. Code:
import subprocess
p1 = subprocess.Popen(["/bin/sh"], stderr = subprocess.PIPE, stdin = subprocess.PIPE, stdout = subprocess.PIPE, encoding = "utf-8")
command = input("Command: ")
p1.stdin.write(command)
p1.stdout.read()
Problem: Nothing gets printed out. I have searched endless hours
online for a reason, over multiple days, but all of them don't seem to
work, and/or advise using communicate() which is something I do not
want to do. When thinking ahead if I am able to implement this with a
socket, I can't have the process closing after each command. I have
also tried flushes everywhere, before write, inbetween the read, after
the read, pretty much everywhere you can think of. It should be simple
enough, without me having to look deep into the io module or the rules
of buffering (too late now). I have been struggling with this for days
on end.
You have a couple of issues, I will try to draw the path, I hope I am not misleading you.
First of all, disclaimer: executing user input is inherently unsafe. If that's not an issue, let's keep on your problem.
I would start by doing
p1 = subprocess.Popen(["/bin/sh"], stderr=subprocess.PIPE, stdin=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True, bufsize=1)
Having a line-buffered PIPE is a good idea, in this scenario.
Then, remember that you have to press enter after the command, so:
command = input("Command: ") + "\n"
The write is correct,
p1.stdin.write(command)
But the, the read is VERY dangerous and you will trivially become deadlocked. Because the stdout is open (without an EOF or anything like that) you should read conservatively, and still, you will have problems on that.
A first idea would be to read lines:
p1.stdout.readline()
But, if you don't know how many lines you can read... then that's a problem. In fact, that specific problem has already been asked.
If you want to experiment, just open an interactive python interpreter, send a "ls\n" command and perform readline(). It will work, until you read the last line, and then... it will wait forever. That is bad behaviour. So you will need to solve that.
Related
Well the first problem I run into is that I have no idea how to respond to a command prompt.
bat_location = "F:/SteamLibrary/steamapps/common/Terraria"
os.chdir(bat_location)
os.system("TerrariaServer.exe -steam -lobby friends -config serverconfig.txt")
all of this works, but then when I want to respond to the command prompt which asks me which world I want to run ( the worlds are indexed by numbers from 1 - n (amount of worlds)) I dont know how to respond to it.
I've looked all over google but the code doesnt seem to work.
So basically what I need is when a cmd asks me for example :
Choose World:
I want to automatically respond with the number 10.
os.system("10")
this doesnt seem to do anything, I've also tried a lot with subprocesses but im clearly lost.
Any help is apriciated!
EDIT NR.1 :
Welp, now I've tried this :
bat_location = r'F:\SteamLibrary\steamapps\common\Terraria'
with Popen('TerrariaServer.exe -steam -lobby friends -config serverconfig.txt',
cwd=f'{bat_location}', stdin=PIPE, shell=True) as proc:
proc.stdin.write(b'10\n')
and all it does, im guessing by the response, it just loops around and around.
EDIT NR.2 :
I WILL CLOSE THIS AND START A NEW THREAD, SINCE MY PROBLEM COMPLETELY DERIVED FROM THE ORIGINAL.
From your last few comments, I realized the problem you were having with Popen. When you pass stdout=PIPE and stderr=PIPE, the outputs of the process are captured by the pipes, so you won't see them unless you read from the pipes.
So here's a simple example that you should be able to work with:
import subprocess
from subprocess import PIPE
from textwrap import dedent
with open('tmp.py', 'w') as f:
f.write(dedent("""
print(input())
print(input())
"""))
with subprocess.Popen(['python3', 'tmp.py'], stdin=PIPE) as proc:
proc.stdin.write(b'Hello, world!\n') # write to the process' input
proc.stdin.write(b'Good bye, world!\n') # write to the process' input
If you want to read the data from the function in Python, you can use stdout=PIPE, then use proc.stdout.read and the like, but you may have to be careful about how you get data from the blocking read functions.
I currently try to do a Buffer Overflow attack to a simple C Program.
This Program takes 2 inputs via C's scanf function. The First input is secure, the second is not. So I found my shellcode, the padding and the new return adress. It should spawn a simple shell. So i tried it with the following:
#!/usr/bin/env python
...
p = subprocess.Popen(["/home/user/Desktop/A3/1/exploitme"], shell=True, stdout = subprocess.PIPE, stdin = subprocess.PIPE, stderr=subprocess.PIPE)
p.stdin.write('A\n')
p.stdin.write(OVERFLOWCODE)
stdout, stderr = p.communicate()
print(stdout)
But i don't see the //bin/sh terminal.
However I think the problem is not the Code i use (it should work fine), the Problem seems to be that like the command itself says that it just creates a subprocess where just the programm can communicate with, and not me.
So my question is, how can I make it possible to run the programm, enter two strings to the scanf's and then take control over the Program? Something like spawn a new Terminal and pipe the two commands in there.
The Problem is I can't just enter the Code manually because there is something like ASLR (it creates a buffer with size of srand of unix time in seconds), so I must calculate the return adress every second new.
Any Ideas to make this work?
I need to run a external exe file inside a python script. I need two things out of this.
Get whatever the exe outputs to the stdout (stderr).
exe stops executing only after I press the enter Key. I can't change this behavior. I need the script the pass the enter Key input after it gets the output from the previous step.
This is what I have done so far and I am not sure how to go after this.
import subprocess
first = subprocess.Popen(["myexe.exe"],shell=True,stdout=subprocess.PIPE)
from subprocess import Popen, PIPE, STDOUT
first = Popen(['myexe.exe'], stdout=PIPE, stderr=STDOUT, stdin=PIPE)
while first.poll() is None:
data = first.stdout.read()
if b'press enter to' in data:
first.stdin.write(b'\n')
first.stdin.close()
first.stdout.close()
This pipes stdin as well, do not forget to close your open file handles (stdin and stdout are also file handles in a sense).
Also avoid shell=True if at all possible, I use it a lot my self but best practices say you shouldn't.
I assumed python 3 here and stdin and stdout assumes bytes data as input and output.
first.poll() will poll for a exit code of your exe, if none is given it means it's still running.
Some other tips
one tedious thing to do can be to pass arguments to Popen, one neat thing to do is:
import shlex
Popen(shlex.split(cmd_str), shell=False)
It preserves space separated inputs with quotes around them, for instance python myscript.py debug "pass this parameter somewhere" would result in three parameters from sys.argv, ['myscript.py', 'debug', 'pass this parameter somewhere'] - might be useful in the future when working with Popen
Another thing that would be good is to check if there's output in stdout before reading from it, otherwise it might hang the application. To do this you could use select.
Or you could use pexpect which is often used with SSH since it lives in another user space than your application when it asks for input, you need to either fork your exe manually and read from that specific pid with os.read() or use pexpect.
I'm having troubles getting this to work. Basically I have a python program that expect some data in stdin, that is reading it as sys.stdin.readlines() I have tested this and it is working without problems with things like echo "" | myprogram.py
I have a second program that using the subprocess module calls on the first program with the following code
proc = subprocess.Popen(final_shell_cmd,
stderr=subprocess.PIPE, stdout=subprocess.PIPE,
shell=False), env=shell_env)
f = ' '.join(shell_cmd_args)
#f.append('\4')
return proc.communicate(f)
The second program is a daemon and i have discovered that the second program works well as long as I hit ctrl-d after calling it from the first program.
So it seems there is something wrong with subprocess not closing the file and my first program expecting more input when nothing more should be sending.
anyone has any idea how I can get this working?
The main problem here is that "shell_cmd_args" may contain passwords and other sensitive information that we do not want to pass in as the command name as it will show in tools like "ps".
You want to redirect the subprocess's stdin, so you need stdin=subprocess.PIPE.
You should not need to write Control-D ('\4') to the file object. Control-D tells the shell to close the standard input that's connected to the program. The program doesn't see a Control-D character in that context.
I am running a sub-program using subprocess.popen. When I start my Python program from the command window (cmd.exe), the program writes some info and dates in the window as the program evolves.
When I run my Python code not in a command window, it opens a new command window for this sub-program's output, and I want to avoid that. When I used the following code, it doesn't show the cmd window, but it also doesn't print the status:
p = subprocess.Popen("c:/flow/flow.exe", shell=True, stdout=subprocess.PIPE)
print p.stdout.read()
How can I show the sub-program's output in my program's output as it occurs?
Use this:
cmd = subprocess.Popen(["c:/flow/flow.exe"], stdout=subprocess.PIPE)
for line in cmd.stdout:
print line.rstrip("\n")
cmd.wait() # you may already be handling this in your current code
Note that you will still have to wait for the sub-program to flush its stdout buffer (which is commonly buffered differently when not writing to a terminal window), so you may not see each line instantaneously as the sub-program prints it (this depends on various OS details and details of the sub-program).
Also notice how I've removed the shell=True and replaced the string argument with a list, which is generally recommended.
Looking for a recipe to process Popen data asynchronously I stumbled upon http://code.activestate.com/recipes/576759-subprocess-with-async-io-pipes-class/
This looks quite promising, however I got the impression that there might be some typos in it. Not tried it yet.
It is an old post, but a common problem with a hard to find solution. Try this: http://code.activestate.com/recipes/440554-module-to-allow-asynchronous-subprocess-use-on-win/