printf and getenv [closed] - c

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 11 years ago.
Ubuntu 10.04, C, gcc, x86 Intel proc:
When trying to print the address of an environmental variable using printf, the address printed is not correct in this toy program (this is a consciously backward version in which I tried to isolate the source of the problem by saving the address value on the heap, not using a pointer directly as I read it can be overwritten, and using a pointer straight up produced the same issue):
#include <stdio.h>
#include <stdlib.h>
int main(){
const char* d = getenv("TEST");
unsigned i = (unsigned*) malloc(sizeof(unsigned));
i = (unsigned*) d;
printf("%s at location 0x%8d.\n", "TEST", i);
}
EDIT: same issue with this (the original) version)
int main(){
const char* d = getenv("TEST");
printf("%s at location %p.\n", "TEST", d);
return 0;
}
This question has nothing to do with how to print a pointer. Kindly read on.
If I change the program to not print TEST's address, but TEST as a string (its value), no problem.
However, the address returned is not the address at which the environmental variable is actually located before entering the print sub-routine; and which, by the above set-up, should be printed. Using main's disassembly and TEST's address in the eax register, I am referred to the proper location of the TEST variable, which is a little further down than main's stack frame at about 0xbffffiii on my system (i any hex value). The address value printed is on the order of 0xbfeiiiii.
I don't understand. Is this a security precaution to prevent environmental variables from being overwritten (eg, to smash the stack)? If yes, does the compiler really keep track of transferring the address as I do above, and silently adjusting its value?
Or am I missing something? (probably)
Many thanks.
P.S.: To remove imaginable sources of issues, I compiled first with no options, then:
gcc -O0 -static -fno-stack-protector -g program.c

This is not the right way to print an address. Just use the %p format to print (void*)d.
printf("%s at location 0x%p.\n", "TEST", (void*)d);

I figured it out, following a comment by R.. further above who pointed me in the direction of ASLR.
I was unfamiliar with ASLR stack protection. What I describe is due to ASLR scrambling the memory address space to prevent prediction of the location of variables relative to it. ASLR has long been default switched on in LINUX kernels it appears.
To see what I meant, get su privileges, then enter (the precise integer to send might vary based on your distro; on mine it is 0, and the default 2. Also better confirm the file only contains 1 integer by first looking at it, as it does on my system):
cd /proc/sys/kernel
export OLD=$(less randomize_va_space) // save old value to restore after
echo 0 > randomize_va_space // 0 == turn off ASLR
Then run my little program again: it will report back the address I expected (around 0xbffffiii). After, obviously, restore old protection using
echo $OLD > randomize_va_space
Many thanks for everyone who spend some of their time trying to help.

Storing a char* pointer in an unsigned variable might work on some systems, but is not portable. For example, on my 64-bit Ubuntu box sizeof(char*)==8 and sizeof(unsigned)==4. The portable way to store a pointer in an integer variable is to use the intptr_t type.
Alternatively, to simply print the address use %p like so:
#include <stdio.h>
#include <stdlib.h>
int main() {
const char* d = getenv("TEST");
printf("%s at location %p.\n", "TEST", d);
}
On my Ubuntu box, this prints out either
TEST at location (nil).
or
TEST at location 0x7fff8cf34628.
depending on whether $TEST is set (of couse the address can vary).

However, the address returned is not the address at which the
environmental variable is actually located before entering the print
sub-routine; and which, by the above set-up, should be printed. Using
main's disassembly and TEST's address in the eax register, I am
referred to the proper location of the TEST variable, which is a
little further down than main's stack frame at about 0xbffffiii on my
system (i any hex value). The address value printed is on the order of
0xbfeiiiii.
Note that there are several copies being made here: the literal "TEST" in your program, used to find the key "TEST" in the environment of your program, the value string for the key "TEST" in that environment and a pointer to that value string returned by getenv(). I don't know what you expected to get, but the environment is generally not near the stack in any of the x86 environments I know.
What you probably saw in the disassembly was the pointer to the "TEST" string in your program, somewhere in the local stackframe for main(). That is not the environment variable, that is a string used to search for the environment variable in the environment, by comparing the string in your program with the real one.
So I don't really know what you expected, but it looks as if you are expecting the wrong thing, sorry.
The address of the literal "TEST" should be somewhere in your program, probably in a read-only segment. The address of the pointer to that string is somewhere close to the stack pointer. The address of the string "TEST" in your environment should not be near the stack at all (probably at a lower address than your program). The string associated with "TEST" should be very near to it, and that should be the address returned by getenv().

