Just as we know,
In Linux world, infinite recusive "main()" in userspace will receive "segmentation fault" messsage, which is actually caused by stack overflow. (just as the following code)
#include <stdio.h>
void main(void)
{
main ();
}
Experiment and Question:
Change code to:
#include <stdio.h>
int cnt = 0;
void main(void) {
printf("cnt %d\n", cnt++);
main();
}
Test environment:
x86-64 ubuntu,
gcc-4.6
I need your help and thanks in advance!
Why Segmentation fault happens in different "cnt" value:
cnt: 523614
cnt: 523602
cnt: 523712
cnt: 523671
This is probably due to Address space layout randomization. If you run the slightly modified example of your program:
#include <stdio.h>
int cnt = 0;
void main(void)
{
int a;
printf("cnt %d %p\n", cnt++, (void*)&a); fflush(stdout);
main();
}
you will see that the address of a is not consistent over various runs of the program. Probably the initial size of the stack is also slightly randomized resulting in a slightly different number of stack frames fitting in this space.
P.S: I've added a fflush so the output of the program can be safely piped through for example tail and grep, otherwise buffering may blur the actual last line of output.
P.S2: I had to change print into printf and add #include <stdio.h>.
P.S3: You should not use an optimization on your program, because otherwise a tail-call optimization will remove your recursion and your program will actually loop forever. My version of the program doesn't do that, because of the aliased a.
Related
I want to create a program exploit that calls testme.c to perform a buffer overflow operation which should call another program myname.c.
The code for the testme.c program:
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv){
char a[100], b[100], c[100], d[100];
// Call the exploitable function
exploitable(argv[1]);
return(0);
}
int exploitable(char *arg){
// Make stack space of 10 bytes
char buffer[10];
// Copy input to buffer
strcpy(buffer, arg);
printf("The buffer says .. [%s/%p].\n", buffer, &buffer);
return(0);
}
The code for the myname.c program:
#include <stdio.h>
#include <time.h>
int main(){
printf("Name: SNS\n");
printf("Location: 41.13957, -104.81815\n");
time_t t;
time(&t);
printf("Date and time: %s\n",ctime(&t));
}
I have disabled address randomization and compiled both programs with -fno-stack-protector. Using gdb I can see that in testme.c, the return address after calling the exploitable function is 0x00000000000011a0:
testmemain
I need this to change to 0x00000000000011a9, which is the address of the main function of the myname.c program:
mynamemain
I know how to overflow the buffer variable in the exploitable function by giving a long enough string input to get a segmentation fault, but I cannot proceed any further than this. I have checked other tutorials in which the next step is to show how to spawn a shell, but I want testme.c to call myname.c through a buffer overflow. I am doing this on a 64-bit Ubuntu virtual machine.
My point is to show someone that every argument you sent to a C function, are pushed on the stack. It also happens in Ruby, Python, Lua, JavaScript, etc.
So I have written a Ruby code that generates a C code:
#!/usr/bin/env ruby
str = Array.new(10, &:itself)
a = <<~EOF
#include <stdio.h>
void x(#{str.map { |x| "int n#{x}" }.join(?,)}) {
printf("%d\\n", n#{str.length - 1}) ;
}
int main() { x(#{str.join(?,)}) ; }
EOF
IO.write('p.c', a)
After running this code with the Ruby interpreter, I get a file called p.c, which has this content:
#include <stdio.h>
void x(int n0,int n1,int n2,int n3,int n4,int n5,int n6,int n7,int n8,int n9) {
printf("%d\n", n9) ;
}
int main() { x(0,1,2,3,4,5,6,7,8,9) ; }
Which is good, and does compile and execute just fine.
But if I give the ruby program an array size of 100,000, it should generate a C file that takes n0 to n999999 arguments. That means 100,000 arguments.
A quick google search shows me that C's arguments are stored on the stack.
Passing these arguments should give me a stackerror, but it doesn't. GCC compiles it just fine, I also get output of 99999.
But with Clang, I get:
p.c:4:17: error: use of undeclared identifier 'n99999'
printf("%d\n", n99999) ;
^
p.c:8:195690: error: too many arguments to function call, expected 34464, have 100000
p.c:3:6: note: 'x' declared here
2 errors generated.
How does GCC deal with that many arguments? In most cases, I get stackerror on other programming languages when the stacksize in 10900.
The best way to prove this to your friend is to write an infinite recursive function:
#include <stdio.h>
void recurse(int x) {
static int iterations=0;
printf("Iteration: %d\n", ++iterations);
recurse(x);
}
int main() {
recurse(1);
}
This will always overflow the stack assuming there is a stack (not all architectures use stacks). It will tell you how many stack frames you get to before the stack overflow happens; this will give you an idea of the depth of the stack.
As for why gcc compiles, gcc does not know the target stack size so it cannot check for a stack overflow. It's theoretically possible to have a stack large enough to accommodate 100,000 arguments. That's less than half a megabyte. Not sure why clang behaves differently; it would depend on seeing the generated C code.
If you can share what computer system/architecture you are using, it would be helpful. You cited information that applies to 64-bit Intel systems (e.g. PC/Windows).
I am trying to compile the following C code on linux:
#include <stdio.h>
/////
void func1();
void func2();
//////
void func1()
{
func2();
}
void func2()
{
func1();
}
int main()
{
func1();//call to function 1
}
If I am not wrong then the program should execute infintely but when i compile and run it on linux it gives Segmentation Fault.
Why is this happening?
Each nested function call consumes some stack space for the arguments and the return address. In your code the nested function calls are unbounded, so they consume an unbounded amount of stack. Once the stack is exhausted, the program goes on to write return addresses outside the memory allocated to the process and crashes.
Depending on the compiler, turning on optimizations might help because of tail call optimization.
Behaviour you are experiencing is called stack overflow. This means, the call stack contained too many items and it overflowed (there was no space left on it to continue execution), and the program crashed with SIGSEGV. There is no exit routine so it was inevitable that such thing would happen.
I don't understand why the address of the variables changes based on how I run the program. I have this simple code in C:
#include <stdlib.h>
#include <stdio.h>
int main(){
char buffer[100];
gets(buffer);
printf("buf: %p\n", (void*)&buffer);
printf(buffer);
return 0;
}
before compiling I used this command to disable the randomization:
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
but this is what happens:
image
in the first execution the address of buffer is bffff084 in the second is bffff024
This happens because of Address Space Layout Randomization. Each time program starts, random number is added to stack address so it would be harder to predict absolute addresses of buffers and write injectable shell code.
Since your program is vulnerable to buffer overflow (due to usage of gets and statically allocated buffer), it does its work.
Today , When i coding, met a question..my Code as follow:
#include<stdlib.h>
void main()
{
system("dir");
getch();
}
The question : The user Screen is nothing..Why ? where is my result?
If you want the output when using system, at least into something you can read in your application, you need to pipe the output:
system("dir > /tmp/output.txt");
FILE *f = fopen("/tmp/output.txt", "r");
char text[1024]; // max sizeof of 1 kb, any more and I'd consider using `malloc()` instead.
fread(text, 1, 1024, f);
printf("%s\n", text);
fclose(f);
There are some problems in your program, at least one of which has already been mentioned.
void main() should be int main(void).
As I recall, the Windows/DOS getch function is declared in <conio.h>; you should have a #include directive for it. Be aware that both <conio.h> and getch are non-standard.
Since main returns int, you should return an int result.
But none of these problems explain the problem you're seeing.
With these changes:
#include <stdlib.h>
#include <conio.h>
int main(void)
{
system("dir");
getch();
return 0;
}
This should work; it should show a directory listing of whatever directory your program runs in (which is determined by TC; I don't know the details).
It's possible that the program is running in an empty directory, which means the dir command wouldn't show any files, but it should still produce some output.
Try commenting out the system() call and adding a printf call (note the added #include <stdio.h>):
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
int main(void)
{
printf("Hello, world\n");
getch();
return 0;
}
This should open a console window, print "Hello, world" in it, and wait for you to type Enter.
If you still don't see any output (either no console window, or a console window with nothing in it), then you have a problem that's not related to the system() call. Most likely the problem has to do with the way you're using Turbo C (I presume that's what "TC" stands for).
The main function in every C program is supposed to return an int you are returning void
Change void to int:
#include<stdlib.h>
int main()
{
system("dir");
getch();
}
When I tested, the dir command ran in my console and printed to standard out.
May be he is the running the program directly in the Turbo C IDE and hence his output is not visible. If he runs the program directly from cmd line it works. I remember you need to run Alt - F5 or some other combination to see the output window in Turbo C++