I have a linux x86 binary that asks for a password and will print out whether the password is correct or incorrect. I would like to use python to fuzz the input.
Below is a screenshot of me running the binary, then giving it the string "asdf", and receiving the string "incorrect"
Screenshot:
So far, I have tried to use the Python3 subprocess module in order to
Here is my script
p = subprocess.Popen("/home/pj/Desktop/L1/lab1",stdin=subprocess.PIPE, stdout=subprocess.PIPE)
print (p.communicate()[0])
the result of running this script is
b'Please supply the code: \nIncorrect\n'
I am expecting to receive only the prompt however the binary is returning a response of incorrect as well before I have gotten the chance to send my input.
How can I improve my script in order to interact with this binary successfully?
Read the documentation carefully (emphasis mine):
Popen.communicate(input=None)
Interact with process: Send data to stdin. Read data from stdout and stderr, until end-of-file is reached. Wait for process to terminate. The optional input argument should be a string to be sent to the child process, or None, if no data should be sent to the child.
communicate()
returns a tuple(stdoutdata, stderrdata)
.Note that if you want to send data to the process’s stdin, you need to create the Popen object with
stdin=PIPE
. Similarly, to get anything other than None in the result tuple, you need to givestdout=PIPE
and/orstderr=PIPE
too.
So, you're sending nothing to the process, and reading all of stdout
at once.
In your case, you don't really need to wait for the prompt to send data to the process because streams work asynchronously: the process will get your input only when it tries to read its STDIN
:
In [10]: p=subprocess.Popen(("bash", "-c","echo -n 'prompt: '; read -r data; echo $data"),stdin=subprocess.PIPE,stdout=subprocess.PIPE)
In [11]: p.communicate('foobar')
Out[11]: ('prompt: foobar\n', None)
If you insist on waiting for the prompt for whatever reason (e.g. your process checks the input before the prompt, too, expecting something else), you need to read STDOUT
manually and be VERY careful how much you read: since Python's file.read
is blocking, a simple read()
will deadlock because it waits for EOF and the subprocess doesn't close STDOUT
-- thus doesn't produce EOF -- until it get input from you. If the input or output length is likely to go over stdio's buffer length (unlikely in your specific case), you also need to do stdout reading and stdin writing in separate threads.
Here's an example using pexpect
that takes care of that for you (I'm using pexpect.fdexpect
instead of pexpect.spawn
suggested in the doc 'cuz it works on all platforms):
In [1]: import pexpect.fdpexpect
In [8]: p=subprocess.Popen(("bash", "-c","echo -n 'prom'; sleep 5; echo 'pt: '; read -r data; echo $data"),stdin=subprocess.PIPE,stdout=subprocess.PIPE)
In [10]: o=pexpect.fdpexpect.fdspawn(p.stdout.fileno())
In [12]: o.expect("prompt: ")
Out[12]: 0
In [16]: p.stdin.write("foobar") #you can communicate() here, it does the same as
# these 3 steps plus protects from deadlock
In [17]: p.stdin.close()
In [18]: p.stdout.read()
Out[18]: 'foobar\n'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With