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.
Related
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.
I was experimenting with pointers. Look at this code:
#include <stdio.h>
int main() {
int numba = 1;
int *otherintptr = &numba;
printf("%d\n", otherintptr);
printf("%d\n", *otherintptr);
*otherintptr++;
printf("%d\n", otherintptr);
printf("%d\n", *otherintptr);
return 0;
}
The output is:
2358852
1
2358856
2358856
Now, I am well aware that (*otherintptr)++ would have incremented my int, but my question is not this.
After the increment, the memory location is correctly increased by 4 bytes, which is the size of an integer.
I'd like to know why the last printf instruction prints the memory location, while I am clearly asking to print the content of memory locations labelled 2358856 (I was expecting some dirty random content).
Note that the second printf statement prints the content of memory cell 2358852, (the integer 1) as expected.
What happens with these two lines
int numba = 1;
int *otherintptr = &numba;
due to the fact the C compiler will generate a sequential memory layout, otherintptr will initially point to the memory address corresponding to the numba variable. And this is relative to the stack frame allocated when main was called.
Now, the next position on the stack (actually the previous if we consider that the stack grows down on x86 based architectures) is occupied by the otherintptr variable. Incrementing otherintptr will make it point to itself, thus you see the same value.
To exemplify, let's assume that the stack for main begins at the 0x20 offset in memory:
0x20: 0x1 #numba variable
0x24: 0x20 #otherintptr variable pointing to numa
After executing the otherintptr++ instruction, the memory layout will look like this:
0x20: 0x1 #numba variable
0x24: 0x24 #otherintptr variable now pointing to itself
This is why the second printf's have the same output.
When you did otherintptr++, you accidentally made otherintptr to point to otherintptr, i.e. to itself. otherintptr just happened to be stored in memory immediately after your numba.
In any case, you got lucky on several occasions here. It is illegal to use an int * pointer to access something that is not an int and not compatible with int. It is illegal to use %d to print pointer values.
I suppose you wanted to increment the integer otherpointer points to (numba). However, you incremented actually the pointer, as ++ binds stronger than *
see here.
So otherpointer pointed past the variable. And as there is no valid variable, dereferencing the pointer is undefined behaviour. Thus, anything can happen and you just were lucky the program did not crash. It just happend by chance otherpointer itself resided at that address.
i am just started learning pointers in c. I have following few doubts. If i find the answers for the below questions. It Will be really useful for me to understand the concept of pointers in c. Thanks in advance.
i)
char *cptr;
int value = 2345;
cptr = (char *)value;
whats the use of (char *) and what it mean in the above code snippet.
ii)
char *cptr;
int value = 2345;
cptr = value;
This also compiles without any error .then whats the difference between i & ii code snippet
iii) &value is returning address of the variable. Is it a virtual memory address in RAM? Suppose another c program running in parallel, will that program can have same memory address as &value. Will each process can have duplicate memory address same as in other process and it is independent of each other?
iv)
#define MY_REGISTER (*(volatile unsigned char*)0x1234)
void main()
{
MY_REGISTER=12;
printf("value in the address tamil is %d",(MY_REGISTER));
}
The above snippet compiled successfully. But it outputs segmentation fault error. I don't know what's the mistake I am doing. I want to know how to access the value of random address, using pointers. Is there any way? Will program have the address 0x1234 for real?
v) printf("value at the address %d",*(236632));//consider the address 236632 available in
//stack
why does the above printf statement showing error?
That's a type cast, it tells the compiler to treat one type as some other (possibly unrelated) type. As for the result, see point 2 below.
That makes cptr point to the address 2345.
Modern operating systems isolate the processes. The address of one variable in one process is not valid in another process, even if started with the same program. In fact, the second process may have a completely different memory map due to Address Space Layout Randomisation (ASLR).
It's because you try to write to address 0x1234 which might be a valid address on some systems, but not on most, and almost never on a PC running e.g. Windows or Linux.
i)
(char *) means, that you cast the data stored in value to a pointer ptr, which points to a char. Which means, that ptr points to the memory location 2345. In your code snipet ptr is undefined though. I guess there is more in that program.
ii)
The difference is, that you now write to cptr, which is (as you defined) a pointer pointing to a char. There is not much of a difference as in i) except, that you write to a different variable, and that you use a implicit cast, which gets resolved by the compiler. Again, cptr points now to the location 2345 and expects there to be a char
iii)
Yes you can say it is a virtual address. Also segmentation plays some parts in this game, but at your stage you don't need to worry about it at all. The OS will resolve that for you and makes sure, that you only overwrite variables in the memory space dedicated to your program. So if you run a program twice at the same time, and you print a pointer, it is most likely the same value, but they won't point at the same value in memory.
iv)
Didn't see the write instruction at first. You can't just write anywhere into memory, as you could overwrite another program's value.
v)
Similar issue as above. You cannot just dereference any number you want to, you first need to cast it to a pointer, otherwise neither the compiler, your OS nor your CPU will have a clue, to what exactely it is pointing to
Hope I could help you, but I recommend, that you dive again in some books about pointers in C.
i.) Type cast, you cast the integer to a char
ii.) You point to the address of 2345.
iii.) Refer to answer from Joachim Pileborg. ^ ASLR
iv.) You can't directly write into an address without knowing if there's already something in / if it even exists.
v.) Because you're actually using a pointer to print a normal integer out, which should throw the error C2100: illegal indirection.
You may think pointers like numbers on mailboxes. When you set a value to a pointer, e.g cptr = 2345 is like you move in front of mailbox 2345. That's ok, no actual interaction with the memory, hence no crash. When you state something like *cptr, this refers to the actual "content of the mailbox". Setting a value for *cptr is like trying to put something in the mailbox in front of you (memory location). If you don't know who it belongs to (how the application uses that memory), it's probably a bad idea. You could use "malloc" to initialize a pointer / allocate memory, and "free" to cleanup after you finish the job.
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
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?