segmentation fault on buffer overflow - c

I am having trouble to run this c code. When I do i get segmentation fault and an error with 'return' return 0xdeadbeef;
Anyone have any suggestions?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int lame(unsigned int size, unsigned int value){
unsigned int array1[4];
unsigned int array2[6];
array2[5] = value;
memcpy(&array1, &array2, size * sizeof(unsigned int));
return 1;
}
void awesome(){
printf("awwwwwww yeaaahhhhh! All awesome, all the time!\n");
}
main(unsigned int argc, char ** argv){
unsigned int size, value;
size = strtoul(argv[1], 0, 10);
value = strtoul(argv[2], 0, 16);
if(!lame(size, value)){
awesome();
}
else{
printf("I am soooo lame :(\n");
}
return 0xdeadbeef;
}

I said that there was "at least one bug on almost every line of your code" and now I will list them. If I don't have any comments on a line, there are no bugs on that line, but you also need to read up on proper code formatting and style.
int lame(unsigned int size, unsigned int value){
unsigned int array1[4];
unsigned int array2[6];
array2[5] = value;
memcpy(&array1, &array2, size * sizeof(unsigned int));
return 1;
}
Undefined behavior on the memcpy line if size is larger than 4. Since size is taken from user input, this program contains a buffer overflow vulnerability, albeit one that might be hard to exploit. (You need to read "Smashing the Stack for Fun and Profit.")
This function has no externally visible side effects. The compiler may, and probably will, delete all of its code except the return 1.
Functions that always return the same constant value should be refactored to return void. Functions that are not used outside the current file should be declared static.
void awesome(){
printf("awwwwwww yeaaahhhhh! All awesome, all the time!\n");
}
This use of printf can be replaced by puts. Functions that are not used outside the current file should be declared static.
main(unsigned int argc, char ** argv){
The first argument to main must have type int, not unsigned int. The return type (which must be int, not void) is missing; many compilers will tolerate this (treating it as implicitly returning int) for backward compatibility with pre-C89 code, but it's still Wrong.
unsigned int size, value;
size = strtoul(argv[1], 0, 10);
value = strtoul(argv[2], 0, 16);
Both size and value should be unsigned long for consistency with what strtoul returns.
Undefined behavior if there are fewer than two command-line arguments.
Need to check both calls to strtoul for failure. This is nontrivial; read the EXAMPLES section of the OpenBSD manpage for strtoul to learn how to do it correctly.
However, props for using strtoul rather than atoi (which you can't check for failure) or sscanf (which has undefined behavior on integer overflow).
if(!lame(size, value)){
awesome();
}
else{
printf("I am soooo lame :(\n");
}
The compiler can and will determine that lame always returns 1, and optimize out the call to awesome. (In fact, it would be entitled to optimize out everything but the above printf, as all control flow paths either trigger undefined behavior or they reach this printf, and there are no other externally visible effects. The compilers I have readily to hand are not quite that clever, but they do remove the if-then-else and all the code inside lame.)
This use of printf can also be replaced by puts.
You will automatically become 23% less lame the moment you stop calling yourself lame.
return 0xdeadbeef;
The value returned by main is meaningful. 0 means success of the overall program, any other value means some sort of failure. Always return 0 unless you intend to indicate failure. Also, only values in the range [0, 127] can be reliably received by the parent process cross-platform; 0xdeadbeef is Right Out.
In your screenshot, main returned void instead of having a missing return type; that plus a return statement with a value should have caused the program to fail to compile. Your compiler might tolerate it in main, though.

Related

Different pointer value before and after return

I have strange problem, i allocated memory using malloc and returned address of this newly allocated memory. But this address is different before and after return (inside and outside function).
Here is the code (care only about 3 last lines):
char* InfoFile_getValue(char* projectName, char* key)
{
char* returnValue = NULL;
char projectInfoPath[200];
sprintf(projectInfoPath,"projects/%s/info.txt",projectName);
FILE* fp = fopen(projectInfoPath,"r");
if (fp != NULL) {
char* ptr;
size_t len = 0;
char* lineFromFile = NULL;
while(getline(&lineFromFile, &len, fp)!=-1)
{
if (strstr(lineFromFile,key))
{
ptr = lineFromFile + strlen(key);
ptr = ptr + strspn(ptr, ": ");
returnValue = malloc(strlen(ptr)+1);
strcpy(returnValue,ptr);
break;
}
}
free(lineFromFile);
fclose(fp);
}
printf("Inside size: %d\n",sizeof(returnValue));
printf("String address inside function %p\n", returnValue);
return returnValue;
}
And then i call this function using:
char* baseString = InfoFile_getValue(projectName, "base");
printf("Outside size: %d\n",sizeof(baseString));
printf("String address outside function: %p\n",baseString);
printf("%s\n", baseString);
I comipled this using CC and below flags:
pkg-config --cflags gtk+-3.0 -Wno-incompatible-pointer-types
-Wno-int-conversion -Wno-discarded-qualifiers pkg-config --libs gtk+-3.0 -lpthread -lm
And it gives following results:
Inside size: 8
String address inside function 0x5567d9ff4540
Outside size: 8
String address outside function: 0xffffffffd9ff4540
Naruszenie ochrony pamięci (zrzut pamięci)
It looks like it cuts this address to 4 bytes and prefixes it with 0xff, but i have no idea why, i have never came across problem like that. Any suggestions will be helpfull.
You seem to get a sign extension of the lower 32 bits of the address. Just a wild guess, but I think that the compiler saw InfoFile_getValue as a function returning an int while pointers are 64 bits long.
The rule is that a function has to be declared before it is used. If it is not, C assumes that it is declared as int func(), that is a function taking any parameters and returning an int. You should make sure that you have:
char* InfoFile_getValue(char* projectName, char* key);
before the function (maybe main) containing char* baseString = InfoFile_getValue(projectName, "base");
That looks like sign extension, so this very much smells like a C90 implicit int bug. That is, the compiler thinks that the function returns int with the value 0xd9ff4540, which on a 32 bit system is most likely a negative 2's complement number. Then somehow it gets converted to 64 bit because of %p and you get sign extension.
Easiest way to solve it this bug to stop using C90 already, it's bloody 30 years old, broken and dangerous. Getting rid of implicit int alone is reason enough to port your code to standard C.
In case you have to use it, make sure that the function declaration and definition are identical and that the caller can see the function declaration. Then maximize compiler warnings and pay attention to them.
Your experiencing value-truncation and sign-extension due to an ill-prepared caller. I.e. the caller isn't aware of the actual function return type due to lack of proper prototype. This can be aggravating unless you keeping a close watch in C, especially when dealing with a code base that seems to work just fine on platforms where int and void* are the same size.
The simplest case to repro this is below, and documents what must be going on.
main.c
#include <stdio.h>
int main()
{
void *p = foo();
printf("main: p = %p\n", p);
}
foo.c
#include <stdio.h>
void *foo()
{
static int x;
void *p = &x;
printf("foo: p = %p\n", p);
return p;
}
Executing the above code after build for both x86 (where int and void* are the typically the same size) and x64 (where int is typically 32bit and void is 64bit) will expose both the problem and the subtlety of how you can miss this in this former case. Both should exhibit warnings similar to this (which you should be treating as errors anyway)
1>main.c(13): warning C4013: 'foo' undefined; assuming extern returning int
1>main.c(13): warning C4047: 'initializing': 'void *' differs in levels of indirection from 'int'
The results of the run on both platforms (obviously the values here can vary on your system)
x86
foo: p = 00A38138
main: p = 00A38138
x64
foo: p = 00007FF7E7B0C160
main: p = FFFFFFFFE7B0C160
With that you can hopefully see how two things are critical:
Always ensure functions you're calling within your source are properly prototyped before their usage.
Always compile with warnings-as-errors to catch problems like this.
Probably the biggest thing to keep in the back of your head is, by not doing both items above, the code still appears to run fine on x86, and still compiles on x64. The former can lull you into a false sense of accomplishment, and the latter just further confirms that, making hunting down problems like this especially irritating. Let the compiler help you. Make sure (1) and (2) are in your routine.

In this case i want to undestand, why is the output 10 instead of 20?

i want to understand why output in this code is 10 not 20
#include<stdio.h>
#include <stdio.h>
int check (int, int);
int main()
{
int c;
c = check(10, 20);
printf("c=%d\n", c);
return 0;
}
int check(int i, int j)
{
int *p, *q;
p=&i;
q=&j;
i>=45?*p:*q;
}
The problem here is that the return value of the check() function is undefined behavior.
In order to get the expected output of 20 you would have to use the return statement like this return i>=45?*p:*q;
You need to do this to actually tell the compiler to write the result to the return register.
If you don't do this the function simply exits without explicitly writing the result value to the return register. Instead the register content is simply left in the state it was last in (in your case 10), but this is in no way guaranteed and will very likely vary with the compiler used.
If you really want to understand it on an instruction level have a look here: godbolt compiler explorer
There on the right you can see the x86 assembly of your program, and if you look closely you can see that the compiler just so happens to use the eax register to compare the value which is also by ABI convention the register used for function return values.

Confused about detecting the errors of this code in c programming language?

The code given below is an exercise that our teacher gave to prepare us for exams.
We are supposed to find the errors that occur in this code and fully explain them .
#define SIZE 10
int start (void a,int k) {
const int size=10;
char array[size];
char string[SIZE];
mycheck(3,4);
array[0]=string[0]='A';
printf("%c %c\n", array[0], string[0]);
myRec(7);
}
int mycheck(int a , int b) {
if (a==0 || b==0 ) {
return 0;
}
else {
return (a*b);
}
}
int myRec(int x) {
if(x==0)
return 0;
else
printf("%d,",x);
myRec(x--);
}
I have found these errors so far:
1.int start (void a,int k)
explanation: We can't have a variable of type void, because void is an incomplete type
2.const int size=10;
explanation:we can't use variable to define size of array
(problem is when I run it in dev-c++ it doesn't show an error so I'm not sure about this)
3.mycheck(3,4);
explanation: prototype of function mycheck() is not declared, so the function mycheck is not visible to the compiler while going through start() function
4.A friend told me that there is an error in function myRec because of this statement myRec(x--);
(I don't really get why is this an error and how you can I explain it?)
5.Main() function doesn't exist.
I'm not sure about this but if i run the code (in dev-c++) without main function I get a compilation error
I'm not sure if the errors that I pointed out are 100% right or if I missed an error or if I explained them correctly.
Please correct me if any of the above is wrong!
a friend told me that there is an error in function myRec cuz of this
statement myRec(x--);
It will lead to stackoverflow. Due to post-decrement, the actual argument passed to function myRec(), never decreases and therefore the condition:
if(x==0)
return 0;
will never become true. Regarding your rest of the errors, it depends on the compiler version being used:
For example C99, you are allowed to have variable size arrays like this:
const int size=10;
char array[size];
char string[SIZE];
but pre C99, you would have to use malloc or calloc. For your functions used without prototype, most compilers would generate a warning and not error and also due to no #include<stdio.h> statement, your printf would also lead to a warning.i Again, lot of these things are compiler dependent.
1.int start (void a,int k)
explanation: We can't have a variable of type void ,because void is an
incomplete type
Correct.
2.const int size=10;
explanation:we can't use variable to define size of array (problem is
when i run it in dev-c++ it doesnt show an error?so im not sure about
this!)
This is also correct, that char array[size];, where size is not a compile-time constant, is invalid in C89. However, in C99 and newer, this is actually valid and would create a variable-length array. It is possible that your Dev-C++ IDE is using GCC with the language set to C99 or newer, or has GNU C extensions enabled to enable this feature.
3.mycheck(3,4);
explanation: prototype of function mycheck() is not declared.So the
function mycheck is not visible to the compiler while going through
start() function
Correct. This can be fixed either by declaring the function's prototype before the start() function, or just moving the whole function to the top of the file. As noted by Toby Speight in the comments, in C89, this should not actually be a compiler error, since functions are implicitly declared when they are used before any actual declaration as int (), i.e. a function returning int with any arguments, which is compatible with the declarations of mycheck and myRec. It is however bad practice to rely on this, and implicit function declaration does not work in C99 or newer.
4.a friend told me that there is an error in function myRec cuz of this statement myRec(x--);
(I don't really get why is this an error and how you can explain it?)
This function is a recursive function. This means it calls itself within itself in order to achieve a kind of looping. However, this function as it is currently written would run forever and cause an infinite loop, and since it is a recursive function, and needs a new stack frame each time it is called, it will most likely end in a stack overflow.
The function is written with this statement:
if(x==0)
return 0;
This is intended to terminate the recursion as soon as x reaches 0. However, this never happens, because of this line of code here:
myRec(x--);
In C, postfix -- and ++ operators evaluate to their original value before the addition or subtraction:
int x = 5;
int y = x--;
/* x is now 4; y is now 5 */
However, using the prefix version of these operators will evaluate to their new value after adding / subtracting 1:
int x = 5;
int y = --x;
/* x is now 4; y is now 4 */
This means that on each recursion, the value of x never actually changes and so never reaches 0.
So this line of code should actually read:
myRec(--x);
Or even just this:
myRec(x - 1);
5.Main() function doesn't exist ...again im not sure about this but if i run the code (in dev-c++) without main function i get a compilation
error
This one could either be right or wrong. If the program is meant to run on its own, then yes, there should be a main function. It's possible that the function start here should actually be int main(void) or int main(int argc, char *argv[]). It is entirely valid however to compile a C file without a main, for example when making a library or one individual compilation unit in a bigger program where main is defined in another file.
Another problem with the program is that myRec is used before it is declared, just like your point 3 where mycheck is used before it is declared.
One more problem is that the functions start and mycheck are declared to return int, yet they both do not contain a return statement which returns an int value.
Other than that, assuming that this is the entire verbatim source of the program, the header stdio.h isn't included, yet the function printf is being used. Finally, there's the issue of inconsistent indentation. This may or may not be something you are being tested for, but it is good practice to indent function bodies, and indentation should be the same number of spaces / tab characters wherever it's used, e.g.:
int myRec(int x) {
if(x==0)
return 0;
else
printf("%d,",x);
myRec(x--);
}
1) Hello friend your Recursive function myRec() will go infinite because it
call itself with post detriment value as per C99 standard it will
first call it self then decrements but when it call itself again it have
to do the same task to calling self so it will never decrements and new
stack is created and none of any stack will clear that recursion so
stack will full and you will get segmentation fault because it will go
beyond stack size.
2) printf("%d,",x); it should be printf("%d",x); and you should include #include library.
I think your another mistake is you are calling your mycheck() and you
returning multiplication of two integer but you are not catch with any
value so that process got west.So while you are returning something you
must have to catch it otherwise no need to return it.
3) In this you Program main() function missing. Program execution starts
with main() so without it your code is nothing. if you want to execute
your code by your own function then you have to do some process but
here main() should be present.or instead of start() main() should
be present.
4) you can also allocate any char buffer like this int j; char array[j=20];
your code should be like this.
#include<stdio.h>
#define SIZE 10
int mycheck(int a , int b) {
if (a==0 || b==0 ) {
return 0;
}
else {
return (a*b);
}
}
int myRec(int x) {
if(x==0)
return 0;
else
printf("%d",x);
myRec(--x);
}
void main (int argc, char** argv) {
const int size=10;
char array[size];
char string[SIZE];
int catch = mycheck(3,4);
printf("return value:: %d\n",catch);
array[0]=string[0]='A';
printf("%c %c\n", array[0], string[0]);
myRec(7);
printf("\n");
}
Enjoy.............

