Kendall Weihe Kendall Weihe - 1 month ago 7
Python Question

Python subprocess hangs

I'm executing the following subprocess...

p.call(["./hex2raw", "<", "exploit4.txt", "|", "./rtarget"])


...and it hangs.

But if I execute
kmwe236@kmwe236:~/CS485/prog3/target26$ ./hex2raw < exploit4.txt | ./rtarget
then it executes fine. Is there something wrong with using the input or piping operator?

I also tried
sp.call(["./hex2raw", "<", "exploit4.txt", "|", "./rtarget"], shell=True)


The entire code looks like this UPDATED WITH SUGGESTIONS

import subprocess as sp
import pdb

for i in range(4201265,4201323):
pdb.set_trace()
d = hex(i)[2:]
output = " "
for i in range(len(d),0,-2):
output = output + d[i-2:i] + " "

out_buffer = "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" + output + "00 00 00 00"

text_file = open("exploit4.txt", "w")
text_file.write("%s" % out_buffer)

# sp.call(["./hex2raw", "<", "exploit4.txt", "|", "./rtarget"], shell=True)
with open("exploit4.txt") as inhandle:
p = sp.Popen("./hex2raw",stdin=inhandle,stdout=sp.PIPE)
p2 = sp.Popen("./rtarget",stdin=p.stdout,stdout=sp.PIPE)
[output,error] = p2.communicate()


I'm getting an error is

File "/usr/lib/python2.7/subprocess.py", line 710, in __init__
errread, errwrite)
File "/usr/lib/python2.7/subprocess.py", line 1327, in _execute_child
raise child_exception
OSError: [Errno 8] Exec format error


After debugging it occurs at the fire subprocess call
p = sp.Popen("./hex2raw",stdin=inhandle,stdout=sp.PIPE)

Answer

Since you're using redirection and piping, you have to enable shell=True

sp.call(["./hex2raw", "<", "exploit4.txt", "|", "./rtarget"],shell=True)

but it would be much cleaner to use Popen on both executables and feeding the contents of exploit4.txt as input. Example below, adapted to your case:

import subprocess

    with open("exploit4.txt") as inhandle:
        p = subprocess.Popen("./hex2raw",stdin=inhandle,stdout=subprocess.PIPE)
        p2 = subprocess.Popen("./rtarget",stdin=p.stdout,stdout=subprocess.PIPE)
        [output,error] = p2.communicate()
        print(output)
        # checking return codes is also a good idea
        rc2 = p2.wait()
        rc = p.wait()

Explanation:

  1. open the input file, get its handle inhandle
  2. open the first subprocess, redirecting stdin with inhandle, and stdout to an output stream. Get the pipe handle (p)
  3. open the second subprocess, redirecting stdin with previous process stdout, and stdout to an output stream
  4. let the second process communicate. It will "pull" the first one by consuming its output: both processes work in a pipe fashion
  5. get return codes and print the result

Note: you get "format error" because one or both executables are actually shell or other non-native executables. In that case, just add the shell=True option to the relevant Popen calls.

Comments