You are assuming that environment variables are stored in some particular place, apparently based on examining memory with gdb. I suggest that it's not your program's output that's incorrect, but your assumptions about where environment variables are stored.
getenv() returns a pointer to a string which hold the value of the specified environment variable. If it's at a different address than what you expected, how is that a problem?
Consider the following program:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
const char *test = getenv("TEST");
if (test == NULL) {
puts("test == NULL");
}
else {
printf("test == %p, points to \"%s\"\n", (void*)test, test);
/* WARNING: The following has undefined behavior! */
*(char*)test = 'X';
system("echo $TEST");
}
return 0;
}
When I run it on my system (Ubuntu 11.04, x86, gcc 4.3.4) with $TEST set to "foobar", it prints:
test == 0x6125f299, points to "foobar"
Xoobar
So getenv() gave me a pointer to a string that, when I modified it, showed up as a change in the environment of a child process.
Again, what exactly is the problem?

Related

Function argument and variable addresses in C

I have the following program:
#include <stdio.h>
void func(char *str) {
int a = 4;
printf("\n str Address: 0x%8X\n", (unsigned int)&str);
printf("\n a Address: 0x%8X\n", (unsigned int)&a);
}
void main()
{
char c = 'y';
func(&c);
}
When I run the program, I get the following result:
str Address: 0x43570EB8
a Address: 0x43570ECC
My understanding is that the stack in Linux grows from high address to low address. Also str as an argument would be pushed first on the stack. If that is the case, why is str address lower than address for variable a ? Am I printing the addresses in an incorrect way ?
Most likely the parameter str is passed in a register. Normally, it would be used from that register and would never exist on the stack. Because your code takes the address of str, the compiler is forced to put it in memory somewhere so it can provide an address. It appears that the compiler created space for a on the stack first (or at least at a higher address), and then created space for str on the stack and copied the value from the register to the stack location.
You should not expect that inspecting the addresses of objects reveals or mirrors other aspects of a platform, such as its Application Binary Interface (which specifies, among other things, how function parameters are passed) or how stack is managed. A C implementation is free to rearrange things as long as the resulting program achieves the same observable behavior as defined by the C standard, and modern C implementations can make large and unexpected transformations while optimizing programs. Observable behavior includes defined outputs of a program but does not include any rules about the ordering of addresses of objects.
Incidentally, regarding your last question, yes, you are printing addresses incorrectly. To print an address, cast it to void * and print it with %p, not %X.

Unexpected address output

I am trying to figure out how the addresses are assigned to variables located on the stack. I ran the little program below:
int main()
{
long a;
int b;
int c;
printf("&a = %p\n", &a);
printf("&b = %p\n", &b);
printf("&c = %p\n", &c);
}
The output I expected was (considering addresses are going down):
&a = 0x7fff6e1acb88
&b = 0x7fff6e1acb80
&c = 0x7fff6e1acb7c
But instead I got:
&a = 0x7fff6e1acb88
&b = 0x7fff6e1acb80
&c = 0x7fff6e1acb84
How come the c variable is located between the a and b variable? Are variables not put on the stack as they are declared?
I tried replacing the type of a from long to int and I got this:
&a = 0x7fff48466a74
&b = 0x7fff48466a78
&c = 0x7fff48466a7c
Here I don't understand why are the addresses going up, while they were going down previously?
I compiled the program using gcc version 4.7.2 (Ubuntu/Linaro 4.7.2-11precise2), if that's of any help.
Are variables not put on the stack as they are declared?
No.
why are the addresses going up, while they were going down previously?
They could going up, but they do not have to.
Compilers is free to rearrage the order of local variables that it sees is fit, or it could even delete or add some.
Variables are not necessarily put on the stack in the order in which they are declared. You can't predict where on the stack they will be -- they could be in any order. As glglgl pointed out in the comments, they don't even have to be on the stack and could simply be held in registers.
Even though the stack pointer is counting downwards on your given CPU, the program will be using stack frames. How a certain parameter is allocated inside the stack frame is implementation-defined.
Also note that some CPUs have up-counting stack pointers.
Also note that local variables are not necessarily allocated on the stack. More often, they are allocated in CPU registers. But when you take the address of a variable, you kind of force the compiler to allocate it on the stack, since registers have no addresses.
The direction of stack growth depends on the architecture. On x86, stack grows down (from higher address to lower). How the variables are put on the stack also depends on the OS's Application binary interface (ABI) and how the compiler follows the ABI convention. But, the compiler may not necessarily follow the ABI conventions all the time.
it depends on the compiler.
for example I test your code with "GNU GCC version 4.8.1" and the Compiler allocate all locale variables in order :
&a = 0x7fffe265d118
&b = 0x7fffe265d114
&c = 0x7fffe265d110
Agreeing with #Lundin that you cannot print the address of the registers these a most likely sitting in. The best thing you can do to see how these are stored would be to dump the object code and investigate what happens when you create more local variables then the amount of registers to hold them. That is when you'll see the stack activity (in the disassembly ).
$ gcc -c main.c -o main.o
$ objdump -D main.o > main.dump

