I need to set an environment variable in Python and find the address in memory where it is located. Since it's on Linux, I don't mind about using libraries that only work consistently on Linux (if that's the only way). How would you do this?
Edit: The scope of the problem is as follows: I'm trying to hack a program for class, and essentially I'm putting my shellcode into an environment variable and then overwriting one byte on the victim code with the address of my environment variable. I need to find a way to automate this in Python, so my question is two-fold:
Is there a way to get the address in
memory of an environment variable?
Can this only be done in bash/C or
can I do it purely in Python?
For accessing and setting environment variables, read up on the os.environ dictionary. You can also use os.putenv to set an environment variable.
The built in function id() returns a unique id for any object, which just happens to be it's memory address.
http://docs.python.org/library/functions.html#id
Pass the address itself in an environment variable, and just read it with os.getenv().
Related
Like I said in the title I don't get what os.getenv("HOME") does in this code. I am following a course on an online site and the tutor was coding an interface with PyQt5 similar to notepad. I searched for an answer but they are a bit too advanced I guess. Also I have no idea what an environment variable is. By the way this is my first question on stack so excuse me for any possible mistakes and insufficient information.
def open_file(self):
file_name=QFileDialog.getOpenFileName(self,"Open File",os.getenv("HOME"))
with open(file_name[0],"r") as file:
self.writing_ar.setText(file.read())
The function above is connected to a button self.open such as self.open.clicked.connect(self.open_file)
And self.writing_ar is a QTextEdit object
In the case of os.getenv('HOME'), it's a UNIX-centric way to get the current user's home directory, which is stored as an environment variable per POSIX specification. A typical home directory location is /Users/yourname on MacOS, or /home/yourname on Linux, or c:\Users\Your Name on Windows -- so that's what this code is trying to look up.
The set of environment variables is effectively a key/value store, mapping strings to other strings, that is copied from any program to other processes it starts; they're thus a way to share configuration and other information between programs (though it only shares information down the tree, propagated only on process creation; changes made by a child process are not seen by its parent; and changes to a parent's environment after a child is started are not seen by the child).
If you want something that works reliably even on Windows, consider os.path.expanduser("~") instead. Thus, your code might become:
file_name = QFileDialog.getOpenFileName(self,
"Open File",
os.path.expanduser("~"))
See also What is the correct cross-platform way to get the home directory in Python?
It basically gets an environment variable for you and cast that onto a python variable.
From the code you shared, there should be a variable defined at the operating system level named HOME.
In Linux, that can be done with
export HOME="something_here"
You can check that this variable has actually been defined by typing
echo "$HOME"
in the terminal.
You can think of the os.getenv() method like it "echoes" the value of that argument onto some variable.
I am trying to do a return-to-libc attack. The problem is that I need the address of an environment variable at the stack for the argument of an gadget. I tried the following code with python. But it seems that it gives an offset or something else ? Not sure about that.
r=process('/rop_level', env={'MYENV': 'cat /flag'})
os.environ.get('MYENV')
h = os.environ.get('MYENV')
hex(id(h))
The result it gives is 0x9d4380. I kinda need an address at stack like 0x7ffe.....
The CTF challenge is located in a container which requires ssh so I may not be able to use gdb.
As you already know, the environment variables are on the stack. So you need to leak the stack address through some way. And you should calculate the offset between leaked stack address and the environment variable by local debugging. then you calculate the environment variable's address.
In Python I can access an environment variable as:
os.environ['FOO']
I would like to know if the variable was set previously via export or if it was set only for the current python script like so:
FOO=BAR python some-script.py
Basically I want to only use FOO if it was set like in the line above and not permanently defined per export.
Arguments to the python script itself unfortunately are no option here. This is a plugin and the parent application does not allow passing custom arguments it does not understand itself.
I was hoping I somehow could access the exact and full command (FOO=BAR python some-script.py) that started python but it appears like there is nothing like that. I guess if there was a feature like this it would be somewhere in the os or sys packages.
The environment is simply an array of C strings, there is no metainformation there which helps you find out whether or not the invoking shell had the variable marked for export or not.
On Linux, you could examine /proc/(pid)/environ of the parent PID (if you have suitable permissions) to see what's in the parent's permanent environment, but this is decidedly nonportable and brittle.
Spending time on this seems misdirected anyway; let the user pass the environment variable in any way they see fit.
Usually, it is a good idea to load a configuration from a configurable file. This is what from_envvar() can do, replacing the from_object() line above:
app.config.from_envvar('FLASKR_SETTINGS', silent=True)
That way someone can set an environment variable called FLASKR_SETTINGS to specify a config file to be loaded which will then override the default values. The silent switch just tells Flask to not complain if no such environment key is set.
I am not too familiar with environment variables. I would like an explanation of the above paragraph in simple terms. My best guess is that when the program reads FLASKR_SETTING does that mean that on my own computer I have set up a mapping to this file with that name with something called an environment variable? Ive messed with my environment path before and to be honest I still don't understand it, so I came here looking for a clear answer
Environment variables are a name,value pair that are defined for a particular process running on a computer (windows or UNIX/LINUX etc.). They are not files. You can create your own environment variables and give it any name/value. For example, FLASKR_SETTING is the name of the environment variable who value could be set to a config file. On a UNIX terminal for example, you can do:
export FLASKR_SETTING = /somepath/config.txt
By doing the above, you have just created an environment variable named FLASKR_SETTING whose value is set to /somepath/config.txt. The reason you use environment variables is because you can tie them to a certain process and use on demand when your process starts. You don't have to worry about saving them in a file. In fact, you can create a launch script for your process/application that can set a variety of environment variables before you starting using the application.
In case of flask, app.config.from_envvar('FLASKR_SETTINGS', silent=True) sets the value of FLASKR_SETTINGS to the value from the env. variable. So it basically translates to:
- Find the config file (/somepath/config.txt etc.)
- lets say the contents of config file is:
SECRET_KEY="whatever"
DEBUG = True
- Then using the 2 above, it will be translated to:
app.config['SECRET_KEY'] = "whatever"
app.config['DEBUG'] = True
So this way, you can just update the config file as needed and you will not need to change your code.
Environment variables are a simple, ad-hoc way of passing information to programs. On unixy machines, from a command shell, it's as simple as
export FLASKR_SETTINGS=/path/to/settings.conf
/path/to/program
This is especially useful when installing programs to start up at reboot; the configuration can be easily included in the same setup script that launches the system program.
I have a DLL obtaining startup options using getenv (<stdlib.h>) call. I would like to set that variable in the same process, before opening the DLL, so that it is accessible via getenv. Which function should I use to set it?
I learned that there are two sets of env vars under windows: one is manipulated via win32 API (GetEnvironemntVariable, SetEnvironmentVariable), another one can be read using getenv, and probably set via _putenv, is that the one I should use?
Is this function accessible from python, perhaps via ctypes?
The current ~VS2019 situation appears to be:
The calls to the getenv function retrieve the values from a block the MS CRT initializes at load time.
Calls to GetEnvironmentVariable retrieve the value from the process environment block.
Calls to SetEnvironmentVariable update only the value from the process environment block. These changes will not be seen by getenv.
Calls to putenv update both the value in the CRT block and also additionally call Win32 SetEnvironmentVariable to update the process environment block.
So, actually regardless of what you use it for:
Use _wputenv_s to set the env var - it will update both.
Use ::GetEnvironmentVariableW to read: It will read from the environment block, which will contain the value regardless of which method was used.
Regarding getenv
If the code using getenv is using the same MS CRT that your code -- that is, the code is dynamically linked to the CRT and actually uses the same version as you, then you can always use putenv.
If the DLL (AND its CRT) is dynamically or delay-loaded and you are able to call putenv before the dll is loaded, then you can use it.
(This is conjecture, I have not tested this exactly:) If the DLL is already loaded in you process and it uses a statically linked CRT, or another CRT than the one you are using, than the environment data for its getenv call is already loaded up, an nothing that you do on your side of the DLL boundary will change that. Out of luck in this case I guess.
Ref:
https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/getenv-wgetenv?view=msvc-170
https://github.com/curl/curl/issues/4774
https://blogs.msmvps.com/senthil/2009/10/13/when-what-you-set-is-not-what-you-get-setenvironmentvariable-and-getenv/
As the question is tagged with Python, the blessed way to manage environment variables in Python is to update the os.environ mapping.
Because the doc for os.putenv() says:
Assignments to items in os.environ are automatically translated into corresponding calls to putenv(); however, calls to putenv() don’t update os.environ, so it is actually preferable to assign to items of os.environ.