Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
int a=10;
char *b ;
b=(char*)&a;
strcpy(b,"xxxxx");
printf("%s",b);
The compilation can pass, but the program exits with an error. Why doesn't this work? What is the mechanism of realization?
It is likely that, in your C implementation, int is four bytes. The C standard defines a char to use one byte. So b = (char *) &a; sets b to point the first byte of the four that make up a. We do not know what lies after those four bytes.
strcpy(b, "xxxxx"); asks strcpy to copy six bytes (the five “x” characters and a terminating null character) to the memory pointed to by b. In the simplest case, this will overwrite two bytes beyond a. This can disrupt your program in a variety of ways—it can corrupt some other data the compiler stored there, it can make your stack frame unusable, it can corrupt a return address, and other things can go wrong.
Additionally, when the compiler translates and optimizes your program, it relies on guarantees made to it by the C standard, such as that the operation strcpy(b, …) will not write outside of the properly defined object pointed to by b, which is a. When you violate those guarantees, the C standard does not define the resulting behavior, and the translations and optimizations made by the compiler may cause your program to go awry in unexpected ways.
int a=10;
char *b ;
b=(char*)&a;
strcpy(b,"xxxxx");
printf("%s",b);
Why doesn't this work?
This doesn't work because strcpy() copy 6 characters (5 times 'x' and one nul terminator) to the address pointed by b and there is not enough room for that, at least if the compiler you used store int type into 32bits (4 bytes).
You didn't showed the full code, but assuming a is a local variable, it is allocated on the stack. You overflow the space allocated for variable a and this means you overwrite something on the stack. That data on the stack is essential for program continuation and being overwritten it crashes the system.
"at will"? No they are actually sentient!
If code does not behave as you expect it is because you have a semantic error - that is code that is syntactically valid (i.e. it compiles) but does not mean what you think it does when executed according to the rules of the language.
Moreover as systems level language C does not protect you from doing invalid things to the execution environment - i.e. runtime errors, and such errors generally have undefined behaviour.
In this case:
b=(char*)&a;
strcpy(b,"xxxxx");
b points to an object of int size. On Windows or any 32 bit system, that will normally be 4 bytes. You then copy 6 bytes to it, overrunning its space. The effect of this is undefined, but it is likely that it will corrupt some adjacent variable in memory or the function return address.
If b were corrupted by the strcpy() error, trying to print the string at b would cause a run-time error is b were no longer a valid address.
If the return address were corrupted, the program would fail when you return from the calling function.
In either case the precise behaviour is not defined, and may not be trapped; it depends on when gets corrupted, what value the corrupted data takes, and how and when that corrupted data is used.
You will be able to observe the effects on the variables and/or call stack by running and stepping this code in a debugger.
Related
This question already has answers here:
How dangerous is it to access an array out of bounds?
(12 answers)
Closed 3 years ago.
My understanding is that if char *my_word is allocated ONE byte of memory malloc(1), then technically, then the following code would produce an out-of-bounds error
char *my_word = malloc(1);
my_word[0] = 'y';
my_word[1] = 'e';
my_word[2] = 's';
and yet, the code runs just fine and doesn't produce any error. In fact, printf("%s", my_word) prints the word just fine.
Why is this not producing an out-of-bounds error if I specifically only allocated 1 byte of memory?
C doesn't have explicit bounds checking. That's part of what makes it fast. But when you write past the bounds of allocated memory, you invoke undefined behavior.
Once you invoke undefined behavior, you can't reliable predict what the program will do. It may crash, it may output strange results, or (as in this case) it may appear to work properly. Additionally, making a seemingly unrelated change such as adding a printf call for debugging or adding an unused local variable can change how undefined behavior manifests itself.
Just because the program could crash doesn't mean it will.
This comes down to the system it is running on. Generally a malloc will allocate in multiples of a certain block size. Eg the block size maybe 16 bytes on your system and malloc will allocate 16 even though you only asked for 1. So in this case you are getting away with overflowing the buffer because you are not writing on memory that is used by anything else.
However you should never rely on this. Always assume that when you write outside the amount requested that bad things will happen.
C does not provide any built-in mechanism to protect you from buffer overflowing, it is up to you to know the size of your buffers and ensure that you never read/write outside of them.
For example if you allocated a buffer a multiple of the block size then writing to the next byte will probably start overwriting critical memory control blocks which may show up as bizarre errors later when you try to free or allocate more memory.
C does not performs bound check. It is just undefined behavior when you access out of bounds which means it can work as normal.
//this code should give segmentation error....but it works fine ....how is it possible.....i just got this code by hit and trail whle i was trying out some code of topic ARRAY OF POINTERS....PLZ can anyone explain
int main()
{
int i,size;
printf("enter the no of names to be entered\n");
scanf("%d",&size);
char *name[size];
for(i=0;i<size;i++)
{
scanf("%s",name[i]);
}
printf("the names in your array are\n");
for(i=0;i<size;i++)
{
printf("%s\n",&name[i]);
}
return 0
The problem in your code (which is incomplete, BTW; you need #include <stdio.h> at the top and a closing } at the bottom) can be illustrated in a much shorter chunk of code:
char *name[10]; // make the size an arbitrary constant
scanf("%s", name[0]); // Read into memory pointed to by an uninitialized pointer
(name could be a single pointer rather than an array, but I wanted to preserve your program's structure for clarity.)
The pointer name[0] has not been initialized, so its value is garbage. You pass that garbage pointer value to scanf, which reads characters from stdin and stores them in whatever memory location that garbage pointer happens to point to.
The behavior is undefined.
That doesn't mean that the program will die with a segmentation fault. C does not require checking for invalid pointers (nor does it forbid it, but most implementations don't do that kind of checking). So the most likely behavior is that your program will take whatever input you provide and attempt to store it in some arbitrary memory location.
If the garbage value of name[0] happens to point to a detectably invalid memory location, your program might die with a segmentation fault. That's if you're luck. If you're not, it might happen to point to some writable memory location that your program is able to modify. Storing data in that location might be harmless, or it might clobber some critical internal data structure that your program depends on.
Again, your program's behavior is undefined. That means the C standard imposes no requirements on its behavior. It might appear to "work", it might blow up in your face, or it might do anything that it's physically possible for a program to do. Apparently to behave correctly is probably the worst consequence of undefined behavior, since it makes it difficult to diagnose the problem (which will probably appear during a critical demo).
Incidentally, using scanf with a %s format specifier is inherently unsafe, since there's no way to limit the amount of data it will attempt to read. Even with a properly initialized pointer, there's no way to guarantee that it points to enough memory to hold whatever input it receives.
You may be accustomed to languages that do run-time checking and can reliably detect (most) problems like this. C is not such a language.
I'm not sure what's your test case (No enough reputation to post a comment). I just try to input it with 0 and 1\n1\n2\n.
It's a little complex to explain the detail. However, Let's start it :-). There are two things you should know. First, main() is a function. Second, you use a C99 feature, variable-length array or gnu extension, zero-length array (supported by gcc), on char *name[size];.
main() is a function, so all the variable declared in this function is local variables. Local variables locate at stack section. You must know about it first.
If you input 1\n1\n2\n, the variable-length array is used. The implementation of it is also to allocate it on stack. Notice that value of each element in array is not initialized as 0. That is the possible answer for you to execute without segmentation fault. You cannot make sure that it'll point to the address which isn't writable (At least failed on me).
If the input is 0\n, you will use extension feature, zero-length array, supported by GNU. As you saw, it means no element in array. The value of name is equal to &size, because size is the last local variable you declared before you declared name[0] (Consider stack pointer). The value of name[0] is equal to dereference to &size, that's zero (='\0') , so it will work fine.
The simple answer to your question is that a segmentation fault is:
A segmentation fault (aka segfault) are caused by a program trying to read or write an illegal memory location.
So it all depends upon what is classed as illegal. If the memory in question is a part of the valid address space, e.g. the stack, for the process the program is running, it may not cause a segfault.
When I run this code in a debugger the line:
scanf("%s, name[i]);
over writes the content of the size variable, clearly not the intended behaviour, and the code essentially goes into an infinite loop.
But that is just what happens on my 64 bit Intel linux machine using gcc 5.4. Another environment will probably do something different.
If I put the missing & in front of name[i] it works OK. Whether that is luck, or expertly exploiting the intended behaviour of C99 variable length arrays, as suggested. I'm afraid I don't know.
So welcome to the world of subtle memory overwriting bugs.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
When we define a variable, and do not initialize it, the block of memory allocated to the variable still contains a value from previous programs, known as garbage value. But suppose, in a hypothetical case, a block of unused memory is present in the system, and when I declare and define a variable, that block of memory is allocated to the variable. If I do not initialize the variable, and try to print the value of the variable, the system doesn't have any garbage value to print. What will be the result? What will the system do?
When we define a variable, and do not initialize it, the block of memory allocated to the variable still contains a value from previous programs, known as garbage value.
If I do not initialize the variable, and try to print it, it doesn't have any garbage value to print.
C does not specify these behaviors. There is no specified garbage value.
If code attempts to print (or use) the value of an uninitialized object, the result is undefined behavior (UB). Anything may happen: a trap error occurs, the value is 42, code dies, anything.
There is a special case if the uninitialized object is an unsigned char in that a value will be there of indeterminate value, just something in the range [0...UCHAR_MAX], but no UB. This is the closest to garbage value C specifies.
Firstly, it isn't defined how an implementation behaves precisely when an uninitialised read is made, by the C standard. Merely that the value is not defined. The system may use whatever method it wishes to choose the value. Or it is even possible it is a trap representation and will crash the program I believe.
However on most real modern OSes. The data in reality is fresh pages that get mapped into the programs address space. For security reasons most kernels actually explicitly ensure these are zeroed out to avoid software spying on data from previous programs which were run and got left in memory.
However some OSes as you say will just leave this data in, meaning the page is either fresh and usually zeroed out or contains arbitrary data from previous programs (or even potentially arbitrary data defined by how the memory starts up, but at least with DRAM, that is generally in a zeroed state).
I think you need more of hardware perspective.
What is a memory? An example of memory: is made up of transistors and capacitors. A transistor and capacitor make a memory bit. A bit is either of value 0 or 1, a hypothetical scenario of non-existance of this bit value does not exist ;) as it has to hold either 0 or 1 and nothing else. If you think there is "nothing" in bit value, that means the hardware(transistor/capacitor) you are imagining is not working.
A bunch of bits makes a word or byte. A bunch of bytes holds an integer/ float or whatever variable you define. So even without initializing the variable, it contains 0's and 1's in each of the memory cells. When you access this - it's called garbage.
But suppose, in a hypothetical case, a block of unused memory is present in the system, and when I declare and define a variable, that block of memory is allocated to the variable. If I do not initialize the variable, and try to print it, it doesn't has any garbage value to print. What will it do?
Any given memory location has some value, no matter how it got there. The "garbage" value doesn't have to come from a program that ran in that space previously, it could just be the initial state of the memory location when the system starts up. The reason it's "garbage" is that you don't know what it is -- you didn't put it there, you don't have any idea how it got there, and you don't really care.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Could anyone clarify this?
char str[1];
strcpy(str, "HHHHHHHHHHHH");
Here I declared a char array with size one, but the program doesn't crash untill I enter more than 12 characters and I only have an array size one. Why?
This code has undefined behaviour, since it writes more than one element into str. It could do anything. It is your responsibility to ensure that you only write into memory that you own.
This is undefined behaviour. In practice, you overwrite memory contents of something. In this case, that array goes to stack, if it is a local variable. It is likely that you have a CPU architecture where stack grows down, so you start overwriting things like other local variables, saved register values and return addresses of function calls.
You probably first overwrote something which had no immediate effect, or you did not notice the effect. This might be a local variable which wasn't initialized yet, or a local variable or saved register value which was not actually used after you overwrote it.
Then when you increased length of overflow, you probably corrupted function return address, and then crash actually happened when you returned from the function. If you had any other memory addresses, that is pointers, crash could also be because you tried to access the value pointed by corrupted pointer.
Finally, if you would increase the overflow size enough, the string copying would eventually directly write outside allowed area and cause immediate crash (assuming CPU and OS which have such memory protection, and not some ancient or embedded system). But this probably was not the reason here, as you wrote only 14 bytes before crash.
But note that above is kinda pointless from point of view of C language, undefined behaviour, which often changes if you chnage anything in the program, compiler options or input data. This can make memory corruption bugs hard to find, as adding debug stuff often makes the problem "disappear" (changes or hides the symptoms).
I am new to the ethical hacking world, and one of the most important things is the stack overflow, anyway I coded a vulnerable C program which has a char name [400] statement, and when I try to run the program with 401A's it doesn't overflow, but the book which I am following says it must overflow and the logic sense says so, so what's wrong???
If you've defined a buffer:
char buf[400];
And wrote 401 bytes into it, the buffer has overflown. The rest, however, depends on the structure of your code:
How is the buffer allocated (statically, dynamically, on the stack)
What comes before and after it in memory
Your architecture's calling convention and ABI (in case of a stack buffer)
some more...
Things are more complex than they seem. To quote Wikipedia:
In computer security and programming,
a buffer overflow, or buffer overrun,
is an anomaly where a process stores
data in a buffer outside the memory
the programmer set aside for it. The
extra data overwrites adjacent memory,
which may contain other data,
including program variables and
program flow control data. This may
result in erratic program behavior,
including memory access errors,
incorrect results, program termination
(a crash), or a breach of system
security.
Note the multiple instances of the word may in this quote. All of this may happen, and it may not. Again, this depends on other factors.
C doesn't check about buffer overflow (overflowing the buffer is an undefined behavior). Usually the system will just allow you (and the hacker) to write beyond the buffer, and this is the reason why buffer overflow is vulnerable.
For example if the code is
char name[400];
char secret_password[400];
...
The memory may be layout as
[John ][12345 ]
name secret_password
Now if you write 401 A followed by a NULL to name, the extra A\0 will be written to secret_password, which basically changed the password from your luggage combination to just "A":
[AAAAAAAAA...AAAAA][A␀345 ]
name secret_password
Stackoverflow and bufferoverflow are different concepts.
Stackoverflow:
The size of a programs stack is static, it never changes at runtime. Since it is not possible to know how much memory your stack will need at runtime a reasonable big memory block is reserved. However some programs exeed this by calling a rekursive function.
A function call reserves as much space as it needs to store lokal variables on the stack and releases the memory once it exits. A recursive function will reserve new memory each time it is entered and release it once it exits. If the recursion never ends due to a programming error, more and more memory on the stack is reserved until the stack is full.
Trying to reserve memory on a full stack will cause an error, the stackoverflow.
Example code:
volatile bool args = false;
int myoverflow(int i){
int a[500];
if(args)
return a[i%500];
else
return myoverflow(i+1);
}
This should overflow the stack. It will reserve 500 * sizeof(int) every time it enters the function.
Bufferoverflow:
You have two variables, an array a and an array b. a can hold 4 elements and b can hold 2.
Now you write 5 elements into a, the 5th element lands in b.
Example:
void main(int ,char**)
{
int a[4];
int b[2];
a[5] = 22;
std::cout<<b[0];
}
This should print 22. it will write outside of a, into the memory used by b.
Note: None of my example functions are guaranteed to work, the compiler is free to optimize function calls and to arrange the memory used on the stack as it wants. It may even print a compile error on accessing memory out of bounds for array a.
Here's a good example in C showing how a buffer overflow can be used to execute arbitrary code. Its objective is to find an input string that will overwrite a return address causing a target function to be executed.
For a very good explanation of buffer overflows I would recommend chapter 5 of Writing Secure Code 2nd Edition.
Other good info on buffer overflows:
Secure programmer: Countering buffer overflows by David Wheeler
Smashing the Stack for Fun and Profit The classic article from Phrack Magazine