Getting address of Environmental Variable

I have an environment variable and I'm trying to get its memory address. I have
memset(&buffer, 0x90, 517);
memcpy(&buffer[517-strlen(shellcode)],shellcode,strlen(shellcode));
setenv("EGG",buffer,1);
putenv(buffer);
printf("EGG address: 0x%1x\n", getenv("EGG"));
system("bash");
The memory address it printed out was 0x804b00c. That looked incorrect. I checked it with GDB x/x 0x804b00c. It said cannot access memory at 0x804b00c. So getenv is basically giving me garbage memory. I have called env to make sure the EGG variable was set, and it was.
Why cannot I get the memory address of EGG?
Thanks for this question, another learning opportunity!
Have distilled your code to the following:
#include <stdio.h>
#include <stdlib.h>
void main()
{
const char shellcode[] = "EGG=whatever";
putenv(shellcode);
printf("EGG address #%08X\n", getenv("EGG"));
printf("EGG value is <%s>.", getenv("EGG"));
}
This code works in an Eclipse/Microsoft C compiler environment. Note, I did not have to call setenv or bash or issue a system command. In this example, the environment variable EGG is set for the process.
Also, notice the difference between address of EGG and its actual value. In the first case getenv returns a char * which is a pointer to storage as defined by the %08X part of the printf statement, while %s essentially de-references the char pointer returned by getenv. Also, getenv() is found thru the #include <stdlib.h> statement.
Preliminary answer is that you have little Endian hardware. Thus, words (4 bytes, aligned at a word boundary) are stored with the halfwords and bytes within the halfwords, SWAPPED. 0x0804b00c is more likely really at 0x0cb04b80.
Will try writing my own c-code to do what you want and will post a second note.

Can an address be assigned to a variable in C?

Is it possible to assign a variable the address you want, in the memory?
I tried to do so but I am getting an error as "Lvalue required as left operand of assignment".
int main() {
int i = 10;
&i = 7200;
printf("i=%d address=%u", i, &i);
}
What is wrong with my approach?
Is there any way in C in which we can assign an address we want, to a variable?
Not directly.
You can do this though : int* i = 7200;
.. and then use i (ie. *i = 10) but you will most likely get a crash. This is only meaningful when doing low level development - device drivers, etc... with known memory addreses.
Assuming you are on an x86-type processer on a modern operating system, it is not possible to write to aribtray memory locations; the CPU works in concert with the OS to protect memory so that one process cannot accidentally (or intentionally) overwrite another processes' memory. Allowing this would be a security risk (see: buffer overflow). If you try to anyway, you get the 'Segmentation fault' error as the OS/CPU prevents you from doing this.
For technical details on this, you want to start with 1, 2, and 3.
Instead, you ask the OS to give you a memory location you can write to, using malloc. In this case, the OS kernel (which is generally the only process that is allowed to write to arbitrary memory locations) finds a free area of memory and allocates it to your process. The allocation process also marks that area of memory as belonging to your process, so that you can read it and write it.
However, a different OS/processor architecture/configuration could allow you to write to an arbitrary location. In that case, this code would work:
#include <stdio.h>
void main() {
int *ptr;
ptr = (int*)7000;
*ptr = 10;
printf("Value: %i", *ptr);
}
C language provides you with no means for "attaching" a name to a specific memory address. I.e. you cannot tell the language that a specific variable name is supposed to refer to a lvalue located at a specific address. So, the answer to your question, as stated, is "no". End of story.
Moreover, formally speaking, there's no alternative portable way to work with specific numerical addresses in C. The language itself defines no features that would help you do that.
However, a specific implementation might provide you with means to access specific addresses. In a typical implementation, converting an integral value Ato a pointer type creates a pointer that points to address A. By dereferencing such pointer you can access that memory location.
Not portably. But some compilers (usually for the embedded world) have extensions to do it.
For example on IAR compiler (here for MSP430), you can do this:
static const char version[] # 0x1000 = "v1.0";
This will put object version at memory address 0x1000.
You can do in the windows system with mingw64 setup in visual studio code tool, here is my code
#include<stdio.h>
int main()
{
int *c;
c = (int *)0x000000000061fe14; // Allocating the address 8-bit with respect to your CPU arch.
*c = NULL; // Initializing the null pointer for allocated address
*c = 0x10; // Assign a hex value (you can assign integer also without '0x')
printf("%p\n",c); // Prints the address of the c pointer variable
printf("%x\n",*c); // Prints the assigned value 0x10 -hex
}
It is tested with mentioned environment. Hope this helps Happy coding !!!
No.
Even if you could, 7200 is not a pointer (memory address), it's an int, so that wouldn't work anyway.
There's probably no way to determine which address a variable will have. But as a last hope for you, there is something called "pointer", so you can modify a value on address 7200 (although this address will probably be inaccessible):
int *i = (int *)7200;
*i = 10;
Use ldscript/linker command file. This will however, assign at link time, not run time.
Linker command file syntax depends largely on specific compiler. So you will need to google for linker command file, for your compiler.
Approximate pseudo syntax would be somewhat like this:
In linker command file:
.section start=0x1000 lenth=0x100 myVariables
In C file:
#pragma section myVariables
int myVar=10;
It's not possible, maybe possible with compiler extensions. You could however access memory at an address you want (if the address is accessible to your process):
int addr = 7200;
*((int*)addr) = newVal;
I think '&' in &a evaluates the address of i at the compile time which i think is a virtual address .So it is not a Lvalue according to your compiler. Use pointer instead

