Playing a bit with Jython lately.
As in other programming languages & scripting tools needed to invoke another Application. Be it another script or Application, one occasionally needs to spawn another stand-alone app:
So looked at some sample code and ended up with something resembling
import sys import os import tempfile import popen2 script_contents = 'Echo "Hello World"' script_file = tempfile.mktemp('.cmd') file = open(script_file, 'w') file.write(script_contents) file.close() command = r'"%s"' % script_file proc = popen2.Popen3(command, True) proc.tochild.close() output = proc.fromchild.read() errors = proc.childerr.read() status = proc.wait() print '[DEBUG] OUTPUT: %s' % output print '[DEBUG] ERRORS: %s' % errors print '[DEBUG] RETURN CODE: %s' % status if os.path.isfile(script_file): os.remove(script_file)
Though, the above script is a bit watered-down it basically does the following:
- Dynamically generates a payload
- Creates a temporary file
- Saves the generated payload unto the temporary file
- Invokes the Temp file
- Cleans-up by removing the temp file
As I tried running the app kept getting an error that resembles the error listed below:
Failed to get environment, environ will be empty: (0, 'Failed to execute command ([\'sh\', \'-c\', \'env\']): java.io.IOException: Cannot run program "sh": CreateProcess error=2, The system cannot find the file specified') script_file name is: e:\temp\tempfile.cmd Traceback (innermost last): File "C:\Windows\TEMP\eqscript1323213519948", line 41, in ? File "E:\Program Files (x86)\jython\Lib\popen2.py", line 72, in __init__ File "E:\Program Files (x86)\jython\Lib\javashell.py", line 64, in execute OSError: (0, 'Failed to execute command ([\'sh\', \'-c\', "e:\\\\temp\\\\tempfile.cmd"\']): java.io.IOException: Cannot run program "sh": CreateProcess error=2, The system cannot find the file specified')
Had a bit of difficulty understanding the problem:
- Was the system having difficulty determining the temporary folder
- Did we not have access to the temporary folder
To get a bit closer to what was happening behind the scene, commented out the bit of code that was removing the script file:
Doing so allowed us to preserve the payload and execute the payload file directly (against the OS).
if os.path.isfile(script_file): os.remove(script_file)
Ended up the at the same place \ space:
Could not execute due to file not found.
More goggling brought us joy. The problem is that sometimes one has to explicitly specify the OS.
The clue came from:
Jython – javaos.getenv() gives “Failed to get environment, environ will be empty”
Try to uncomment and change the os setting in the 'registry' file (it is in the same directory as your jython.jar / i hope) # python.os determines operating-specific features, similar to and overriding the # Java property "os.name". # Some generic values are also supported: 'nt', 'ce' and 'posix'. # Uncomment the following line for the most generic OS behavior available. #python.os=None python.os=nt # try nt or dos
Once we knew we had to deal with the registry file the next question is what is actual name of the registry file, where should it be placed, what determines where the system looks for it:
The easiest path would have being to go back and read the Language’s documentation, but as always took the laziest path. Googled for it:
Found some help along the way via:
- “Failed to execute command ([\’sh\’, \’-c\’, \’env\’]): java.io.IOException: Cannot run program “sh”: CreateProcess error=2, The system cannot find the file specified.”
The registry file:
- The name of the registry file is registry
- Review our jython is invoked – In our case jython.bat and make a note of any arguments passed in or initialized
In our case, we created a file named registry and added this lone line:
Things worked well once we explicitly specified that our OS is Windows.
It is probably that by default the OS is Unix.
But, as Billy Currington said, thank God for good directions, on my way back home, went back (after the fact) and read the Jython’s FAQ:
The location and name of the registry was a bit clearer:
Where’s the registry file?
Jython’s installation includes a file called “registry” that you will find in the root directory of the Jython installation (e.g. /usr/local/jython or c:jython).
At initialization, Jython searches for the “registry” file in the directory specified by the “python.home” property, or the “.jython” file in the user’s home directory.
The “python.home” property is often set in the startup with Java’s -D switch. The shell script that starts Jython (jython.bat or jython) demonstrates the use of the -D switch to set the “python.home” property. When embedding Jython, it is often still best to use the -D switch because the -D properties appear in System.getProperties(), which is usually the “preProperties” (first arg) in the static PythonInterpreter.initialize method. With python.home in the preProperties, the interpreter successfully loads preProperties, registry properties, and postProperties (the second arg to initialize) in the correct order.
If you wish to use your home directory, and do not know where your home directory is, don’t worry- Jython knows:>>> print java.lang.System.getProperty ("user.home")