Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 8 years ago.
Questions asking us to recommend or find a tool, library or favorite off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Improve this question
First off the computer I'm running this on is an Intel System running Linux on a 32-bit stack. My professor posed a challenge question to us in class.
Here is the code before I ask the question
// funWithFooAndBar.c
#include <stdio.h>
#include <stdlib.h>
void bar()
{
printf("Now inside bar()!\n");
}
void foo()
{
void *addr[1];
printf("Now inside foo()!\n");
// this is where I need to modify my code,
//I was given the hint that it will only be two lines of code
// So something like:
addr[1] = bar;
addr[5] = addr[4];
addr[4] = bar;;
}
int main (int argc, char *argv[])
{
foo();
printf("Back in main\n");
return 0;
}
The goal is to smash the stack by writing beyond the end of an array, and through that, overwrite the return address so that the function call to foo () returns to bar () on its way back to main. So my output is supposed to look like:
Now inside foo() !
Now inside bar() !
Back in main
In order to do this I have to overflow the array so that the return address is overwritten with the address of the bar.I'm pretty sure that it will have to involve the address of function bar() which will equate to &bar()
The question he posed was what two lines of code could we add (where I commented) to make the output as a shown above.
Thanks!
Edit: I was hoping more for an explanation than a direct answer, I know what I'm supposed to do, just not how to translate that to the c code.
Edit: made an attempt
After reading the article that R M linked:
addr[1] = bar;
addr[5] = addr[4];
addr[4] = bar;
Turns out to work.
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
Why this version of C code is not working (cause segmentation fault)
#include <stdio.h>
int main()
{
int *p;
*p = 10;
return 0;
}
while this one is working?
int main()
{
char c = 'c';
int *p;
*p = 10;
return 0;
}
Both code snippets are wrong, we can't say that one is more wrong than the other, p is uninitialized in both cases and therefore it may or may not contain a valid memory address, it's impossible to predict, this means that the behavior is undefined. That being the case, working, whatever that may mean, is well within the realm of possible outcomes.
For int* p, no storage space is allocated for the actual integer number.
You need to modify your code as follows to make it work properly.
In C++, you can use new, but in C you can use malloc.
#include <stdio.h>
int main()
{
int* p = malloc(sizeof(int));
*p = 10;
free(p);
return 0;
}
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 6 years ago.
Improve this question
I am graduate looking to find work soon but I have a question about code security.
In Java there are no out-of-bound arrays and there are no pointers which suggests Java is more secure than C. In C these out-of-bounds arrays can cause stack corruption or buffer overflow and dangling pointers. In an interview I may be asked "how can a hacker take advantages of these?"
How do I go about answering this?
Examples are welcome.
Well, you could talk specifically about Heartbleed (there is a ton of documentation out there).
Basically, there was an api call that could be made via the network, where your code would request a communication keep-alive, which would normally look like:
You: send me "potato", which is 6 chars.
Response: potato
However, there was no check that the text requested, and the length of the text sent in were aligned, so you could do this:
You: send me "potato", which is 512 chars.
Response potato&&&�#((#(#)%#(((#%)password:1234#(%()#%((#%#(#%)(#)(%)(##()JFJFEOIJF#)J(JF)(#J)(#J#)(J#))J#....
Where the responding computer would send potato, plus 506 bytes of what is essentially the stack around that local variable, which could contain almost anything, including passwords, etc.
That a good enough example?
Unless your job involves security, I don't think that you'll be asked this. Identifying vulnerabilities is relatively easy but exploiting them is hard, and I think that most employers would be perfectly happy knowing that you know you need to check your bounds.
billjamesdev explains information disclosure through overflow, and this is basically what the Heartbleed bug was about. However, there are much worse possible outcomes, the most famous of which being arbitrary, remote code execution: basically, somebody else running any code that they like in your program because of a software vulnerability. Stack-based buffer overflows are easier to exploit to get RCE, but heap-based buffers can also be exploited to some extent.
In this tiny function:
int foo() {
char bar[4];
}
The array bar lives on the stack. One other interesting thing that lives on the stack, though, is the function's return address. If you overwrite that address, when the function returns, it will jump to a location of your choosing instead of where the developer thought that it would go back. Say that you have these two functions:
int main() {
char bar[4];
scanf("Enter no more than 4 characters: %s\n", bar);
}
int bar() {
system("sh"); // starts a shell on Linux
}
and assume that bar lives at the memory address 0x41414141 (which is highly unlikely, but it makes the demonstration easier because 0x41 is the ASCII code for 'A'). If you run that program on Linux and input this:
Enter no more than 4 characters: 00001111AAAA
On x86, this will fill up the character buffer with ASCII zeroes, overwrite a special value called the parent's base frame pointer (it is very important to your program but hackers don't usually need to care about it) with ASCII ones, and overwrite the return address with 0x41414141. When main returns, instead of terminating the program, it will start a shell.
There are a lot of variations on attacks, but the basic idea is that buffer overflows may allow a hacker to hijack the execution flow of your program.
This is a good example of one I seen recently. This is a bit contrived but it's quite easy to understand.
We have a dispatch table with some functions in it and due to an error we're able to call the wrong function.
#include <assert.h>
#include <float.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SETBIT(X,Y) X|=(1ULL<<(Y))
typedef void (*method)(void);
void unsafe();
void safe();
void safe(void) {
printf("anyone can call this\n");
}
void unsafe(void) {
fprintf(stderr, "wtf, how did this get called\n");
abort();
}
static method dispatch_table[2] = {0};
typedef struct node {
union container {
float fdata;
int idata;
} data;
uint32_t func;
} Node;
int main(void) {
size_t nsize1 = sizeof(Node);
assert(nsize1 == 8);
assert(sizeof(int) == 4);
assert(sizeof(float) == 4);
assert(sizeof(double) == 8);
dispatch_table[0] = &safe;
dispatch_table[1] = &unsafe;
Node n = {.data.fdata = 10.0};
n.func = 0;
//The problem starts here
void *bad = (void*)&n;
uint64_t *badder = (uint64_t*)bad;
SETBIT(*badder, 32);// Off by one error
printf("%d\n", n.func);
dispatch_table[n.func]();
return 0;
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I use C language for a natural language processing project.
I would like to store a dictionary file.
I used the following define statement
#define DICSIZE 46000
The question is about the number 46000 because it is the maximum number I can enter.
If I try a bigger number the program stop running.
How can I solve this problem?
Program stops not because of DICSIZE macro. It's usage.
I guess, some array is allocated locally(i.e In stack) by passing this macro as array size.
int myArray[DICSIZE];
So when the number is increased, you may face problem. I suggest to allocate memory dynamically using malloc().
I suspect you have a large array declared locally in a function like this:
int main()
{
MyRecordType myArray[DICSIZE];
...
return 0;
}
When DICSIZE gets large, myArray gets large, and you run out of stack space.
Use dynamic memory allocation instead:
int main()
{
MyRecordType * myArray = malloc(DICSIZE * sizeof(myArray[0]));
assert(myArray);
...
free(myArray);
return 0;
}
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
I'm not sure what the following does and i'm hoping someone can clarify the purpose of having the asterisk in front of the functions name:
char *Foo(char *ptr) {
return NULL;
}
I understand that you can pass by value the memory location of something in the function argument call and *ptr would be the pointer to it. I understand you can create a pointer function that can be used to point to other functions like a regular pointer points to variable memory location but in this case this is not a function pointer that we can point to other functions, or is it? This seems like a real function.
Foo is a function.
It has input: ptr of type char*
It has output of type char*
char* means "pointer to char"
it returns NULL.
That is the most plain explanation I can think of.
its misleading you, the * by the name isn't related to the name
it means the same as char* Foo(char* ptr)
which means a function which takes a char* and returns a char*
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I have written this code:
void f1(void)
{
sprintf("\nf1.");
}
void f2(void)
{
sprintf("\nf2.");
}
void f3(void)
{
sprintf("\nf3.");
}
void f4(void)
{
sprintf("\nf4.");
}
int main()
{
// int i;
void (*f[4])(void);
f[1]=f1;
f[2]=f2;
f[3]=f3;
f[4]=f4;
(*f[1])();
(*f[2])();
(*f[3])();
(*f[4])();
/*for(i=0;i<4;i++)
{
(*f[i])();
}*/
getch();
}
The program compiles, runs, and shows the output
f1.
f2.
f3.
f4.
but when I press enter, it throws the exception stating "Run-Time Check Failure #2 - Stack around the variable 'f' was corrupted."
Please explain to me the reason for this, and also when to use snprintf and sprintf.
Also, let me know why I cannot use
for(i=0;i<4;i++)
{
(*f[i])();
}
for function pointer. It's throwing an error for this as well.
void (*f[4])(void);
f[4]=f4;
Arrays start from 0 in C. Accessing f[4] is illegal.
In addition to your out of bounds array problem, you must have this line:
#include <stdio.h>
because you're using the sprintf function. If you do this, your compiler should give you an error to say you've called it incorrectly. Your compiler has probably warned you that it's used an implicit declaration. As it stands, it's going ahead and calling the function incorrectly and hoping for the best. This may also be causing a stack problem.