C: return address of function (mac)

following short c program:
void foo(int a, int b) {
printf("a = %p b = %p\n", &a, &b);
}
main() {
foo(1, 2);
}
ok, now I used gdb to view this program. I got as output:
a = 0x7fff5fbff9ac b = 0x7fff5fbff9a8
and stopped execution after the output (in foo()). now I examined 0x7fff5fbff9ac and the content was:
1....correct
then 0x7fff5fbff9a8 and the content:
2...correct
now I wanted to view the return address of the function and examined (a + 4 bytes) with:
x/g 0x7fff5fbff9b1 (8 bytes!! address, therefore "g" (giant word))
and its content was:
(gdb) x/g 0x7fff5fbff9b1
0x7fff5fbff9b1: 0xd700007fff5fbff9
BUT: THIS IS NOT THE RETURN ADR FROM MAIN! where is my fault?
There are a whole bunch of faulty assumptions in your question.
You're assuming that integer arguments are passed on the stack immediately above the return address (as they are in many--not all--x86 ABIs under the default calling conventions). If this were the case, then immediately following the call, your stack would look like this:
// stack frame of main( )
// ...
value of b
value of a
return address <--- stack pointer
However, your assumption is incorrect. You have compiled your code into a 64-bit executable (as evidenced by the size of the pointer you are printing). Per the OS X ABI, in a 64-bit Intel executable, the first few integer arguments are passed in register, not on the stack. Thus, immediately following the call, the stack actually looks like this:
// stack frame of main( )
// ...
return address <--- stack pointer
Since you take the address of a and b, they will be written to the stack at some point before the call to printf( ) (unless the compiler is really clever, and realizes that it doesn't actually need to hand printf( ) valid pointers because it won't use the value pointed to, but that would be pretty evil as optimizations go), but you really don't know where they will be relative to the return address; in fact, because the 64-bit ABI provides a red zone, you don't even know whether they're above or below the stack pointer. Thus, at the time that you print out the address of a and b, your stack looks like this:
// stack frame of main( )
// ...
return address |
// ... |
// a and b are somewhere down here | <-- stack pointer points somewhere in here
// ... |
In general, the C language standard says nothing about stack layouts, or even that there needs to be a stack at all. You cannot get this sort of information in any portable fashion from C code.
Firstly, &a + 4 is 0x7FFF5FBFF9B0, so you are looking one byte offset from where you think you are.
Secondly, the saved frame pointer lies between a and the return address, and this is the value you are seeing.
What you are doing wrong is making a whole bunch of incorrect and random assumptions about the layout of the stack frame on your given platform. Where did you get that weird idea about "a + 4 bytes" location supposedly holding the return address?
If you really want to do this, get the documentation for your platform (or do some reverse engineering) to find out where and how exactly the return address is stored. Making random guesses and then asking other people why your random guesses do not produce results you for some reason expect is not exactly a productive way to do it.

Resources