Function working fine in stand alone mode but not in a larger program

I have a c program with multiple headers and source files. On running, the program gives segmentation fault. On using "up" and "print variable" commands, i figured that the function "busntoint()" is not working properly.
I have following functions for converting a string of length n from binary to decimal:
unsigned int busntoint(int n, busn bus)
{
unsigned int value = 0;
int i;
for (i=0; i < n; i++) {
if (bus[i] == '1') value += (unsigned int)pow(2,(n-1-i));
}
return value;
}
unsigned int bus2toint(bus2 bus)
{
return busntoint(2, bus);
}
unsigned int bus32toint(bus32 bus)
{
return busntoint(32, bus);
}
I then wrote another program to check the working of these functions. It works just fine and gives the correct and expected output. I dunno why it is not working properly in the "bigger" program.
If it's useful, following is the definition of variables:
typedef char bus2[3];
typedef char bus3[4];
typedef char bus5[6];
typedef char bus6[7];
typedef char bus8[9];
typedef char bus16[17];
typedef char bus32[33];
The usage of the function in the "bigger" program is as follows:
int LoadMemory(char * binfilename, bus8 memory[4096])
{
//some code
int addr = bus32toint(line);
setbit8(memory[addr], &line[33]);
//some code
}
p addr in gdb gives garbage value, leading to segmentation fault in memory[addr].
Your first problem probably lies in your abuse of pow to compute powers of two and the possible overflow that your computation may encounter.
The correct way of computing integer powers of two is the shift operator, here that would be
2u << (n-1-i)
the suffix u is to ensure that this has the correct type (unsigned). But then you also have to ensure that the value by which you are shifting is not too large, you must guarantee that the corresponding power will still fit into an unsigned. You didn't tell us on what architecture your are, not all have unsigned with 32 bit.
Then your LoadMemory function also looks bogus. As far as I can see there can no guarantee be given that addr (for which you didn't show the type) is smaller than 4096.
Use unsigned int addr = bus32toint(line);

How to determine the length of a function?

Consider the following code that takes the function f(), copies the function itself in its entirety to a buffer, modifies its code and runs the altered function. In practice, the original function that returns number 22 is cloned and modified to return number 42.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ENOUGH 1000
#define MAGICNUMBER 22
#define OTHERMAGICNUMBER 42
int f(void)
{
return MAGICNUMBER;
}
int main(void)
{
int i,k;
char buffer[ENOUGH];
/* Pointer to original function f */
int (*srcfptr)(void) = f;
/* Pointer to hold the manipulated function */
int (*dstfptr)(void) = (void*)buffer;
char* byte;
memcpy(dstfptr, srcfptr, ENOUGH);
/* Replace magic number inside the function with another */
for (i=0; i < ENOUGH; i++) {
byte = ((char*)dstfptr)+i;
if (*byte == MAGICNUMBER) {
*byte = OTHERMAGICNUMBER;
}
}
k = dstfptr();
/* Prints the other magic number */
printf("Hello %d!\n", k);
return 0;
}
The code now relies on just guessing that the function will fit in the 1000 byte buffer. It also violates rules by copying too much to the buffer, since the function f() will be most likely a lot shorter than 1000 bytes.
This brings us to the question: Is there a method to figure out the size of any given function in C? Some methods include looking into intermediate linker output, and guessing based on the instructions in the function, but that's just not quite enough. Is there any way to be sure?
Please note: It compiles and works on my system but doesn't quite adhere to standards because conversions between function pointers and void* aren't exactly allowed:
$ gcc -Wall -ansi -pedantic fptr.c -o fptr
fptr.c: In function 'main':
fptr.c:21: warning: ISO C forbids initialization between function pointer and 'void *'
fptr.c:23: warning: ISO C forbids passing argument 1 of 'memcpy' between function pointer and 'void *'
/usr/include/string.h:44: note: expected 'void * __restrict__' but argument is of type 'int (*)(void)'
fptr.c:23: warning: ISO C forbids passing argument 2 of 'memcpy' between function pointer and 'void *'
/usr/include/string.h:44: note: expected 'const void * __restrict__' but argument is of type 'int (*)(void)'
fptr.c:26: warning: ISO C forbids conversion of function pointer to object pointer type
$ ./fptr
Hello 42!
$
Please note: on some systems executing from writable memory is not possible and this code will crash. It has been tested with gcc 4.4.4 on Linux running on x86_64 architecture.
You cannot do this in C. Even if you knew the length, the address of a function matters, because function calls and accesses to certain types of data will use program-counter-relative addressing. Thus, a copy of the function located at a different address will not do the same thing as the original. Of course there are many other issues too.
In the C standard, there is no notion of introspection or reflection, thus you'd need to devise a method yourself, as you have done, some other safer methods exists however.
There are two ways:
Disassemble the function (at runtime) till you hit the final RETN/JMP/etc, while accounting for switch/jump tables. This of course requires some heavy analysis of the function you disassemble (using an engine like beaEngine), this is of course the most reliable, but its slow and heavy.
Abuse compilation units, this is very risky, and not fool proof, but if you know you compiler generates functions sequentially in their compilation unit, you can do something along these lines:
void MyFunc()
{
//...
}
void MyFuncSentinel()
{
}
//somewhere in code
size_t z = (uintptr_t)MyFuncSentinel - (uintptr_t)MyFunc;
uint8_t* buf = (uint8_t*)malloc(z);
memcpy(buf,(char*)MyFunc,z);
this will have some extra padding, but it will be minimal (and unreachable). although highly risky, its a lot faster that the disassemble method.
note: both methods will require that the target code has read permissions.
#R.. raises a very good point, your code won't be relocatable unless its PIC or you reassasmble it in-place to adjust the addresses etc.
Here is a standards compliant way of achieving the result you want:
int f(int magicNumber)
{
return magicNumber;
}
int main(void)
{
k = f(OTHERMAGICNUMBER);
/* Prints the other magic number */
printf("Hello %d!\n", k);
return 0;
}
Now, you may have lots of uses of f() all over the place with no arguments and not want to go through your code changing every one, so you could do this instead
int f()
{
return newf(MAGICNUMBER);
}
int newf(int magicNumber)
{
return magicNumber;
}
int main(void)
{
k = newf(OTHERMAGICNUMBER);
/* Prints the other magic number */
printf("Hello %d!\n", k);
return 0;
}
I'm not suggesting this is a direct answer to your problem but that what you are doing is so horrible, you need to rethink your design.
Well, you can obtain the length of a function at runtime using labels:
int f()
{
int length;
start:
length = &&end - &&start + 11; // 11 is the length of function prologue
// and epilogue, got with gdb
printf("Magic number: %d\n", MagicNumber);
end:
return length;
}
After executing this function we know its length, so we can malloc for the right length, copy and editing the code, then executing it.
int main()
{
int (*pointerToF)(), (*newFunc)(), length, i;
char *buffer, *byte;
length = f();
buffer = malloc(length);
if(!buffer) {
printf("can't malloc\n");
return 0;
}
pointerToF = f;
newFunc = (void*)buffer;
memcpy(newFunc, pointerToF, length);
for (i=0; i < length; i++) {
byte = ((char*)newFunc)+i;
if (*byte == MagicNumber) {
*byte = CrackedNumber;
}
}
newFunc();
}
Now there's another bigger problem though, the one #R. mentioned. Using this function once modified (correctly) results in segmentation fault when calling printf because the call instruction has to specify an offset which will be wrong. You can see this with gdb, using disassemble f to see the original code and x/15i buffer to see the edited one.
By the way, both my code and yours compile without warnings but crash on my machine (gcc 4.4.3) when calling the edited function.

Resources